diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ca0973 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c17bfbf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "js/skinny-coffee-machine"] + path = js/skinny-coffee-machine + url = git://github.com/fredwu/skinny-coffee-machine.git +[submodule "js/jqstub"] + path = js/jqstub + url = git://github.com/fredwu/jqstub.git diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d335152 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 +before_install: + - git submodule update --init --recursive diff --git a/README.md b/README.md index 9081d77..aa2dbcc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Endless Scroll [![endorse](http://api.coderwall.com/fredwu/endorsecount.png)](http://coderwall.com/fredwu) +# Endless Scroll [![endorse](http://api.coderwall.com/fredwu/endorsecount.png)](http://coderwall.com/fredwu) [![Build Status](https://secure.travis-ci.org/fredwu/jquery-endless-scroll.png?branch=2.0-rewrite)](http://travis-ci.org/fredwu/jquery-endless-scroll) + +#### This branch is currently being rewritten, please ignore the documentation below (they are for version 1.x). If you don't already know, [endless scrolling](http://www.google.com/search?q=endless+scroll) (or infinite scrolling or pagination) is a popular technique amongst modern websites such as [Google Reader](http://reader.google.com/) and [Live Image Search](http://www.live.com/?scope=images), whereby instead of paging through items using traditional pagination links, the page just keeps loading with new items attached to the end. @@ -46,7 +48,7 @@ There are a few options to customise the behaviour of this plugin: content String or Function - Plain HTML content to insert after each call, can be either a string or a function that returns a string, when passed as a function it accepts three arguments: + Plain HTML content to insert after each call, can be either a string or a function that returns a string, when passed as a function it accepts three arguments: insertBefore @@ -76,12 +78,12 @@ There are a few options to customise the behaviour of this plugin: callback Function - Callback function, accepts three arguments: + Callback function, accepts three arguments: ceaseFire Function - Stops the event (no more endless scrolling) if the function returns true, accepts three arguments: + Stops the event (no more endless scrolling) if the function returns true, accepts three arguments: @@ -126,12 +128,23 @@ The command for automatically compiling to JavaScript is: coffee -w -b -o js/ -c src/ ``` +Starting from v2.0.0 the code base is tested with [Mocha](http://visionmedia.github.com/mocha/) and [Chai](http://chaijs.com/). The tests can be found in `test/`, please write the tests in `test/tests.coffee`. Again, to automatically compile the test code to JavaScript: + +```bash +coffee -w -b -o test/ -c test/ +``` + ## Browser Support All modern browsers (Firefox, Chrome, Safari, Opera, IE7+) should be supported. Please [open an issue](https://github.com/fredwu/jquery-endless-scroll/issues) if Endless Scroll doesn't work on a particular browser. ## Changelog +v2.0.0 + +- Completely rewritten from the ground up with tests. +- A new demo page based on Twitter Bootstrap. + v1.8.0 [2012-04-17] - Added `ceaseFireOnEmpty`. @@ -231,4 +244,4 @@ Check out my other jQuery plugins: Copyright (c) 2008-2012 Fred Wu -Dual licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) and [GPL](http://www.gnu.org/licenses/gpl.html) licenses. +Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) license. diff --git a/css/bootstrap.min.css b/css/bootstrap.min.css new file mode 100644 index 0000000..3119038 --- /dev/null +++ b/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.1.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:20px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:1;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1{font-size:36px;line-height:40px}h2{font-size:30px;line-height:40px}h3{font-size:24px;line-height:40px}h4{font-size:18px;line-height:20px}h5{font-size:14px;line-height:20px}h6{font-size:12px;line-height:20px}h1 small{font-size:24px}h2 small{font-size:18px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal dt{float:left;width:120px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:130px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:9px;font-size:14px;line-height:20px;color:#555;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}input,textarea{width:210px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal;cursor:pointer}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #bbb}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:18px;padding-left:18px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"]{float:left}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning .checkbox:focus,.control-group.warning .radio:focus,.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error .checkbox:focus,.control-group.error .radio:focus,.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success .checkbox:focus,.control-group.success .radio:focus,.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;font-size:14px;vertical-align:top;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn{margin-left:-1px;vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:160px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:160px}.form-horizontal .help-block{margin-top:10px;margin-bottom:0}.form-horizontal .form-actions{padding-left:160px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child,.table-bordered tfoot:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child,.table-bordered tfoot:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-right-topleft:4px}.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table [class*=span],.row-fluid table [class*=span]{display:table-cell;float:none;margin-left:0}table .span1{float:none;width:44px;margin-left:0}table .span2{float:none;width:124px;margin-left:0}table .span3{float:none;width:204px;margin-left:0}table .span4{float:none;width:284px;margin-left:0}table .span5{float:none;width:364px;margin-left:0}table .span6{float:none;width:444px;margin-left:0}table .span7{float:none;width:524px;margin-left:0}table .span8{float:none;width:604px;margin-left:0}table .span9{float:none;width:684px;margin-left:0}table .span10{float:none;width:764px;margin-left:0}table .span11{float:none;width:844px;margin-left:0}table .span12{float:none;width:924px;margin-left:0}table .span13{float:none;width:1004px;margin-left:0}table .span14{float:none;width:1084px;margin-left:0}table .span15{float:none;width:1164px;margin-left:0}table .span16{float:none;width:1244px;margin-left:0}table .span17{float:none;width:1324px;margin-left:0}table .span18{float:none;width:1404px;margin-left:0}table .span19{float:none;width:1484px;margin-left:0}table .span20{float:none;width:1564px;margin-left:0}table .span21{float:none;width:1644px;margin-left:0}table .span22{float:none;width:1724px;margin-left:0}table .span23{float:none;width:1804px;margin-left:0}table .span24{float:none;width:1884px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.info td{background-color:#d9edf7}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav>.active>a>[class^="icon-"],.nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#08c;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#08c;background-color:#0081c2;background-image:linear-gradient(to bottom,#08c,#0077b3);background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:"\2191"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover .dropdown-menu{display:block}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;overflow:visible \9;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 14px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;*line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.btn-large [class^="icon-"]{margin-top:2px}.btn-small{padding:3px 9px;font-size:12px;line-height:18px}.btn-small [class^="icon-"]{margin-top:0}.btn-mini{padding:2px 6px;font-size:11px;line-height:16px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-image:-moz-linear-gradient(top,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-image:-moz-linear-gradient(top,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-group{position:relative;*margin-left:.3em;font-size:0;white-space:nowrap}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}.btn-toolbar .btn+.btn,.btn-toolbar .btn-group+.btn,.btn-toolbar .btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu{font-size:14px}.btn-group>.btn-mini{font-size:11px}.btn-group>.btn-small{font-size:12px}.btn-group>.btn-large{font-size:16px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-top:0;border-bottom:5px solid #000}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical .btn{display:block;float:none;width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical .btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical .btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical .btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical .btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical .btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;color:#c09853;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible;color:#555}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar .container{width:auto}.nav-collapse.collapse{height:auto}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#555;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px}.navbar-link{color:#555}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:6px}.navbar .btn-group .btn{margin:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;width:100%;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner,.navbar-static-top .navbar-inner{border:0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1),0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1);box-shadow:inset 0 1px 0 rgba(0,0,0,0.1),0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#555;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse{color:#999}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-image:-moz-linear-gradient(top,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb .divider{padding:0 5px;color:#ccc}.breadcrumb .active{color:#999}.pagination{height:40px;margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination li{display:inline}.pagination a,.pagination span{float:left;padding:0 14px;line-height:38px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination a:hover,.pagination .active a,.pagination .active span{background-color:#f5f5f5}.pagination .active a,.pagination .active span{color:#999;cursor:default}.pagination .disabled span,.pagination .disabled a,.pagination .disabled a:hover{color:#999;cursor:default;background-color:transparent}.pagination li:first-child a,.pagination li:first-child span{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.pagination li:last-child a,.pagination li:last-child span{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next a{float:right}.pager .previous a{float:left}.pager .disabled a,.pager .disabled a:hover{color:#999;cursor:default;background-color:#fff}.modal-open .dropdown-menu{z-index:2050}.modal-open .dropdown.open{*z-index:2050}.modal-open .popover{z-index:2060}.modal-open .tooltip{z-index:2080}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:50%;left:50%;z-index:1050;width:560px;margin:-250px 0 0 -280px;overflow:auto;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:50%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-bottom:10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-right:10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}.popover .arrow,.popover .arrow:after{position:absolute;display:inline-block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow:after{z-index:-1;content:""}.popover.top .arrow{bottom:-10px;left:50%;margin-left:-10px;border-top-color:#fff;border-width:10px 10px 0}.popover.top .arrow:after{bottom:-1px;left:-11px;border-top-color:rgba(0,0,0,0.25);border-width:11px 11px 0}.popover.right .arrow{top:50%;left:-10px;margin-top:-10px;border-right-color:#fff;border-width:10px 10px 10px 0}.popover.right .arrow:after{bottom:-11px;left:-1px;border-right-color:rgba(0,0,0,0.25);border-width:11px 11px 11px 0}.popover.bottom .arrow{top:-10px;left:50%;margin-left:-10px;border-bottom-color:#fff;border-width:0 10px 10px}.popover.bottom .arrow:after{top:-1px;left:-11px;border-bottom-color:rgba(0,0,0,0.25);border-width:0 11px 11px}.popover.left .arrow{top:50%;right:-10px;margin-top:-10px;border-left-color:#fff;border-width:10px 0 10px 10px}.popover.left .arrow:after{right:-1px;bottom:-11px;border-left-color:rgba(0,0,0,0.25);border-width:11px 0 11px 11px}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.label,.badge{font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel .item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel .item>img{display:block;line-height:1}.carousel .active,.carousel .next,.carousel .prev{display:block}.carousel .active{left:0}.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}.carousel .next{left:100%}.carousel .prev{left:-100%}.carousel .next.left,.carousel .prev.right{left:0}.carousel .active.left{left:-100%}.carousel .active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit p{font-size:18px;font-weight:200;line-height:30px;color:inherit}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/css/endless-scroll-demo.css b/css/endless-scroll-demo.css new file mode 100644 index 0000000..8124e84 --- /dev/null +++ b/css/endless-scroll-demo.css @@ -0,0 +1,30 @@ +section { + padding-top: 90px; +} + +ul { + height: 200px; + overflow-y: auto; +} + + ul li { + list-style: none; + } + +.navbar .nav { + position: absolute; + padding-left: 200px; + left: auto; + bottom: 20px; +} + +.footer { + background-color: #F5F5F5; + border-top: 1px solid #E5E5E5; + margin-top: 70px; + padding: 50px 0; +} + + .footer p { + text-align: center; + } diff --git a/grunt.js b/grunt.js new file mode 100644 index 0000000..080fcef --- /dev/null +++ b/grunt.js @@ -0,0 +1,53 @@ +module.exports = function(grunt) { + grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + min: { + dist: { + src: ['js/<%= pkg.name %>.js'], + dest: 'js/<%= pkg.name %>.min.js' + } + }, + watch: { + coffee: { + files: ['src/*.coffee', 'test/*.coffee'], + tasks: 'coffee' + }, + tests: { + files: ['js/*.js', 'test/*.js'], + tasks: 'mocha' + } + }, + coffee: { + app: { + src: ['src/*.coffee'], + dest: 'js', + options: { + bare: true + } + }, + tests: { + src: ['test/*.coffee'], + dest: 'test/', + options: { + bare: false + } + } + }, + mocha: { + tests: ['test/tests-jquery.html', 'test/tests-zepto.html'] + } + }); + + grunt.loadNpmTasks('grunt-coffee'); + grunt.loadNpmTasks('grunt-mocha'); + + grunt.registerTask('test', 'mocha'); + grunt.registerTask('default', 'coffee mocha'); +}; diff --git a/index.html b/index.html index 209a3c8..eeddec4 100644 --- a/index.html +++ b/index.html @@ -4,103 +4,84 @@ Endless Scroll Demo (by Fred Wu) - - + + + + - -

Endless Scroll Demo

-

by Fred Wu

+ + -
-

Ends in 10 calls:

- -
+
+
+ -
-

Never ending:

-
    -
  • Grass Blades
  • -
  • Stones
  • -
  • Sea Mist
  • -
  • Pier
  • -
  • Lotus
  • -
  • Mojave
  • -
  • Lightning
  • -
  • Grass Blades
  • -
-
+
    +
  • 1
  • +
  • 2
  • +
  • 3
  • +
  • 4
  • +
  • 5
  • +
  • 6
  • +
  • 7
  • +
  • 8
  • +
  • 9
  • +
  • 10
  • +
  • 11
  • +
  • 12
  • +
  • 13
  • +
  • 14
  • +
  • 15
  • +
  • 16
  • +
  • 17
  • +
  • 18
  • +
  • 19
  • +
  • 20
  • +
+
-
-

Copyright © Fred Wu

+
+ + +
    +
  • Grass Blades
  • +
  • Stones
  • +
  • Sea Mist
  • +
  • Pier
  • +
  • Lotus
  • +
  • Mojave
  • +
  • Lightning
  • +
  • Grass Blades
  • +
+
- + - \ No newline at end of file + + diff --git a/jquery-endless-scroll.jquery.json b/jquery-endless-scroll.jquery.json new file mode 120000 index 0000000..2ff8622 --- /dev/null +++ b/jquery-endless-scroll.jquery.json @@ -0,0 +1 @@ +package.json \ No newline at end of file diff --git a/js/bootstrap.min.js b/js/bootstrap.min.js new file mode 100644 index 0000000..66e887b --- /dev/null +++ b/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! +* Bootstrap.js by @fat & @mdo +* Copyright 2012 Twitter, Inc. +* http://www.apache.org/licenses/LICENSE-2.0.txt +*/ +!function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.parent('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(function(){e("body").on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})})}(window.jQuery),!function(e){"use strict";function r(){i(e(t)).removeClass("open")}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(function(){e("body").on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.remove().css({top:0,left:0,display:"block"}).appendTo(t?this.$element:document.body),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.remove()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.remove(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'
',trigger:"hover",title:"",delay:0,html:!0}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'

'})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active a").last()[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(function(){e("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length"+t+""})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),(e.browser.webkit||e.browser.msie)&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1},e.fn.typeahead.Constructor=t,e(function(){e("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery); \ No newline at end of file diff --git a/js/jqstub b/js/jqstub new file mode 160000 index 0000000..75179e0 --- /dev/null +++ b/js/jqstub @@ -0,0 +1 @@ +Subproject commit 75179e088c208b29472e36b7a98ac64bd3e69791 diff --git a/js/jquery.endless-scroll.js b/js/jquery.endless-scroll.js index 34088c8..1fe8b1b 100644 --- a/js/jquery.endless-scroll.js +++ b/js/jquery.endless-scroll.js @@ -1,14 +1,11 @@ -// Generated by CoffeeScript 1.3.1 /* Endless Scroll plugin for jQuery - v1.8.0 + v2.0.0.dev Copyright (c) 2008-2012 Fred Wu - Dual licensed under the MIT and GPL licenses: - http://www.opensource.org/licenses/mit-license.php - http://www.gnu.org/licenses/gpl.html + Licensed under the MIT licenses: http://www.opensource.org/licenses/mit-license.php */ /* @@ -19,325 +16,107 @@ // using some custom options $("#images").endlessScroll({ - fireOnce: false, + fireOnce: false, fireDelay: false, - loader: '
    ', - callback: function(){ + loader: '
    ', + callback: function(){ alert('test'); } }); Configuration options: - pagesToKeep integer the number of 'pages' to keep before either end of the scrolling content are discarded, - by default (value set to `null`) no content will be discarded + pagesToKeep integer the number of 'pages' to keep before either end of the scrolling content are + discarded, by default (value set to `null`) no content will be discarded + inflowPixels integer the number of pixels from the boundary of the element that triggers the event + fireOnce boolean only fire once until the execution of the current event is completed + fireDelay integer delay the subsequent firing, in milliseconds, 0 or false to disable delay + loader string the HTML to be displayed during loading + content string|function Plain HTML content to insert after each call, can be either a string or a function that returns a string, when passed as a function it accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' + insertBefore string jQuery selector syntax: where to put the loader as well as the plain HTML data + insertAfter string jQuery selector syntax: where to put the loader as well as the plain HTML data + intervalFrequency integer set the frequency of the scroll event checking, the larger the frequency number, the less memory it consumes - but also the less sensitive the event trigger becomes - ceaseFireOnEmpty boolean ceases fire automatically when the content is empty, set it to `false` if you are using - `callback` instead of `content` for loading content + + ceaseFireOnEmpty boolean ceases fire automatically when the content is empty, set it to `false` if you are + using `callback` instead of `content` for loading content + resetCounter function resets the fire sequence counter if the function returns true, this function could also perform hook actions since it is applied at the start of the event + callback function callback function, accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' + ceaseFire function stops the event (no more endless scrolling) if the function returns true, accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' */ -var EndlessScroll; +var EndlessScroll, Whether, dependencyLib; + +window.EndlessScroll = EndlessScroll; EndlessScroll = (function() { var defaults; - EndlessScroll.name = 'EndlessScroll'; - defaults = { - pagesToKeep: null, - inflowPixels: 50, - fireOnce: true, - fireDelay: 150, - loader: 'Loading...', - content: '', - insertBefore: null, - insertAfter: null, - intervalFrequency: 250, - ceaseFireOnEmpty: true, - resetCounter: function() { - return false; - }, - callback: function() { - return true; - }, - ceaseFire: function() { - return false; - } + topPixels: 50, + bottomPixels: 50, + intervalFrequency: 250 }; function EndlessScroll(scope, options) { - var _this = this; this.options = $.extend({}, defaults, options); - this.pagesStack = [0]; - this.scrollDirection = 'next'; - this.firing = true; - this.fired = false; - this.fireSequence = 0; - this.pageSequence = 0; - this.nextSequence = 1; - this.prevSequence = -1; - this.lastScrollTop = 0; - this.insertLocation = this.options.insertAfter; - this.didScroll = false; - this.isScrollable = true; - this.target = scope; - this.targetId = ''; - this.content = ''; - this.lastContent = 'dummy'; - this.innerWrap = $('.endless_scroll_inner_wrap', this.target); - this.handleDeprecatedOptions(); - this.setInsertPositionsWhenNecessary(); - $(scope).scroll(function() { - _this.detectTarget(scope); - return _this.detectScrollDirection(); - }); } EndlessScroll.prototype.run = function() { - var _this = this; - return setInterval((function() { - if (!_this.shouldTryFiring()) { - return; - } - if (_this.ceaseFireWhenNecessary()) { - return; - } - if (!_this.shouldBeFiring()) { - return; - } - _this.resetFireSequenceWhenNecessary(); - _this.acknowledgeFiring(); - _this.insertLoader(); - if (_this.hasContent()) { - _this.showContent(); - _this.fireCallback(); - _this.cleanUpPagesWhenNecessary(); - _this.delayFiringWhenNecessary(); - } - _this.removeLoader(); - return _this.lastContent = _this.content; - }), this.options.intervalFrequency); - }; - - EndlessScroll.prototype.handleDeprecatedOptions = function() { - if (this.options.data) { - this.options.content = this.options.data; - } - if (this.options.bottomPixels) { - return this.options.inflowPixels = this.options.bottomPixels; - } - }; - - EndlessScroll.prototype.setInsertPositionsWhenNecessary = function() { - var container; - container = "" + this.target.selector + " div.endless_scroll_inner_wrap"; - if (defaults.insertBefore === null) { - this.options.insertBefore = "" + container + " div:first"; - } - if (defaults.insertAfter === null) { - return this.options.insertAfter = "" + container + " div:last"; - } - }; - - EndlessScroll.prototype.detectTarget = function(scope) { - this.target = scope; - return this.targetId = $(this.target).attr('id'); - }; - - EndlessScroll.prototype.detectScrollDirection = function() { - var currentScrollTop; - this.didScroll = true; - currentScrollTop = $(this.target).scrollTop(); - if (currentScrollTop > this.lastScrollTop) { - this.scrollDirection = 'next'; - } else { - this.scrollDirection = 'prev'; - } - return this.lastScrollTop = currentScrollTop; - }; - - EndlessScroll.prototype.shouldTryFiring = function() { - var shouldTryOrNot; - shouldTryOrNot = this.didScroll && this.firing === true; - if (shouldTryOrNot) { - this.didScroll = false; - } - return shouldTryOrNot; - }; - - EndlessScroll.prototype.ceaseFireWhenNecessary = function() { - if (this.options.ceaseFireOnEmpty === true && this.lastContent === '' || this.options.ceaseFire.apply(this.target, [this.fireSequence, this.pageSequence, this.scrollDirection])) { - this.firing = false; + return setInterval(function() { return true; - } else { - return false; - } - }; - - EndlessScroll.prototype.wrapContainer = function(target) { - if (this.innerWrap.length === 0) { - return this.innerWrap = $(target).wrapInner('
    ').wrapInner('
    ').find('.endless_scroll_inner_wrap'); - } - }; - - EndlessScroll.prototype.scrollableAreaMargin = function(innerWrap, target) { - var margin; - switch (this.scrollDirection) { - case 'next': - margin = innerWrap.height() - $(target).height() <= $(target).scrollTop() + this.options.inflowPixels; - if (margin) { - target.scrollTop(innerWrap.height() - $(target).height() - this.options.inflowPixels); - } - break; - case 'prev': - margin = $(target).scrollTop() <= this.options.inflowPixels; - if (margin) { - target.scrollTop(this.options.inflowPixels); - } - } - return margin; - }; - - EndlessScroll.prototype.calculateScrollableCanvas = function() { - if (this.target[0] === document || this.target[0] === window) { - this.wrapContainer("body"); - return this.isScrollable = this.scrollableAreaMargin($(document), $(window)); - } else { - this.wrapContainer(this.target); - return this.isScrollable = this.innerWrap.length > 0 && this.scrollableAreaMargin(this.innerWrap, this.target); - } + }, this.options.intervalFrequency); }; - EndlessScroll.prototype.shouldBeFiring = function() { - this.calculateScrollableCanvas(); - return this.isScrollable && (this.options.fireOnce === false || (this.options.fireOnce === true && this.fired !== true)); - }; - - EndlessScroll.prototype.resetFireSequenceWhenNecessary = function() { - if (this.options.resetCounter.apply(this.target) === true) { - return this.fireSequence = 0; - } - }; - - EndlessScroll.prototype.acknowledgeFiring = function() { - this.fired = true; - this.fireSequence++; - switch (this.scrollDirection) { - case 'next': - return this.pageSequence = this.nextSequence++; - case 'prev': - return this.pageSequence = this.prevSequence--; - } - }; - - EndlessScroll.prototype.insertContent = function(content) { - switch (this.scrollDirection) { - case 'next': - return $(this.options.insertAfter).after(content); - case 'prev': - return $(this.options.insertBefore).before(content); - } - }; - - EndlessScroll.prototype.insertLoader = function() { - return this.insertContent("
    " + this.options.loader + "
    "); - }; - - EndlessScroll.prototype.removeLoader = function() { - return $('.endless_scroll_loader_' + this.targetId).fadeOut(function() { - return $(this).remove(); - }); - }; - - EndlessScroll.prototype.hasContent = function() { - if (typeof this.options.content === 'function') { - this.content = this.options.content.apply(this.target, [this.fireSequence, this.pageSequence, this.scrollDirection]); - } else { - this.content = this.options.content; - } - return this.content !== false; - }; - - EndlessScroll.prototype.showContent = function() { - $('#endless_scroll_content_current').removeAttr('id'); - return this.insertContent("
    " + this.content + "
    "); - }; + return EndlessScroll; - EndlessScroll.prototype.fireCallback = function() { - return this.options.callback.apply(this.target, [this.fireSequence, this.pageSequence, this.scrollDirection]); - }; +})(); - EndlessScroll.prototype.cleanUpPagesWhenNecessary = function() { - var pageToRemove; - if (!(this.options.pagesToKeep >= 1)) { - return; - } - switch (this.scrollDirection) { - case 'next': - this.pagesStack.push(this.pageSequence); - break; - case 'prev': - this.pagesStack.unshift(this.pageSequence); - } - if (this.pagesStack.length > this.options.pagesToKeep) { - switch (this.scrollDirection) { - case 'next': - pageToRemove = this.prevSequence = this.pagesStack.shift(); - break; - case 'prev': - pageToRemove = this.nextSequence = this.pagesStack.pop(); - } - } - this.removePage(pageToRemove); - return this.calculateScrollableCanvas(); - }; +Whether = (function() { - EndlessScroll.prototype.removePage = function(page) { - return $(".endless_scroll_content[data-page='" + page + "']", this.target).remove(); - }; + function Whether() {} - EndlessScroll.prototype.delayFiringWhenNecessary = function() { - var _this = this; - if (this.options.fireDelay > 0) { - $('body').after('
    '); - return $('#endless_scroll_marker').fadeTo(this.options.fireDelay, 1, function() { - $('#endless_scroll_marker').remove(); - return _this.fired = false; - }); - } else { - return this.fired = false; - } + Whether.DocumentIsScrollableDownward = function(options) { + return $(document).height() - $(window).height() <= $(window).scrollTop() + options.bottomPixels; }; - return EndlessScroll; + return Whether; })(); +dependencyLib = typeof Zepto === 'undefined' ? jQuery : Zepto; + (function($) { return $.fn.endlessScroll = function(options) { return new EndlessScroll(this, options).run(); }; -})(jQuery); +})(dependencyLib); diff --git a/js/jquery.min.js b/js/jquery.min.js index 93adea1..ef6e4e8 100644 --- a/js/jquery.min.js +++ b/js/jquery.min.js @@ -1,4 +1,2 @@ -/*! jQuery v1.7.2 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+""),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
    a",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="
    "+""+"
    ",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="
    t
    ",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="
    ",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&j.push({elem:this,matches:d.slice(e)});for(k=0;k0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(;d1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===""&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file +/*! jQuery v@1.8.0 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.0",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return typeof a=="object"?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
    a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length||!d)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
    t
    ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
    ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/^(?:\{.*\}|\[.*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||++p.uuid:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.shift(),e=p._queueHooks(a,b),f=function(){p.dequeue(a,b)};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),delete e.stop,d.call(a,f,e)),!c.length&&e&&e.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c-1)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c-1)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;jq&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bd(a,b,c,d){var e=0,f=b.length;for(;e0?h(g,c,f):[]}function bf(a,c,d,e,f){var g,h,i,j,k,l,m,n,p=0,q=f.length,s=L.POS,t=new RegExp("^"+s.source+"(?!"+r+")","i"),u=function(){var a=1,c=arguments.length-2;for(;ai){m=a.slice(i,g.index),i=n,l=[c],B.test(m)&&(k&&(l=k),k=e);if(h=H.test(m))m=m.slice(0,-5).replace(B,"$&*");g.length>1&&g[0].replace(t,u),k=be(m,g[1],g[2],l,k,h)}}k?(j=j.concat(k),(m=a.slice(i))&&m!==")"?B.test(m)?bd(m,j,d,e):Z(m,c,d,e?e.concat(k):k):o.apply(d,j)):Z(a,c,d,e)}return q===1?d:Z.uniqueSort(d)}function bg(a,b,c){var d,e,f,g=[],i=0,j=D.exec(a),k=!j.pop()&&!j.pop(),l=k&&a.match(C)||[""],m=$.preFilter,n=$.filter,o=!c&&b!==h;for(;(e=l[i])!=null&&k;i++){g.push(d=[]),o&&(e=" "+e);while(e){k=!1;if(j=B.exec(e))e=e.slice(j[0].length),k=d.push({part:j.pop().replace(A," "),captures:j});for(f in n)(j=L[f].exec(e))&&(!m[f]||(j=m[f](j,b,c)))&&(e=e.slice(j.shift().length),k=d.push({part:f,captures:j}));if(!k)break}}return k||Z.error(a),g}function bh(a,b,e){var f=b.dir,g=m++;return a||(a=function(a){return a===e}),b.first?function(b,c){while(b=b[f])if(b.nodeType===1)return a(b,c)&&b}:function(b,e){var h,i=g+"."+d,j=i+"."+c;while(b=b[f])if(b.nodeType===1){if((h=b[q])===j)return b.sizset;if(typeof h=="string"&&h.indexOf(i)===0){if(b.sizset)return b}else{b[q]=j;if(a(b,e))return b.sizset=!0,b;b.sizset=!1}}}}function bi(a,b){return a?function(c,d){var e=b(c,d);return e&&a(e===!0?c:e,d)}:b}function bj(a,b,c){var d,e,f=0;for(;d=a[f];f++)$.relative[d.part]?e=bh(e,$.relative[d.part],b):(d.captures.push(b,c),e=bi(e,$.filter[d.part].apply(null,d.captures)));return e}function bk(a){return function(b,c){var d,e=0;for(;d=a[e];e++)if(d(b,c))return!0;return!1}}var c,d,e,f,g,h=a.document,i=h.documentElement,j="undefined",k=!1,l=!0,m=0,n=[].slice,o=[].push,q=("sizcache"+Math.random()).replace(".",""),r="[\\x20\\t\\r\\n\\f]",s="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",t=s.replace("w","w#"),u="([*^$|!~]?=)",v="\\["+r+"*("+s+")"+r+"*(?:"+u+r+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+t+")|)|)"+r+"*\\]",w=":("+s+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",x=":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",y=r+"*([\\x20\\t\\r\\n\\f>+~])"+r+"*",z="(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|"+v+"|"+w.replace(2,7)+"|[^\\\\(),])+",A=new RegExp("^"+r+"+|((?:^|[^\\\\])(?:\\\\.)*)"+r+"+$","g"),B=new RegExp("^"+y),C=new RegExp(z+"?(?="+r+"*,|$)","g"),D=new RegExp("^(?:(?!,)(?:(?:^|,)"+r+"*"+z+")*?|"+r+"*(.*?))(\\)|$)"),E=new RegExp(z.slice(19,-6)+"\\x20\\t\\r\\n\\f>+~])+|"+y,"g"),F=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,G=/[\x20\t\r\n\f]*[+~]/,H=/:not\($/,I=/h\d/i,J=/input|select|textarea|button/i,K=/\\(?!\\)/g,L={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),NAME:new RegExp("^\\[name=['\"]?("+s+")['\"]?\\]"),TAG:new RegExp("^("+s.replace("[-","[-\\*")+")"),ATTR:new RegExp("^"+v),PSEUDO:new RegExp("^"+w),CHILD:new RegExp("^:(only|nth|last|first)-child(?:\\("+r+"*(even|odd|(([+-]|)(\\d*)n|)"+r+"*(?:([+-]|)"+r+"*(\\d+)|))"+r+"*\\)|)","i"),POS:new RegExp(x,"ig"),needsContext:new RegExp("^"+r+"*[>+~]|"+x,"i")},M={},N=[],O={},P=[],Q=function(a){return a.sizzleFilter=!0,a},R=function(a){return function(b){return b.nodeName.toLowerCase()==="input"&&b.type===a}},S=function(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}},T=function(a){var b=!1,c=h.createElement("div");try{b=a(c)}catch(d){}return c=null,b},U=T(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),V=T(function(a){a.id=q+0,a.innerHTML="
    ",i.insertBefore(a,i.firstChild);var b=h.getElementsByName&&h.getElementsByName(q).length===2+h.getElementsByName(q+0).length;return g=!h.getElementById(q),i.removeChild(a),b}),W=T(function(a){return a.appendChild(h.createComment("")),a.getElementsByTagName("*").length===0}),X=T(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==j&&a.firstChild.getAttribute("href")==="#"}),Y=T(function(a){return a.innerHTML="",!a.getElementsByClassName||a.getElementsByClassName("e").length===0?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length!==1)}),Z=function(a,b,c,d){c=c||[],b=b||h;var e,f,g,i,j=b.nodeType;if(j!==1&&j!==9)return[];if(!a||typeof a!="string")return c;g=ba(b);if(!g&&!d)if(e=F.exec(a))if(i=e[1]){if(j===9){f=b.getElementById(i);if(!f||!f.parentNode)return c;if(f.id===i)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(i))&&bb(b,f)&&f.id===i)return c.push(f),c}else{if(e[2])return o.apply(c,n.call(b.getElementsByTagName(a),0)),c;if((i=e[3])&&Y&&b.getElementsByClassName)return o.apply(c,n.call(b.getElementsByClassName(i),0)),c}return bm(a,b,c,d,g)},$=Z.selectors={cacheLength:50,match:L,order:["ID","TAG"],attrHandle:{},createPseudo:Q,find:{ID:g?function(a,b,c){if(typeof b.getElementById!==j&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==j&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==j&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:W?function(a,b){if(typeof b.getElementsByTagName!==j)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(K,""),a[3]=(a[4]||a[5]||"").replace(K,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||Z.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&Z.error(a[0]),a},PSEUDO:function(a){var b,c=a[4];return L.CHILD.test(a[0])?null:(c&&(b=D.exec(c))&&b.pop()&&(a[0]=a[0].slice(0,b[0].length-c.length-1),c=b[0].slice(0,-1)),a.splice(2,3,c||a[3]),a)}},filter:{ID:g?function(a){return a=a.replace(K,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(K,""),function(b){var c=typeof b.getAttributeNode!==j&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(K,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=M[a];return b||(b=M[a]=new RegExp("(^|"+r+")"+a+"("+r+"|$)"),N.push(a),N.length>$.cacheLength&&delete M[N.shift()]),function(a){return b.test(a.className||typeof a.getAttribute!==j&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return b?function(d){var e=Z.attr(d,a),f=e+"";if(e==null)return b==="!=";switch(b){case"=":return f===c;case"!=":return f!==c;case"^=":return c&&f.indexOf(c)===0;case"*=":return c&&f.indexOf(c)>-1;case"$=":return c&&f.substr(f.length-c.length)===c;case"~=":return(" "+f+" ").indexOf(c)>-1;case"|=":return f===c||f.substr(0,c.length+1)===c+"-"}}:function(b){return Z.attr(b,a)!=null}},CHILD:function(a,b,c,d){if(a==="nth"){var e=m++;return function(a){var b,f,g=0,h=a;if(c===1&&d===0)return!0;b=a.parentNode;if(b&&(b[q]!==e||!a.sizset)){for(h=b.firstChild;h;h=h.nextSibling)if(h.nodeType===1){h.sizset=++g;if(h===a)break}b[q]=e}return f=a.sizset-d,c===0?f===0:f%c===0&&f/c>=0}}return function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b,c,d){var e=$.pseudos[a]||$.pseudos[a.toLowerCase()];return e||Z.error("unsupported pseudo: "+a),e.sizzleFilter?e(b,c,d):e}},pseudos:{not:Q(function(a,b,c){var d=bl(a.replace(A,"$1"),b,c);return function(a){return!d(a)}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!$.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},contains:Q(function(a){return function(b){return(b.textContent||b.innerText||bc(b)).indexOf(a)>-1}}),has:Q(function(a){return function(b){return Z(a,b).length>0}}),header:function(a){return I.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:R("radio"),checkbox:R("checkbox"),file:R("file"),password:R("password"),image:R("image"),submit:S("submit"),reset:S("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return J.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b,c){return c?a.slice(1):[a[0]]},last:function(a,b,c){var d=a.pop();return c?a:[d]},even:function(a,b,c){var d=[],e=c?1:0,f=a.length;for(;e$.cacheLength&&delete O[P.shift()],g};Z.matches=function(a,b){return Z(a,null,null,b)},Z.matchesSelector=function(a,b){return Z(b,null,null,[a]).length>0};var bm=function(a,b,e,f,g){a=a.replace(A,"$1");var h,i,j,k,l,m,p,q,r,s=a.match(C),t=a.match(E),u=b.nodeType;if(L.POS.test(a))return bf(a,b,e,f,s);if(f)h=n.call(f,0);else if(s&&s.length===1){if(t.length>1&&u===9&&!g&&(s=L.ID.exec(t[0]))){b=$.find.ID(s[1],b,g)[0];if(!b)return e;a=a.slice(t.shift().length)}q=(s=G.exec(t[0]))&&!s.index&&b.parentNode||b,r=t.pop(),m=r.split(":not")[0];for(j=0,k=$.order.length;j",a.querySelectorAll("[selected]").length||e.push("\\["+r+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),T(function(a){a.innerHTML="

    ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+r+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=e.length&&new RegExp(e.join("|")),bm=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a)))if(d.nodeType===9)try{return o.apply(f,n.call(d.querySelectorAll(a),0)),f}catch(i){}else if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){var j=d.getAttribute("id"),k=j||q,l=G.test(a)&&d.parentNode||d;j?k=k.replace(c,"\\$&"):d.setAttribute("id",k);try{return o.apply(f,n.call(l.querySelectorAll(a.replace(C,"[id='"+k+"'] $&")),0)),f}catch(i){}finally{j||d.removeAttribute("id")}}return b(a,d,f,g,h)},g&&(T(function(b){a=g.call(b,"div");try{g.call(b,"[test!='']:sizzle"),f.push($.match.PSEUDO)}catch(c){}}),f=new RegExp(f.join("|")),Z.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!ba(b)&&!f.test(c)&&(!e||!e.test(c)))try{var h=g.call(b,c);if(h||a||b.document&&b.document.nodeType!==11)return h}catch(i){}return Z(c,null,null,[b]).length>0})}(),Z.attr=p.attr,p.find=Z,p.expr=Z.selectors,p.expr[":"]=p.expr.pseudos,p.unique=Z.uniqueSort,p.text=Z.getText,p.isXMLDoc=Z.isXML,p.contains=Z.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
    ","
    "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=0,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(g=b===e&&bA;(h=a[s])!=null;s++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{g=g||bk(b),l=l||g.appendChild(b.createElement("div")),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(f=n.length-1;f>=0;--f)p.nodeName(n[f],"tbody")&&!n[f].childNodes.length&&n[f].parentNode.removeChild(n[f])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l=g.lastChild}h.nodeType?t.push(h):t=p.merge(t,h)}l&&(g.removeChild(l),h=l=g=null);if(!p.support.appendChecked)for(s=0;(h=t[s])!=null;s++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(s=0;(h=t[s])!=null;s++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[s+1,0].concat(r)),s+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^margin/,bO=new RegExp("^("+q+")(.*)$","i"),bP=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bQ=new RegExp("^([-+])=("+q+")","i"),bR={},bS={position:"absolute",visibility:"hidden",display:"block"},bT={letterSpacing:0,fontWeight:400,lineHeight:1},bU=["Top","Right","Bottom","Left"],bV=["Webkit","O","Moz","ms"],bW=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return bZ(this,!0)},hide:function(){return bZ(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bW.apply(this,arguments):this.each(function(){(c?a:bY(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bX(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bQ.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bX(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bT&&(f=bT[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(a,b){var c,d,e,f,g=getComputedStyle(a,null),h=a.style;return g&&(c=g[b],c===""&&!p.contains(a.ownerDocument.documentElement,a)&&(c=p.style(a,b)),bP.test(c)&&bN.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=c,c=g.width,h.width=d,h.minWidth=e,h.maxWidth=f)),c}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bP.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0||bH(a,"display")!=="none"?ca(a,b,d):p.swap(a,bS,function(){return ca(a,b,d)})},set:function(a,c,d){return b$(a,c,d?b_(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bP.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bU[d]+b]=e[d]||e[d-2]||e[0];return f}},bN.test(a)||(p.cssHooks[a+b].set=b$)});var cc=/%20/g,cd=/\[\]$/,ce=/\r?\n/g,cf=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,cg=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||cg.test(this.nodeName)||cf.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(ce,"\r\n")}}):{name:b.name,value:c.replace(ce,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ch(d,a[d],c,f);return e.join("&").replace(cc,"+")};var ci,cj,ck=/#.*$/,cl=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cm=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,cn=/^(?:GET|HEAD)$/,co=/^\/\//,cp=/\?/,cq=/)<[^<]*)*<\/script>/gi,cr=/([?&])_=[^&]*/,cs=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,ct=p.fn.load,cu={},cv={},cw=["*/"]+["*"];try{ci=f.href}catch(cx){ci=e.createElement("a"),ci.href="",ci=ci.href}cj=cs.exec(ci.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&ct)return ct.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
    ").append(a.replace(cq,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cA(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cA(a,b),a},ajaxSettings:{url:ci,isLocal:cm.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cw},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cy(cu),ajaxTransport:cy(cv),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cB(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cC(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=""+(c||y),k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cl.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(ck,"").replace(co,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=cs.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]==cj[1]&&i[2]==cj[2]&&(i[3]||(i[1]==="http:"?80:443))==(cj[3]||(cj[1]==="http:"?80:443)))),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cz(cu,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!cn.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cp.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cr,"$1_="+z);l.url=A+(A===l.url?(cp.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cw+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cz(cv,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cD=[],cE=/\?/,cF=/(=)\?(?=&|$)|\?\?/,cG=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cD.pop()||p.expando+"_"+cG++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cF.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cF.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cF,"$1"+f):m?c.data=i.replace(cF,"$1"+f):k&&(c.url+=(cE.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cD.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cH,cI=a.ActiveXObject?function(){for(var a in cH)cH[a](0,1)}:!1,cJ=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cK()||cL()}:cK,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cI&&delete cH[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cJ,cI&&(cH||(cH={},p(a).unload(cI)),cH[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cM,cN,cO=/^(?:toggle|show|hide)$/,cP=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cQ=/queueHooks$/,cR=[cX],cS={"*":[function(a,b){var c,d,e,f=this.createTween(a,b),g=cP.exec(b),h=f.cur(),i=+h||0,j=1;if(g){c=+g[2],d=g[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&i){i=p.css(f.elem,a,!0)||c||1;do e=j=j||".5",i=i/j,p.style(f.elem,a,i+d),j=f.cur()/h;while(j!==1&&j!==e)}f.unit=d,f.start=i,f.end=g[1]?i+(g[1]+1)*c:c}return f}]};p.Animation=p.extend(cV,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c$.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c$.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=c_(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); diff --git a/js/skinny-coffee-machine b/js/skinny-coffee-machine new file mode 160000 index 0000000..9af4d71 --- /dev/null +++ b/js/skinny-coffee-machine @@ -0,0 +1 @@ +Subproject commit 9af4d717e2186900f0414f8444f9dd7d18a4cac2 diff --git a/js/zepto.min.js b/js/zepto.min.js new file mode 100644 index 0000000..b6488d8 --- /dev/null +++ b/js/zepto.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.0rc1-146-g4364a33 - polyfill zepto event detect fx ajax form - zeptojs.com/license */ +(function(e){String.prototype.trim===e&&(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Array.prototype.reduce===e&&(Array.prototype.reduce=function(t){if(this===void 0||this===null)throw new TypeError;var n=Object(this),r=n.length>>>0,i=0,s;if(typeof t!="function")throw new TypeError;if(r==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);while(i0?n.fn.concat.apply([],e):e}function q(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function R(e){return e in f?f[e]:f[e]=new RegExp("(^|\\s)"+e+"(\\s|$)")}function U(e,t){return typeof t=="number"&&!c[q(e)]?t+"px":t}function z(e){var t,n;return a[e]||(t=u.createElement(e),u.body.appendChild(t),n=l(t,"").getPropertyValue("display"),t.parentNode.removeChild(t),n=="none"&&(n="block"),a[e]=n),a[e]}function W(e){return"children"in e?s.call(e.children):n.map(e.childNodes,function(e){if(e.nodeType==1)return e})}function X(n,r,i){for(t in r)i&&H(r[t])?(H(n[t])||(n[t]={}),X(n[t],r[t],i)):r[t]!==e&&(n[t]=r[t])}function V(t,r){return r===e?n(t):n(t).filter(r)}function $(e,t,n,r){return M(t)?t.call(e,n,r):t}function J(e,t,n){n==null?e.removeAttribute(t):e.setAttribute(t,n)}function K(t,n){var r=t.className,i=r&&r.baseVal!==e;if(n===e)return i?r.baseVal:r;i?r.baseVal=n:t.className=n}function Q(e){var t;try{return e?e=="true"||(e=="false"?!1:e=="null"?null:isNaN(t=Number(e))?/^[\[\{]/.test(e)?n.parseJSON(e):e:t):e}catch(r){return e}}function G(e,t){t(e);for(var n in e.childNodes)G(e.childNodes[n],t)}var e,t,n,r,i=[],s=i.slice,o=i.filter,u=window.document,a={},f={},l=u.defaultView.getComputedStyle,c={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},h=/^\s*<(\w+|!)[^>]*>/,p=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/^(?:body|html)$/i,v=["val","css","html","text","data","width","height","offset"],m=["after","prepend","before","append"],g=u.createElement("table"),y=u.createElement("tr"),b={tr:u.createElement("tbody"),tbody:g,thead:g,tfoot:g,td:y,th:y,"*":u.createElement("div")},w=/complete|loaded|interactive/,E=/^\.([\w-]+)$/,S=/^#([\w-]*)$/,x=/^[\w-]+$/,T={},N=T.toString,C={},k,L,A=u.createElement("div");return C.matches=function(e,t){if(!e||e.nodeType!==1)return!1;var n=e.webkitMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.matchesSelector;if(n)return n.call(e,t);var r,i=e.parentNode,s=!i;return s&&(i=A).appendChild(e),r=~C.qsa(i,t).indexOf(e),s&&A.removeChild(e),r},k=function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},L=function(e){return o.call(e,function(t,n){return e.indexOf(t)==n})},C.fragment=function(t,r,i){t.replace&&(t=t.replace(p,"<$1>")),r===e&&(r=h.test(t)&&RegExp.$1),r in b||(r="*");var o,u,a=b[r];return a.innerHTML=""+t,u=n.each(s.call(a.childNodes),function(){a.removeChild(this)}),H(i)&&(o=n(u),n.each(i,function(e,t){v.indexOf(e)>-1?o[e](t):o.attr(e,t)})),u},C.Z=function(e,t){return e=e||[],e.__proto__=n.fn,e.selector=t||"",e},C.isZ=function(e){return e instanceof C.Z},C.init=function(t,r){if(!t)return C.Z();if(M(t))return n(u).ready(t);if(C.isZ(t))return t;var i;if(B(t))i=F(t);else if(P(t))i=[H(t)?n.extend({},t):t],t=null;else if(h.test(t))i=C.fragment(t.trim(),RegExp.$1,r),t=null;else{if(r!==e)return n(r).find(t);i=C.qsa(u,t)}return C.Z(i,t)},n=function(e,t){return C.init(e,t)},n.extend=function(e){var t,n=s.call(arguments,1);return typeof e=="boolean"&&(t=e,e=n.shift()),n.forEach(function(n){X(e,n,t)}),e},C.qsa=function(e,t){var n;return D(e)&&S.test(t)?(n=e.getElementById(RegExp.$1))?[n]:[]:e.nodeType!==1&&e.nodeType!==9?[]:s.call(E.test(t)?e.getElementsByClassName(RegExp.$1):x.test(t)?e.getElementsByTagName(t):e.querySelectorAll(t))},n.contains=function(e,t){return e!==t&&e.contains(t)},n.type=O,n.isFunction=M,n.isWindow=_,n.isArray=B,n.isPlainObject=H,n.isEmptyObject=function(e){var t;for(t in e)return!1;return!0},n.inArray=function(e,t,n){return i.indexOf.call(t,e,n)},n.camelCase=k,n.trim=function(e){return e.trim()},n.uuid=0,n.support={},n.expr={},n.map=function(e,t){var n,r=[],i,s;if(j(e))for(i=0;i=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(e){return i.every.call(this,function(t,n){return e.call(t,n,t)!==!1}),this},filter:function(e){return M(e)?this.not(this.not(e)):n(o.call(this,function(t){return C.matches(t,e)}))},add:function(e,t){return n(L(this.concat(n(e,t))))},is:function(e){return this.length>0&&C.matches(this[0],e)},not:function(t){var r=[];if(M(t)&&t.call!==e)this.each(function(e){t.call(this,e)||r.push(this)});else{var i=typeof t=="string"?this.filter(t):j(t)&&M(t.item)?s.call(t):n(t);this.forEach(function(e){i.indexOf(e)<0&&r.push(e)})}return n(r)},has:function(e){return this.filter(function(){return P(e)?n.contains(this,e):n(this).find(e).size()})},eq:function(e){return e===-1?this.slice(e):this.slice(e,+e+1)},first:function(){var e=this[0];return e&&!P(e)?e:n(e)},last:function(){var e=this[this.length-1];return e&&!P(e)?e:n(e)},find:function(e){var t;return this.length==1?t=n(C.qsa(this[0],e)):t=this.map(function(){return C.qsa(this,e)}),t},closest:function(e,t){var r=this[0];while(r&&!C.matches(r,e))r=r!==t&&!D(r)&&r.parentNode;return n(r)},parents:function(e){var t=[],r=this;while(r.length>0)r=n.map(r,function(e){if((e=e.parentNode)&&!D(e)&&t.indexOf(e)<0)return t.push(e),e});return V(t,e)},parent:function(e){return V(L(this.pluck("parentNode")),e)},children:function(e){return V(this.map(function(){return W(this)}),e)},contents:function(){return this.map(function(){return s.call(this.childNodes)})},siblings:function(e){return V(this.map(function(e,t){return o.call(W(t.parentNode),function(e){return e!==t})}),e)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(e){return n.map(this,function(t){return t[e]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),l(this,"").getPropertyValue("display")=="none"&&(this.style.display=z(this.nodeName))})},replaceWith:function(e){return this.before(e).remove()},wrap:function(e){var t=M(e);if(this[0]&&!t)var r=n(e).get(0),i=r.parentNode||this.length>1;return this.each(function(s){n(this).wrapAll(t?e.call(this,s):i?r.cloneNode(!0):r)})},wrapAll:function(e){if(this[0]){n(this[0]).before(e=n(e));var t;while((t=e.children()).length)e=t.first();n(e).append(this)}return this},wrapInner:function(e){var t=M(e);return this.each(function(r){var i=n(this),s=i.contents(),o=t?e.call(this,r):e;s.length?s.wrapAll(o):i.append(o)})},unwrap:function(){return this.parent().each(function(){n(this).replaceWith(n(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var r=n(this);(t===e?r.css("display")=="none":t)?r.show():r.hide()})},prev:function(e){return n(this.pluck("previousElementSibling")).filter(e||"*")},next:function(e){return n(this.pluck("nextElementSibling")).filter(e||"*")},html:function(t){return t===e?this.length>0?this[0].innerHTML:null:this.each(function(e){var r=this.innerHTML;n(this).empty().append($(this,t,e,r))})},text:function(t){return t===e?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=t})},attr:function(n,r){var i;return typeof n=="string"&&r===e?this.length==0||this[0].nodeType!==1?e:n=="value"&&this[0].nodeName=="INPUT"?this.val():!(i=this[0].getAttribute(n))&&n in this[0]?this[0][n]:i:this.each(function(e){if(this.nodeType!==1)return;if(P(n))for(t in n)J(this,t,n[t]);else J(this,n,$(this,r,e,this.getAttribute(n)))})},removeAttr:function(e){return this.each(function(){this.nodeType===1&&J(this,e)})},prop:function(t,n){return n===e?this[0]&&this[0][t]:this.each(function(e){this[t]=$(this,n,e,this[t])})},data:function(t,n){var r=this.attr("data-"+q(t),n);return r!==null?Q(r):e},val:function(t){return t===e?this[0]&&(this[0].multiple?n(this[0]).find("option").filter(function(e){return this.selected}).pluck("value"):this[0].value):this.each(function(e){this.value=$(this,t,e,this.value)})},offset:function(e){if(e)return this.each(function(t){var r=n(this),i=$(this,e,t,r.offset()),s=r.offsetParent().offset(),o={top:i.top-s.top,left:i.left-s.left};r.css("position")=="static"&&(o.position="relative"),r.css(o)});if(this.length==0)return null;var t=this[0].getBoundingClientRect();return{left:t.left+window.pageXOffset,top:t.top+window.pageYOffset,width:t.width,height:t.height}},css:function(e,n){if(arguments.length<2&&typeof e=="string")return this[0]&&(this[0].style[k(e)]||l(this[0],"").getPropertyValue(e));var r="";for(t in e)!e[t]&&e[t]!==0?this.each(function(){this.style.removeProperty(q(t))}):r+=q(t)+":"+U(t,e[t])+";";return typeof e=="string"&&(!n&&n!==0?this.each(function(){this.style.removeProperty(q(e))}):r=q(e)+":"+U(e,n)),this.each(function(){this.style.cssText+=";"+r})},index:function(e){return e?this.indexOf(n(e)[0]):this.parent().children().indexOf(this[0])},hasClass:function(e){return i.some.call(this,function(e){return this.test(K(e))},R(e))},addClass:function(e){return this.each(function(t){r=[];var i=K(this),s=$(this,e,t,i);s.split(/\s+/g).forEach(function(e){n(this).hasClass(e)||r.push(e)},this),r.length&&K(this,i+(i?" ":"")+r.join(" "))})},removeClass:function(t){return this.each(function(n){if(t===e)return K(this,"");r=K(this),$(this,t,n,r).split(/\s+/g).forEach(function(e){r=r.replace(R(e)," ")}),K(this,r.trim())})},toggleClass:function(t,r){return this.each(function(i){var s=n(this),o=$(this,t,i,K(this));o.split(/\s+/g).forEach(function(t){(r===e?!s.hasClass(t):r)?s.addClass(t):s.removeClass(t)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var e=this[0],t=this.offsetParent(),r=this.offset(),i=d.test(t[0].nodeName)?{top:0,left:0}:t.offset();return r.top-=parseFloat(n(e).css("margin-top"))||0,r.left-=parseFloat(n(e).css("margin-left"))||0,i.top+=parseFloat(n(t[0]).css("border-top-width"))||0,i.left+=parseFloat(n(t[0]).css("border-left-width"))||0,{top:r.top-i.top,left:r.left-i.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||u.body;while(e&&!d.test(e.nodeName)&&n(e).css("position")=="static")e=e.offsetParent;return e})}},n.fn.detach=n.fn.remove,["width","height"].forEach(function(t){n.fn[t]=function(r){var i,s=this[0],o=t.replace(/./,function(e){return e[0].toUpperCase()});return r===e?_(s)?s["inner"+o]:D(s)?s.documentElement["offset"+o]:(i=this.offset())&&i[t]:this.each(function(e){s=n(this),s.css(t,$(this,r,e,s[t]()))})}}),m.forEach(function(e,t){var r=t%2;n.fn[e]=function(){var e,i=n.map(arguments,function(t){return e=O(t),e=="object"||e=="array"||t==null?t:C.fragment(t)}),s,o=this.length>1;return i.length<1?this:this.each(function(e,u){s=r?u:u.parentNode,u=t==0?u.nextSibling:t==1?u.firstChild:t==2?u:null,i.forEach(function(e){if(o)e=e.cloneNode(!0);else if(!s)return n(e).remove();G(s.insertBefore(e,u),function(e){e.nodeName!=null&&e.nodeName.toUpperCase()==="SCRIPT"&&(!e.type||e.type==="text/javascript")&&!e.src&&window.eval.call(window,e.innerHTML)})})})},n.fn[r?e+"To":"insert"+(t?"Before":"After")]=function(t){return n(t)[e](this),this}}),C.Z.prototype=n.fn,C.uniq=L,C.deserializeValue=Q,n.zepto=C,n}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(e){function o(e){return e._zid||(e._zid=r++)}function u(e,t,r,i){t=a(t);if(t.ns)var s=f(t.ns);return(n[o(e)]||[]).filter(function(e){return e&&(!t.e||e.e==t.e)&&(!t.ns||s.test(e.ns))&&(!r||o(e.fn)===o(r))&&(!i||e.sel==i)})}function a(e){var t=(""+e).split(".");return{e:t[0],ns:t.slice(1).sort().join(" ")}}function f(e){return new RegExp("(?:^| )"+e.replace(" "," .* ?")+"(?: |$)")}function l(t,n,r){e.type(t)!="string"?e.each(t,r):t.split(/\s/).forEach(function(e){r(e,n)})}function c(e,t){return e.del&&(e.e=="focus"||e.e=="blur")||!!t}function h(e){return s[e]||e}function p(t,r,i,u,f,p){var d=o(t),v=n[d]||(n[d]=[]);l(r,i,function(n,r){var i=a(n);i.fn=r,i.sel=u,i.e in s&&(r=function(t){var n=t.relatedTarget;if(!n||n!==this&&!e.contains(this,n))return i.fn.apply(this,arguments)}),i.del=f&&f(r,n);var o=i.del||r;i.proxy=function(e){var n=o.apply(t,[e].concat(e.data));return n===!1&&(e.preventDefault(),e.stopPropagation()),n},i.i=v.length,v.push(i),t.addEventListener(h(i.e),i.proxy,c(i,p))})}function d(e,t,r,i,s){var a=o(e);l(t||"",r,function(t,r){u(e,t,r,i).forEach(function(t){delete n[a][t.i],e.removeEventListener(h(t.e),t.proxy,c(t,s))})})}function b(t){var n,r={originalEvent:t};for(n in t)!g.test(n)&&t[n]!==undefined&&(r[n]=t[n]);return e.each(y,function(e,n){r[e]=function(){return this[n]=v,t[e].apply(t,arguments)},r[n]=m}),r}function w(e){if(!("defaultPrevented"in e)){e.defaultPrevented=!1;var t=e.preventDefault;e.preventDefault=function(){this.defaultPrevented=!0,t.call(this)}}}var t=e.zepto.qsa,n={},r=1,i={},s={mouseenter:"mouseover",mouseleave:"mouseout"};i.click=i.mousedown=i.mouseup=i.mousemove="MouseEvents",e.event={add:p,remove:d},e.proxy=function(t,n){if(e.isFunction(t)){var r=function(){return t.apply(n,arguments)};return r._zid=o(t),r}if(typeof n=="string")return e.proxy(t[n],t);throw new TypeError("expected function")},e.fn.bind=function(e,t){return this.each(function(){p(this,e,t)})},e.fn.unbind=function(e,t){return this.each(function(){d(this,e,t)})},e.fn.one=function(e,t){return this.each(function(n,r){p(this,e,t,null,function(e,t){return function(){var n=e.apply(r,arguments);return d(r,t,e),n}})})};var v=function(){return!0},m=function(){return!1},g=/^([A-Z]|layer[XY]$)/,y={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};e.fn.delegate=function(t,n,r){return this.each(function(i,s){p(s,n,r,t,function(n){return function(r){var i,o=e(r.target).closest(t,s).get(0);if(o)return i=e.extend(b(r),{currentTarget:o,liveFired:s}),n.apply(o,[i].concat([].slice.call(arguments,1)))}})})},e.fn.undelegate=function(e,t,n){return this.each(function(){d(this,t,n,e)})},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,n,r){return!n||e.isFunction(n)?this.bind(t,n||r):this.delegate(n,t,r)},e.fn.off=function(t,n,r){return!n||e.isFunction(n)?this.unbind(t,n||r):this.undelegate(n,t,r)},e.fn.trigger=function(t,n){if(typeof t=="string"||e.isPlainObject(t))t=e.Event(t);return w(t),t.data=n,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(t)})},e.fn.triggerHandler=function(t,n){var r,i;return this.each(function(s,o){r=b(typeof t=="string"?e.Event(t):t),r.data=n,r.target=o,e.each(u(o,t.type||t),function(e,t){i=t.proxy(r);if(r.isImmediatePropagationStopped())return!1})}),i},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(t){e.fn[t]=function(e){return e?this.bind(t,e):this.trigger(t)}}),["focus","blur"].forEach(function(t){e.fn[t]=function(e){return e?this.bind(t,e):this.each(function(){try{this[t]()}catch(e){}}),this}}),e.Event=function(e,t){typeof e!="string"&&(t=e,e=t.type);var n=document.createEvent(i[e]||"Events"),r=!0;if(t)for(var s in t)s=="bubbles"?r=!!t[s]:n[s]=t[s];return n.initEvent(e,r,!0,null,null,null,null,null,null,null,null,null,null,null,null),n.isDefaultPrevented=function(){return this.defaultPrevented},n}}(Zepto),function(e){function t(e){var t=this.os={},n=this.browser={},r=e.match(/WebKit\/([\d.]+)/),i=e.match(/(Android)\s+([\d.]+)/),s=e.match(/(iPad).*OS\s([\d_]+)/),o=!s&&e.match(/(iPhone\sOS)\s([\d_]+)/),u=e.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),a=u&&e.match(/TouchPad/),f=e.match(/Kindle\/([\d.]+)/),l=e.match(/Silk\/([\d._]+)/),c=e.match(/(BlackBerry).*Version\/([\d.]+)/),h=e.match(/(BB10).*Version\/([\d.]+)/),p=e.match(/(RIM\sTablet\sOS)\s([\d.]+)/),d=e.match(/PlayBook/),v=e.match(/Chrome\/([\d.]+)/)||e.match(/CriOS\/([\d.]+)/),m=e.match(/Firefox\/([\d.]+)/);if(n.webkit=!!r)n.version=r[1];i&&(t.android=!0,t.version=i[2]),o&&(t.ios=t.iphone=!0,t.version=o[2].replace(/_/g,".")),s&&(t.ios=t.ipad=!0,t.version=s[2].replace(/_/g,".")),u&&(t.webos=!0,t.version=u[2]),a&&(t.touchpad=!0),c&&(t.blackberry=!0,t.version=c[2]),h&&(t.bb10=!0,t.version=h[2]),p&&(t.rimtabletos=!0,t.version=p[2]),d&&(n.playbook=!0),f&&(t.kindle=!0,t.version=f[1]),l&&(n.silk=!0,n.version=l[1]),!l&&t.android&&e.match(/Kindle Fire/)&&(n.silk=!0),v&&(n.chrome=!0,n.version=v[1]),m&&(n.firefox=!0,n.version=m[1]),t.tablet=!!(s||d||i&&!e.match(/Mobile/)||m&&e.match(/Tablet/)),t.phone=!t.tablet&&!!(i||o||u||c||h||v||m)}t.call(e,navigator.userAgent),e.__detect=t}(Zepto),function(e,t){function y(e){return b(e.replace(/([a-z])([A-Z])/,"$1-$2"))}function b(e){return e.toLowerCase()}function w(e){return r?r+e:b(e)}var n="",r,i,s,o={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},u=window.document,a=u.createElement("div"),f=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,l,c,h,p,d,v,m,g={};e.each(o,function(e,i){if(a.style[e+"TransitionProperty"]!==t)return n="-"+b(e)+"-",r=i,!1}),l=n+"transform",g[c=n+"transition-property"]=g[h=n+"transition-duration"]=g[p=n+"transition-timing-function"]=g[d=n+"animation-name"]=g[v=n+"animation-duration"]=g[m=n+"animation-timing-function"]="",e.fx={off:r===t&&a.style.transitionProperty===t,speeds:{_default:400,fast:200,slow:600},cssPrefix:n,transitionEnd:w("TransitionEnd"),animationEnd:w("AnimationEnd")},e.fn.animate=function(t,n,r,i){return e.isPlainObject(n)&&(r=n.easing,i=n.complete,n=n.duration),n&&(n=(typeof n=="number"?n:e.fx.speeds[n]||e.fx.speeds._default)/1e3),this.anim(t,n,r,i)},e.fn.anim=function(n,r,i,s){var o,u={},a,b="",w=this,E,S=e.fx.transitionEnd;r===t&&(r=.4),e.fx.off&&(r=0);if(typeof n=="string")u[d]=n,u[v]=r+"s",u[m]=i||"linear",S=e.fx.animationEnd;else{a=[];for(o in n)f.test(o)?b+=o+"("+n[o]+") ":(u[o]=n[o],a.push(y(o)));b&&(u[l]=b,a.push(l)),r>0&&typeof n=="object"&&(u[c]=a.join(", "),u[h]=r+"s",u[p]=i||"linear")}return E=function(t){if(typeof t!="undefined"){if(t.target!==t.currentTarget)return;e(t.target).unbind(S,E)}e(this).css(g),s&&s.call(this)},r>0&&this.bind(S,E),this.size()&&this.get(0).clientLeft,this.css(u),r<=0&&setTimeout(function(){w.each(function(){E.call(this)})},0),this},a=null}(Zepto),function($){function triggerAndReturn(e,t,n){var r=$.Event(t);return $(e).trigger(r,n),!r.defaultPrevented}function triggerGlobal(e,t,n,r){if(e.global)return triggerAndReturn(t||document,n,r)}function ajaxStart(e){e.global&&$.active++===0&&triggerGlobal(e,null,"ajaxStart")}function ajaxStop(e){e.global&&!--$.active&&triggerGlobal(e,null,"ajaxStop")}function ajaxBeforeSend(e,t){var n=t.context;if(t.beforeSend.call(n,e,t)===!1||triggerGlobal(t,n,"ajaxBeforeSend",[e,t])===!1)return!1;triggerGlobal(t,n,"ajaxSend",[e,t])}function ajaxSuccess(e,t,n){var r=n.context,i="success";n.success.call(r,e,i,t),triggerGlobal(n,r,"ajaxSuccess",[t,n,e]),ajaxComplete(i,t,n)}function ajaxError(e,t,n,r){var i=r.context;r.error.call(i,n,t,e),triggerGlobal(r,i,"ajaxError",[n,r,e]),ajaxComplete(t,n,r)}function ajaxComplete(e,t,n){var r=n.context;n.complete.call(r,t,e),triggerGlobal(n,r,"ajaxComplete",[t,n]),ajaxStop(n)}function empty(){}function mimeToDataType(e){return e&&(e==htmlType?"html":e==jsonType?"json":scriptTypeRE.test(e)?"script":xmlTypeRE.test(e)&&"xml")||"text"}function appendQuery(e,t){return(e+"&"+t).replace(/[&?]{1,2}/,"?")}function serializeData(e){e.processData&&e.data&&$.type(e.data)!="string"&&(e.data=$.param(e.data,e.traditional)),e.data&&(!e.type||e.type.toUpperCase()=="GET")&&(e.url=appendQuery(e.url,e.data))}function parseArguments(e,t,n,r){var i=!$.isFunction(t);return{url:e,data:i?t:undefined,success:i?$.isFunction(n)?n:undefined:t,dataType:i?r||n:n}}function serialize(e,t,n,r){var i,s=$.isArray(t);$.each(t,function(t,o){i=$.type(o),r&&(t=n?r:r+"["+(s?"":t)+"]"),!r&&s?e.add(o.name,o.value):i=="array"||!n&&i=="object"?serialize(e,o,n,t):e.add(t,o)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(e){if("type"in e){var t="jsonp"+ ++jsonpID,n=document.createElement("script"),r=function(){clearTimeout(o),$(n).remove(),delete window[t]},i=function(n){r();if(!n||n=="timeout")window[t]=empty;ajaxError(null,n||"abort",s,e)},s={abort:i},o;return serializeData(e),ajaxBeforeSend(s,e)===!1?(i("abort"),!1):(window[t]=function(t){r(),ajaxSuccess(t,s,e)},n.onerror=function(){i("error")},n.src=e.url.replace(/=\?/,"="+t),$("head").append(n),e.timeout>0&&(o=setTimeout(function(){i("timeout")},e.timeout)),s)}return $.ajax(e)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host);var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);settings.url||(settings.url=window.location.toString()),serializeData(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(e,t,n,r){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(e,t,n,r){var i=parseArguments.apply(null,arguments);return i.type="POST",$.ajax(i)},$.getJSON=function(e,t,n){var r=parseArguments.apply(null,arguments);return r.dataType="json",$.ajax(r)},$.fn.load=function(e,t,n){if(!this.length)return this;var r=this,i=e.split(/\s/),s,o=parseArguments(e,t,n),u=o.success;return i.length>1&&(o.url=i[0],s=i[1]),o.success=function(e){r.html(s?$("
    ").html(e.replace(rscript,"")).find(s):e),u&&u.apply(r,arguments)},$.ajax(o),this};var escape=encodeURIComponent;$.param=function(e,t){var n=[];return n.add=function(e,t){this.push(escape(e)+"="+escape(t))},serialize(n,e,t),n.join("&").replace(/%20/g,"+")}}(Zepto),function(e){e.fn.serializeArray=function(){var t=[],n;return e(Array.prototype.slice.call(this.get(0).elements)).each(function(){n=e(this);var r=n.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&r!="submit"&&r!="reset"&&r!="button"&&(r!="radio"&&r!="checkbox"||this.checked)&&t.push({name:n.attr("name"),value:n.val()})}),t},e.fn.serialize=function(){var e=[];return this.serializeArray().forEach(function(t){e.push(encodeURIComponent(t.name)+"="+encodeURIComponent(t.value))}),e.join("&")},e.fn.submit=function(t){if(t)this.bind("submit",t);else if(this.length){var n=e.Event("submit");this.eq(0).trigger(n),n.defaultPrevented||this.get(0).submit()}return this}}(Zepto); \ No newline at end of file diff --git a/node_modules/grunt-coffee/.npmignore b/node_modules/grunt-coffee/.npmignore new file mode 100644 index 0000000..083de6b --- /dev/null +++ b/node_modules/grunt-coffee/.npmignore @@ -0,0 +1,2 @@ +/node_modules/ +tmp diff --git a/node_modules/grunt-coffee/.travis.yml b/node_modules/grunt-coffee/.travis.yml new file mode 100644 index 0000000..8111245 --- /dev/null +++ b/node_modules/grunt-coffee/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 \ No newline at end of file diff --git a/node_modules/grunt-coffee/LICENSE-MIT b/node_modules/grunt-coffee/LICENSE-MIT new file mode 100644 index 0000000..aaf6762 --- /dev/null +++ b/node_modules/grunt-coffee/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Aaron D. Valade + +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/README.md b/node_modules/grunt-coffee/README.md new file mode 100644 index 0000000..a4f6d33 --- /dev/null +++ b/node_modules/grunt-coffee/README.md @@ -0,0 +1,93 @@ +[![build status](https://secure.travis-ci.org/avalade/grunt-coffee.png)](http://travis-ci.org/avalade/grunt-coffee) +# grunt-coffee + +JavaScripts your Coffee + +## Getting Started +Install this grunt plugin next to your project's [grunt.js gruntfile][getting_started] with: `npm install grunt-coffee` + +Then add this line to your project's `grunt.js` gruntfile: + +```javascript +grunt.loadNpmTasks('grunt-coffee'); +``` + +[grunt]: https://github.com/cowboy/grunt +[getting_started]: https://github.com/cowboy/grunt/blob/master/docs/getting_started.md + +## Documentation +You'll need to install `grunt-coffee` first: + + npm install grunt-coffee + +Then modify your `grunt.js` file by adding the following line: + + grunt.loadNpmTasks('grunt-coffee'); + +Then add some configuration for the plugin like so: + + grunt.initConfig({ + ... + coffee: { + app: { + src: ['path/to/coffee/files/*.coffee'], + dest: 'where/you/want/your/js/files', + options: { + bare: true + } + } + }, + ... + }); + +Then just run `grunt coffee` and enjoy! + +Grunt Coffee will, by default, run coffee with the `--bare` flag set. +If you want to run it with the top level variable safety, make sure +you set your options to: + + options: { + bare: false + } + +If you have `dest` path and want to preserve the directory structure of your coffee files, pass the `preserve_dirs` option. + + options: { + preserve_dirs: true + } + +Also, if you just want to preserve the directory structure, starting from a base path, pass the `base_path` option. + + options: { + preserve_dirs: true, + base_path: 'path/to' + } + +This will create the files under `where/you/want/your/js/files/coffee/files/`. + +## 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][grunt]. + +## Release History +0.0.6 - addressed when Javascript files are included in the src matcher, thanks [Enleur](https://github.com/Enleur) and [brewster1134](https://github.com/brewster1134) + +0.0.5 - added `base_path` option, thanks +[siriux](https://github.com/siriux) and +[William](https://github.com/wlepinski). + +0.0.4 - added preservation of directory structure, thanks +[Kevin](https://github.com/rockwood). Also added a unique copy of the +options for each call to the helper, thanks [Ken](https://github.com/elfsternberg). + +0.0.3 - added relative compilation and compound file suffixes, thanks +[Pete](https://github.com/petebacondarwin). Also added real error +messages, thanks [Tim](https://github.com/timoxley) + +0.0.2 - added the options object, thanks +[Derek](https://github.com/dlindahl)! + +0.0.1 - The bare minimum necessary... don't expect it to work + +## License +Copyright (c) 2012 Aaron D. Valade +Licensed under the MIT license. diff --git a/node_modules/grunt-coffee/grunt.js b/node_modules/grunt-coffee/grunt.js new file mode 100644 index 0000000..1bc5c42 --- /dev/null +++ b/node_modules/grunt-coffee/grunt.js @@ -0,0 +1,40 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'default' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + node: true, + es5: true + }, + globals: {} + } + }); + + // Load local tasks. + grunt.loadTasks('tasks'); + + // Default task. + grunt.registerTask('default', 'lint test'); + +}; diff --git a/node_modules/grunt-coffee/node_modules/.bin/cake b/node_modules/grunt-coffee/node_modules/.bin/cake new file mode 120000 index 0000000..d95f32a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/.bin/cake @@ -0,0 +1 @@ +../coffee-script/bin/cake \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/.bin/coffee b/node_modules/grunt-coffee/node_modules/.bin/coffee new file mode 120000 index 0000000..b57f275 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/.bin/coffee @@ -0,0 +1 @@ +../coffee-script/bin/coffee \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/.bin/grunt b/node_modules/grunt-coffee/node_modules/.bin/grunt new file mode 120000 index 0000000..47724d2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/.bin/grunt @@ -0,0 +1 @@ +../grunt/bin/grunt \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/.npmignore b/node_modules/grunt-coffee/node_modules/coffee-script/.npmignore new file mode 100644 index 0000000..21e430d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/.npmignore @@ -0,0 +1,11 @@ +*.coffee +*.html +.DS_Store +.git* +Cakefile +documentation/ +examples/ +extras/coffee-script.js +raw/ +src/ +test/ diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/CNAME b/node_modules/grunt-coffee/node_modules/coffee-script/CNAME new file mode 100644 index 0000000..faadabe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/CNAME @@ -0,0 +1 @@ +coffeescript.org \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/LICENSE b/node_modules/grunt-coffee/node_modules/coffee-script/LICENSE new file mode 100644 index 0000000..dbe6b4e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2012 Jeremy Ashkenas + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/README b/node_modules/grunt-coffee/node_modules/coffee-script/README new file mode 100644 index 0000000..69ee6f4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/README @@ -0,0 +1,51 @@ + + { + } } { + { { } } + } }{ { + { }{ } } _____ __ __ + ( }{ }{ { ) / ____| / _|/ _| + .- { { } { }} -. | | ___ | |_| |_ ___ ___ + ( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \ + |`-..________ ..-'| | |___| (_) | | | || __/ __/ + | | \_____\___/|_| |_| \___|\___| + | ;--. + | (__ \ _____ _ _ + | | ) ) / ____| (_) | | + | |/ / | (___ ___ _ __ _ _ __ | |_ + | ( / \___ \ / __| '__| | '_ \| __| + | |/ ____) | (__| | | | |_) | |_ + | | |_____/ \___|_| |_| .__/ \__| + `-.._________..-' | | + |_| + + + CoffeeScript is a little language that compiles into JavaScript. + + Install Node.js, and then the CoffeeScript compiler: + sudo bin/cake install + + Or, if you have the Node Package Manager installed: + npm install -g coffee-script + (Leave off the -g if you don't wish to install globally.) + + Execute a script: + coffee /path/to/script.coffee + + Compile a script: + coffee -c /path/to/script.coffee + + For documentation, usage, and examples, see: + http://coffeescript.org/ + + To suggest a feature, report a bug, or general discussion: + http://github.com/jashkenas/coffee-script/issues/ + + If you'd like to chat, drop by #coffeescript on Freenode IRC, + or on webchat.freenode.net. + + The source repository: + git://github.com/jashkenas/coffee-script.git + + All contributors are listed here: + http://github.com/jashkenas/coffee-script/contributors diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/Rakefile b/node_modules/grunt-coffee/node_modules/coffee-script/Rakefile new file mode 100644 index 0000000..dfb85da --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/Rakefile @@ -0,0 +1,78 @@ +require 'rubygems' +require 'erb' +require 'fileutils' +require 'rake/testtask' +require 'json' + +desc "Build the documentation page" +task :doc do + source = 'documentation/index.html.erb' + child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" } + at_exit { Process.kill("INT", child) } + Signal.trap("INT") { exit } + loop do + mtime = File.stat(source).mtime + if !@mtime || mtime > @mtime + rendered = ERB.new(File.read(source)).result(binding) + File.open('index.html', 'w+') {|f| f.write(rendered) } + end + @mtime = mtime + sleep 1 + end +end + +desc "Build coffee-script-source gem" +task :gem do + require 'rubygems' + require 'rubygems/package' + + gemspec = Gem::Specification.new do |s| + s.name = 'coffee-script-source' + s.version = JSON.parse(File.read('package.json'))["version"] + s.date = Time.now.strftime("%Y-%m-%d") + + s.homepage = "http://jashkenas.github.com/coffee-script/" + s.summary = "The CoffeeScript Compiler" + s.description = <<-EOS + CoffeeScript is a little language that compiles into JavaScript. + Underneath all of those embarrassing braces and semicolons, + JavaScript has always had a gorgeous object model at its heart. + CoffeeScript is an attempt to expose the good parts of JavaScript + in a simple way. + EOS + + s.files = [ + 'lib/coffee_script/coffee-script.js', + 'lib/coffee_script/source.rb' + ] + + s.authors = ['Jeremy Ashkenas'] + s.email = 'jashkenas@gmail.com' + s.rubyforge_project = 'coffee-script-source' + end + + file = File.open("coffee-script-source.gem", "w") + Gem::Package.open(file, 'w') do |pkg| + pkg.metadata = gemspec.to_yaml + + path = "lib/coffee_script/source.rb" + contents = <<-ERUBY +module CoffeeScript + module Source + def self.bundled_path + File.expand_path("../coffee-script.js", __FILE__) + end + end +end + ERUBY + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + + contents = File.read("extras/coffee-script.js") + path = "lib/coffee_script/coffee-script.js" + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + end +end diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/bin/cake b/node_modules/grunt-coffee/node_modules/coffee-script/bin/cake new file mode 100755 index 0000000..5965f4e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/bin/cake @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/cake').run(); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/bin/coffee b/node_modules/grunt-coffee/node_modules/coffee-script/bin/coffee new file mode 100755 index 0000000..3d1d71c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/bin/coffee @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/command').run(); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/extras/jsl.conf b/node_modules/grunt-coffee/node_modules/coffee-script/extras/jsl.conf new file mode 100644 index 0000000..1190da5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/extras/jsl.conf @@ -0,0 +1,44 @@ +# JavaScriptLint configuration file for CoffeeScript. + ++no_return_value # function {0} does not always return a value ++duplicate_formal # duplicate formal argument {0} +-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0} ++var_hides_arg # variable {0} hides argument ++redeclared_var # redeclaration of {0} {1} +-anon_no_return_value # anonymous function does not always return a value ++missing_semicolon # missing semicolon ++meaningless_block # meaningless block; curly braces have no impact +-comma_separated_stmts # multiple statements separated by commas (use semicolons?) ++unreachable_code # unreachable code ++missing_break # missing break statement +-missing_break_for_last_case # missing break statement for last case in switch +-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) +-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement +-useless_void # use of the void type may be unnecessary (void is always undefined) ++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs ++use_of_label # use of label +-block_without_braces # block statement without curly braces ++leading_decimal_point # leading decimal point may indicate a number or an object member ++trailing_decimal_point # trailing decimal point may indicate a number or an object member ++octal_number # leading zeros make an octal number ++nested_comment # nested comment ++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma ++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement ++empty_statement # empty statement or extra semicolon +-missing_option_explicit # the "option explicit" control comment is missing ++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag ++dup_option_explicit # duplicate "option explicit" control comment ++useless_assign # useless assignment ++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity ++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent) +-missing_default_case # missing default case in switch statement ++duplicate_case_in_switch # duplicate case in switch statements ++default_not_at_end # the default case is not at the end of the switch statement ++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax ++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax ++useless_comparison # useless comparison; comparing identical expressions ++with_statement # with statement hides undeclared variables; use temporary variable instead ++trailing_comma_in_array # extra comma is not recommended in array initializers ++assign_to_function_call # assignment to a function call ++parseint_missing_radix # parseInt missing radix parameter ++lambda_assign_requires_semicolon diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/browser.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/browser.js new file mode 100644 index 0000000..825cbf3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/browser.js @@ -0,0 +1,92 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var CoffeeScript, runScripts; + + CoffeeScript = require('./coffee-script'); + + CoffeeScript.require = require; + + CoffeeScript["eval"] = function(code, options) { + var _ref; + if (options == null) { + options = {}; + } + if ((_ref = options.bare) == null) { + options.bare = true; + } + return eval(CoffeeScript.compile(code, options)); + }; + + CoffeeScript.run = function(code, options) { + if (options == null) { + options = {}; + } + options.bare = true; + return Function(CoffeeScript.compile(code, options))(); + }; + + if (typeof window === "undefined" || window === null) { + return; + } + + CoffeeScript.load = function(url, callback) { + var xhr; + xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP'); + xhr.open('GET', url, true); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + var _ref; + if (xhr.readyState === 4) { + if ((_ref = xhr.status) === 0 || _ref === 200) { + CoffeeScript.run(xhr.responseText); + } else { + throw new Error("Could not load " + url); + } + if (callback) { + return callback(); + } + } + }; + return xhr.send(null); + }; + + runScripts = function() { + var coffees, execute, index, length, s, scripts; + scripts = document.getElementsByTagName('script'); + coffees = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = scripts.length; _i < _len; _i++) { + s = scripts[_i]; + if (s.type === 'text/coffeescript') { + _results.push(s); + } + } + return _results; + })(); + index = 0; + length = coffees.length; + (execute = function() { + var script; + script = coffees[index++]; + if ((script != null ? script.type : void 0) === 'text/coffeescript') { + if (script.src) { + return CoffeeScript.load(script.src, execute); + } else { + CoffeeScript.run(script.innerHTML); + return execute(); + } + } + })(); + return null; + }; + + if (window.addEventListener) { + addEventListener('DOMContentLoaded', runScripts, false); + } else { + attachEvent('onload', runScripts); + } + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/cake.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/cake.js new file mode 100644 index 0000000..1523418 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/cake.js @@ -0,0 +1,111 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + tasks = {}; + + options = {}; + + switches = []; + + oparse = null; + + helpers.extend(global, { + task: function(name, description, action) { + var _ref; + if (!action) { + _ref = [description, action], action = _ref[0], description = _ref[1]; + } + return tasks[name] = { + name: name, + description: description, + action: action + }; + }, + option: function(letter, flag, description) { + return switches.push([letter, flag, description]); + }, + invoke: function(name) { + if (!tasks[name]) { + missingTask(name); + } + return tasks[name].action(options); + } + }); + + exports.run = function() { + var arg, args, _i, _len, _ref, _results; + global.__originalDirname = fs.realpathSync('.'); + process.chdir(cakefileDirectory(__originalDirname)); + args = process.argv.slice(2); + CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { + filename: 'Cakefile' + }); + oparse = new optparse.OptionParser(switches); + if (!args.length) { + return printTasks(); + } + try { + options = oparse.parse(args); + } catch (e) { + return fatalError("" + e); + } + _ref = options["arguments"]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + arg = _ref[_i]; + _results.push(invoke(arg)); + } + return _results; + }; + + printTasks = function() { + var cakefilePath, desc, name, relative, spaces, task; + relative = path.relative || path.resolve; + cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile'); + console.log("" + cakefilePath + " defines the following tasks:\n"); + for (name in tasks) { + task = tasks[name]; + spaces = 20 - name.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + desc = task.description ? "# " + task.description : ''; + console.log("cake " + name + spaces + " " + desc); + } + if (switches.length) { + return console.log(oparse.help()); + } + }; + + fatalError = function(message) { + console.error(message + '\n'); + console.log('To see a list of all tasks/options, run "cake"'); + return process.exit(1); + }; + + missingTask = function(task) { + return fatalError("No such task: " + task); + }; + + cakefileDirectory = function(dir) { + var parent; + if (path.existsSync(path.join(dir, 'Cakefile'))) { + return dir; + } + parent = path.normalize(path.join(dir, '..')); + if (parent !== dir) { + return cakefileDirectory(parent); + } + throw new Error("Cakefile not found in " + (process.cwd())); + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/coffee-script.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/coffee-script.js new file mode 100644 index 0000000..c43fa49 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/coffee-script.js @@ -0,0 +1,167 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref, + __hasProp = {}.hasOwnProperty; + + fs = require('fs'); + + path = require('path'); + + _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED; + + parser = require('./parser').parser; + + vm = require('vm'); + + if (require.extensions) { + require.extensions['.coffee'] = function(module, filename) { + var content; + content = compile(fs.readFileSync(filename, 'utf8'), { + filename: filename + }); + return module._compile(content, filename); + }; + } else if (require.registerExtension) { + require.registerExtension('.coffee', function(content) { + return compile(content); + }); + } + + exports.VERSION = '1.3.3'; + + exports.RESERVED = RESERVED; + + exports.helpers = require('./helpers'); + + exports.compile = compile = function(code, options) { + var header, js, merge; + if (options == null) { + options = {}; + } + merge = exports.helpers.merge; + try { + js = (parser.parse(lexer.tokenize(code))).compile(options); + if (!options.header) { + return js; + } + } catch (err) { + if (options.filename) { + err.message = "In " + options.filename + ", " + err.message; + } + throw err; + } + header = "Generated by CoffeeScript " + this.VERSION; + return "// " + header + "\n" + js; + }; + + exports.tokens = function(code, options) { + return lexer.tokenize(code, options); + }; + + exports.nodes = function(source, options) { + if (typeof source === 'string') { + return parser.parse(lexer.tokenize(source, options)); + } else { + return parser.parse(source); + } + }; + + exports.run = function(code, options) { + var mainModule; + if (options == null) { + options = {}; + } + mainModule = require.main; + mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.'; + mainModule.moduleCache && (mainModule.moduleCache = {}); + mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename))); + if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) { + return mainModule._compile(compile(code, options), mainModule.filename); + } else { + return mainModule._compile(code, mainModule.filename); + } + }; + + exports["eval"] = function(code, options) { + var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref1, _ref2, _require; + if (options == null) { + options = {}; + } + if (!(code = code.trim())) { + return; + } + Script = vm.Script; + if (Script) { + if (options.sandbox != null) { + if (options.sandbox instanceof Script.createContext().constructor) { + sandbox = options.sandbox; + } else { + sandbox = Script.createContext(); + _ref1 = options.sandbox; + for (k in _ref1) { + if (!__hasProp.call(_ref1, k)) continue; + v = _ref1[k]; + sandbox[k] = v; + } + } + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; + } else { + sandbox = global; + } + sandbox.__filename = options.filename || 'eval'; + sandbox.__dirname = path.dirname(sandbox.__filename); + if (!(sandbox !== global || sandbox.module || sandbox.require)) { + Module = require('module'); + sandbox.module = _module = new Module(options.modulename || 'eval'); + sandbox.require = _require = function(path) { + return Module._load(path, _module, true); + }; + _module.filename = sandbox.__filename; + _ref2 = Object.getOwnPropertyNames(require); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + r = _ref2[_i]; + if (r !== 'paths') { + _require[r] = require[r]; + } + } + _require.paths = _module.paths = Module._nodeModulePaths(process.cwd()); + _require.resolve = function(request) { + return Module._resolveFilename(request, _module); + }; + } + } + o = {}; + for (k in options) { + if (!__hasProp.call(options, k)) continue; + v = options[k]; + o[k] = v; + } + o.bare = true; + js = compile(code, o); + if (sandbox === global) { + return vm.runInThisContext(js); + } else { + return vm.runInContext(js, sandbox); + } + }; + + lexer = new Lexer; + + parser.lexer = { + lex: function() { + var tag, _ref1; + _ref1 = this.tokens[this.pos++] || [''], tag = _ref1[0], this.yytext = _ref1[1], this.yylineno = _ref1[2]; + return tag; + }, + setInput: function(tokens) { + this.tokens = tokens; + return this.pos = 0; + }, + upcomingInput: function() { + return ""; + } + }; + + parser.yy = require('./nodes'); + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/command.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/command.js new file mode 100644 index 0000000..e02da9f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/command.js @@ -0,0 +1,500 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, hidden, joinTimeout, lint, loadRequires, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec; + + EventEmitter = require('events').EventEmitter; + + helpers.extend(CoffeeScript, new EventEmitter); + + printLine = function(line) { + return process.stdout.write(line + '\n'); + }; + + printWarn = function(line) { + return process.stderr.write(line + '\n'); + }; + + hidden = function(file) { + return /^\.|~$/.test(file); + }; + + BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.'; + + SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; + + opts = {}; + + sources = []; + + sourceCode = []; + + notSources = {}; + + watchers = {}; + + optionParser = null; + + exports.run = function() { + var literals, source, _i, _len, _results; + parseOptions(); + if (opts.nodejs) { + return forkNode(); + } + if (opts.help) { + return usage(); + } + if (opts.version) { + return version(); + } + if (opts.require) { + loadRequires(); + } + if (opts.interactive) { + return require('./repl'); + } + if (opts.watch && !fs.watch) { + return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + "."); + } + if (opts.stdio) { + return compileStdio(); + } + if (opts["eval"]) { + return compileScript(null, sources[0]); + } + if (!sources.length) { + return require('./repl'); + } + literals = opts.run ? sources.splice(1) : []; + process.argv = process.argv.slice(0, 2).concat(literals); + process.argv[0] = 'coffee'; + process.execPath = require.main.filename; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + source = sources[_i]; + _results.push(compilePath(source, true, path.normalize(source))); + } + return _results; + }; + + compilePath = function(source, topLevel, base) { + return fs.stat(source, function(err, stats) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + if (topLevel && source.slice(-7) !== '.coffee') { + source = sources[sources.indexOf(source)] = "" + source + ".coffee"; + return compilePath(source, topLevel, base); + } + if (topLevel) { + console.error("File not found: " + source); + process.exit(1); + } + return; + } + if (stats.isDirectory()) { + if (opts.watch) { + watchDir(source, base); + } + return fs.readdir(source, function(err, files) { + var file, index, _ref1, _ref2; + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + index = sources.indexOf(source); + files = files.filter(function(file) { + return !hidden(file); + }); + [].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(path.join(source, file)); + } + return _results; + })())), _ref1; + [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() { + return null; + }))), _ref2; + return files.forEach(function(file) { + return compilePath(path.join(source, file), false, base); + }); + }); + } else if (topLevel || path.extname(source) === '.coffee') { + if (opts.watch) { + watch(source, base); + } + return fs.readFile(source, function(err, code) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + return compileScript(source, code.toString(), base); + }); + } else { + notSources[source] = true; + return removeSource(source, base); + } + }); + }; + + compileScript = function(file, input, base) { + var o, options, t, task; + o = opts; + options = compileOptions(file); + try { + t = task = { + file: file, + input: input, + options: options + }; + CoffeeScript.emit('compile', task); + if (o.tokens) { + return printTokens(CoffeeScript.tokens(t.input)); + } else if (o.nodes) { + return printLine(CoffeeScript.nodes(t.input).toString().trim()); + } else if (o.run) { + return CoffeeScript.run(t.input, t.options); + } else if (o.join && t.file !== o.join) { + sourceCode[sources.indexOf(t.file)] = t.input; + return compileJoin(); + } else { + t.output = CoffeeScript.compile(t.input, t.options); + CoffeeScript.emit('success', task); + if (o.print) { + return printLine(t.output.trim()); + } else if (o.compile) { + return writeJs(t.file, t.output, base); + } else if (o.lint) { + return lint(t.file, t.output); + } + } + } catch (err) { + CoffeeScript.emit('failure', err, task); + if (CoffeeScript.listeners('failure').length) { + return; + } + if (o.watch) { + return printLine(err.message + '\x07'); + } + printWarn(err instanceof Error && err.stack || ("ERROR: " + err)); + return process.exit(1); + } + }; + + compileStdio = function() { + var code, stdin; + code = ''; + stdin = process.openStdin(); + stdin.on('data', function(buffer) { + if (buffer) { + return code += buffer.toString(); + } + }); + return stdin.on('end', function() { + return compileScript(null, code); + }); + }; + + joinTimeout = null; + + compileJoin = function() { + if (!opts.join) { + return; + } + if (!sourceCode.some(function(code) { + return code === null; + })) { + clearTimeout(joinTimeout); + return joinTimeout = wait(100, function() { + return compileScript(opts.join, sourceCode.join('\n'), opts.join); + }); + } + }; + + loadRequires = function() { + var realFilename, req, _i, _len, _ref1; + realFilename = module.filename; + module.filename = '.'; + _ref1 = opts.require; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + req = _ref1[_i]; + require(req); + } + return module.filename = realFilename; + }; + + watch = function(source, base) { + var compile, compileTimeout, prevStats, rewatch, watchErr, watcher; + prevStats = null; + compileTimeout = null; + watchErr = function(e) { + if (e.code === 'ENOENT') { + if (sources.indexOf(source) === -1) { + return; + } + try { + rewatch(); + return compile(); + } catch (e) { + removeSource(source, base, true); + return compileJoin(); + } + } else { + throw e; + } + }; + compile = function() { + clearTimeout(compileTimeout); + return compileTimeout = wait(25, function() { + return fs.stat(source, function(err, stats) { + if (err) { + return watchErr(err); + } + if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) { + return rewatch(); + } + prevStats = stats; + return fs.readFile(source, function(err, code) { + if (err) { + return watchErr(err); + } + compileScript(source, code.toString(), base); + return rewatch(); + }); + }); + }); + }; + try { + watcher = fs.watch(source, compile); + } catch (e) { + watchErr(e); + } + return rewatch = function() { + if (watcher != null) { + watcher.close(); + } + return watcher = fs.watch(source, compile); + }; + }; + + watchDir = function(source, base) { + var readdirTimeout, watcher; + readdirTimeout = null; + try { + return watcher = fs.watch(source, function() { + clearTimeout(readdirTimeout); + return readdirTimeout = wait(25, function() { + return fs.readdir(source, function(err, files) { + var file, _i, _len, _results; + if (err) { + if (err.code !== 'ENOENT') { + throw err; + } + watcher.close(); + return unwatchDir(source, base); + } + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + if (!(!hidden(file) && !notSources[file])) { + continue; + } + file = path.join(source, file); + if (sources.some(function(s) { + return s.indexOf(file) >= 0; + })) { + continue; + } + sources.push(file); + sourceCode.push(null); + _results.push(compilePath(file, false, base)); + } + return _results; + }); + }); + }); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; + } + } + }; + + unwatchDir = function(source, base) { + var file, prevSources, toRemove, _i, _len; + prevSources = sources.slice(0); + toRemove = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + file = sources[_i]; + if (file.indexOf(source) >= 0) { + _results.push(file); + } + } + return _results; + })(); + for (_i = 0, _len = toRemove.length; _i < _len; _i++) { + file = toRemove[_i]; + removeSource(file, base, true); + } + if (!sources.some(function(s, i) { + return prevSources[i] !== s; + })) { + return; + } + return compileJoin(); + }; + + removeSource = function(source, base, removeJs) { + var index, jsPath; + index = sources.indexOf(source); + sources.splice(index, 1); + sourceCode.splice(index, 1); + if (removeJs && !opts.join) { + jsPath = outputPath(source, base); + return path.exists(jsPath, function(exists) { + if (exists) { + return fs.unlink(jsPath, function(err) { + if (err && err.code !== 'ENOENT') { + throw err; + } + return timeLog("removed " + source); + }); + } + }); + } + }; + + outputPath = function(source, base) { + var baseDir, dir, filename, srcDir; + filename = path.basename(source, path.extname(source)) + '.js'; + srcDir = path.dirname(source); + baseDir = base === '.' ? srcDir : srcDir.substring(base.length); + dir = opts.output ? path.join(opts.output, baseDir) : srcDir; + return path.join(dir, filename); + }; + + writeJs = function(source, js, base) { + var compile, jsDir, jsPath; + jsPath = outputPath(source, base); + jsDir = path.dirname(jsPath); + compile = function() { + if (js.length <= 0) { + js = ' '; + } + return fs.writeFile(jsPath, js, function(err) { + if (err) { + return printLine(err.message); + } else if (opts.compile && opts.watch) { + return timeLog("compiled " + source); + } + }); + }; + return path.exists(jsDir, function(exists) { + if (exists) { + return compile(); + } else { + return exec("mkdir -p " + jsDir, compile); + } + }); + }; + + wait = function(milliseconds, func) { + return setTimeout(func, milliseconds); + }; + + timeLog = function(message) { + return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message); + }; + + lint = function(file, js) { + var conf, jsl, printIt; + printIt = function(buffer) { + return printLine(file + ':\t' + buffer.toString().trim()); + }; + conf = __dirname + '/../../extras/jsl.conf'; + jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]); + jsl.stdout.on('data', printIt); + jsl.stderr.on('data', printIt); + jsl.stdin.write(js); + return jsl.stdin.end(); + }; + + printTokens = function(tokens) { + var strings, tag, token, value; + strings = (function() { + var _i, _len, _ref1, _results; + _results = []; + for (_i = 0, _len = tokens.length; _i < _len; _i++) { + token = tokens[_i]; + _ref1 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref1[0], value = _ref1[1]; + _results.push("[" + tag + " " + value + "]"); + } + return _results; + })(); + return printLine(strings.join(' ')); + }; + + parseOptions = function() { + var i, o, source, _i, _len; + optionParser = new optparse.OptionParser(SWITCHES, BANNER); + o = opts = optionParser.parse(process.argv.slice(2)); + o.compile || (o.compile = !!o.output); + o.run = !(o.compile || o.print || o.lint); + o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)); + sources = o["arguments"]; + for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { + source = sources[i]; + sourceCode[i] = null; + } + }; + + compileOptions = function(filename) { + return { + filename: filename, + bare: opts.bare, + header: opts.compile + }; + }; + + forkNode = function() { + var args, nodeArgs; + nodeArgs = opts.nodejs.split(/\s+/); + args = process.argv.slice(1); + args.splice(args.indexOf('--nodejs'), 2); + return spawn(process.execPath, nodeArgs.concat(args), { + cwd: process.cwd(), + env: process.env, + customFds: [0, 1, 2] + }); + }; + + usage = function() { + return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help()); + }; + + version = function() { + return printLine("CoffeeScript version " + CoffeeScript.VERSION); + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/grammar.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/grammar.js new file mode 100644 index 0000000..5662138 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/grammar.js @@ -0,0 +1,606 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap; + + Parser = require('jison').Parser; + + unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/; + + o = function(patternString, action, options) { + var match; + patternString = patternString.replace(/\s{2,}/g, ' '); + if (!action) { + return [patternString, '$$ = $1;', options]; + } + action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())"; + action = action.replace(/\bnew /g, '$&yy.'); + action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&'); + return [patternString, "$$ = " + action + ";", options]; + }; + + grammar = { + Root: [ + o('', function() { + return new Block; + }), o('Body'), o('Block TERMINATOR') + ], + Body: [ + o('Line', function() { + return Block.wrap([$1]); + }), o('Body TERMINATOR Line', function() { + return $1.push($3); + }), o('Body TERMINATOR') + ], + Line: [o('Expression'), o('Statement')], + Statement: [ + o('Return'), o('Comment'), o('STATEMENT', function() { + return new Literal($1); + }) + ], + Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')], + Block: [ + o('INDENT OUTDENT', function() { + return new Block; + }), o('INDENT Body OUTDENT', function() { + return $2; + }) + ], + Identifier: [ + o('IDENTIFIER', function() { + return new Literal($1); + }) + ], + AlphaNumeric: [ + o('NUMBER', function() { + return new Literal($1); + }), o('STRING', function() { + return new Literal($1); + }) + ], + Literal: [ + o('AlphaNumeric'), o('JS', function() { + return new Literal($1); + }), o('REGEX', function() { + return new Literal($1); + }), o('DEBUGGER', function() { + return new Literal($1); + }), o('UNDEFINED', function() { + return new Undefined; + }), o('NULL', function() { + return new Null; + }), o('BOOL', function() { + return new Bool($1); + }) + ], + Assign: [ + o('Assignable = Expression', function() { + return new Assign($1, $3); + }), o('Assignable = TERMINATOR Expression', function() { + return new Assign($1, $4); + }), o('Assignable = INDENT Expression OUTDENT', function() { + return new Assign($1, $4); + }) + ], + AssignObj: [ + o('ObjAssignable', function() { + return new Value($1); + }), o('ObjAssignable : Expression', function() { + return new Assign(new Value($1), $3, 'object'); + }), o('ObjAssignable :\ + INDENT Expression OUTDENT', function() { + return new Assign(new Value($1), $4, 'object'); + }), o('Comment') + ], + ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')], + Return: [ + o('RETURN Expression', function() { + return new Return($2); + }), o('RETURN', function() { + return new Return; + }) + ], + Comment: [ + o('HERECOMMENT', function() { + return new Comment($1); + }) + ], + Code: [ + o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() { + return new Code($2, $5, $4); + }), o('FuncGlyph Block', function() { + return new Code([], $2, $1); + }) + ], + FuncGlyph: [ + o('->', function() { + return 'func'; + }), o('=>', function() { + return 'boundfunc'; + }) + ], + OptComma: [o(''), o(',')], + ParamList: [ + o('', function() { + return []; + }), o('Param', function() { + return [$1]; + }), o('ParamList , Param', function() { + return $1.concat($3); + }), o('ParamList OptComma TERMINATOR Param', function() { + return $1.concat($4); + }), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Param: [ + o('ParamVar', function() { + return new Param($1); + }), o('ParamVar ...', function() { + return new Param($1, null, true); + }), o('ParamVar = Expression', function() { + return new Param($1, $3); + }) + ], + ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')], + Splat: [ + o('Expression ...', function() { + return new Splat($1); + }) + ], + SimpleAssignable: [ + o('Identifier', function() { + return new Value($1); + }), o('Value Accessor', function() { + return $1.add($2); + }), o('Invocation Accessor', function() { + return new Value($1, [].concat($2)); + }), o('ThisProperty') + ], + Assignable: [ + o('SimpleAssignable'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + Value: [ + o('Assignable'), o('Literal', function() { + return new Value($1); + }), o('Parenthetical', function() { + return new Value($1); + }), o('Range', function() { + return new Value($1); + }), o('This') + ], + Accessor: [ + o('. Identifier', function() { + return new Access($2); + }), o('?. Identifier', function() { + return new Access($2, 'soak'); + }), o(':: Identifier', function() { + return [new Access(new Literal('prototype')), new Access($2)]; + }), o('::', function() { + return new Access(new Literal('prototype')); + }), o('Index') + ], + Index: [ + o('INDEX_START IndexValue INDEX_END', function() { + return $2; + }), o('INDEX_SOAK Index', function() { + return extend($2, { + soak: true + }); + }) + ], + IndexValue: [ + o('Expression', function() { + return new Index($1); + }), o('Slice', function() { + return new Slice($1); + }) + ], + Object: [ + o('{ AssignList OptComma }', function() { + return new Obj($2, $1.generated); + }) + ], + AssignList: [ + o('', function() { + return []; + }), o('AssignObj', function() { + return [$1]; + }), o('AssignList , AssignObj', function() { + return $1.concat($3); + }), o('AssignList OptComma TERMINATOR AssignObj', function() { + return $1.concat($4); + }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Class: [ + o('CLASS', function() { + return new Class; + }), o('CLASS Block', function() { + return new Class(null, null, $2); + }), o('CLASS EXTENDS Expression', function() { + return new Class(null, $3); + }), o('CLASS EXTENDS Expression Block', function() { + return new Class(null, $3, $4); + }), o('CLASS SimpleAssignable', function() { + return new Class($2); + }), o('CLASS SimpleAssignable Block', function() { + return new Class($2, null, $3); + }), o('CLASS SimpleAssignable EXTENDS Expression', function() { + return new Class($2, $4); + }), o('CLASS SimpleAssignable EXTENDS Expression Block', function() { + return new Class($2, $4, $5); + }) + ], + Invocation: [ + o('Value OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('Invocation OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('SUPER', function() { + return new Call('super', [new Splat(new Literal('arguments'))]); + }), o('SUPER Arguments', function() { + return new Call('super', $2); + }) + ], + OptFuncExist: [ + o('', function() { + return false; + }), o('FUNC_EXIST', function() { + return true; + }) + ], + Arguments: [ + o('CALL_START CALL_END', function() { + return []; + }), o('CALL_START ArgList OptComma CALL_END', function() { + return $2; + }) + ], + This: [ + o('THIS', function() { + return new Value(new Literal('this')); + }), o('@', function() { + return new Value(new Literal('this')); + }) + ], + ThisProperty: [ + o('@ Identifier', function() { + return new Value(new Literal('this'), [new Access($2)], 'this'); + }) + ], + Array: [ + o('[ ]', function() { + return new Arr([]); + }), o('[ ArgList OptComma ]', function() { + return new Arr($2); + }) + ], + RangeDots: [ + o('..', function() { + return 'inclusive'; + }), o('...', function() { + return 'exclusive'; + }) + ], + Range: [ + o('[ Expression RangeDots Expression ]', function() { + return new Range($2, $4, $3); + }) + ], + Slice: [ + o('Expression RangeDots Expression', function() { + return new Range($1, $3, $2); + }), o('Expression RangeDots', function() { + return new Range($1, null, $2); + }), o('RangeDots Expression', function() { + return new Range(null, $2, $1); + }), o('RangeDots', function() { + return new Range(null, null, $1); + }) + ], + ArgList: [ + o('Arg', function() { + return [$1]; + }), o('ArgList , Arg', function() { + return $1.concat($3); + }), o('ArgList OptComma TERMINATOR Arg', function() { + return $1.concat($4); + }), o('INDENT ArgList OptComma OUTDENT', function() { + return $2; + }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Arg: [o('Expression'), o('Splat')], + SimpleArgs: [ + o('Expression'), o('SimpleArgs , Expression', function() { + return [].concat($1, $3); + }) + ], + Try: [ + o('TRY Block', function() { + return new Try($2); + }), o('TRY Block Catch', function() { + return new Try($2, $3[0], $3[1]); + }), o('TRY Block FINALLY Block', function() { + return new Try($2, null, null, $4); + }), o('TRY Block Catch FINALLY Block', function() { + return new Try($2, $3[0], $3[1], $5); + }) + ], + Catch: [ + o('CATCH Identifier Block', function() { + return [$2, $3]; + }) + ], + Throw: [ + o('THROW Expression', function() { + return new Throw($2); + }) + ], + Parenthetical: [ + o('( Body )', function() { + return new Parens($2); + }), o('( INDENT Body OUTDENT )', function() { + return new Parens($3); + }) + ], + WhileSource: [ + o('WHILE Expression', function() { + return new While($2); + }), o('WHILE Expression WHEN Expression', function() { + return new While($2, { + guard: $4 + }); + }), o('UNTIL Expression', function() { + return new While($2, { + invert: true + }); + }), o('UNTIL Expression WHEN Expression', function() { + return new While($2, { + invert: true, + guard: $4 + }); + }) + ], + While: [ + o('WhileSource Block', function() { + return $1.addBody($2); + }), o('Statement WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Expression WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Loop', function() { + return $1; + }) + ], + Loop: [ + o('LOOP Block', function() { + return new While(new Literal('true')).addBody($2); + }), o('LOOP Expression', function() { + return new While(new Literal('true')).addBody(Block.wrap([$2])); + }) + ], + For: [ + o('Statement ForBody', function() { + return new For($1, $2); + }), o('Expression ForBody', function() { + return new For($1, $2); + }), o('ForBody Block', function() { + return new For($2, $1); + }) + ], + ForBody: [ + o('FOR Range', function() { + return { + source: new Value($2) + }; + }), o('ForStart ForSource', function() { + $2.own = $1.own; + $2.name = $1[0]; + $2.index = $1[1]; + return $2; + }) + ], + ForStart: [ + o('FOR ForVariables', function() { + return $2; + }), o('FOR OWN ForVariables', function() { + $3.own = true; + return $3; + }) + ], + ForValue: [ + o('Identifier'), o('ThisProperty'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + ForVariables: [ + o('ForValue', function() { + return [$1]; + }), o('ForValue , ForValue', function() { + return [$1, $3]; + }) + ], + ForSource: [ + o('FORIN Expression', function() { + return { + source: $2 + }; + }), o('FOROF Expression', function() { + return { + source: $2, + object: true + }; + }), o('FORIN Expression WHEN Expression', function() { + return { + source: $2, + guard: $4 + }; + }), o('FOROF Expression WHEN Expression', function() { + return { + source: $2, + guard: $4, + object: true + }; + }), o('FORIN Expression BY Expression', function() { + return { + source: $2, + step: $4 + }; + }), o('FORIN Expression WHEN Expression BY Expression', function() { + return { + source: $2, + guard: $4, + step: $6 + }; + }), o('FORIN Expression BY Expression WHEN Expression', function() { + return { + source: $2, + step: $4, + guard: $6 + }; + }) + ], + Switch: [ + o('SWITCH Expression INDENT Whens OUTDENT', function() { + return new Switch($2, $4); + }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() { + return new Switch($2, $4, $6); + }), o('SWITCH INDENT Whens OUTDENT', function() { + return new Switch(null, $3); + }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() { + return new Switch(null, $3, $5); + }) + ], + Whens: [ + o('When'), o('Whens When', function() { + return $1.concat($2); + }) + ], + When: [ + o('LEADING_WHEN SimpleArgs Block', function() { + return [[$2, $3]]; + }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() { + return [[$2, $3]]; + }) + ], + IfBlock: [ + o('IF Expression Block', function() { + return new If($2, $3, { + type: $1 + }); + }), o('IfBlock ELSE IF Expression Block', function() { + return $1.addElse(new If($4, $5, { + type: $3 + })); + }) + ], + If: [ + o('IfBlock'), o('IfBlock ELSE Block', function() { + return $1.addElse($3); + }), o('Statement POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }), o('Expression POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }) + ], + Operation: [ + o('UNARY Expression', function() { + return new Op($1, $2); + }), o('- Expression', (function() { + return new Op('-', $2); + }), { + prec: 'UNARY' + }), o('+ Expression', (function() { + return new Op('+', $2); + }), { + prec: 'UNARY' + }), o('-- SimpleAssignable', function() { + return new Op('--', $2); + }), o('++ SimpleAssignable', function() { + return new Op('++', $2); + }), o('SimpleAssignable --', function() { + return new Op('--', $1, null, true); + }), o('SimpleAssignable ++', function() { + return new Op('++', $1, null, true); + }), o('Expression ?', function() { + return new Existence($1); + }), o('Expression + Expression', function() { + return new Op('+', $1, $3); + }), o('Expression - Expression', function() { + return new Op('-', $1, $3); + }), o('Expression MATH Expression', function() { + return new Op($2, $1, $3); + }), o('Expression SHIFT Expression', function() { + return new Op($2, $1, $3); + }), o('Expression COMPARE Expression', function() { + return new Op($2, $1, $3); + }), o('Expression LOGIC Expression', function() { + return new Op($2, $1, $3); + }), o('Expression RELATION Expression', function() { + if ($2.charAt(0) === '!') { + return new Op($2.slice(1), $1, $3).invert(); + } else { + return new Op($2, $1, $3); + } + }), o('SimpleAssignable COMPOUND_ASSIGN\ + Expression', function() { + return new Assign($1, $3, $2); + }), o('SimpleAssignable COMPOUND_ASSIGN\ + INDENT Expression OUTDENT', function() { + return new Assign($1, $4, $2); + }), o('SimpleAssignable EXTENDS Expression', function() { + return new Extends($1, $3); + }) + ] + }; + + operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']]; + + tokens = []; + + for (name in grammar) { + alternatives = grammar[name]; + grammar[name] = (function() { + var _i, _j, _len, _len1, _ref, _results; + _results = []; + for (_i = 0, _len = alternatives.length; _i < _len; _i++) { + alt = alternatives[_i]; + _ref = alt[0].split(' '); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + token = _ref[_j]; + if (!grammar[token]) { + tokens.push(token); + } + } + if (name === 'Root') { + alt[1] = "return " + alt[1]; + } + _results.push(alt); + } + return _results; + })(); + } + + exports.parser = new Parser({ + tokens: tokens.join(' '), + bnf: grammar, + operators: operators.reverse(), + startSymbol: 'Root' + }); + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/helpers.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/helpers.js new file mode 100644 index 0000000..b0a997b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/helpers.js @@ -0,0 +1,77 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var extend, flatten; + + exports.starts = function(string, literal, start) { + return literal === string.substr(start, literal.length); + }; + + exports.ends = function(string, literal, back) { + var len; + len = literal.length; + return literal === string.substr(string.length - len - (back || 0), len); + }; + + exports.compact = function(array) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + item = array[_i]; + if (item) { + _results.push(item); + } + } + return _results; + }; + + exports.count = function(string, substr) { + var num, pos; + num = pos = 0; + if (!substr.length) { + return 1 / 0; + } + while (pos = 1 + string.indexOf(substr, pos)) { + num++; + } + return num; + }; + + exports.merge = function(options, overrides) { + return extend(extend({}, options), overrides); + }; + + extend = exports.extend = function(object, properties) { + var key, val; + for (key in properties) { + val = properties[key]; + object[key] = val; + } + return object; + }; + + exports.flatten = flatten = function(array) { + var element, flattened, _i, _len; + flattened = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + element = array[_i]; + if (element instanceof Array) { + flattened = flattened.concat(flatten(element)); + } else { + flattened.push(element); + } + } + return flattened; + }; + + exports.del = function(obj, key) { + var val; + val = obj[key]; + delete obj[key]; + return val; + }; + + exports.last = function(array, back) { + return array[array.length - (back || 0) - 1]; + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/index.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/index.js new file mode 100644 index 0000000..d344c41 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/index.js @@ -0,0 +1,11 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var key, val, _ref; + + _ref = require('./coffee-script'); + for (key in _ref) { + val = _ref[key]; + exports[key] = val; + } + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/lexer.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/lexer.js new file mode 100644 index 0000000..f80a443 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/lexer.js @@ -0,0 +1,788 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES; + + _ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last; + + exports.Lexer = Lexer = (function() { + + function Lexer() {} + + Lexer.prototype.tokenize = function(code, opts) { + var i, tag; + if (opts == null) { + opts = {}; + } + if (WHITESPACE.test(code)) { + code = "\n" + code; + } + code = code.replace(/\r/g, '').replace(TRAILING_SPACES, ''); + this.code = code; + this.line = opts.line || 0; + this.indent = 0; + this.indebt = 0; + this.outdebt = 0; + this.indents = []; + this.ends = []; + this.tokens = []; + i = 0; + while (this.chunk = code.slice(i)) { + i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken(); + } + this.closeIndentation(); + if (tag = this.ends.pop()) { + this.error("missing " + tag); + } + if (opts.rewrite === false) { + return this.tokens; + } + return (new Rewriter).rewrite(this.tokens); + }; + + Lexer.prototype.identifierToken = function() { + var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3; + if (!(match = IDENTIFIER.exec(this.chunk))) { + return 0; + } + input = match[0], id = match[1], colon = match[2]; + if (id === 'own' && this.tag() === 'FOR') { + this.token('OWN', id); + return id.length; + } + forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@'); + tag = 'IDENTIFIER'; + if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) { + tag = id.toUpperCase(); + if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) { + tag = 'LEADING_WHEN'; + } else if (tag === 'FOR') { + this.seenFor = true; + } else if (tag === 'UNLESS') { + tag = 'IF'; + } else if (__indexOf.call(UNARY, tag) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(RELATION, tag) >= 0) { + if (tag !== 'INSTANCEOF' && this.seenFor) { + tag = 'FOR' + tag; + this.seenFor = false; + } else { + tag = 'RELATION'; + if (this.value() === '!') { + this.tokens.pop(); + id = '!' + id; + } + } + } + } + if (__indexOf.call(JS_FORBIDDEN, id) >= 0) { + if (forcedIdentifier) { + tag = 'IDENTIFIER'; + id = new String(id); + id.reserved = true; + } else if (__indexOf.call(RESERVED, id) >= 0) { + this.error("reserved word \"" + id + "\""); + } + } + if (!forcedIdentifier) { + if (__indexOf.call(COFFEE_ALIASES, id) >= 0) { + id = COFFEE_ALIAS_MAP[id]; + } + tag = (function() { + switch (id) { + case '!': + return 'UNARY'; + case '==': + case '!=': + return 'COMPARE'; + case '&&': + case '||': + return 'LOGIC'; + case 'true': + case 'false': + return 'BOOL'; + case 'break': + case 'continue': + return 'STATEMENT'; + default: + return tag; + } + })(); + } + this.token(tag, id); + if (colon) { + this.token(':', ':'); + } + return input.length; + }; + + Lexer.prototype.numberToken = function() { + var binaryLiteral, lexedLength, match, number, octalLiteral; + if (!(match = NUMBER.exec(this.chunk))) { + return 0; + } + number = match[0]; + if (/^0[BOX]/.test(number)) { + this.error("radix prefix '" + number + "' must be lowercase"); + } else if (/E/.test(number) && !/^0x/.test(number)) { + this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'"); + } else if (/^0\d*[89]/.test(number)) { + this.error("decimal literal '" + number + "' must not be prefixed with '0'"); + } else if (/^0\d+/.test(number)) { + this.error("octal literal '" + number + "' must be prefixed with '0o'"); + } + lexedLength = number.length; + if (octalLiteral = /^0o([0-7]+)/.exec(number)) { + number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16); + } + if (binaryLiteral = /^0b([01]+)/.exec(number)) { + number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16); + } + this.token('NUMBER', number); + return lexedLength; + }; + + Lexer.prototype.stringToken = function() { + var match, octalEsc, string; + switch (this.chunk.charAt(0)) { + case "'": + if (!(match = SIMPLESTR.exec(this.chunk))) { + return 0; + } + this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n')); + break; + case '"': + if (!(string = this.balancedString(this.chunk, '"'))) { + return 0; + } + if (0 < string.indexOf('#{', 1)) { + this.interpolateString(string.slice(1, -1)); + } else { + this.token('STRING', this.escapeLines(string)); + } + break; + default: + return 0; + } + if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) { + this.error("octal escape sequences " + string + " are not allowed"); + } + this.line += count(string, '\n'); + return string.length; + }; + + Lexer.prototype.heredocToken = function() { + var doc, heredoc, match, quote; + if (!(match = HEREDOC.exec(this.chunk))) { + return 0; + } + heredoc = match[0]; + quote = heredoc.charAt(0); + doc = this.sanitizeHeredoc(match[2], { + quote: quote, + indent: null + }); + if (quote === '"' && 0 <= doc.indexOf('#{')) { + this.interpolateString(doc, { + heredoc: true + }); + } else { + this.token('STRING', this.makeString(doc, quote, true)); + } + this.line += count(heredoc, '\n'); + return heredoc.length; + }; + + Lexer.prototype.commentToken = function() { + var comment, here, match; + if (!(match = this.chunk.match(COMMENT))) { + return 0; + } + comment = match[0], here = match[1]; + if (here) { + this.token('HERECOMMENT', this.sanitizeHeredoc(here, { + herecomment: true, + indent: Array(this.indent + 1).join(' ') + })); + } + this.line += count(comment, '\n'); + return comment.length; + }; + + Lexer.prototype.jsToken = function() { + var match, script; + if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) { + return 0; + } + this.token('JS', (script = match[0]).slice(1, -1)); + return script.length; + }; + + Lexer.prototype.regexToken = function() { + var flags, length, match, prev, regex, _ref2, _ref3; + if (this.chunk.charAt(0) !== '/') { + return 0; + } + if (match = HEREGEX.exec(this.chunk)) { + length = this.heregexToken(match); + this.line += count(match[0], '\n'); + return length; + } + prev = last(this.tokens); + if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) { + return 0; + } + if (!(match = REGEX.exec(this.chunk))) { + return 0; + } + _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2]; + if (regex.slice(0, 2) === '/*') { + this.error('regular expressions cannot begin with `*`'); + } + if (regex === '//') { + regex = '/(?:)/'; + } + this.token('REGEX', "" + regex + flags); + return match.length; + }; + + Lexer.prototype.heregexToken = function(match) { + var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5; + heregex = match[0], body = match[1], flags = match[2]; + if (0 > body.indexOf('#{')) { + re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/'); + if (re.match(/^\*/)) { + this.error('regular expressions cannot begin with `*`'); + } + this.token('REGEX', "/" + (re || '(?:)') + "/" + flags); + return heregex.length; + } + this.token('IDENTIFIER', 'RegExp'); + this.tokens.push(['CALL_START', '(']); + tokens = []; + _ref2 = this.interpolateString(body, { + regex: true + }); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1]; + if (tag === 'TOKENS') { + tokens.push.apply(tokens, value); + } else { + if (!(value = value.replace(HEREGEX_OMIT, ''))) { + continue; + } + value = value.replace(/\\/g, '\\\\'); + tokens.push(['STRING', this.makeString(value, '"', true)]); + } + tokens.push(['+', '+']); + } + tokens.pop(); + if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') { + this.tokens.push(['STRING', '""'], ['+', '+']); + } + (_ref5 = this.tokens).push.apply(_ref5, tokens); + if (flags) { + this.tokens.push([',', ','], ['STRING', '"' + flags + '"']); + } + this.token(')', ')'); + return heregex.length; + }; + + Lexer.prototype.lineToken = function() { + var diff, indent, match, noNewlines, prev, size; + if (!(match = MULTI_DENT.exec(this.chunk))) { + return 0; + } + indent = match[0]; + this.line += count(indent, '\n'); + this.seenFor = false; + prev = last(this.tokens, 1); + size = indent.length - 1 - indent.lastIndexOf('\n'); + noNewlines = this.unfinished(); + if (size - this.indebt === this.indent) { + if (noNewlines) { + this.suppressNewlines(); + } else { + this.newlineToken(); + } + return indent.length; + } + if (size > this.indent) { + if (noNewlines) { + this.indebt = size - this.indent; + this.suppressNewlines(); + return indent.length; + } + diff = size - this.indent + this.outdebt; + this.token('INDENT', diff); + this.indents.push(diff); + this.ends.push('OUTDENT'); + this.outdebt = this.indebt = 0; + } else { + this.indebt = 0; + this.outdentToken(this.indent - size, noNewlines); + } + this.indent = size; + return indent.length; + }; + + Lexer.prototype.outdentToken = function(moveOut, noNewlines) { + var dent, len; + while (moveOut > 0) { + len = this.indents.length - 1; + if (this.indents[len] === void 0) { + moveOut = 0; + } else if (this.indents[len] === this.outdebt) { + moveOut -= this.outdebt; + this.outdebt = 0; + } else if (this.indents[len] < this.outdebt) { + this.outdebt -= this.indents[len]; + moveOut -= this.indents[len]; + } else { + dent = this.indents.pop() - this.outdebt; + moveOut -= dent; + this.outdebt = 0; + this.pair('OUTDENT'); + this.token('OUTDENT', dent); + } + } + if (dent) { + this.outdebt -= moveOut; + } + while (this.value() === ';') { + this.tokens.pop(); + } + if (!(this.tag() === 'TERMINATOR' || noNewlines)) { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.whitespaceToken = function() { + var match, nline, prev; + if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) { + return 0; + } + prev = last(this.tokens); + if (prev) { + prev[match ? 'spaced' : 'newLine'] = true; + } + if (match) { + return match[0].length; + } else { + return 0; + } + }; + + Lexer.prototype.newlineToken = function() { + while (this.value() === ';') { + this.tokens.pop(); + } + if (this.tag() !== 'TERMINATOR') { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.suppressNewlines = function() { + if (this.value() === '\\') { + this.tokens.pop(); + } + return this; + }; + + Lexer.prototype.literalToken = function() { + var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5; + if (match = OPERATOR.exec(this.chunk)) { + value = match[0]; + if (CODE.test(value)) { + this.tagParameters(); + } + } else { + value = this.chunk.charAt(0); + } + tag = value; + prev = last(this.tokens); + if (value === '=' && prev) { + if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) { + this.error("reserved word \"" + (this.value()) + "\" can't be assigned"); + } + if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') { + prev[0] = 'COMPOUND_ASSIGN'; + prev[1] += '='; + return value.length; + } + } + if (value === ';') { + this.seenFor = false; + tag = 'TERMINATOR'; + } else if (__indexOf.call(MATH, value) >= 0) { + tag = 'MATH'; + } else if (__indexOf.call(COMPARE, value) >= 0) { + tag = 'COMPARE'; + } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) { + tag = 'COMPOUND_ASSIGN'; + } else if (__indexOf.call(UNARY, value) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(SHIFT, value) >= 0) { + tag = 'SHIFT'; + } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) { + tag = 'LOGIC'; + } else if (prev && !prev.spaced) { + if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) { + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + tag = 'CALL_START'; + } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) { + tag = 'INDEX_START'; + switch (prev[0]) { + case '?': + prev[0] = 'INDEX_SOAK'; + } + } + } + switch (value) { + case '(': + case '{': + case '[': + this.ends.push(INVERSES[value]); + break; + case ')': + case '}': + case ']': + this.pair(value); + } + this.token(tag, value); + return value.length; + }; + + Lexer.prototype.sanitizeHeredoc = function(doc, options) { + var attempt, herecomment, indent, match, _ref2; + indent = options.indent, herecomment = options.herecomment; + if (herecomment) { + if (HEREDOC_ILLEGAL.test(doc)) { + this.error("block comment cannot contain \"*/\", starting"); + } + if (doc.indexOf('\n') <= 0) { + return doc; + } + } else { + while (match = HEREDOC_INDENT.exec(doc)) { + attempt = match[1]; + if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) { + indent = attempt; + } + } + } + if (indent) { + doc = doc.replace(RegExp("\\n" + indent, "g"), '\n'); + } + if (!herecomment) { + doc = doc.replace(/^\n/, ''); + } + return doc; + }; + + Lexer.prototype.tagParameters = function() { + var i, stack, tok, tokens; + if (this.tag() !== ')') { + return this; + } + stack = []; + tokens = this.tokens; + i = tokens.length; + tokens[--i][0] = 'PARAM_END'; + while (tok = tokens[--i]) { + switch (tok[0]) { + case ')': + stack.push(tok); + break; + case '(': + case 'CALL_START': + if (stack.length) { + stack.pop(); + } else if (tok[0] === '(') { + tok[0] = 'PARAM_START'; + return this; + } else { + return this; + } + } + } + return this; + }; + + Lexer.prototype.closeIndentation = function() { + return this.outdentToken(this.indent); + }; + + Lexer.prototype.balancedString = function(str, end) { + var continueCount, i, letter, match, prev, stack, _i, _ref2; + continueCount = 0; + stack = [end]; + for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) { + if (continueCount) { + --continueCount; + continue; + } + switch (letter = str.charAt(i)) { + case '\\': + ++continueCount; + continue; + case end: + stack.pop(); + if (!stack.length) { + return str.slice(0, i + 1 || 9e9); + } + end = stack[stack.length - 1]; + continue; + } + if (end === '}' && (letter === '"' || letter === "'")) { + stack.push(end = letter); + } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) { + continueCount += match[0].length - 1; + } else if (end === '}' && letter === '{') { + stack.push(end = '}'); + } else if (end === '"' && prev === '#' && letter === '{') { + stack.push(end = '}'); + } + prev = letter; + } + return this.error("missing " + (stack.pop()) + ", starting"); + }; + + Lexer.prototype.interpolateString = function(str, options) { + var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4; + if (options == null) { + options = {}; + } + heredoc = options.heredoc, regex = options.regex; + tokens = []; + pi = 0; + i = -1; + while (letter = str.charAt(i += 1)) { + if (letter === '\\') { + i += 1; + continue; + } + if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) { + continue; + } + if (pi < i) { + tokens.push(['NEOSTRING', str.slice(pi, i)]); + } + inner = expr.slice(1, -1); + if (inner.length) { + nested = new Lexer().tokenize(inner, { + line: this.line, + rewrite: false + }); + nested.pop(); + if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') { + nested.shift(); + } + if (len = nested.length) { + if (len > 1) { + nested.unshift(['(', '(', this.line]); + nested.push([')', ')', this.line]); + } + tokens.push(['TOKENS', nested]); + } + } + i += expr.length; + pi = i + 1; + } + if ((i > pi && pi < str.length)) { + tokens.push(['NEOSTRING', str.slice(pi)]); + } + if (regex) { + return tokens; + } + if (!tokens.length) { + return this.token('STRING', '""'); + } + if (tokens[0][0] !== 'NEOSTRING') { + tokens.unshift(['', '']); + } + if (interpolated = tokens.length > 1) { + this.token('(', '('); + } + for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) { + _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1]; + if (i) { + this.token('+', '+'); + } + if (tag === 'TOKENS') { + (_ref4 = this.tokens).push.apply(_ref4, value); + } else { + this.token('STRING', this.makeString(value, '"', heredoc)); + } + } + if (interpolated) { + this.token(')', ')'); + } + return tokens; + }; + + Lexer.prototype.pair = function(tag) { + var size, wanted; + if (tag !== (wanted = last(this.ends))) { + if ('OUTDENT' !== wanted) { + this.error("unmatched " + tag); + } + this.indent -= size = last(this.indents); + this.outdentToken(size, true); + return this.pair(tag); + } + return this.ends.pop(); + }; + + Lexer.prototype.token = function(tag, value) { + return this.tokens.push([tag, value, this.line]); + }; + + Lexer.prototype.tag = function(index, tag) { + var tok; + return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]); + }; + + Lexer.prototype.value = function(index, val) { + var tok; + return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]); + }; + + Lexer.prototype.unfinished = function() { + var _ref2; + return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); + }; + + Lexer.prototype.escapeLines = function(str, heredoc) { + return str.replace(MULTILINER, heredoc ? '\\n' : ''); + }; + + Lexer.prototype.makeString = function(body, quote, heredoc) { + if (!body) { + return quote + quote; + } + body = body.replace(/\\([\s\S])/g, function(match, contents) { + if (contents === '\n' || contents === quote) { + return contents; + } else { + return match; + } + }); + body = body.replace(RegExp("" + quote, "g"), '\\$&'); + return quote + this.escapeLines(body, heredoc) + quote; + }; + + Lexer.prototype.error = function(message) { + throw SyntaxError("" + message + " on line " + (this.line + 1)); + }; + + return Lexer; + + })(); + + JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super']; + + COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']; + + COFFEE_ALIAS_MAP = { + and: '&&', + or: '||', + is: '==', + isnt: '!=', + not: '!', + yes: 'true', + no: 'false', + on: 'true', + off: 'false' + }; + + COFFEE_ALIASES = (function() { + var _results; + _results = []; + for (key in COFFEE_ALIAS_MAP) { + _results.push(key); + } + return _results; + })(); + + COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES); + + RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield']; + + STRICT_PROSCRIBED = ['arguments', 'eval']; + + JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED); + + exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED); + + exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED; + + IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/; + + NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; + + HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/; + + OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/; + + WHITESPACE = /^[^\n\S]+/; + + COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/; + + CODE = /^[-=]>/; + + MULTI_DENT = /^(?:\n[^\n\S]*)+/; + + SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; + + JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; + + REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/; + + HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/; + + HEREGEX_OMIT = /\s+(?:#.*)?/g; + + MULTILINER = /\n/g; + + HEREDOC_INDENT = /\n+([^\n\S]*)/g; + + HEREDOC_ILLEGAL = /\*\//; + + LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/; + + TRAILING_SPACES = /\s+$/; + + COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']; + + UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO']; + + LOGIC = ['&&', '||', '&', '|', '^']; + + SHIFT = ['<<', '>>', '>>>']; + + COMPARE = ['==', '!=', '<', '>', '<=', '>=']; + + MATH = ['*', '/', '%']; + + RELATION = ['IN', 'OF', 'INSTANCEOF']; + + BOOL = ['TRUE', 'FALSE']; + + NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']; + + NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING'); + + CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']; + + INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL', 'NULL', 'UNDEFINED'); + + LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/nodes.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/nodes.js new file mode 100644 index 0000000..799b68e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/nodes.js @@ -0,0 +1,2986 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref, _ref1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + Scope = require('./scope').Scope; + + _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED; + + _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last; + + exports.extend = extend; + + YES = function() { + return true; + }; + + NO = function() { + return false; + }; + + THIS = function() { + return this; + }; + + NEGATE = function() { + this.negated = !this.negated; + return this; + }; + + exports.Base = Base = (function() { + + function Base() {} + + Base.prototype.compile = function(o, lvl) { + var node; + o = extend({}, o); + if (lvl) { + o.level = lvl; + } + node = this.unfoldSoak(o) || this; + node.tab = o.indent; + if (o.level === LEVEL_TOP || !node.isStatement(o)) { + return node.compileNode(o); + } else { + return node.compileClosure(o); + } + }; + + Base.prototype.compileClosure = function(o) { + if (this.jumps()) { + throw SyntaxError('cannot use a pure statement in an expression.'); + } + o.sharedScope = true; + return Closure.wrap(this).compileNode(o); + }; + + Base.prototype.cache = function(o, level, reused) { + var ref, sub; + if (!this.isComplex()) { + ref = level ? this.compile(o, level) : this; + return [ref, ref]; + } else { + ref = new Literal(reused || o.scope.freeVariable('ref')); + sub = new Assign(ref, this); + if (level) { + return [sub.compile(o, level), ref.value]; + } else { + return [sub, ref]; + } + } + }; + + Base.prototype.compileLoopReference = function(o, name) { + var src, tmp; + src = tmp = this.compile(o, LEVEL_LIST); + if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) { + src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src; + } + return [src, tmp]; + }; + + Base.prototype.makeReturn = function(res) { + var me; + me = this.unwrapAll(); + if (res) { + return new Call(new Literal("" + res + ".push"), [me]); + } else { + return new Return(me); + } + }; + + Base.prototype.contains = function(pred) { + var contains; + contains = false; + this.traverseChildren(false, function(node) { + if (pred(node)) { + contains = true; + return false; + } + }); + return contains; + }; + + Base.prototype.containsType = function(type) { + return this instanceof type || this.contains(function(node) { + return node instanceof type; + }); + }; + + Base.prototype.lastNonComment = function(list) { + var i; + i = list.length; + while (i--) { + if (!(list[i] instanceof Comment)) { + return list[i]; + } + } + return null; + }; + + Base.prototype.toString = function(idt, name) { + var tree; + if (idt == null) { + idt = ''; + } + if (name == null) { + name = this.constructor.name; + } + tree = '\n' + idt + name; + if (this.soak) { + tree += '?'; + } + this.eachChild(function(node) { + return tree += node.toString(idt + TAB); + }); + return tree; + }; + + Base.prototype.eachChild = function(func) { + var attr, child, _i, _j, _len, _len1, _ref2, _ref3; + if (!this.children) { + return this; + } + _ref2 = this.children; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + attr = _ref2[_i]; + if (this[attr]) { + _ref3 = flatten([this[attr]]); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + child = _ref3[_j]; + if (func(child) === false) { + return this; + } + } + } + } + return this; + }; + + Base.prototype.traverseChildren = function(crossScope, func) { + return this.eachChild(function(child) { + if (func(child) === false) { + return false; + } + return child.traverseChildren(crossScope, func); + }); + }; + + Base.prototype.invert = function() { + return new Op('!', this); + }; + + Base.prototype.unwrapAll = function() { + var node; + node = this; + while (node !== (node = node.unwrap())) { + continue; + } + return node; + }; + + Base.prototype.children = []; + + Base.prototype.isStatement = NO; + + Base.prototype.jumps = NO; + + Base.prototype.isComplex = YES; + + Base.prototype.isChainable = NO; + + Base.prototype.isAssignable = NO; + + Base.prototype.unwrap = THIS; + + Base.prototype.unfoldSoak = NO; + + Base.prototype.assigns = NO; + + return Base; + + })(); + + exports.Block = Block = (function(_super) { + + __extends(Block, _super); + + function Block(nodes) { + this.expressions = compact(flatten(nodes || [])); + } + + Block.prototype.children = ['expressions']; + + Block.prototype.push = function(node) { + this.expressions.push(node); + return this; + }; + + Block.prototype.pop = function() { + return this.expressions.pop(); + }; + + Block.prototype.unshift = function(node) { + this.expressions.unshift(node); + return this; + }; + + Block.prototype.unwrap = function() { + if (this.expressions.length === 1) { + return this.expressions[0]; + } else { + return this; + } + }; + + Block.prototype.isEmpty = function() { + return !this.expressions.length; + }; + + Block.prototype.isStatement = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.isStatement(o)) { + return true; + } + } + return false; + }; + + Block.prototype.jumps = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.jumps(o)) { + return exp; + } + } + }; + + Block.prototype.makeReturn = function(res) { + var expr, len; + len = this.expressions.length; + while (len--) { + expr = this.expressions[len]; + if (!(expr instanceof Comment)) { + this.expressions[len] = expr.makeReturn(res); + if (expr instanceof Return && !expr.expression) { + this.expressions.splice(len, 1); + } + break; + } + } + return this; + }; + + Block.prototype.compile = function(o, level) { + if (o == null) { + o = {}; + } + if (o.scope) { + return Block.__super__.compile.call(this, o, level); + } else { + return this.compileRoot(o); + } + }; + + Block.prototype.compileNode = function(o) { + var code, codes, node, top, _i, _len, _ref2; + this.tab = o.indent; + top = o.level === LEVEL_TOP; + codes = []; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + node = node.unwrapAll(); + node = node.unfoldSoak(o) || node; + if (node instanceof Block) { + codes.push(node.compileNode(o)); + } else if (top) { + node.front = true; + code = node.compile(o); + if (!node.isStatement(o)) { + code = "" + this.tab + code + ";"; + if (node instanceof Literal) { + code = "" + code + "\n"; + } + } + codes.push(code); + } else { + codes.push(node.compile(o, LEVEL_LIST)); + } + } + if (top) { + if (this.spaced) { + return "\n" + (codes.join('\n\n')) + "\n"; + } else { + return codes.join('\n'); + } + } + code = codes.join(', ') || 'void 0'; + if (codes.length > 1 && o.level >= LEVEL_LIST) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Block.prototype.compileRoot = function(o) { + var code, exp, i, prelude, preludeExps, rest; + o.indent = o.bare ? '' : TAB; + o.scope = new Scope(null, this, null); + o.level = LEVEL_TOP; + this.spaced = true; + prelude = ""; + if (!o.bare) { + preludeExps = (function() { + var _i, _len, _ref2, _results; + _ref2 = this.expressions; + _results = []; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + if (!(exp.unwrap() instanceof Comment)) { + break; + } + _results.push(exp); + } + return _results; + }).call(this); + rest = this.expressions.slice(preludeExps.length); + this.expressions = preludeExps; + if (preludeExps.length) { + prelude = "" + (this.compileNode(merge(o, { + indent: '' + }))) + "\n"; + } + this.expressions = rest; + } + code = this.compileWithDeclarations(o); + if (o.bare) { + return code; + } + return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n"; + }; + + Block.prototype.compileWithDeclarations = function(o) { + var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4; + code = post = ''; + _ref2 = this.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + exp = exp.unwrap(); + if (!(exp instanceof Comment || exp instanceof Literal)) { + break; + } + } + o = merge(o, { + level: LEVEL_TOP + }); + if (i) { + rest = this.expressions.splice(i, 9e9); + _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1]; + _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1]; + this.expressions = rest; + } + post = this.compileNode(o); + scope = o.scope; + if (scope.expressions === this) { + declars = o.scope.hasDeclarations(); + assigns = scope.hasAssignments; + if (declars || assigns) { + if (i) { + code += '\n'; + } + code += "" + this.tab + "var "; + if (declars) { + code += scope.declaredVariables().join(', '); + } + if (assigns) { + if (declars) { + code += ",\n" + (this.tab + TAB); + } + code += scope.assignedVariables().join(",\n" + (this.tab + TAB)); + } + code += ';\n'; + } + } + return code + post; + }; + + Block.wrap = function(nodes) { + if (nodes.length === 1 && nodes[0] instanceof Block) { + return nodes[0]; + } + return new Block(nodes); + }; + + return Block; + + })(Base); + + exports.Literal = Literal = (function(_super) { + + __extends(Literal, _super); + + function Literal(value) { + this.value = value; + } + + Literal.prototype.makeReturn = function() { + if (this.isStatement()) { + return this; + } else { + return Literal.__super__.makeReturn.apply(this, arguments); + } + }; + + Literal.prototype.isAssignable = function() { + return IDENTIFIER.test(this.value); + }; + + Literal.prototype.isStatement = function() { + var _ref2; + return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger'; + }; + + Literal.prototype.isComplex = NO; + + Literal.prototype.assigns = function(name) { + return name === this.value; + }; + + Literal.prototype.jumps = function(o) { + if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) { + return this; + } + if (this.value === 'continue' && !(o != null ? o.loop : void 0)) { + return this; + } + }; + + Literal.prototype.compileNode = function(o) { + var code, _ref2; + code = this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value; + if (this.isStatement()) { + return "" + this.tab + code + ";"; + } else { + return code; + } + }; + + Literal.prototype.toString = function() { + return ' "' + this.value + '"'; + }; + + return Literal; + + })(Base); + + exports.Undefined = (function(_super) { + + __extends(Undefined, _super); + + function Undefined() { + return Undefined.__super__.constructor.apply(this, arguments); + } + + Undefined.prototype.isAssignable = NO; + + Undefined.prototype.isComplex = NO; + + Undefined.prototype.compileNode = function(o) { + if (o.level >= LEVEL_ACCESS) { + return '(void 0)'; + } else { + return 'void 0'; + } + }; + + return Undefined; + + })(Base); + + exports.Null = (function(_super) { + + __extends(Null, _super); + + function Null() { + return Null.__super__.constructor.apply(this, arguments); + } + + Null.prototype.isAssignable = NO; + + Null.prototype.isComplex = NO; + + Null.prototype.compileNode = function() { + return "null"; + }; + + return Null; + + })(Base); + + exports.Bool = (function(_super) { + + __extends(Bool, _super); + + Bool.prototype.isAssignable = NO; + + Bool.prototype.isComplex = NO; + + Bool.prototype.compileNode = function() { + return this.val; + }; + + function Bool(val) { + this.val = val; + } + + return Bool; + + })(Base); + + exports.Return = Return = (function(_super) { + + __extends(Return, _super); + + function Return(expr) { + if (expr && !expr.unwrap().isUndefined) { + this.expression = expr; + } + } + + Return.prototype.children = ['expression']; + + Return.prototype.isStatement = YES; + + Return.prototype.makeReturn = THIS; + + Return.prototype.jumps = THIS; + + Return.prototype.compile = function(o, level) { + var expr, _ref2; + expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0; + if (expr && !(expr instanceof Return)) { + return expr.compile(o, level); + } else { + return Return.__super__.compile.call(this, o, level); + } + }; + + Return.prototype.compileNode = function(o) { + return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";"); + }; + + return Return; + + })(Base); + + exports.Value = Value = (function(_super) { + + __extends(Value, _super); + + function Value(base, props, tag) { + if (!props && base instanceof Value) { + return base; + } + this.base = base; + this.properties = props || []; + if (tag) { + this[tag] = true; + } + return this; + } + + Value.prototype.children = ['base', 'properties']; + + Value.prototype.add = function(props) { + this.properties = this.properties.concat(props); + return this; + }; + + Value.prototype.hasProperties = function() { + return !!this.properties.length; + }; + + Value.prototype.isArray = function() { + return !this.properties.length && this.base instanceof Arr; + }; + + Value.prototype.isComplex = function() { + return this.hasProperties() || this.base.isComplex(); + }; + + Value.prototype.isAssignable = function() { + return this.hasProperties() || this.base.isAssignable(); + }; + + Value.prototype.isSimpleNumber = function() { + return this.base instanceof Literal && SIMPLENUM.test(this.base.value); + }; + + Value.prototype.isString = function() { + return this.base instanceof Literal && IS_STRING.test(this.base.value); + }; + + Value.prototype.isAtomic = function() { + var node, _i, _len, _ref2; + _ref2 = this.properties.concat(this.base); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + if (node.soak || node instanceof Call) { + return false; + } + } + return true; + }; + + Value.prototype.isStatement = function(o) { + return !this.properties.length && this.base.isStatement(o); + }; + + Value.prototype.assigns = function(name) { + return !this.properties.length && this.base.assigns(name); + }; + + Value.prototype.jumps = function(o) { + return !this.properties.length && this.base.jumps(o); + }; + + Value.prototype.isObject = function(onlyGenerated) { + if (this.properties.length) { + return false; + } + return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated); + }; + + Value.prototype.isSplice = function() { + return last(this.properties) instanceof Slice; + }; + + Value.prototype.unwrap = function() { + if (this.properties.length) { + return this; + } else { + return this.base; + } + }; + + Value.prototype.cacheReference = function(o) { + var base, bref, name, nref; + name = last(this.properties); + if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { + return [this, this]; + } + base = new Value(this.base, this.properties.slice(0, -1)); + if (base.isComplex()) { + bref = new Literal(o.scope.freeVariable('base')); + base = new Value(new Parens(new Assign(bref, base))); + } + if (!name) { + return [base, bref]; + } + if (name.isComplex()) { + nref = new Literal(o.scope.freeVariable('name')); + name = new Index(new Assign(nref, name.index)); + nref = new Index(nref); + } + return [base.add(name), new Value(bref || base.base, [nref || name])]; + }; + + Value.prototype.compileNode = function(o) { + var code, prop, props, _i, _len; + this.base.front = this.front; + props = this.properties; + code = this.base.compile(o, props.length ? LEVEL_ACCESS : null); + if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) { + code = "" + code + "."; + } + for (_i = 0, _len = props.length; _i < _len; _i++) { + prop = props[_i]; + code += prop.compile(o); + } + return code; + }; + + Value.prototype.unfoldSoak = function(o) { + var result, + _this = this; + if (this.unfoldedSoak != null) { + return this.unfoldedSoak; + } + result = (function() { + var fst, i, ifn, prop, ref, snd, _i, _len, _ref2; + if (ifn = _this.base.unfoldSoak(o)) { + Array.prototype.push.apply(ifn.body.properties, _this.properties); + return ifn; + } + _ref2 = _this.properties; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + prop = _ref2[i]; + if (!prop.soak) { + continue; + } + prop.soak = false; + fst = new Value(_this.base, _this.properties.slice(0, i)); + snd = new Value(_this.base, _this.properties.slice(i)); + if (fst.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, fst)); + snd.base = ref; + } + return new If(new Existence(fst), snd, { + soak: true + }); + } + return null; + })(); + return this.unfoldedSoak = result || false; + }; + + return Value; + + })(Base); + + exports.Comment = Comment = (function(_super) { + + __extends(Comment, _super); + + function Comment(comment) { + this.comment = comment; + } + + Comment.prototype.isStatement = YES; + + Comment.prototype.makeReturn = THIS; + + Comment.prototype.compileNode = function(o, level) { + var code; + code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/\n"); + if ((level || o.level) === LEVEL_TOP) { + code = o.indent + code; + } + return code; + }; + + return Comment; + + })(Base); + + exports.Call = Call = (function(_super) { + + __extends(Call, _super); + + function Call(variable, args, soak) { + this.args = args != null ? args : []; + this.soak = soak; + this.isNew = false; + this.isSuper = variable === 'super'; + this.variable = this.isSuper ? null : variable; + } + + Call.prototype.children = ['variable', 'args']; + + Call.prototype.newInstance = function() { + var base, _ref2; + base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable; + if (base instanceof Call && !base.isNew) { + base.newInstance(); + } else { + this.isNew = true; + } + return this; + }; + + Call.prototype.superReference = function(o) { + var accesses, method, name; + method = o.scope.namedMethod(); + if (!method) { + throw SyntaxError('cannot call super outside of a function.'); + } + name = method.name; + if (name == null) { + throw SyntaxError('cannot call super on an anonymous function.'); + } + if (method.klass) { + accesses = [new Access(new Literal('__super__'))]; + if (method["static"]) { + accesses.push(new Access(new Literal('constructor'))); + } + accesses.push(new Access(new Literal(name))); + return (new Value(new Literal(method.klass), accesses)).compile(o); + } else { + return "" + name + ".__super__.constructor"; + } + }; + + Call.prototype.superThis = function(o) { + var method; + method = o.scope.method; + return (method && !method.klass && method.context) || "this"; + }; + + Call.prototype.unfoldSoak = function(o) { + var call, ifn, left, list, rite, _i, _len, _ref2, _ref3; + if (this.soak) { + if (this.variable) { + if (ifn = unfoldSoak(o, this, 'variable')) { + return ifn; + } + _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; + } else { + left = new Literal(this.superReference(o)); + rite = new Value(left); + } + rite = new Call(rite, this.args); + rite.isNew = this.isNew; + left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); + return new If(left, new Value(rite), { + soak: true + }); + } + call = this; + list = []; + while (true) { + if (call.variable instanceof Call) { + list.push(call); + call = call.variable; + continue; + } + if (!(call.variable instanceof Value)) { + break; + } + list.push(call); + if (!((call = call.variable.base) instanceof Call)) { + break; + } + } + _ref3 = list.reverse(); + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + call = _ref3[_i]; + if (ifn) { + if (call.variable instanceof Call) { + call.variable = ifn; + } else { + call.variable.base = ifn; + } + } + ifn = unfoldSoak(o, call, 'variable'); + } + return ifn; + }; + + Call.prototype.filterImplicitObjects = function(list) { + var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2; + nodes = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + node = list[_i]; + if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) { + nodes.push(node); + continue; + } + obj = null; + _ref2 = node.base.properties; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + prop = _ref2[_j]; + if (prop instanceof Assign || prop instanceof Comment) { + if (!obj) { + nodes.push(obj = new Obj(properties = [], true)); + } + properties.push(prop); + } else { + nodes.push(prop); + obj = null; + } + } + } + return nodes; + }; + + Call.prototype.compileNode = function(o) { + var arg, args, code, _ref2; + if ((_ref2 = this.variable) != null) { + _ref2.front = this.front; + } + if (code = Splat.compileSplattedArray(o, this.args, true)) { + return this.compileSplat(o, code); + } + args = this.filterImplicitObjects(this.args); + args = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + _results.push(arg.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (this.isSuper) { + return this.superReference(o) + (".call(" + (this.superThis(o)) + (args && ', ' + args) + ")"); + } else { + return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); + } + }; + + Call.prototype.compileSuper = function(args, o) { + return "" + (this.superReference(o)) + ".call(" + (this.superThis(o)) + (args.length ? ', ' : '') + args + ")"; + }; + + Call.prototype.compileSplat = function(o, splatArgs) { + var base, fun, idt, name, ref; + if (this.isSuper) { + return "" + (this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", " + splatArgs + ")"; + } + if (this.isNew) { + idt = this.tab + TAB; + return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args), t = typeof result;\n" + idt + "return t == \"object\" || t == \"function\" ? result || child : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})"; + } + base = new Value(this.variable); + if ((name = base.properties.pop()) && base.isComplex()) { + ref = o.scope.freeVariable('ref'); + fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o)); + } else { + fun = base.compile(o, LEVEL_ACCESS); + if (SIMPLENUM.test(fun)) { + fun = "(" + fun + ")"; + } + if (name) { + ref = fun; + fun += name.compile(o); + } else { + ref = 'null'; + } + } + return "" + fun + ".apply(" + ref + ", " + splatArgs + ")"; + }; + + return Call; + + })(Base); + + exports.Extends = Extends = (function(_super) { + + __extends(Extends, _super); + + function Extends(child, parent) { + this.child = child; + this.parent = parent; + } + + Extends.prototype.children = ['child', 'parent']; + + Extends.prototype.compile = function(o) { + return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o); + }; + + return Extends; + + })(Base); + + exports.Access = Access = (function(_super) { + + __extends(Access, _super); + + function Access(name, tag) { + this.name = name; + this.name.asKey = true; + this.soak = tag === 'soak'; + } + + Access.prototype.children = ['name']; + + Access.prototype.compile = function(o) { + var name; + name = this.name.compile(o); + if (IDENTIFIER.test(name)) { + return "." + name; + } else { + return "[" + name + "]"; + } + }; + + Access.prototype.isComplex = NO; + + return Access; + + })(Base); + + exports.Index = Index = (function(_super) { + + __extends(Index, _super); + + function Index(index) { + this.index = index; + } + + Index.prototype.children = ['index']; + + Index.prototype.compile = function(o) { + return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]"; + }; + + Index.prototype.isComplex = function() { + return this.index.isComplex(); + }; + + return Index; + + })(Base); + + exports.Range = Range = (function(_super) { + + __extends(Range, _super); + + Range.prototype.children = ['from', 'to']; + + function Range(from, to, tag) { + this.from = from; + this.to = to; + this.exclusive = tag === 'exclusive'; + this.equals = this.exclusive ? '' : '='; + } + + Range.prototype.compileVariables = function(o) { + var step, _ref2, _ref3, _ref4, _ref5; + o = merge(o, { + top: true + }); + _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1]; + _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1]; + if (step = del(o, 'step')) { + _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1]; + } + _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1]; + if (this.stepVar) { + return this.stepNum = this.stepVar.match(SIMPLENUM); + } + }; + + Range.prototype.compileNode = function(o) { + var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3; + if (!this.fromVar) { + this.compileVariables(o); + } + if (!o.index) { + return this.compileArray(o); + } + known = this.fromNum && this.toNum; + idx = del(o, 'index'); + idxName = del(o, 'name'); + namedIndex = idxName && idxName !== idx; + varPart = "" + idx + " = " + this.fromC; + if (this.toC !== this.toVar) { + varPart += ", " + this.toC; + } + if (this.step !== this.stepVar) { + varPart += ", " + this.step; + } + _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1]; + condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); + stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--"; + if (namedIndex) { + varPart = "" + idxName + " = " + varPart; + } + if (namedIndex) { + stepPart = "" + idxName + " = " + stepPart; + } + return "" + varPart + "; " + condPart + "; " + stepPart; + }; + + Range.prototype.compileArray = function(o) { + var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results; + if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { + range = (function() { + _results = []; + for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + if (this.exclusive) { + range.pop(); + } + return "[" + (range.join(', ')) + "]"; + } + idt = this.tab + TAB; + i = o.scope.freeVariable('i'); + result = o.scope.freeVariable('results'); + pre = "\n" + idt + result + " = [];"; + if (this.fromNum && this.toNum) { + o.index = i; + body = this.compileNode(o); + } else { + vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : ''); + cond = "" + this.fromVar + " <= " + this.toVar; + body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--"; + } + post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; + hasArgs = function(node) { + return node != null ? node.contains(function(n) { + return n instanceof Literal && n.value === 'arguments' && !n.asKey; + }) : void 0; + }; + if (hasArgs(this.from) || hasArgs(this.to)) { + args = ', arguments'; + } + return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")"; + }; + + return Range; + + })(Base); + + exports.Slice = Slice = (function(_super) { + + __extends(Slice, _super); + + Slice.prototype.children = ['range']; + + function Slice(range) { + this.range = range; + Slice.__super__.constructor.call(this); + } + + Slice.prototype.compileNode = function(o) { + var compiled, from, fromStr, to, toStr, _ref2; + _ref2 = this.range, to = _ref2.to, from = _ref2.from; + fromStr = from && from.compile(o, LEVEL_PAREN) || '0'; + compiled = to && to.compile(o, LEVEL_PAREN); + if (to && !(!this.range.exclusive && +compiled === -1)) { + toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? "" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), "" + compiled + " + 1 || 9e9")); + } + return ".slice(" + fromStr + (toStr || '') + ")"; + }; + + return Slice; + + })(Base); + + exports.Obj = Obj = (function(_super) { + + __extends(Obj, _super); + + function Obj(props, generated) { + this.generated = generated != null ? generated : false; + this.objects = this.properties = props || []; + } + + Obj.prototype.children = ['properties']; + + Obj.prototype.compileNode = function(o) { + var i, idt, indent, join, lastNoncom, node, obj, prop, propName, propNames, props, _i, _j, _len, _len1, _ref2; + props = this.properties; + propNames = []; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.isComplex()) { + prop = prop.variable; + } + if (prop != null) { + propName = prop.unwrapAll().value.toString(); + if (__indexOf.call(propNames, propName) >= 0) { + throw SyntaxError("multiple object literal properties named \"" + propName + "\""); + } + propNames.push(propName); + } + } + if (!props.length) { + return (this.front ? '({})' : '{}'); + } + if (this.generated) { + for (_j = 0, _len1 = props.length; _j < _len1; _j++) { + node = props[_j]; + if (node instanceof Value) { + throw new Error('cannot have an implicit value in an implicit object'); + } + } + } + idt = o.indent += TAB; + lastNoncom = this.lastNonComment(this.properties); + props = (function() { + var _k, _len2, _results; + _results = []; + for (i = _k = 0, _len2 = props.length; _k < _len2; i = ++_k) { + prop = props[i]; + join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; + indent = prop instanceof Comment ? '' : idt; + if (prop instanceof Value && prop["this"]) { + prop = new Assign(prop.properties[0].name, prop, 'object'); + } + if (!(prop instanceof Comment)) { + if (!(prop instanceof Assign)) { + prop = new Assign(prop, prop, 'object'); + } + (prop.variable.base || prop.variable).asKey = true; + } + _results.push(indent + prop.compile(o, LEVEL_TOP) + join); + } + return _results; + })(); + props = props.join(''); + obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; + if (this.front) { + return "(" + obj + ")"; + } else { + return obj; + } + }; + + Obj.prototype.assigns = function(name) { + var prop, _i, _len, _ref2; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.assigns(name)) { + return true; + } + } + return false; + }; + + return Obj; + + })(Base); + + exports.Arr = Arr = (function(_super) { + + __extends(Arr, _super); + + function Arr(objs) { + this.objects = objs || []; + } + + Arr.prototype.children = ['objects']; + + Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects; + + Arr.prototype.compileNode = function(o) { + var code, obj, objs; + if (!this.objects.length) { + return '[]'; + } + o.indent += TAB; + objs = this.filterImplicitObjects(this.objects); + if (code = Splat.compileSplattedArray(o, objs)) { + return code; + } + code = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = objs.length; _i < _len; _i++) { + obj = objs[_i]; + _results.push(obj.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (code.indexOf('\n') >= 0) { + return "[\n" + o.indent + code + "\n" + this.tab + "]"; + } else { + return "[" + code + "]"; + } + }; + + Arr.prototype.assigns = function(name) { + var obj, _i, _len, _ref2; + _ref2 = this.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj.assigns(name)) { + return true; + } + } + return false; + }; + + return Arr; + + })(Base); + + exports.Class = Class = (function(_super) { + + __extends(Class, _super); + + function Class(variable, parent, body) { + this.variable = variable; + this.parent = parent; + this.body = body != null ? body : new Block; + this.boundFuncs = []; + this.body.classBody = true; + } + + Class.prototype.children = ['variable', 'parent', 'body']; + + Class.prototype.determineName = function() { + var decl, tail; + if (!this.variable) { + return null; + } + decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value; + if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) { + throw SyntaxError("variable name may not be " + decl); + } + return decl && (decl = IDENTIFIER.test(decl) && decl); + }; + + Class.prototype.setContext = function(name) { + return this.body.traverseChildren(false, function(node) { + if (node.classBody) { + return false; + } + if (node instanceof Literal && node.value === 'this') { + return node.value = name; + } else if (node instanceof Code) { + node.klass = name; + if (node.bound) { + return node.context = name; + } + } + }); + }; + + Class.prototype.addBoundFunctions = function(o) { + var bvar, lhs, _i, _len, _ref2, _results; + if (this.boundFuncs.length) { + _ref2 = this.boundFuncs; + _results = []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + bvar = _ref2[_i]; + lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); + _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"))); + } + return _results; + } + }; + + Class.prototype.addProperties = function(node, name, o) { + var assign, base, exprs, func, props; + props = node.base.properties.slice(0); + exprs = (function() { + var _results; + _results = []; + while (assign = props.shift()) { + if (assign instanceof Assign) { + base = assign.variable.base; + delete assign.context; + func = assign.value; + if (base.value === 'constructor') { + if (this.ctor) { + throw new Error('cannot define more than one constructor in a class'); + } + if (func.bound) { + throw new Error('cannot define a constructor as a bound function'); + } + if (func instanceof Code) { + assign = this.ctor = func; + } else { + this.externalCtor = o.scope.freeVariable('class'); + assign = new Assign(new Literal(this.externalCtor), func); + } + } else { + if (assign.variable["this"]) { + func["static"] = true; + if (func.bound) { + func.context = name; + } + } else { + assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); + if (func instanceof Code && func.bound) { + this.boundFuncs.push(base); + func.bound = false; + } + } + } + } + _results.push(assign); + } + return _results; + }).call(this); + return compact(exprs); + }; + + Class.prototype.walkBody = function(name, o) { + var _this = this; + return this.traverseChildren(false, function(child) { + var exps, i, node, _i, _len, _ref2; + if (child instanceof Class) { + return false; + } + if (child instanceof Block) { + _ref2 = exps = child.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + node = _ref2[i]; + if (node instanceof Value && node.isObject(true)) { + exps[i] = _this.addProperties(node, name, o); + } + } + return child.expressions = exps = flatten(exps); + } + }); + }; + + Class.prototype.hoistDirectivePrologue = function() { + var expressions, index, node; + index = 0; + expressions = this.body.expressions; + while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) { + ++index; + } + return this.directives = expressions.splice(0, index); + }; + + Class.prototype.ensureConstructor = function(name) { + if (!this.ctor) { + this.ctor = new Code; + if (this.parent) { + this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)")); + } + if (this.externalCtor) { + this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); + } + this.ctor.body.makeReturn(); + this.body.expressions.unshift(this.ctor); + } + this.ctor.ctor = this.ctor.name = name; + this.ctor.klass = null; + return this.ctor.noReturn = true; + }; + + Class.prototype.compileNode = function(o) { + var call, decl, klass, lname, name, params, _ref2; + decl = this.determineName(); + name = decl || '_Class'; + if (name.reserved) { + name = "_" + name; + } + lname = new Literal(name); + this.hoistDirectivePrologue(); + this.setContext(name); + this.walkBody(name, o); + this.ensureConstructor(name); + this.body.spaced = true; + if (!(this.ctor instanceof Code)) { + this.body.expressions.unshift(this.ctor); + } + this.body.expressions.push(lname); + (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives); + this.addBoundFunctions(o); + call = Closure.wrap(this.body); + if (this.parent) { + this.superClass = new Literal(o.scope.freeVariable('super', false)); + this.body.expressions.unshift(new Extends(lname, this.superClass)); + call.args.push(this.parent); + params = call.variable.params || call.variable.base.params; + params.push(new Param(this.superClass)); + } + klass = new Parens(call, true); + if (this.variable) { + klass = new Assign(this.variable, klass); + } + return klass.compile(o); + }; + + return Class; + + })(Base); + + exports.Assign = Assign = (function(_super) { + + __extends(Assign, _super); + + function Assign(variable, value, context, options) { + var forbidden, name, _ref2; + this.variable = variable; + this.value = value; + this.context = context; + this.param = options && options.param; + this.subpattern = options && options.subpattern; + forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0); + if (forbidden && this.context !== 'object') { + throw SyntaxError("variable name may not be \"" + name + "\""); + } + } + + Assign.prototype.children = ['variable', 'value']; + + Assign.prototype.isStatement = function(o) { + return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0; + }; + + Assign.prototype.assigns = function(name) { + return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); + }; + + Assign.prototype.unfoldSoak = function(o) { + return unfoldSoak(o, this, 'variable'); + }; + + Assign.prototype.compileNode = function(o) { + var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5; + if (isValue = this.variable instanceof Value) { + if (this.variable.isArray() || this.variable.isObject()) { + return this.compilePatternMatch(o); + } + if (this.variable.isSplice()) { + return this.compileSplice(o); + } + if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') { + return this.compileConditional(o); + } + } + name = this.variable.compile(o, LEVEL_LIST); + if (!this.context) { + if (!(varBase = this.variable.unwrapAll()).isAssignable()) { + throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned."); + } + if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) { + if (this.param) { + o.scope.add(name, 'var'); + } else { + o.scope.find(name); + } + } + } + if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) { + if (match[1]) { + this.value.klass = match[1]; + } + this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5]; + } + val = this.value.compile(o, LEVEL_LIST); + if (this.context === 'object') { + return "" + name + ": " + val; + } + val = name + (" " + (this.context || '=') + " ") + val; + if (o.level <= LEVEL_LIST) { + return val; + } else { + return "(" + val + ")"; + } + }; + + Assign.prototype.compilePatternMatch = function(o) { + var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + top = o.level === LEVEL_TOP; + value = this.value; + objects = this.variable.base.objects; + if (!(olen = objects.length)) { + code = value.compile(o); + if (o.level >= LEVEL_OP) { + return "(" + code + ")"; + } else { + return code; + } + } + isObject = this.variable.isObject(); + if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { + if (obj instanceof Assign) { + _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value; + } else { + if (obj.base instanceof Parens) { + _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1]; + } else { + idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); + } + } + acc = IDENTIFIER.test(idx.unwrap().value || 0); + value = new Value(value); + value.properties.push(new (acc ? Access : Index)(idx)); + if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o))); + } + return new Assign(obj, value, null, { + param: this.param + }).compile(o, LEVEL_TOP); + } + vvar = value.compile(o, LEVEL_LIST); + assigns = []; + splat = false; + if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) { + assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar); + vvar = ref; + } + for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) { + obj = objects[i]; + idx = i; + if (isObject) { + if (obj instanceof Assign) { + _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value; + } else { + if (obj.base instanceof Parens) { + _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1]; + } else { + idx = obj["this"] ? obj.properties[0].name : obj; + } + } + } + if (!splat && obj instanceof Splat) { + name = obj.name.unwrap().value; + obj = obj.unwrap(); + val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i; + if (rest = olen - i - 1) { + ivar = o.scope.freeVariable('i'); + val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])"; + } else { + val += ") : []"; + } + val = new Literal(val); + splat = "" + ivar + "++"; + } else { + name = obj.unwrap().value; + if (obj instanceof Splat) { + obj = obj.name.compile(o); + throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "..."); + } + if (typeof idx === 'number') { + idx = new Literal(splat || idx); + acc = false; + } else { + acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); + } + val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]); + } + if ((name != null) && __indexOf.call(RESERVED, name) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o))); + } + assigns.push(new Assign(obj, val, null, { + param: this.param, + subpattern: true + }).compile(o, LEVEL_LIST)); + } + if (!(top || this.subpattern)) { + assigns.push(vvar); + } + code = assigns.join(', '); + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Assign.prototype.compileConditional = function(o) { + var left, right, _ref2; + _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1]; + if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { + throw new Error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been defined."); + } + if (__indexOf.call(this.context, "?") >= 0) { + o.isExistentialEquals = true; + } + return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o); + }; + + Assign.prototype.compileSplice = function(o) { + var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4; + _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive; + name = this.variable.compile(o); + _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1]; + if (to) { + if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) { + to = +to.compile(o) - +fromRef; + if (!exclusive) { + to += 1; + } + } else { + to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef; + if (!exclusive) { + to += ' + 1'; + } + } + } else { + to = "9e9"; + } + _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1]; + code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef; + if (o.level > LEVEL_TOP) { + return "(" + code + ")"; + } else { + return code; + } + }; + + return Assign; + + })(Base); + + exports.Code = Code = (function(_super) { + + __extends(Code, _super); + + function Code(params, body, tag) { + this.params = params || []; + this.body = body || new Block; + this.bound = tag === 'boundfunc'; + if (this.bound) { + this.context = '_this'; + } + } + + Code.prototype.children = ['params', 'body']; + + Code.prototype.isStatement = function() { + return !!this.ctor; + }; + + Code.prototype.jumps = NO; + + Code.prototype.compileNode = function(o) { + var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + o.scope = new Scope(o.scope, this.body, this); + o.scope.shared = del(o, 'sharedScope'); + o.indent += TAB; + delete o.bare; + delete o.isExistentialEquals; + params = []; + exprs = []; + _ref2 = this.paramNames(); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + name = _ref2[_i]; + if (!o.scope.check(name)) { + o.scope.parameter(name); + } + } + _ref3 = this.params; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + param = _ref3[_j]; + if (!param.splat) { + continue; + } + _ref4 = this.params; + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + p = _ref4[_k].name; + if (p["this"]) { + p = p.properties[0].name; + } + if (p.value) { + o.scope.add(p.value, 'var', true); + } + } + splats = new Assign(new Value(new Arr((function() { + var _l, _len3, _ref5, _results; + _ref5 = this.params; + _results = []; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + p = _ref5[_l]; + _results.push(p.asReference(o)); + } + return _results; + }).call(this))), new Value(new Literal('arguments'))); + break; + } + _ref5 = this.params; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + param = _ref5[_l]; + if (param.isComplex()) { + val = ref = param.asReference(o); + if (param.value) { + val = new Op('?', ref, param.value); + } + exprs.push(new Assign(new Value(param.name), val, '=', { + param: true + })); + } else { + ref = param; + if (param.value) { + lit = new Literal(ref.name.value + ' == null'); + val = new Assign(new Value(param.name), param.value, '='); + exprs.push(new If(lit, val)); + } + } + if (!splats) { + params.push(ref); + } + } + wasEmpty = this.body.isEmpty(); + if (splats) { + exprs.unshift(splats); + } + if (exprs.length) { + (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs); + } + for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { + p = params[i]; + o.scope.parameter(params[i] = p.compile(o)); + } + uniqs = []; + _ref7 = this.paramNames(); + for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) { + name = _ref7[_n]; + if (__indexOf.call(uniqs, name) >= 0) { + throw SyntaxError("multiple parameters named '" + name + "'"); + } + uniqs.push(name); + } + if (!(wasEmpty || this.noReturn)) { + this.body.makeReturn(); + } + if (this.bound) { + if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) { + this.bound = this.context = o.scope.parent.method.context; + } else if (!this["static"]) { + o.scope.parent.assign('_this', 'this'); + } + } + idt = o.indent; + code = 'function'; + if (this.ctor) { + code += ' ' + this.name; + } + code += '(' + params.join(', ') + ') {'; + if (!this.body.isEmpty()) { + code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab; + } + code += '}'; + if (this.ctor) { + return this.tab + code; + } + if (this.front || (o.level >= LEVEL_ACCESS)) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Code.prototype.paramNames = function() { + var names, param, _i, _len, _ref2; + names = []; + _ref2 = this.params; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + names.push.apply(names, param.names()); + } + return names; + }; + + Code.prototype.traverseChildren = function(crossScope, func) { + if (crossScope) { + return Code.__super__.traverseChildren.call(this, crossScope, func); + } + }; + + return Code; + + })(Base); + + exports.Param = Param = (function(_super) { + + __extends(Param, _super); + + function Param(name, value, splat) { + var _ref2; + this.name = name; + this.value = value; + this.splat = splat; + if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("parameter name \"" + name + "\" is not allowed"); + } + } + + Param.prototype.children = ['name', 'value']; + + Param.prototype.compile = function(o) { + return this.name.compile(o, LEVEL_LIST); + }; + + Param.prototype.asReference = function(o) { + var node; + if (this.reference) { + return this.reference; + } + node = this.name; + if (node["this"]) { + node = node.properties[0].name; + if (node.value.reserved) { + node = new Literal(o.scope.freeVariable(node.value)); + } + } else if (node.isComplex()) { + node = new Literal(o.scope.freeVariable('arg')); + } + node = new Value(node); + if (this.splat) { + node = new Splat(node); + } + return this.reference = node; + }; + + Param.prototype.isComplex = function() { + return this.name.isComplex(); + }; + + Param.prototype.names = function(name) { + var atParam, names, obj, _i, _len, _ref2; + if (name == null) { + name = this.name; + } + atParam = function(obj) { + var value; + value = obj.properties[0].name.value; + if (value.reserved) { + return []; + } else { + return [value]; + } + }; + if (name instanceof Literal) { + return [name.value]; + } + if (name instanceof Value) { + return atParam(name); + } + names = []; + _ref2 = name.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj instanceof Assign) { + names.push(obj.value.unwrap().value); + } else if (obj instanceof Splat) { + names.push(obj.name.unwrap().value); + } else if (obj instanceof Value) { + if (obj.isArray() || obj.isObject()) { + names.push.apply(names, this.names(obj.base)); + } else if (obj["this"]) { + names.push.apply(names, atParam(obj)); + } else { + names.push(obj.base.value); + } + } else { + throw SyntaxError("illegal parameter " + (obj.compile())); + } + } + return names; + }; + + return Param; + + })(Base); + + exports.Splat = Splat = (function(_super) { + + __extends(Splat, _super); + + Splat.prototype.children = ['name']; + + Splat.prototype.isAssignable = YES; + + function Splat(name) { + this.name = name.compile ? name : new Literal(name); + } + + Splat.prototype.assigns = function(name) { + return this.name.assigns(name); + }; + + Splat.prototype.compile = function(o) { + if (this.index != null) { + return this.compileParam(o); + } else { + return this.name.compile(o); + } + }; + + Splat.prototype.unwrap = function() { + return this.name; + }; + + Splat.compileSplattedArray = function(o, list, apply) { + var args, base, code, i, index, node, _i, _len; + index = -1; + while ((node = list[++index]) && !(node instanceof Splat)) { + continue; + } + if (index >= list.length) { + return ''; + } + if (list.length === 1) { + code = list[0].compile(o, LEVEL_LIST); + if (apply) { + return code; + } + return "" + (utility('slice')) + ".call(" + code + ")"; + } + args = list.slice(index); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + node = args[i]; + code = node.compile(o, LEVEL_LIST); + args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]"; + } + if (index === 0) { + return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")"); + } + base = (function() { + var _j, _len1, _ref2, _results; + _ref2 = list.slice(0, index); + _results = []; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + node = _ref2[_j]; + _results.push(node.compile(o, LEVEL_LIST)); + } + return _results; + })(); + return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")"; + }; + + return Splat; + + })(Base); + + exports.While = While = (function(_super) { + + __extends(While, _super); + + function While(condition, options) { + this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; + this.guard = options != null ? options.guard : void 0; + } + + While.prototype.children = ['condition', 'guard', 'body']; + + While.prototype.isStatement = YES; + + While.prototype.makeReturn = function(res) { + if (res) { + return While.__super__.makeReturn.apply(this, arguments); + } else { + this.returns = !this.jumps({ + loop: true + }); + return this; + } + }; + + While.prototype.addBody = function(body) { + this.body = body; + return this; + }; + + While.prototype.jumps = function() { + var expressions, node, _i, _len; + expressions = this.body.expressions; + if (!expressions.length) { + return false; + } + for (_i = 0, _len = expressions.length; _i < _len; _i++) { + node = expressions[_i]; + if (node.jumps({ + loop: true + })) { + return node; + } + } + return false; + }; + + While.prototype.compileNode = function(o) { + var body, code, rvar, set; + o.indent += TAB; + set = ''; + body = this.body; + if (body.isEmpty()) { + body = ''; + } else { + if (this.returns) { + body.makeReturn(rvar = o.scope.freeVariable('results')); + set = "" + this.tab + rvar + " = [];\n"; + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab; + } + code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}"); + if (this.returns) { + code += "\n" + this.tab + "return " + rvar + ";"; + } + return code; + }; + + return While; + + })(Base); + + exports.Op = Op = (function(_super) { + var CONVERSIONS, INVERSIONS; + + __extends(Op, _super); + + function Op(op, first, second, flip) { + if (op === 'in') { + return new In(first, second); + } + if (op === 'do') { + return this.generateDo(first); + } + if (op === 'new') { + if (first instanceof Call && !first["do"] && !first.isNew) { + return first.newInstance(); + } + if (first instanceof Code && first.bound || first["do"]) { + first = new Parens(first); + } + } + this.operator = CONVERSIONS[op] || op; + this.first = first; + this.second = second; + this.flip = !!flip; + return this; + } + + CONVERSIONS = { + '==': '===', + '!=': '!==', + 'of': 'in' + }; + + INVERSIONS = { + '!==': '===', + '===': '!==' + }; + + Op.prototype.children = ['first', 'second']; + + Op.prototype.isSimpleNumber = NO; + + Op.prototype.isUnary = function() { + return !this.second; + }; + + Op.prototype.isComplex = function() { + var _ref2; + return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex(); + }; + + Op.prototype.isChainable = function() { + var _ref2; + return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!=='; + }; + + Op.prototype.invert = function() { + var allInvertable, curr, fst, op, _ref2; + if (this.isChainable() && this.first.isChainable()) { + allInvertable = true; + curr = this; + while (curr && curr.operator) { + allInvertable && (allInvertable = curr.operator in INVERSIONS); + curr = curr.first; + } + if (!allInvertable) { + return new Parens(this).invert(); + } + curr = this; + while (curr && curr.operator) { + curr.invert = !curr.invert; + curr.operator = INVERSIONS[curr.operator]; + curr = curr.first; + } + return this; + } else if (op = INVERSIONS[this.operator]) { + this.operator = op; + if (this.first.unwrap() instanceof Op) { + this.first.invert(); + } + return this; + } else if (this.second) { + return new Parens(this).invert(); + } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { + return fst; + } else { + return new Op('!', this); + } + }; + + Op.prototype.unfoldSoak = function(o) { + var _ref2; + return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); + }; + + Op.prototype.generateDo = function(exp) { + var call, func, param, passedParams, ref, _i, _len, _ref2; + passedParams = []; + func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; + _ref2 = func.params || []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + if (param.value) { + passedParams.push(param.value); + delete param.value; + } else { + passedParams.push(param); + } + } + call = new Call(exp, passedParams); + call["do"] = true; + return call; + }; + + Op.prototype.compileNode = function(o) { + var code, isChain, _ref2, _ref3; + isChain = this.isChainable() && this.first.isChainable(); + if (!isChain) { + this.first.front = this.front; + } + if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { + throw SyntaxError('delete operand may not be argument or var'); + } + if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) { + throw SyntaxError('prefix increment/decrement may not have eval or arguments operand'); + } + if (this.isUnary()) { + return this.compileUnary(o); + } + if (isChain) { + return this.compileChain(o); + } + if (this.operator === '?') { + return this.compileExistence(o); + } + code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP); + if (o.level <= LEVEL_OP) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Op.prototype.compileChain = function(o) { + var code, fst, shared, _ref2; + _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; + fst = this.first.compile(o, LEVEL_OP); + code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP)); + return "(" + code + ")"; + }; + + Op.prototype.compileExistence = function(o) { + var fst, ref; + if (this.first.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, this.first)); + } else { + fst = this.first; + ref = fst; + } + return new If(new Existence(fst), ref, { + type: 'if' + }).addElse(this.second).compile(o); + }; + + Op.prototype.compileUnary = function(o) { + var op, parts, plusMinus; + if (o.level >= LEVEL_ACCESS) { + return (new Parens(this)).compile(o); + } + parts = [op = this.operator]; + plusMinus = op === '+' || op === '-'; + if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { + parts.push(' '); + } + if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) { + this.first = new Parens(this.first); + } + parts.push(this.first.compile(o, LEVEL_OP)); + if (this.flip) { + parts.reverse(); + } + return parts.join(''); + }; + + Op.prototype.toString = function(idt) { + return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); + }; + + return Op; + + })(Base); + + exports.In = In = (function(_super) { + + __extends(In, _super); + + function In(object, array) { + this.object = object; + this.array = array; + } + + In.prototype.children = ['object', 'array']; + + In.prototype.invert = NEGATE; + + In.prototype.compileNode = function(o) { + var hasSplat, obj, _i, _len, _ref2; + if (this.array instanceof Value && this.array.isArray()) { + _ref2 = this.array.base.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (!(obj instanceof Splat)) { + continue; + } + hasSplat = true; + break; + } + if (!hasSplat) { + return this.compileOrTest(o); + } + } + return this.compileLoopTest(o); + }; + + In.prototype.compileOrTest = function(o) { + var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3; + if (this.array.base.objects.length === 0) { + return "" + (!!this.negated); + } + _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1]; + _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; + tests = (function() { + var _i, _len, _ref4, _results; + _ref4 = this.array.base.objects; + _results = []; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + item = _ref4[i]; + _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS)); + } + return _results; + }).call(this); + tests = tests.join(cnj); + if (o.level < LEVEL_OP) { + return tests; + } else { + return "(" + tests + ")"; + } + }; + + In.prototype.compileLoopTest = function(o) { + var code, ref, sub, _ref2; + _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1]; + code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0'); + if (sub === ref) { + return code; + } + code = sub + ', ' + code; + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + In.prototype.toString = function(idt) { + return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); + }; + + return In; + + })(Base); + + exports.Try = Try = (function(_super) { + + __extends(Try, _super); + + function Try(attempt, error, recovery, ensure) { + this.attempt = attempt; + this.error = error; + this.recovery = recovery; + this.ensure = ensure; + } + + Try.prototype.children = ['attempt', 'recovery', 'ensure']; + + Try.prototype.isStatement = YES; + + Try.prototype.jumps = function(o) { + var _ref2; + return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0); + }; + + Try.prototype.makeReturn = function(res) { + if (this.attempt) { + this.attempt = this.attempt.makeReturn(res); + } + if (this.recovery) { + this.recovery = this.recovery.makeReturn(res); + } + return this; + }; + + Try.prototype.compileNode = function(o) { + var catchPart, ensurePart, errorPart, tryPart; + o.indent += TAB; + errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; + tryPart = this.attempt.compile(o, LEVEL_TOP); + catchPart = (function() { + var _ref2; + if (this.recovery) { + if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("catch variable may not be \"" + this.error.value + "\""); + } + if (!o.scope.check(this.error.value)) { + o.scope.add(this.error.value, 'param'); + } + return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"; + } else if (!(this.ensure || this.recovery)) { + return ' catch (_error) {}'; + } + }).call(this); + ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : ''; + return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart; + }; + + return Try; + + })(Base); + + exports.Throw = Throw = (function(_super) { + + __extends(Throw, _super); + + function Throw(expression) { + this.expression = expression; + } + + Throw.prototype.children = ['expression']; + + Throw.prototype.isStatement = YES; + + Throw.prototype.jumps = NO; + + Throw.prototype.makeReturn = THIS; + + Throw.prototype.compileNode = function(o) { + return this.tab + ("throw " + (this.expression.compile(o)) + ";"); + }; + + return Throw; + + })(Base); + + exports.Existence = Existence = (function(_super) { + + __extends(Existence, _super); + + function Existence(expression) { + this.expression = expression; + } + + Existence.prototype.children = ['expression']; + + Existence.prototype.invert = NEGATE; + + Existence.prototype.compileNode = function(o) { + var cmp, cnj, code, _ref2; + this.expression.front = this.front; + code = this.expression.compile(o, LEVEL_OP); + if (IDENTIFIER.test(code) && !o.scope.check(code)) { + _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1]; + code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; + } else { + code = "" + code + " " + (this.negated ? '==' : '!=') + " null"; + } + if (o.level <= LEVEL_COND) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Existence; + + })(Base); + + exports.Parens = Parens = (function(_super) { + + __extends(Parens, _super); + + function Parens(body) { + this.body = body; + } + + Parens.prototype.children = ['body']; + + Parens.prototype.unwrap = function() { + return this.body; + }; + + Parens.prototype.isComplex = function() { + return this.body.isComplex(); + }; + + Parens.prototype.compileNode = function(o) { + var bare, code, expr; + expr = this.body.unwrap(); + if (expr instanceof Value && expr.isAtomic()) { + expr.front = this.front; + return expr.compile(o); + } + code = expr.compile(o, LEVEL_PAREN); + bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns)); + if (bare) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Parens; + + })(Base); + + exports.For = For = (function(_super) { + + __extends(For, _super); + + function For(body, source) { + var _ref2; + this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; + this.body = Block.wrap([body]); + this.own = !!source.own; + this.object = !!source.object; + if (this.object) { + _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1]; + } + if (this.index instanceof Value) { + throw SyntaxError('index cannot be a pattern matching expression'); + } + this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; + this.pattern = this.name instanceof Value; + if (this.range && this.index) { + throw SyntaxError('indexes do not apply to range loops'); + } + if (this.range && this.pattern) { + throw SyntaxError('cannot pattern match over range loops'); + } + this.returns = false; + } + + For.prototype.children = ['body', 'source', 'guard', 'step']; + + For.prototype.compileNode = function(o) { + var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2; + body = Block.wrap([this.body]); + lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0; + if (lastJumps && lastJumps instanceof Return) { + this.returns = false; + } + source = this.range ? this.source.base : this.source; + scope = o.scope; + name = this.name && this.name.compile(o, LEVEL_LIST); + index = this.index && this.index.compile(o, LEVEL_LIST); + if (name && !this.pattern) { + scope.find(name); + } + if (index) { + scope.find(index); + } + if (this.returns) { + rvar = scope.freeVariable('results'); + } + ivar = (this.object && index) || scope.freeVariable('i'); + kvar = (this.range && name) || index || ivar; + kvarAssign = kvar !== ivar ? "" + kvar + " = " : ""; + if (this.step && !this.range) { + stepvar = scope.freeVariable("step"); + } + if (this.pattern) { + name = ivar; + } + varPart = ''; + guardPart = ''; + defPart = ''; + idt1 = this.tab + TAB; + if (this.range) { + forPart = source.compile(merge(o, { + index: ivar, + name: name, + step: this.step + })); + } else { + svar = this.source.compile(o, LEVEL_LIST); + if ((name || this.own) && !IDENTIFIER.test(svar)) { + defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n"; + svar = ref; + } + if (name && !this.pattern) { + namePart = "" + name + " = " + svar + "[" + kvar + "]"; + } + if (!this.object) { + lvar = scope.freeVariable('len'); + forVarPart = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; + if (this.step) { + forVarPart += ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)); + } + stepPart = "" + kvarAssign + (this.step ? "" + ivar + " += " + stepvar : (kvar !== ivar ? "++" + ivar : "" + ivar + "++")); + forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart; + } + } + if (this.returns) { + resultPart = "" + this.tab + rvar + " = [];\n"; + returnResult = "\n" + this.tab + "return " + rvar + ";"; + body.makeReturn(rvar); + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + if (this.pattern) { + body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]"))); + } + defPart += this.pluckDirectCall(o, body); + if (namePart) { + varPart = "\n" + idt1 + namePart + ";"; + } + if (this.object) { + forPart = "" + kvar + " in " + svar; + if (this.own) { + guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;"; + } + } + body = body.compile(merge(o, { + indent: idt1 + }), LEVEL_TOP); + if (body) { + body = '\n' + body + '\n'; + } + return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || ''); + }; + + For.prototype.pluckDirectCall = function(o, body) { + var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + defs = ''; + _ref2 = body.expressions; + for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) { + expr = _ref2[idx]; + expr = expr.unwrapAll(); + if (!(expr instanceof Call)) { + continue; + } + val = expr.variable.unwrapAll(); + if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) { + continue; + } + fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val; + ref = new Literal(o.scope.freeVariable('fn')); + base = new Value(ref); + if (val.base) { + _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1]; + } + body.expressions[idx] = new Call(base, expr.args); + defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'; + } + return defs; + }; + + return For; + + })(While); + + exports.Switch = Switch = (function(_super) { + + __extends(Switch, _super); + + function Switch(subject, cases, otherwise) { + this.subject = subject; + this.cases = cases; + this.otherwise = otherwise; + } + + Switch.prototype.children = ['subject', 'cases', 'otherwise']; + + Switch.prototype.isStatement = YES; + + Switch.prototype.jumps = function(o) { + var block, conds, _i, _len, _ref2, _ref3, _ref4; + if (o == null) { + o = { + block: true + }; + } + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1]; + if (block.jumps(o)) { + return block; + } + } + return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0; + }; + + Switch.prototype.makeReturn = function(res) { + var pair, _i, _len, _ref2, _ref3; + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + pair = _ref2[_i]; + pair[1].makeReturn(res); + } + if (res) { + this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); + } + if ((_ref3 = this.otherwise) != null) { + _ref3.makeReturn(res); + } + return this; + }; + + Switch.prototype.compileNode = function(o) { + var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5; + idt1 = o.indent + TAB; + idt2 = o.indent = idt1 + TAB; + code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n"); + _ref3 = this.cases; + for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { + _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1]; + _ref5 = flatten([conditions]); + for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) { + cond = _ref5[_j]; + if (!this.subject) { + cond = cond.invert(); + } + code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n"); + } + if (body = block.compile(o, LEVEL_TOP)) { + code += body + '\n'; + } + if (i === this.cases.length - 1 && !this.otherwise) { + break; + } + expr = this.lastNonComment(block.expressions); + if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) { + continue; + } + code += idt2 + 'break;\n'; + } + if (this.otherwise && this.otherwise.expressions.length) { + code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n"); + } + return code + this.tab + '}'; + }; + + return Switch; + + })(Base); + + exports.If = If = (function(_super) { + + __extends(If, _super); + + function If(condition, body, options) { + this.body = body; + if (options == null) { + options = {}; + } + this.condition = options.type === 'unless' ? condition.invert() : condition; + this.elseBody = null; + this.isChain = false; + this.soak = options.soak; + } + + If.prototype.children = ['condition', 'body', 'elseBody']; + + If.prototype.bodyNode = function() { + var _ref2; + return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.elseBodyNode = function() { + var _ref2; + return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.addElse = function(elseBody) { + if (this.isChain) { + this.elseBodyNode().addElse(elseBody); + } else { + this.isChain = elseBody instanceof If; + this.elseBody = this.ensureBlock(elseBody); + } + return this; + }; + + If.prototype.isStatement = function(o) { + var _ref2; + return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0); + }; + + If.prototype.jumps = function(o) { + var _ref2; + return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0); + }; + + If.prototype.compileNode = function(o) { + if (this.isStatement(o)) { + return this.compileStatement(o); + } else { + return this.compileExpression(o); + } + }; + + If.prototype.makeReturn = function(res) { + if (res) { + this.elseBody || (this.elseBody = new Block([new Literal('void 0')])); + } + this.body && (this.body = new Block([this.body.makeReturn(res)])); + this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)])); + return this; + }; + + If.prototype.ensureBlock = function(node) { + if (node instanceof Block) { + return node; + } else { + return new Block([node]); + } + }; + + If.prototype.compileStatement = function(o) { + var body, child, cond, exeq, ifPart; + child = del(o, 'chainChild'); + exeq = del(o, 'isExistentialEquals'); + if (exeq) { + return new If(this.condition.invert(), this.elseBodyNode(), { + type: 'if' + }).compile(o); + } + cond = this.condition.compile(o, LEVEL_PAREN); + o.indent += TAB; + body = this.ensureBlock(this.body); + ifPart = "if (" + cond + ") {\n" + (body.compile(o)) + "\n" + this.tab + "}"; + if (!child) { + ifPart = this.tab + ifPart; + } + if (!this.elseBody) { + return ifPart; + } + return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"); + }; + + If.prototype.compileExpression = function(o) { + var alt, body, code, cond; + cond = this.condition.compile(o, LEVEL_COND); + body = this.bodyNode().compile(o, LEVEL_LIST); + alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0'; + code = "" + cond + " ? " + body + " : " + alt; + if (o.level >= LEVEL_COND) { + return "(" + code + ")"; + } else { + return code; + } + }; + + If.prototype.unfoldSoak = function() { + return this.soak && this; + }; + + return If; + + })(Base); + + Closure = { + wrap: function(expressions, statement, noReturn) { + var args, call, func, mentionsArgs, meth; + if (expressions.jumps()) { + return expressions; + } + func = new Code([], Block.wrap([expressions])); + args = []; + if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) { + meth = new Literal(mentionsArgs ? 'apply' : 'call'); + args = [new Literal('this')]; + if (mentionsArgs) { + args.push(new Literal('arguments')); + } + func = new Value(func, [new Access(meth)]); + } + func.noReturn = noReturn; + call = new Call(func, args); + if (statement) { + return Block.wrap([call]); + } else { + return call; + } + }, + literalArgs: function(node) { + return node instanceof Literal && node.value === 'arguments' && !node.asKey; + }, + literalThis: function(node) { + return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); + } + }; + + unfoldSoak = function(o, parent, name) { + var ifn; + if (!(ifn = parent[name].unfoldSoak(o))) { + return; + } + parent[name] = ifn.body; + ifn.body = new Value(parent); + return ifn; + }; + + UTILITIES = { + "extends": function() { + return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"; + }, + bind: function() { + return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }'; + }, + indexOf: function() { + return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; + }, + hasProp: function() { + return '{}.hasOwnProperty'; + }, + slice: function() { + return '[].slice'; + } + }; + + LEVEL_TOP = 1; + + LEVEL_PAREN = 2; + + LEVEL_LIST = 3; + + LEVEL_COND = 4; + + LEVEL_OP = 5; + + LEVEL_ACCESS = 6; + + TAB = ' '; + + IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"; + + IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$"); + + SIMPLENUM = /^[+-]?\d+$/; + + METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$"); + + IS_STRING = /^['"]/; + + utility = function(name) { + var ref; + ref = "__" + name; + Scope.root.assign(ref, UTILITIES[name]()); + return ref; + }; + + multident = function(code, tab) { + code = code.replace(/\n/g, '$&' + tab); + return code.replace(/\s+$/, ''); + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/optparse.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/optparse.js new file mode 100644 index 0000000..d7fda40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/optparse.js @@ -0,0 +1,138 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; + + exports.OptionParser = OptionParser = (function() { + + function OptionParser(rules, banner) { + this.banner = banner; + this.rules = buildRules(rules); + } + + OptionParser.prototype.parse = function(args) { + var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref; + options = { + "arguments": [] + }; + skippingArgument = false; + originalArgs = args; + args = normalizeArguments(args); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + arg = args[i]; + if (skippingArgument) { + skippingArgument = false; + continue; + } + if (arg === '--') { + pos = originalArgs.indexOf('--'); + options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); + break; + } + isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); + seenNonOptionArg = options["arguments"].length > 0; + if (!seenNonOptionArg) { + matchedRule = false; + _ref = this.rules; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + rule = _ref[_j]; + if (rule.shortFlag === arg || rule.longFlag === arg) { + value = true; + if (rule.hasArgument) { + skippingArgument = true; + value = args[i + 1]; + } + options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; + matchedRule = true; + break; + } + } + if (isOption && !matchedRule) { + throw new Error("unrecognized option: " + arg); + } + } + if (seenNonOptionArg || !isOption) { + options["arguments"].push(arg); + } + } + return options; + }; + + OptionParser.prototype.help = function() { + var letPart, lines, rule, spaces, _i, _len, _ref; + lines = []; + if (this.banner) { + lines.unshift("" + this.banner + "\n"); + } + _ref = this.rules; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + spaces = 15 - rule.longFlag.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; + lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); + } + return "\n" + (lines.join('\n')) + "\n"; + }; + + return OptionParser; + + })(); + + LONG_FLAG = /^(--\w[\w\-]*)/; + + SHORT_FLAG = /^(-\w)$/; + + MULTI_FLAG = /^-(\w{2,})/; + + OPTIONAL = /\[(\w+(\*?))\]/; + + buildRules = function(rules) { + var tuple, _i, _len, _results; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + tuple = rules[_i]; + if (tuple.length < 3) { + tuple.unshift(null); + } + _results.push(buildRule.apply(null, tuple)); + } + return _results; + }; + + buildRule = function(shortFlag, longFlag, description, options) { + var match; + if (options == null) { + options = {}; + } + match = longFlag.match(OPTIONAL); + longFlag = longFlag.match(LONG_FLAG)[1]; + return { + name: longFlag.substr(2), + shortFlag: shortFlag, + longFlag: longFlag, + description: description, + hasArgument: !!(match && match[1]), + isList: !!(match && match[2]) + }; + }; + + normalizeArguments = function(args) { + var arg, l, match, result, _i, _j, _len, _len1, _ref; + args = args.slice(0); + result = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + if (match = arg.match(MULTI_FLAG)) { + _ref = match[1].split(''); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + l = _ref[_j]; + result.push('-' + l); + } + } else { + result.push(arg); + } + } + return result; + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/parser.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/parser.js new file mode 100755 index 0000000..f049903 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/parser.js @@ -0,0 +1,683 @@ +/* Jison generated parser */ +var parser = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"UNDEFINED":36,"NULL":37,"BOOL":38,"Assignable":39,"=":40,"AssignObj":41,"ObjAssignable":42,":":43,"ThisProperty":44,"RETURN":45,"HERECOMMENT":46,"PARAM_START":47,"ParamList":48,"PARAM_END":49,"FuncGlyph":50,"->":51,"=>":52,"OptComma":53,",":54,"Param":55,"ParamVar":56,"...":57,"Array":58,"Object":59,"Splat":60,"SimpleAssignable":61,"Accessor":62,"Parenthetical":63,"Range":64,"This":65,".":66,"?.":67,"::":68,"Index":69,"INDEX_START":70,"IndexValue":71,"INDEX_END":72,"INDEX_SOAK":73,"Slice":74,"{":75,"AssignList":76,"}":77,"CLASS":78,"EXTENDS":79,"OptFuncExist":80,"Arguments":81,"SUPER":82,"FUNC_EXIST":83,"CALL_START":84,"CALL_END":85,"ArgList":86,"THIS":87,"@":88,"[":89,"]":90,"RangeDots":91,"..":92,"Arg":93,"SimpleArgs":94,"TRY":95,"Catch":96,"FINALLY":97,"CATCH":98,"THROW":99,"(":100,")":101,"WhileSource":102,"WHILE":103,"WHEN":104,"UNTIL":105,"Loop":106,"LOOP":107,"ForBody":108,"FOR":109,"ForStart":110,"ForSource":111,"ForVariables":112,"OWN":113,"ForValue":114,"FORIN":115,"FOROF":116,"BY":117,"SWITCH":118,"Whens":119,"ELSE":120,"When":121,"LEADING_WHEN":122,"IfBlock":123,"IF":124,"POST_IF":125,"UNARY":126,"-":127,"+":128,"--":129,"++":130,"?":131,"MATH":132,"SHIFT":133,"COMPARE":134,"LOGIC":135,"RELATION":136,"COMPOUND_ASSIGN":137,"$accept":0,"$end":1}, +terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"}, +productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1:return this.$ = new yy.Block; +break; +case 2:return this.$ = $$[$0]; +break; +case 3:return this.$ = $$[$0-1]; +break; +case 4:this.$ = yy.Block.wrap([$$[$0]]); +break; +case 5:this.$ = $$[$0-2].push($$[$0]); +break; +case 6:this.$ = $$[$0-1]; +break; +case 7:this.$ = $$[$0]; +break; +case 8:this.$ = $$[$0]; +break; +case 9:this.$ = $$[$0]; +break; +case 10:this.$ = $$[$0]; +break; +case 11:this.$ = new yy.Literal($$[$0]); +break; +case 12:this.$ = $$[$0]; +break; +case 13:this.$ = $$[$0]; +break; +case 14:this.$ = $$[$0]; +break; +case 15:this.$ = $$[$0]; +break; +case 16:this.$ = $$[$0]; +break; +case 17:this.$ = $$[$0]; +break; +case 18:this.$ = $$[$0]; +break; +case 19:this.$ = $$[$0]; +break; +case 20:this.$ = $$[$0]; +break; +case 21:this.$ = $$[$0]; +break; +case 22:this.$ = $$[$0]; +break; +case 23:this.$ = $$[$0]; +break; +case 24:this.$ = new yy.Block; +break; +case 25:this.$ = $$[$0-1]; +break; +case 26:this.$ = new yy.Literal($$[$0]); +break; +case 27:this.$ = new yy.Literal($$[$0]); +break; +case 28:this.$ = new yy.Literal($$[$0]); +break; +case 29:this.$ = $$[$0]; +break; +case 30:this.$ = new yy.Literal($$[$0]); +break; +case 31:this.$ = new yy.Literal($$[$0]); +break; +case 32:this.$ = new yy.Literal($$[$0]); +break; +case 33:this.$ = new yy.Undefined; +break; +case 34:this.$ = new yy.Null; +break; +case 35:this.$ = new yy.Bool($$[$0]); +break; +case 36:this.$ = new yy.Assign($$[$0-2], $$[$0]); +break; +case 37:this.$ = new yy.Assign($$[$0-3], $$[$0]); +break; +case 38:this.$ = new yy.Assign($$[$0-4], $$[$0-1]); +break; +case 39:this.$ = new yy.Value($$[$0]); +break; +case 40:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object'); +break; +case 41:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object'); +break; +case 42:this.$ = $$[$0]; +break; +case 43:this.$ = $$[$0]; +break; +case 44:this.$ = $$[$0]; +break; +case 45:this.$ = $$[$0]; +break; +case 46:this.$ = new yy.Return($$[$0]); +break; +case 47:this.$ = new yy.Return; +break; +case 48:this.$ = new yy.Comment($$[$0]); +break; +case 49:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]); +break; +case 50:this.$ = new yy.Code([], $$[$0], $$[$0-1]); +break; +case 51:this.$ = 'func'; +break; +case 52:this.$ = 'boundfunc'; +break; +case 53:this.$ = $$[$0]; +break; +case 54:this.$ = $$[$0]; +break; +case 55:this.$ = []; +break; +case 56:this.$ = [$$[$0]]; +break; +case 57:this.$ = $$[$0-2].concat($$[$0]); +break; +case 58:this.$ = $$[$0-3].concat($$[$0]); +break; +case 59:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 60:this.$ = new yy.Param($$[$0]); +break; +case 61:this.$ = new yy.Param($$[$0-1], null, true); +break; +case 62:this.$ = new yy.Param($$[$0-2], $$[$0]); +break; +case 63:this.$ = $$[$0]; +break; +case 64:this.$ = $$[$0]; +break; +case 65:this.$ = $$[$0]; +break; +case 66:this.$ = $$[$0]; +break; +case 67:this.$ = new yy.Splat($$[$0-1]); +break; +case 68:this.$ = new yy.Value($$[$0]); +break; +case 69:this.$ = $$[$0-1].add($$[$0]); +break; +case 70:this.$ = new yy.Value($$[$0-1], [].concat($$[$0])); +break; +case 71:this.$ = $$[$0]; +break; +case 72:this.$ = $$[$0]; +break; +case 73:this.$ = new yy.Value($$[$0]); +break; +case 74:this.$ = new yy.Value($$[$0]); +break; +case 75:this.$ = $$[$0]; +break; +case 76:this.$ = new yy.Value($$[$0]); +break; +case 77:this.$ = new yy.Value($$[$0]); +break; +case 78:this.$ = new yy.Value($$[$0]); +break; +case 79:this.$ = $$[$0]; +break; +case 80:this.$ = new yy.Access($$[$0]); +break; +case 81:this.$ = new yy.Access($$[$0], 'soak'); +break; +case 82:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])]; +break; +case 83:this.$ = new yy.Access(new yy.Literal('prototype')); +break; +case 84:this.$ = $$[$0]; +break; +case 85:this.$ = $$[$0-1]; +break; +case 86:this.$ = yy.extend($$[$0], { + soak: true + }); +break; +case 87:this.$ = new yy.Index($$[$0]); +break; +case 88:this.$ = new yy.Slice($$[$0]); +break; +case 89:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated); +break; +case 90:this.$ = []; +break; +case 91:this.$ = [$$[$0]]; +break; +case 92:this.$ = $$[$0-2].concat($$[$0]); +break; +case 93:this.$ = $$[$0-3].concat($$[$0]); +break; +case 94:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 95:this.$ = new yy.Class; +break; +case 96:this.$ = new yy.Class(null, null, $$[$0]); +break; +case 97:this.$ = new yy.Class(null, $$[$0]); +break; +case 98:this.$ = new yy.Class(null, $$[$0-1], $$[$0]); +break; +case 99:this.$ = new yy.Class($$[$0]); +break; +case 100:this.$ = new yy.Class($$[$0-1], null, $$[$0]); +break; +case 101:this.$ = new yy.Class($$[$0-2], $$[$0]); +break; +case 102:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]); +break; +case 103:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 104:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 105:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]); +break; +case 106:this.$ = new yy.Call('super', $$[$0]); +break; +case 107:this.$ = false; +break; +case 108:this.$ = true; +break; +case 109:this.$ = []; +break; +case 110:this.$ = $$[$0-2]; +break; +case 111:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 112:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 113:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this'); +break; +case 114:this.$ = new yy.Arr([]); +break; +case 115:this.$ = new yy.Arr($$[$0-2]); +break; +case 116:this.$ = 'inclusive'; +break; +case 117:this.$ = 'exclusive'; +break; +case 118:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]); +break; +case 119:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]); +break; +case 120:this.$ = new yy.Range($$[$0-1], null, $$[$0]); +break; +case 121:this.$ = new yy.Range(null, $$[$0], $$[$0-1]); +break; +case 122:this.$ = new yy.Range(null, null, $$[$0]); +break; +case 123:this.$ = [$$[$0]]; +break; +case 124:this.$ = $$[$0-2].concat($$[$0]); +break; +case 125:this.$ = $$[$0-3].concat($$[$0]); +break; +case 126:this.$ = $$[$0-2]; +break; +case 127:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 128:this.$ = $$[$0]; +break; +case 129:this.$ = $$[$0]; +break; +case 130:this.$ = $$[$0]; +break; +case 131:this.$ = [].concat($$[$0-2], $$[$0]); +break; +case 132:this.$ = new yy.Try($$[$0]); +break; +case 133:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]); +break; +case 134:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]); +break; +case 135:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]); +break; +case 136:this.$ = [$$[$0-1], $$[$0]]; +break; +case 137:this.$ = new yy.Throw($$[$0]); +break; +case 138:this.$ = new yy.Parens($$[$0-1]); +break; +case 139:this.$ = new yy.Parens($$[$0-2]); +break; +case 140:this.$ = new yy.While($$[$0]); +break; +case 141:this.$ = new yy.While($$[$0-2], { + guard: $$[$0] + }); +break; +case 142:this.$ = new yy.While($$[$0], { + invert: true + }); +break; +case 143:this.$ = new yy.While($$[$0-2], { + invert: true, + guard: $$[$0] + }); +break; +case 144:this.$ = $$[$0-1].addBody($$[$0]); +break; +case 145:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 146:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 147:this.$ = $$[$0]; +break; +case 148:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]); +break; +case 149:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]])); +break; +case 150:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 151:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 152:this.$ = new yy.For($$[$0], $$[$0-1]); +break; +case 153:this.$ = { + source: new yy.Value($$[$0]) + }; +break; +case 154:this.$ = (function () { + $$[$0].own = $$[$0-1].own; + $$[$0].name = $$[$0-1][0]; + $$[$0].index = $$[$0-1][1]; + return $$[$0]; + }()); +break; +case 155:this.$ = $$[$0]; +break; +case 156:this.$ = (function () { + $$[$0].own = true; + return $$[$0]; + }()); +break; +case 157:this.$ = $$[$0]; +break; +case 158:this.$ = $$[$0]; +break; +case 159:this.$ = new yy.Value($$[$0]); +break; +case 160:this.$ = new yy.Value($$[$0]); +break; +case 161:this.$ = [$$[$0]]; +break; +case 162:this.$ = [$$[$0-2], $$[$0]]; +break; +case 163:this.$ = { + source: $$[$0] + }; +break; +case 164:this.$ = { + source: $$[$0], + object: true + }; +break; +case 165:this.$ = { + source: $$[$0-2], + guard: $$[$0] + }; +break; +case 166:this.$ = { + source: $$[$0-2], + guard: $$[$0], + object: true + }; +break; +case 167:this.$ = { + source: $$[$0-2], + step: $$[$0] + }; +break; +case 168:this.$ = { + source: $$[$0-4], + guard: $$[$0-2], + step: $$[$0] + }; +break; +case 169:this.$ = { + source: $$[$0-4], + step: $$[$0-2], + guard: $$[$0] + }; +break; +case 170:this.$ = new yy.Switch($$[$0-3], $$[$0-1]); +break; +case 171:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]); +break; +case 172:this.$ = new yy.Switch(null, $$[$0-1]); +break; +case 173:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]); +break; +case 174:this.$ = $$[$0]; +break; +case 175:this.$ = $$[$0-1].concat($$[$0]); +break; +case 176:this.$ = [[$$[$0-1], $$[$0]]]; +break; +case 177:this.$ = [[$$[$0-2], $$[$0-1]]]; +break; +case 178:this.$ = new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + }); +break; +case 179:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + })); +break; +case 180:this.$ = $$[$0]; +break; +case 181:this.$ = $$[$0-2].addElse($$[$0]); +break; +case 182:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 183:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 184:this.$ = new yy.Op($$[$0-1], $$[$0]); +break; +case 185:this.$ = new yy.Op('-', $$[$0]); +break; +case 186:this.$ = new yy.Op('+', $$[$0]); +break; +case 187:this.$ = new yy.Op('--', $$[$0]); +break; +case 188:this.$ = new yy.Op('++', $$[$0]); +break; +case 189:this.$ = new yy.Op('--', $$[$0-1], null, true); +break; +case 190:this.$ = new yy.Op('++', $$[$0-1], null, true); +break; +case 191:this.$ = new yy.Existence($$[$0-1]); +break; +case 192:this.$ = new yy.Op('+', $$[$0-2], $$[$0]); +break; +case 193:this.$ = new yy.Op('-', $$[$0-2], $$[$0]); +break; +case 194:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 195:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 196:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 197:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 198:this.$ = (function () { + if ($$[$0-1].charAt(0) === '!') { + return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); + } else { + return new yy.Op($$[$0-1], $$[$0-2], $$[$0]); + } + }()); +break; +case 199:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]); +break; +case 200:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]); +break; +case 201:this.$ = new yy.Extends($$[$0-2], $$[$0]); +break; +} +}, +table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}], +defaultActions: {60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}}; +undefined +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = parser; +exports.parse = function () { return parser.parse.apply(parser, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + if (typeof process !== 'undefined') { + var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); + } else { + var cwd = require("file").path(require("file").cwd()); + var source = cwd.join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +} \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/repl.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/repl.js new file mode 100644 index 0000000..b4a4765 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/repl.js @@ -0,0 +1,261 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, REPL_PROMPT_MULTILINE, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, multilineMode, pipedInput, readline, repl, run, stdin, stdout; + + stdin = process.openStdin(); + + stdout = process.stdout; + + CoffeeScript = require('./coffee-script'); + + readline = require('readline'); + + inspect = require('util').inspect; + + Script = require('vm').Script; + + Module = require('module'); + + REPL_PROMPT = 'coffee> '; + + REPL_PROMPT_MULTILINE = '------> '; + + REPL_PROMPT_CONTINUATION = '......> '; + + enableColours = false; + + if (process.platform !== 'win32') { + enableColours = !process.env.NODE_DISABLE_COLORS; + } + + error = function(err) { + return stdout.write((err.stack || err.toString()) + '\n'); + }; + + ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/; + + SIMPLEVAR = /(\w+)$/i; + + autocomplete = function(text) { + return completeAttribute(text) || completeVariable(text) || [[], text]; + }; + + completeAttribute = function(text) { + var all, completions, key, match, obj, possibilities, prefix, val; + if (match = text.match(ACCESSOR)) { + all = match[0], obj = match[1], prefix = match[2]; + try { + val = Script.runInThisContext(obj); + } catch (error) { + return; + } + val = Object(val); + possibilities = Object.getOwnPropertyNames(val); + for (key in val) { + if (~possibilities.indexOf(val)) { + possibilities.push(key); + } + } + completions = getCompletions(prefix, possibilities); + return [completions, prefix]; + } + }; + + completeVariable = function(text) { + var completions, free, keywords, possibilities, r, vars, _ref; + free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0; + if (text === "") { + free = ""; + } + if (free != null) { + vars = Script.runInThisContext('Object.getOwnPropertyNames(Object(this))'); + keywords = (function() { + var _i, _len, _ref1, _results; + _ref1 = CoffeeScript.RESERVED; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + r = _ref1[_i]; + if (r.slice(0, 2) !== '__') { + _results.push(r); + } + } + return _results; + })(); + possibilities = vars.concat(keywords); + completions = getCompletions(free, possibilities); + return [completions, free]; + } + }; + + getCompletions = function(prefix, candidates) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + el = candidates[_i]; + if (el.indexOf(prefix) === 0) { + _results.push(el); + } + } + return _results; + }; + + process.on('uncaughtException', error); + + backlog = ''; + + run = function(buffer) { + var code, returnValue, _; + buffer = buffer.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3"); + buffer = buffer.replace(/[\r\n]+$/, ""); + if (multilineMode) { + backlog += "" + buffer + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + if (!buffer.toString().trim() && !backlog) { + repl.prompt(); + return; + } + code = backlog += buffer; + if (code[code.length - 1] === '\\') { + backlog = "" + backlog.slice(0, -1) + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + repl.setPrompt(REPL_PROMPT); + backlog = ''; + try { + _ = global._; + returnValue = CoffeeScript["eval"]("_=(" + code + "\n)", { + filename: 'repl', + modulename: 'repl' + }); + if (returnValue === void 0) { + global._ = _; + } + repl.output.write("" + (inspect(returnValue, false, 2, enableColours)) + "\n"); + } catch (err) { + error(err); + } + return repl.prompt(); + }; + + if (stdin.readable) { + pipedInput = ''; + repl = { + prompt: function() { + return stdout.write(this._prompt); + }, + setPrompt: function(p) { + return this._prompt = p; + }, + input: stdin, + output: stdout, + on: function() {} + }; + stdin.on('data', function(chunk) { + var line, lines, _i, _len, _ref; + pipedInput += chunk; + if (!/\n/.test(pipedInput)) { + return; + } + lines = pipedInput.split("\n"); + pipedInput = lines[lines.length - 1]; + _ref = lines.slice(0, -1); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + }); + stdin.on('end', function() { + var line, _i, _len, _ref; + _ref = pipedInput.trim().split("\n"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + stdout.write('\n'); + return process.exit(0); + }); + } else { + if (readline.createInterface.length < 3) { + repl = readline.createInterface(stdin, autocomplete); + stdin.on('data', function(buffer) { + return repl.write(buffer); + }); + } else { + repl = readline.createInterface(stdin, stdout, autocomplete); + } + } + + multilineMode = false; + + repl.input.on('keypress', function(char, key) { + var cursorPos, newPrompt; + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) { + return; + } + cursorPos = repl.cursor; + repl.output.cursorTo(0); + repl.output.clearLine(1); + multilineMode = !multilineMode; + if (!multilineMode && backlog) { + repl._line(); + } + backlog = ''; + repl.setPrompt((newPrompt = multilineMode ? REPL_PROMPT_MULTILINE : REPL_PROMPT)); + repl.prompt(); + return repl.output.cursorTo(newPrompt.length + (repl.cursor = cursorPos)); + }); + + repl.input.on('keypress', function(char, key) { + if (!(multilineMode && repl.line)) { + return; + } + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'd')) { + return; + } + multilineMode = false; + return repl._line(); + }); + + repl.on('attemptClose', function() { + if (multilineMode) { + multilineMode = false; + repl.output.cursorTo(0); + repl.output.clearLine(1); + repl._onLine(repl.line); + return; + } + if (backlog) { + backlog = ''; + repl.output.write('\n'); + repl.setPrompt(REPL_PROMPT); + return repl.prompt(); + } else { + return repl.close(); + } + }); + + repl.on('close', function() { + repl.output.write('\n'); + return repl.input.destroy(); + }); + + repl.on('line', run); + + repl.setPrompt(REPL_PROMPT); + + repl.prompt(); + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/rewriter.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/rewriter.js new file mode 100644 index 0000000..d26133c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/rewriter.js @@ -0,0 +1,349 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __slice = [].slice; + + exports.Rewriter = (function() { + + function Rewriter() {} + + Rewriter.prototype.rewrite = function(tokens) { + this.tokens = tokens; + this.removeLeadingNewlines(); + this.removeMidExpressionNewlines(); + this.closeOpenCalls(); + this.closeOpenIndexes(); + this.addImplicitIndentation(); + this.tagPostfixConditionals(); + this.addImplicitBraces(); + this.addImplicitParentheses(); + return this.tokens; + }; + + Rewriter.prototype.scanTokens = function(block) { + var i, token, tokens; + tokens = this.tokens; + i = 0; + while (token = tokens[i]) { + i += block.call(this, token, i, tokens); + } + return true; + }; + + Rewriter.prototype.detectEnd = function(i, condition, action) { + var levels, token, tokens, _ref, _ref1; + tokens = this.tokens; + levels = 0; + while (token = tokens[i]) { + if (levels === 0 && condition.call(this, token, i)) { + return action.call(this, token, i); + } + if (!token || levels < 0) { + return action.call(this, token, i - 1); + } + if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) { + levels += 1; + } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) { + levels -= 1; + } + i += 1; + } + return i - 1; + }; + + Rewriter.prototype.removeLeadingNewlines = function() { + var i, tag, _i, _len, _ref; + _ref = this.tokens; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + tag = _ref[i][0]; + if (tag !== 'TERMINATOR') { + break; + } + } + if (i) { + return this.tokens.splice(0, i); + } + }; + + Rewriter.prototype.removeMidExpressionNewlines = function() { + return this.scanTokens(function(token, i, tokens) { + var _ref; + if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) { + return 1; + } + tokens.splice(i, 1); + return 0; + }); + }; + + Rewriter.prototype.closeOpenCalls = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')'; + }; + action = function(token, i) { + return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'CALL_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.closeOpenIndexes = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === ']' || _ref === 'INDEX_END'; + }; + action = function(token, i) { + return token[0] = 'INDEX_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'INDEX_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.addImplicitBraces = function() { + var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine; + stack = []; + start = null; + startsLine = null; + sameLine = true; + startIndent = 0; + startIndex = 0; + condition = function(token, i) { + var one, tag, three, two, _ref, _ref1; + _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2]; + if ('HERECOMMENT' === (one != null ? one[0] : void 0)) { + return false; + } + tag = token[0]; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + sameLine = false; + } + return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT')); + }; + action = function(token, i) { + var tok; + tok = this.generate('}', '}', token[2]); + return this.tokens.splice(i, 0, tok); + }; + return this.scanTokens(function(token, i, tokens) { + var ago, idx, prevTag, tag, tok, value, _ref, _ref1; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { + stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]); + return 1; + } + if (__indexOf.call(EXPRESSION_END, tag) >= 0) { + start = stack.pop(); + return 1; + } + if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) { + return 1; + } + sameLine = true; + startIndex = i + 1; + stack.push(['{']); + idx = ago === '@' ? i - 2 : i - 1; + while (this.tag(idx - 2) === 'HERECOMMENT') { + idx -= 2; + } + prevTag = this.tag(idx - 1); + startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0); + value = new String('{'); + value.generated = true; + tok = this.generate('{', value, token[2]); + tokens.splice(idx, 0, tok); + this.detectEnd(i + 2, condition, action); + return 2; + }); + }; + + Rewriter.prototype.addImplicitParentheses = function() { + var action, condition, noCall, seenControl, seenSingle; + noCall = seenSingle = seenControl = false; + condition = function(token, i) { + var post, tag, _ref, _ref1; + tag = token[0]; + if (!seenSingle && token.fromThen) { + return true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') { + seenSingle = true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') { + seenControl = true; + } + if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') { + return true; + } + return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{'))); + }; + action = function(token, i) { + return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2])); + }; + return this.scanTokens(function(token, i, tokens) { + var callObject, current, next, prev, tag, _ref, _ref1, _ref2; + tag = token[0]; + if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') { + noCall = true; + } + _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2]; + callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0); + seenSingle = false; + seenControl = false; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + noCall = false; + } + if (prev && !prev.spaced && tag === '?') { + token.call = true; + } + if (token.fromThen) { + return 1; + } + if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) { + return 1; + } + tokens.splice(i, 0, this.generate('CALL_START', '(', token[2])); + this.detectEnd(i + 1, condition, action); + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + return 2; + }); + }; + + Rewriter.prototype.addImplicitIndentation = function() { + var action, condition, indent, outdent, starter; + starter = indent = outdent = null; + condition = function(token, i) { + var _ref; + return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN')); + }; + action = function(token, i) { + return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent); + }; + return this.scanTokens(function(token, i, tokens) { + var tag, _ref, _ref1; + tag = token[0]; + if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') { + tokens.splice(i, 1); + return 0; + } + if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { + tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token)))); + return 2; + } + if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) { + tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token)))); + return 4; + } + if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { + starter = tag; + _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1]; + if (starter === 'THEN') { + indent.fromThen = true; + } + tokens.splice(i + 1, 0, indent); + this.detectEnd(i + 2, condition, action); + if (tag === 'THEN') { + tokens.splice(i, 1); + } + return 1; + } + return 1; + }); + }; + + Rewriter.prototype.tagPostfixConditionals = function() { + var action, condition, original; + original = null; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT'; + }; + action = function(token, i) { + if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) { + return original[0] = 'POST_' + original[0]; + } + }; + return this.scanTokens(function(token, i) { + if (token[0] !== 'IF') { + return 1; + } + original = token; + this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.indentation = function(token, implicit) { + var indent, outdent; + if (implicit == null) { + implicit = false; + } + indent = ['INDENT', 2, token[2]]; + outdent = ['OUTDENT', 2, token[2]]; + if (implicit) { + indent.generated = outdent.generated = true; + } + return [indent, outdent]; + }; + + Rewriter.prototype.generate = function(tag, value, line) { + var tok; + tok = [tag, value, line]; + tok.generated = true; + return tok; + }; + + Rewriter.prototype.tag = function(i) { + var _ref; + return (_ref = this.tokens[i]) != null ? _ref[0] : void 0; + }; + + return Rewriter; + + })(); + + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']]; + + exports.INVERSES = INVERSES = {}; + + EXPRESSION_START = []; + + EXPRESSION_END = []; + + for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) { + _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1]; + EXPRESSION_START.push(INVERSES[rite] = left); + EXPRESSION_END.push(INVERSES[left] = rite); + } + + EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); + + IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; + + IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++']; + + IMPLICIT_UNSPACED_CALL = ['+', '-']; + + IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']; + + IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']; + + SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']; + + SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']; + + LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/scope.js b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/scope.js new file mode 100644 index 0000000..3efc4ed --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/lib/coffee-script/scope.js @@ -0,0 +1,146 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var Scope, extend, last, _ref; + + _ref = require('./helpers'), extend = _ref.extend, last = _ref.last; + + exports.Scope = Scope = (function() { + + Scope.root = null; + + function Scope(parent, expressions, method) { + this.parent = parent; + this.expressions = expressions; + this.method = method; + this.variables = [ + { + name: 'arguments', + type: 'arguments' + } + ]; + this.positions = {}; + if (!this.parent) { + Scope.root = this; + } + } + + Scope.prototype.add = function(name, type, immediate) { + if (this.shared && !immediate) { + return this.parent.add(name, type, immediate); + } + if (Object.prototype.hasOwnProperty.call(this.positions, name)) { + return this.variables[this.positions[name]].type = type; + } else { + return this.positions[name] = this.variables.push({ + name: name, + type: type + }) - 1; + } + }; + + Scope.prototype.namedMethod = function() { + if (this.method.name || !this.parent) { + return this.method; + } + return this.parent.namedMethod(); + }; + + Scope.prototype.find = function(name) { + if (this.check(name)) { + return true; + } + this.add(name, 'var'); + return false; + }; + + Scope.prototype.parameter = function(name) { + if (this.shared && this.parent.check(name, true)) { + return; + } + return this.add(name, 'param'); + }; + + Scope.prototype.check = function(name) { + var _ref1; + return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0)); + }; + + Scope.prototype.temporary = function(name, index) { + if (name.length > 1) { + return '_' + name + (index > 1 ? index - 1 : ''); + } else { + return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); + } + }; + + Scope.prototype.type = function(name) { + var v, _i, _len, _ref1; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.name === name) { + return v.type; + } + } + return null; + }; + + Scope.prototype.freeVariable = function(name, reserve) { + var index, temp; + if (reserve == null) { + reserve = true; + } + index = 0; + while (this.check((temp = this.temporary(name, index)))) { + index++; + } + if (reserve) { + this.add(temp, 'var', true); + } + return temp; + }; + + Scope.prototype.assign = function(name, value) { + this.add(name, { + value: value, + assigned: true + }, true); + return this.hasAssignments = true; + }; + + Scope.prototype.hasDeclarations = function() { + return !!this.declaredVariables().length; + }; + + Scope.prototype.declaredVariables = function() { + var realVars, tempVars, v, _i, _len, _ref1; + realVars = []; + tempVars = []; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type === 'var') { + (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name); + } + } + return realVars.sort().concat(tempVars.sort()); + }; + + Scope.prototype.assignedVariables = function() { + var v, _i, _len, _ref1, _results; + _ref1 = this.variables; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type.assigned) { + _results.push("" + v.name + " = " + v.type.value); + } + } + return _results; + }; + + return Scope; + + })(); + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/coffee-script/package.json b/node_modules/grunt-coffee/node_modules/coffee-script/package.json new file mode 100644 index 0000000..45da57c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/coffee-script/package.json @@ -0,0 +1,45 @@ +{ + "name": "coffee-script", + "description": "Unfancy JavaScript", + "keywords": [ + "javascript", + "language", + "coffeescript", + "compiler" + ], + "author": { + "name": "Jeremy Ashkenas" + }, + "version": "1.3.3", + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE" + } + ], + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "lib": "./lib/coffee-script" + }, + "main": "./lib/coffee-script/coffee-script", + "bin": { + "coffee": "./bin/coffee", + "cake": "./bin/cake" + }, + "homepage": "http://coffeescript.org", + "bugs": "https://github.com/jashkenas/coffee-script/issues", + "repository": { + "type": "git", + "url": "git://github.com/jashkenas/coffee-script.git" + }, + "devDependencies": { + "uglify-js": ">=1.0.0", + "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 new file mode 100644 index 0000000..25f5634 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/.npmignore @@ -0,0 +1,2 @@ +node_modules +/tmp diff --git a/node_modules/grunt-coffee/node_modules/grunt/LICENSE-MIT b/node_modules/grunt-coffee/node_modules/grunt/LICENSE-MIT new file mode 100644 index 0000000..90c336c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 "Cowboy" Ben Alman + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/README.md b/node_modules/grunt-coffee/node_modules/grunt/README.md new file mode 100644 index 0000000..9012df8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/README.md @@ -0,0 +1,83 @@ +# grunt +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](/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](/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](/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. + +## Why does grunt exist? +Doing 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. + +Being 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. + +## Installing grunt + +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](/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](/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. +* 2012/07/30 - v0.3.12 - Fixing a bug in node 0.8.x where utils.spawn would terminate before receiving all child stdout. +* 2012/06/25 - v0.3.10 - Updating a few dependencies to work with node 0.8.x (0.6.x should still work). +* 2012/04/18 - v0.3.9 - The min task (via the uglify helper) now appends a semicolon to the end of the generated source. +* 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. +* 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. +* 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. +* 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. +* 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. +* 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. +* 2012/03/25 - v0.3.1 - Added a few methods. Substantially reworked the init task and templates. +* 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. +* 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. +* 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). +* 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. +* 2012/01/22 - v0.2.0 - Added "init" task with a sample template, reworked a lot of code. Hopefully it's backwards-compatible. +* 2012/01/11 - v0.1.0 - Initial release. + +## License +Copyright (c) 2012 "Cowboy" Ben Alman +Licensed under the MIT license. + + + +[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/ +[jshint]: http://www.jshint.com/ +[uglify]: https://github.com/mishoo/UglifyJS/ +[nodeunit]: https://github.com/caolan/nodeunit +[qunit]: http://docs.jquery.com/QUnit +[phantom]: http://www.phantomjs.org/ diff --git a/node_modules/grunt-coffee/node_modules/grunt/bin/grunt b/node_modules/grunt-coffee/node_modules/grunt/bin/grunt new file mode 100755 index 0000000..a774f87 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/bin/grunt @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +// Nodejs libs. +var fs = require('fs'); +var path = require('path'); +// In Nodejs 0.8.0, existsSync moved from path -> fs. +var existsSync = fs.existsSync || path.existsSync; + +// Badass internal grunt lib. +var findup = require('../lib/util/findup'); + +// Where might a locally-installed grunt live? +var dir = path.resolve(findup(process.cwd(), 'grunt.js'), '../node_modules/grunt'); + +// If grunt is installed locally, use it. Otherwise use this grunt. +if (!existsSync(dir)) { dir = '../lib/grunt'; } + +// Run grunt. +require(dir).cli(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp b/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp new file mode 100755 index 0000000..072b2dd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/dev/init.exp @@ -0,0 +1,152 @@ +#!/usr/bin/expect -f + +# OMG THIS WAS A PAIN TO CREATE + +if {$argc == 0} { + # No template specified, iterate over all templates. + set templates [list jquery commonjs node gruntplugin gruntfile] +} else { + # One or more templates were specified, iterate over those. + set templates [lrange $argv 0 end] +} + +foreach template $templates { + +set project "grunt-init-$template-sample" + +# Disable git pushing when debugging. +set gitpush 1 + +# Grunt version +set version [exec grunt --version] + +# Stop any already-running logging. +log_file + +# Start logging fresh, saving output for later use. +log_file -noappend /tmp/grunt-expect-out + +# Spawn bash without all my crazy dotfiles stuff. +set timeout -1 +spawn bash --noprofile --norc +match_max 100000 + +# Make the prompt look nice. +expect "$ " +send "PS1='\n$ '\r" +expect "\r" + +# Cleanup any existing session. +expect "$ " +send "cd /tmp\r" +expect "$ " +send "rm -rf /tmp/$project\r" + +# Session logging starts here. +expect "$ " +send "mkdir $project && cd $project\r" + +# Initialize the current directory. +expect "$ " +send "git init\r" +expect "$ " +send "git remote add origin git@github.com:gruntjs/$project.git\r" + +# Note that the "--no-color" will be stripped out later. +expect "$ " +send "grunt init:$template --no-color\r" + +# Don't start answering prompts until this line is encountered. +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 (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} +} + +# Pre-grunt file structure. +expect "$ " +send "tree\r" + +# Let grunt grunt the newly-created file structure. +expect "$ " +send "grunt --no-color\r" + +# Post-grunt file structure. Any built files should appear here. +expect "$ " +send "tree\r" + +# Commit everything. +expect "$ " +send "git add .\r" +expect "$ " +send "git commit -m 'Committing sample \"grunt init:$template\" task output.'\r" + +# Session logging stops here. +expect "$ " +send "# EOF\n" + +# Add meta-content to the README. +expect "$ " +send "echo -e '# Grunt \"init:$template\" sample + +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 init template as +\[grunt issues\]\[issues\]. Instead of watching or forking this repository, +watch \[grunt\]\[grunt\] and use the grunt \[init task\]\[init\]._ + +## Project Creation Transcript +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 \"generated\" branch\]\[prev\].**' > README.md\r" +expect "$ " +send "echo -e ' + +\[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\] sample repositories. + +```' >> README.md\r" +expect "$ " +# Strip out everything before the "mkdir" and after the "EOF". Also remove any "--no-color" bits. +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 '``` +' >> 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" + +# Push to GitHub. +if {$gitpush} { + expect "$ " + send "git push -uf --all origin\r" +} + +expect "$ " +send "exit\r" + +expect eof + +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/README.md b/node_modules/grunt-coffee/node_modules/grunt/docs/README.md new file mode 100644 index 0000000..517d703 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/README.md @@ -0,0 +1 @@ +[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 new file mode 100644 index 0000000..32ef7c8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api.md @@ -0,0 +1,410 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# The grunt API + +Grunt exposes all of its methods and properties on the `grunt` object that gets passed into the `module.exports` function exported in your [grunt.js gruntfile](getting_started.md) or in your [tasks file](types_of_tasks.md). + +For example, your project's [grunt.js gruntfile](getting_started.md) might look like this: + +```javascript +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + lint: { + all: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + jshint: { + options: { + browser: true + } + } + }); + + // Load tasks from "grunt-sample" grunt plugin installed via Npm. + grunt.loadNpmTasks('grunt-sample'); + + // Default task. + grunt.registerTask('default', 'lint sample'); + +}; +``` + +And if you're creating a [grunt plugin](plugins.md) or just organizing tasks into a folder, a [custom tasks file](types_of_tasks.md) might look like this: + +```javascript +module.exports = function(grunt) { + + // Create a new task. + grunt.registerTask('awesome', 'Print out "awesome!!!"', function() { + var awesome = grunt.helper('awesome'); + grunt.log.write(awesome); + }); + + // Register a helper. + grunt.registerHelper('awesome', function() { + return 'awesome!!!'; + }); + +}; +``` + +But these are just examples. For more information, read on. + +## A Very Important Note +Your `grunt.js` gruntfile or tasks file **must** contain this code, once and **only** once. If it doesn't, things won't work. For the sake of brevity, this "wrapper" code has been omitted from all future examples on this page, but it needs to be there. Like in the previous examples. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Config +_Note that the method listed below is also available on the [grunt.config](api_config.md) object in addition to the `grunt` object._ + + +### grunt.initConfig +Initialize a configuration object for the current project. The specified `configObject` is used by tasks and helpers and can also be accessed using the [grunt.config](api_config.md) method. Nearly every project's [grunt.js gruntfile](getting_started.md) will call this method. + +Note that any specified `` and `` [directives](api_task.md) will be automatically processed when the config object is initialized. + +```javascript +grunt.initConfig(configObject) +``` + +This example contains sample config data for the [lint task](task_lint.md): + +```javascript +grunt.initConfig({ + lint: { + all: ['lib/*.js', 'test/*.js', 'grunt.js'] + } +}); +``` + +See the [configuring grunt](getting_started.md) page for more configuration examples. + +_This method is an alias for the [grunt.config.init](api_config.md) method._ + + +## Creating Tasks +Tasks are grunt's bread and butter. The stuff you do most often, like `lint` or `test`. Every time grunt is run, you specify one or more tasks to run, which tells grunt what you'd like it to do. + +If you don't specify a task, but a task named "default" has been defined, that task will run (unsurprisingly) by default. + +_Note that the methods listed below are also available on the [grunt.task](api_task.md) object in addition to the `grunt` object._ + + +### grunt.registerTask +Register an "alias task" or a task function. This method supports the following two signatures: + +**Alias task** + +If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified task in `taskList` will be run, in the order specified. The `taskList` argument can be a space-separated string or an array of task names. + +```javascript +grunt.registerTask(taskName, taskList) +``` + +This example alias task defines a "default" task whereby the "lint", "qunit", "concat" and "min" tasks are run automatically if grunt is executed without any tasks specified: + +```javascript +task.registerTask('default', 'lint qunit concat min'); +``` + +**Function task** + +If a `description` and `taskFunction` are passed, the specified function will be executed whenever the task is run. In addition, the specified description will be shown when `grunt --help` is run. Task-specific properties and methods are available inside the task function as properties of the `this` object. The task function can return `false` to indicate that the task has failed. + +Note that the `grunt.registerMultiTask` method, explained below, can be used to define a special type of task known as a "multi task." + +```javascript +grunt.registerTask(taskName, description, taskFunction) +``` + +This example task logs `foo, testing 123` if grunt is run via `grunt foo:testing:123`. If the task is run without arguments as `grunt foo` the task logs `foo, no args`. + +```javascript +grunt.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) { + if (arguments.length === 0) { + grunt.log.writeln(this.name + ", no args"); + } else { + grunt.log.writeln(this.name + ", " + arg1 + " " + arg2); + } +}); +``` + +See the [creating tasks](types_of_tasks.md) documentation for more examples of tasks and alias tasks. + +_This method is an alias for the [grunt.task.registerTask](api_task.md) method._ + + +### grunt.registerMultiTask +Register a "multi task." A multi task is a task that implicitly iterates over all of its named sub-properties (AKA targets) if no target was specified. In addition to the default properties and methods, extra multi task-specific properties are available inside the task function as properties of the `this` object. + +Many of the built-in tasks, including the [lint task](task_lint.md), [concat task](task_concat.md) and [min task](task_min.md) are multi tasks. + +```javascript +grunt.registerMultiTask(taskName, description, taskFunction) +``` + +Given the specified configuration, this example multi task would log `foo: 1,2,3` if grunt was run via `grunt log:foo`, or it would log `bar: hello world` if grunt was run via `grunt log:bar`. If grunt was run as `grunt log` however, it would log `foo: 1,2,3` then `bar: hello world` then `baz: false`. + +```javascript +grunt.initConfig({ + log: { + foo: [1, 2, 3], + bar: 'hello world', + baz: false + } +}); + +grunt.registerMultiTask('log', 'Log stuff.', function() { + grunt.log.writeln(this.target + ': ' + this.data); +}); +``` + +See the [creating tasks](types_of_tasks.md) documentation for more examples of multi tasks. + +_This method is an alias for the [grunt.task.registerMultiTask](api_task.md) method._ + + +### grunt.registerInitTask +Register an "init task." An init task is a task that doesn't require any configuration data, and as such will still run even if grunt can't find a [grunt.js gruntfile](getting_started.md). The included [init task](task_init.md) is an example of an "init task." + +```javascript +grunt.registerInitTask(taskName, description, taskFunction) +``` + +For an init task example, see the [init task source](../tasks/init.js). + +_This method is an alias for the [grunt.task.registerInitTask](api_task.md) method._ + +### grunt.renameTask +Rename a task. This might be useful if you want to override the default behavior of a task, while retaining the old name. + +```javascript +grunt.renameTask(oldname, newname) +``` + +_This method is an alias for the [grunt.task.renameTask](api_task.md) method._ + +## Inside Tasks +An object is made available as `this` inside each task function that contains a number of useful task-specific properties and methods. This same object is also exposed as `grunt.task.current` for use in [templates](api_template.md). + +### this.async / grunt.task.current.async +If a task is asynchronous, this method must be invoked to instruct grunt to wait. It returns a handle to a "done" function that should be called when the task has completed. `false` can be passed to the done function to indicate that the task has failed. If this method isn't invoked, the task executes synchronously. + +```javascript +// Tell grunt this task is asynchronous. +var done = this.async(); +// Your async code. +setTimeout(function() { + // Let's simulate an error, sometimes. + var success = Math.random() > 0.5; + // All done! + done(success); +}, 1000); +``` + +### this.requires / grunt.task.current.requires +If one task depends on the successful completion of another task (or tasks), this method can be used to force grunt to abort if the other task didn't run, or if the other task failed. The task list can be a space-separated string, an array of task names, or individual task name arguments. + +Note that this won't actually run the specified task(s), it will just fail the current task if they haven't already run successfully. + +```javascript +this.requires(taskList) +``` + +### this.requiresConfig / grunt.task.current.requiresConfig +Fail the current task if one or more required [config](api_config.md) properties is missing. One or more string or array config properties may be specified. + +```javascript +this.requiresConfig(prop [, prop [, ...]]) +``` + +See the [grunt.config documentation](api_config.md) for more information about config properties. + +_This method is an alias for the [grunt.config.requires](api_config.md) method._ + +### this.name / grunt.task.current.name +The name of the task, as defined in `grunt.registerTask`. For example, if a "sample" task was run as `grunt sample` or `grunt sample:foo`, inside the task function, `this.name` would be `"sample"`. + +### this.nameArgs / grunt.task.current.nameArgs +The name of the task, as specified with any colon-separated arguments or flags on the command-line. For example, if a "sample" task was run as `grunt sample:foo`, inside the task function, `this.nameArgs` would be `"sample:foo"`. + +### this.args / grunt.task.current.args +An array of arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.args` would be `["foo", "bar"]`. Note that in multi tasks, the target is removed from the `this.args` array and is not passed into the task function. + +### this.flags / grunt.task.current.flags +An object generated from the arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.flags` would be `{foo: true, bar: true}`. In a multi task, the target name is not set as a flag. + +### this.errorCount / grunt.task.current.errorCount +The number of [grunt.log.error](api_log.md) calls that occurred during this task. This can be used to fail a task if errors occurred during the task. + + +## Inside Multi Tasks + +### this.target / grunt.task.current.target +In a multi task, this is the name of the target currently being iterated over. For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.target` would be `"foo"`. + +### this.data / grunt.task.current.data +In a multi task, this is the actual data stored in the grunt config object for the given target. For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.data` would be `"bar"`. + +### this.file / grunt.task.current.file +In a multi task, target data can be stored in two different formats. A relatively basic "compact" format and a much more flexible "full" format. When the compact format is used, that key and value are made available as `this.file.dest` and `this.file.src`, respectively. When the full format is used, the specified `src` and `dest` values are used for `this.file.dest` and `this.file.src`. + +Note that while grunt supports expanding [templates](api_template.md) for both `src` and `dest`, they only work for the `dest` file path when the _full_ format is used. + +```javascript +grunt.initConfig({ + concat: { + // This is the "compact" format. + 'dist/built.js': ['src/file1.js', 'src/file2.js'], + // This is the "full" format. + built: { + src: ['src/file1.js', 'src/file2.js'], + dest: 'dist/built.js' + } + } +}); +``` + + +## Loading Externally-Defined Tasks +For most projects, tasks and helpers will be defined in the [grunt.js gruntfile](getting_started.md). For larger projects, or in cases where tasks and helpers need to be shared across projects, tasks can be loaded from one or more external directories or Npm-installed grunt plugins. + +_Note that the methods listed below are also available on the [grunt.task](api_task.md) object in addition to the `grunt` object._ + +### grunt.loadTasks +Load task-related files from the specified directory, relative to the [grunt.js gruntfile](getting_started.md). This method can be used to load task-related files from a local grunt plugin by specifying the path to that plugin's "tasks" subdirectory. + +```javascript +grunt.loadTasks(tasksPath) +``` + +_This method is an alias for the [grunt.task.loadTasks](api_task.md) method._ + + +### grunt.loadNpmTasks +Load tasks and helpers from the specified grunt plugin. This plugin must be installed locally via npm, and must be relative to the [grunt.js gruntfile](getting_started.md). Grunt plugins can be created by using the [gruntplugin init template](task_init.md). + +```javascript +grunt.loadNpmTasks(pluginName) +``` + +_This method is an alias for the [grunt.task.loadNpmTasks](api_task.md) method._ + + +## Defining and Executing Helpers +Helpers are utility functions that can be used by any task. + +For example, in the [min task](../tasks/min.js), the majority of the actual minification work is done in an `uglify` helper, so that other tasks can utilize that minification code if they want to. + +See the list of [built-in helpers](helpers_directives.md) for examples. + +_Note that the methods listed below are also available on the [grunt.task](api_task.md) object in addition to the `grunt` object._ + +### grunt.registerHelper +Register a helper function that can be used by any task. When called as a directive, `this.directive` will be true inside of the helper. + +```javascript +grunt.registerHelper(helperName, helperFunction) +``` + +In this example helper, the numbers `1` and `2` are passed in and the value `3` is returned. + +```javascript +grunt.registerHelper('add_two_nums', function(a, b) { + return a + b; +}); +``` + +_This method is an alias for the [grunt.task.registerHelper](api_task.md) method._ + +### grunt.renameHelper +Rename a helper. This might be useful if you want to override the default behavior of a helper, while retaining the old name (to avoid having to completely recreate an already-made task just because you needed to override or extend a built-in helper). + +```javascript +grunt.renameHelper(oldname, newname) +``` + +_This method is an alias for the [grunt.task.renameHelper](api_task.md) method._ + +### grunt.helper +Invoke a registered helper function. + +```javascript +grunt.helper(helperName [, arguments...]) +``` + +In this example, the previously defined `add_two_nums` helper is invoked. + +```javascript +grunt.helper('add_two_nums', 1, 2) // 3 +``` + +_This method is an alias for the [grunt.task.helper](api_task.md) method._ + + +## Warnings and Fatal Errors +If something explodes (or is about to explode) inside a helper or task, it can force grunt to abort. See the [exit codes documentation](exit_codes.md) for a list of all built-in grunt exit codes. + +### grunt.warn +Display a warning and abort grunt immediately. Grunt will continue processing tasks if the `--force` command-line option was specified. The `error` argument can be a string message or an error object. + +```javascript +grunt.warn(error [, errorcode]) +``` + +If `--debug 9` is specified on the command-line and an error object was specified, a stack trace will be logged. + +_This method is an alias for the [grunt.fail.warn](api_fail.md) method._ + +### grunt.fatal +Display a warning and abort grunt immediately. The `error` argument can be a string message or an error object. + +```javascript +grunt.fail(error [, errorcode]) +``` + +If `--debug 9` is specified on the command-line and an error object was specified, a stack trace will be logged. + +_This method is an alias for the [grunt.fail.fatal](api_fail.md) method._ + + +## Command-line Options + +### grunt.option +Retrieve the value of a command-line option, eg. `debug`. Note that for each command-line option, the inverse can be tested, eg. `no-debug`. + +```javascript +grunt.option(optionName) +``` + +## Miscellaneous + +### grunt.version +The current grunt version, as a string. + +```javascript +grunt.version +``` + +### grunt.npmTasks +Inside a [grunt plugin](plugins.md) bin script, this method _must_ be called to inform grunt where to look for that plugin's tasks files. The `npmModuleName` must be the grunt plugin's Npm module name. The [gruntplugin init template](task_init.md), will automatically configure this for you. + +```javascript +grunt.npmTasks(npmModuleName) +``` + +## Other Methods + +* [grunt.utils](api_utils.md) - Miscellaneous utilities, including Underscore.js, Async and Hooker. +* [grunt.template](api_template.md) - Underscore.js template processing and other template-related methods. +* [grunt.task](api_task.md) - Register and run tasks and helpers, load external tasks. +* [grunt.file](api_file.md) - Wildcard expansion, file reading, writing, directory traversing. +* [grunt.config](api_config.md) - Access project-specific configuration data defined in the [grunt.js gruntfile](getting_started.md). +* [grunt.log](api_log.md), [grunt.verbose](api_log.md) - Output messages to the console. +* [grunt.fail](api_fail.md) - For when something goes horribly wrong. 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 new file mode 100644 index 0000000..b475ad9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_config.md @@ -0,0 +1,94 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.config + +Access project-specific configuration data defined in the [grunt.js gruntfile](getting_started.md). + +See the [config lib source](../lib/grunt/config.js) for more information. + +## The config API + +Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object, and any method marked with a ☆ (white star) is also available inside tasks on the `this` object. Just so you know. See the [API main page](api.md) for more usage information. + +## Initializing Config Data +_Note that the method listed below is also available on the `grunt` object as [grunt.initConfig](api.md)._ + +### grunt.config.init ☃ +Initialize a configuration object for the current project. The specified `configObject` is used by tasks and helpers and can also be accessed using the `grunt.config` method. Nearly every project's [grunt.js gruntfile](getting_started.md) will call this method. + +```javascript +grunt.config.init(configObject) +``` + +Note that any specified `` and `` [directives](api_task.md) will be automatically processed when the config object is initialized. + +This example contains sample config data for the [lint task](task_lint.md): + +```javascript +grunt.config.init({ + lint: { + all: ['lib/*.js', 'test/*.js', 'grunt.js'] + } +}); +``` + +See the [configuring grunt](getting_started.md) page for more configuration examples. + +_This method is also available as [grunt.initConfig](api.md)._ + + +## Accessing Config Data +The following methods allow grunt configuration data to be accessed either via dot-delimited string like `'pkg.author.name'` or via array of property name parts like `['pkg', 'author', 'name']`. + +Note that if a specified property name contains a `.` dot, it must be escaped with a literal backslash, eg. `'concat.dist/built\\.js'`. If an array of parts is specified, grunt will handle the escaping internally with the `grunt.config.escape` method. + +### grunt.config +Get or set a value from the project's grunt configuration. This method serves as an alias to other methods; if two arguments are passed, `grunt.config.set` is called, otherwise `grunt.config.get` is called. + +```javascript +grunt.config([prop [, value]]) +``` + +### grunt.config.get +Get a value from the project's grunt configuration. If `prop` is specified, that property's value is returned, or `null` if that property is not defined. If `prop` isn't specified, a copy of the entire config object is returned. + +```javascript +grunt.config.get([prop]) +``` + +Any `<% %>` templates in returned values will not be automatically processed, but can be processed afterwards using the [grunt.template.process](api_template.md) method. If you want to do both at once, the `grunt.config.process` method can be used. + +### grunt.config.set +Set a value into the project's grunt configuration. + +```javascript +grunt.config.set(prop, value) +``` + +Note that any specified `` and `` [directives](api_task.md) will be automatically processed when the config data is set. + +### grunt.config.escape +Escape `.` dots in the given `propString`. This should be used for property names that contain dots. + +```javascript +grunt.config.escape(propString) +``` + +### grunt.config.process +Behaves like `grunt.config.get`, but additionally recursively processes all `<% %>` templates in the returned data. + +```javascript +grunt.config.process([prop]) +``` + +## Requiring Config Data +_Note that the method listed below is also available inside tasks on the `this` object as [this.requiresConfig](api.md)._ + +### grunt.config.requires ☆ +Fail the current task if one or more required config properties is missing. One or more string or array config properties may be specified. + +```javascript +grunt.config.requires(prop [, prop [, ...]]) +``` + +_This method is also available inside tasks as [this.requiresConfig](api.md)._ 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 new file mode 100644 index 0000000..29a6e17 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_fail.md @@ -0,0 +1,35 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.fail + +For when something goes horribly wrong. + +See the [fail lib source](../lib/grunt/fail.js) for more information. + +## The fail API + +If something explodes (or is about to explode) inside a helper or task, it can force grunt to abort. See the [exit codes documentation](exit_codes.md) for a list of all built-in grunt exit codes. + +Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object. Just so you know. See the [API main page](api.md) for more usage information. + +### grunt.warn ☃ +Display a warning and abort grunt immediately. Grunt will continue processing tasks if the `--force` command-line option was specified. The `error` argument can be a string message or an error object. + +```javascript +grunt.warn(error [, errorcode]) +``` + +If `--debug 9` is specified on the command-line and an error object was specified, a stack trace will be logged. + +_This method is also available as [grunt.warn](api.md)._ + +### grunt.fatal ☃ +Display a warning and abort grunt immediately. The `error` argument can be a string message or an error object. + +```javascript +grunt.fail(error [, errorcode]) +``` + +If `--debug 9` is specified on the command-line and an error object was specified, a stack trace will be logged. + +_This method is also available as [grunt.fatal](api.md)._ 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 new file mode 100644 index 0000000..303e6f4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_file.md @@ -0,0 +1,184 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.file + +Wildcard expansion, file reading, writing, directory traversing. + +See the [file lib source](../lib/grunt/file.js) for more information. + +## The file API +There are many provided methods for reading and writing files, as well as traversing the filesystem and finding files by wildcard patterns. Many of these methods are wrappers around core Node.js file functionality, but with additional error handling and logging. + +_Note: all file paths are relative to the [grunt.js gruntfile](getting_started.md) unless the current working directory is changed with `grunt.file.setBase` or the `--base` command-line option._ + +### grunt.file.read +Read and return a file's contents. The `encoding` argument defaults to `utf8` if unspecified. + +```javascript +grunt.file.read(filepath, encoding) +``` + +### grunt.file.readJSON +Read a file's contents, parsing the data as JSON and returning the result. + +```javascript +grunt.file.readJSON(filepath) +``` + +### grunt.file.write +Write the specified contents to a file, creating intermediate directories if necessary. + +_If the `--no-write` command-line option is specified, the file won't actually be written._ + +```javascript +grunt.file.write(filepath, contents) +``` + +### grunt.file.copy +Copy a source file to a destination path, creating intermediate directories if necessary. + +_If the `--no-write` command-line option is specified, the file won't actually be written._ + +```javascript +grunt.file.copy(srcpath, destpath [, options]) +``` + +The `options` object has these possible properties: + +```javascript +var options = { + // If specified, the file contents will be parsed as `utf8` and passed into + // the function, whose return value will be used as the destination file's + // contents. If this function returns false, the file copy will be aborted. + process: processFunction, + // These optional wildcard patterns will be matched against the filepath using + // grunt.file.isMatch. If a specified wildcard pattern matches, the file will + // not be processed via `processFunction`. Note that `true` may also be + // specified to prvent processing. + noProcess: wildcardPatterns +}; +``` + +### grunt.file.mkdir +Works like `mkdir -p`. Create a directory along with any intermediate directories. + +_If the `--no-write` command-line option is specified, directories won't actually be created._ + +```javascript +grunt.file.mkdir(dirpath) +``` + +### grunt.file.recurse +Recurse into a directory, executing `callback` for each file. + +```javascript +grunt.file.recurse(rootdir, callback) +``` + +The callback function receives the following arguments: + +```javascript +function callback(abspath, rootdir, subdir, filename) { + // The full path to the current file, which is nothing more than + // the rootdir + subdir + filename arguments, joined. + abspath + // The root director, as originally specified. + rootdir + // The current file's directory, relative to rootdir. + subdir + // The filename of the current file, without any directory parts. + filename +} +``` + +### grunt.file.findup +Search for a filename in the given directory followed by all parent directories. Returns the first matching filepath found, otherwise returns `null`. + +```javascript +grunt.file.findup(rootdir, filename) +``` + +### grunt.file.isPathAbsolute +Is a given file path absolute? Returns a boolean. + +Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. + +```javascript +grunt.file.isPathAbsolute(path1 [, path2 [, ...]]) +``` + +### grunt.file.userDir +Return a file path relative to the user's `.grunt` directory, which is `%USERPROFILE%\.grunt\` on Windows, and `~/.grunt/` on OS X or Linux. If no file path is specified, the base user `.grunt` directory path will be returned. If the specified path is not found, `null` is returned. + +Windows users: `%USERPROFILE%` is generally your `Documents and Settings` directory. + +_Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path._ + +```javascript +grunt.file.userDir([path1, [, path2 [, ...]]]) +``` + +### grunt.file.setBase +Change grunt's current working directory. By default, all file paths are relative to the [grunt.js gruntfile](getting_started.md). This works just like the `--base` command-line option. + +```javascript +grunt.file.setBase(path1 [, path2 [, ...]]) +``` + +Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. + + +## File Lists and Wildcards +Wildcard patterns are resolved using the [glob-whatev library](https://github.com/cowboy/node-glob-whatev). See the [minimatch](https://github.com/isaacs/minimatch) module documentation for more details on supported wildcard patterns. + +There are also a number of [task-specific file listing methods](api_task.md) that find files inside grunt plugins and task directories. + +_Note: all file paths are relative to the [grunt.js gruntfile](getting_started.md) unless the current working directory is changed with `grunt.file.setBase` or the `--base` command-line option._ + +### grunt.file.expand +Return a unique array of all file or directory paths that match the given wildcard pattern(s). This method accepts one or more comma separated wildcard patterns as well as an array of wildcard patterns. + +The `options` object supports all [minimatch](https://github.com/isaacs/minimatch) options. + +```javascript +grunt.file.expand([options, ] patterns) +``` + +### grunt.file.expandDirs +This method behaves the same as `grunt.file.expand` except it only returns directory paths. + +```javascript +grunt.file.expandDirs([options, ] patterns) +``` + +### grunt.file.expandFiles +This method behaves the same as `grunt.file.expand` except it only returns file paths. + +```javascript +grunt.file.expandFiles([options, ] patterns) +``` + +This method is used by many built-in tasks to handle wildcard expansion of the specified source files. See the [concat task source](../tasks/concat.js) for an example. + +### grunt.file.expandFileURLs +Return a unique array of all `file://` URLs for files that match the given wildcard pattern(s). Any absolute `file://`, `http://` or `https://` URLs specified will be passed through. This method accepts one or more comma separated wildcard patterns (or URLs), as well as an array of wildcard patterns (or URLs). + +```javascript +grunt.file.expandFileURLs(patternsOrURLs) +``` + +See the [qunit task source](../tasks/qunit.js) for an example. + +### grunt.file.isMatch +Match one or more wildcard patterns against a file path. If any of the specified matches, return `true` otherwise return `false`. This method accepts a single string wildcard pattern as well as an array of wildcard patterns. Note that `true` may also be specified to prvent processing. + +```javascript +grunt.file.isMatch(patterns, filepath) +``` + +Patterns without slashes will be matched against the basename of the path if it contains slashes, eg. pattern `*.js` will match filepath `path/to/file.js`. + +## External libraries + +### grunt.file.glob +[glob-whatev](https://github.com/cowboy/node-glob-whatev) - Synchronous file globbing utility. 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 new file mode 100644 index 0000000..72335f0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_log.md @@ -0,0 +1,144 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.log, grunt.verbose + +Output messages to the console. + +See the [log lib source](../lib/grunt/log.js) for more information. + +## The log API +Grunt output should look consistent, and maybe even pretty. As such, there is a plethora of logging methods, and a few useful patterns. All of the methods that actually log something are chainable. + +_Note: all methods available under `grunt.verbose` work exactly like `grunt.log` methods, but only log if the `--verbose` command-line option was specified._ + +### grunt.log.write / grunt.verbose.write +Log the specified `msg` string, with no trailing newline. + +```javascript +grunt.log.write(msg) +``` + +### grunt.log.writeln / grunt.verbose.writeln +Log the specified `msg` string, with trailing newline. + +```javascript +grunt.log.writeln([msg]) +``` + +### grunt.log.error / grunt.verbose.error +If `msg` string is omitted, logs `ERROR` in red, otherwise logs `>> msg`, with trailing newline. + +```javascript +grunt.log.error([msg]) +``` + +### grunt.log.ok / grunt.verbose.ok +If `msg` string is omitted, logs `OK` in green, otherwise logs `>> msg`, with trailing newline. + +```javascript +grunt.log.ok([msg]) +``` + +### grunt.log.subhead / grunt.verbose.subhead +Log the specified `msg` string in **bold**, with trailing newline. + +```javascript +grunt.log.subhead(msg) +``` + +### grunt.log.writeflags / grunt.verbose.writeflags +Log a list of `obj` properties (good for debugging flags). + +```javascript +grunt.log.writeflags(obj, prefix) +``` + +### grunt.log.debug / grunt.verbose.debug +Logs a debugging message, but only if the `--debug` command-line option was specified. + +```javascript +grunt.log.debug(msg) +``` + +## Verbose and Notverbose +All logging methods available under `grunt.verbose` work exactly like their `grunt.log` counterparts, but only log if the `--verbose` command-line option was specified. There is also a "notverbose" counterpart available at both `grunt.log.notverbose` and `grunt.log.verbose.or`. In fact, the `.or` property can be used on both `verbose` and `notverbose` to effectively toggle between the two. + +### grunt.verbose / grunt.log.verbose +This object contains all methods of `grunt.log` but only logs if the `--verbose` command-line option was specified. + +```javascript +grunt.verbose +``` + +### grunt.verbose.or / grunt.log.notverbose +This object contains all methods of `grunt.log` but only logs if the `--verbose` command-line option was _not_ specified. + +```javascript +grunt.verbose.or +``` + +## Utility Methods +These methods don't actually log, they just return strings that can be used in other methods. + +### grunt.log.wordlist +Returns a comma-separated list of `arr` array items. + +```javascript +grunt.log.wordlist(arr) +``` + +### grunt.log.uncolor +Removes all color information from a string, making it suitable for testing `.length` or perhaps logging to a file. + +```javascript +grunt.log.uncolor(str) +``` + +### grunt.log.wraptext +Wrap `text` string to `width` characters with `\n`, ensuring that words are not split in the middle unless absolutely necessary. + +```javascript +grunt.log.wraptext(width, text) +``` + +### grunt.log.table +Wrap `texts` array of strings to columns `widths` characters wide. A wrapper for the `grunt.log.wraptext` method that can be used to generate output in columns. + +```javascript +grunt.log.table(widths, texts) +``` + + +## An Example + +A common pattern is to only log when in `--verbose` mode OR if an error occurs, like so: + +```javascript +grunt.registerHelper('something', function(arg) { + var result; + var msg = 'Doing something...'; + grunt.verbose.write(msg); + try { + result = doSomethingThatThrowsAnExceptionOnError(arg); + // Success! + grunt.verbose.ok(); + return result; + } catch(e) { + // Something went wrong. + grunt.verbose.or.write(msg).error().error(e.message); + grunt.fail.warn('Something went wrong.', 50); + } +}); +``` + +An explanation of the above code: + +1. `grunt.verbose.write(msg);` logs the message (no newline), but only in `--verbose` mode. +2. `grunt.verbose.ok();` logs OK in green, with a newline. +3. `grunt.verbose.or.write(msg).error().error(e.message);` does a few things: + 1. `grunt.verbose.or.write(msg)` logs the message (no newline) if not in `--verbose` mode, and returns the `notverbose` object. + 2. `.error()` logs ERROR in red, with a newline, and returns the `notverbose` object. + 3. `.error(e.message);` logs the actual error message (and returns the `notverbose` object). +4. `grunt.fail.warn('Something went wrong.', 50);` logs a warning in bright yellow, exiting grunt with exit code 50, unless `--force` was specified. + +Take a look at the [built-in tasks source code](../tasks) for more examples. 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 new file mode 100644 index 0000000..a5a1d77 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_task.md @@ -0,0 +1,416 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.task + +Register and run tasks and helpers, load external tasks. + +See the [task lib source](../lib/grunt/task.js) and [task util lib source](../lib/util/task.js) for more information. + +## The task API + +Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object. Just so you know. See the [API main page](api.md) for more usage information. + + +## Creating Tasks +Tasks are grunt's bread and butter. The stuff you do most often, like `lint` or `test`. Every time grunt is run, you specify one more more tasks to run, which tells grunt what you'd like it to do. + +If you don't specify a task, but a task named "default" has been defined, that task will run (unsurprisingly) by default. + +### grunt.task.registerTask ☃ +Register an "alias task" or a task function. This method supports the following two signatures: + +**Alias task** + +If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified task in `taskList` will be run, in the order specified. The `taskList` argument can be a space-separated string or an array of task names. + +```javascript +grunt.task.registerTask(taskName, taskList) +``` + +This example alias task defines a "default" task whereby the "lint", "qunit", "concat" and "min" tasks are run automatically if grunt is executed without any tasks specified: + +```javascript +task.registerTask('default', 'lint qunit concat min'); +``` + +**Function task** + +If a `description` and `taskFunction` are passed, the specified function will be executed whenever the task is run. In addition, the specified description will be shown when `grunt --help` is run. Task-specific properties and methods are available inside the task function as properties of the `this` object. The task function can return `false` to indicate that the task has failed. + +Note that the `grunt.task.registerMultiTask` method, explained below, can be used to define a special type of task known as a "multi task." + +```javascript +grunt.task.registerTask(taskName, description, taskFunction) +``` + +This example task logs `foo, testing 123` if grunt is run via `grunt foo:testing:123`. If the task is run without arguments as `grunt foo` the task logs `foo, no args`. + +```javascript +grunt.task.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) { + if (arguments.length === 0) { + grunt.log.writeln(this.name + ", no args"); + } else { + grunt.log.writeln(this.name + ", " + arg1 + " " + arg2); + } +}); +``` + +See the [creating tasks](types_of_tasks.md) documentation for more examples of tasks and alias tasks. + +_This method is also available as [grunt.registerTask](api.md)._ + + +### grunt.task.registerMultiTask ☃ +Register a "multi task." A multi task is a task that implicitly iterates over all of its named sub-properties (AKA targets) if no target was specified. In addition to the default properties and methods, extra multi task-specific properties are available inside the task function as properties of the `this` object. + +Many of the built-in tasks, including the [lint task](task_lint.md), [concat task](task_concat.md) and [min task](task_min.md) are multi tasks. + +```javascript +grunt.task.registerMultiTask(taskName, description, taskFunction) +``` + +Given the specified configuration, this example multi task would log `foo: 1,2,3` if grunt was run via `grunt log:foo`, or it would log `bar: hello world` if grunt was run via `grunt log:bar`. If grunt was run as `grunt log` however, it would log `foo: 1,2,3` then `bar: hello world` then `baz: false`. + +```javascript +grunt.initConfig({ + log: { + foo: [1, 2, 3], + bar: 'hello world', + baz: false + } +}); + +grunt.task.registerMultiTask('log', 'Log stuff.', function() { + grunt.log.writeln(this.target + ': ' + this.data); +}); +``` + +See the [creating tasks](types_of_tasks.md) documentation for more examples of multi tasks. + +_This method is also available as [grunt.registerMultiTask](api.md)._ + + +### grunt.task.registerInitTask ☃ +Register an "init task." An init task is a task that doesn't require any configuration data, and as such will still run even if grunt can't find a [grunt.js gruntfile](getting_started.md). The included [init task](task_init.md) is an example of an "init task." + +```javascript +grunt.task.registerInitTask(taskName, description, taskFunction) +``` + +For an init task example, see the [init task source](../tasks/init.js). + +_This method is also available as [grunt.registerInitTask](api.md)._ + +### grunt.task.renameTask ☃ +Rename a task. This might be useful if you want to override the default behavior of a task, while retaining the old name. + +```javascript +grunt.task.renameTask(oldname, newname) +``` + +_This method is also available as [grunt.renameTask](api.md)._ + +## Inside Tasks +An object is made available as `this` inside each task function that contains a number of useful task-specific properties and methods. This same object is also exposed as `grunt.task.current` for use in [templates](api_template.md). + +### this.async / grunt.task.current.async +If a task is asynchronous, this method must be invoked to instruct grunt to wait. It returns a handle to a "done" function that should be called when the task has completed. `false` can be passed to the done function to indicate that the task has failed. If this method isn't invoked, the task executes synchronously. + +```javascript +// Tell grunt this task is asynchronous. +var done = this.async(); +// Your async code. +setTimeout(function() { + // Let's simulate an error, sometimes. + var success = Math.random() > 0.5; + // All done! + done(success); +}, 1000); +``` + +### this.requires / grunt.task.current.requires +If one task depends on the successful completion of another task (or tasks), this method can be used to force grunt to abort if the other task didn't run, or if the other task failed. The task list can be a space-separated string, an array of task names, or individual task name arguments. + +Note that this won't actually run the specified task(s), it will just fail the current task if they haven't already run successfully. + +```javascript +this.requires(taskList) +``` + +### this.requiresConfig / grunt.task.current.requiresConfig +Fail the current task if one or more required [config](api_config.md) properties is missing. One or more string or array config properties may be specified. + +```javascript +this.requiresConfig(prop [, prop [, ...]]) +``` + +See the [grunt.config documentation](api_config.md) for more information about config properties. + +_This method is an alias for the [grunt.config.requires](api_config.md) method._ + +### this.name / grunt.task.current.name +The name of the task, as defined in `grunt.registerTask`. For example, if a "sample" task was run as `grunt sample` or `grunt sample:foo`, inside the task function, `this.name` would be `"sample"`. + +### this.nameArgs / grunt.task.current.nameArgs +The name of the task, as specified with any colon-separated arguments or flags on the command-line. For example, if a "sample" task was run as `grunt sample:foo`, inside the task function, `this.nameArgs` would be `"sample:foo"`. + +### this.args / grunt.task.current.args +An array of arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.args` would be `["foo", "bar"]`. Note that in multi tasks, the target is removed from the `this.args` array and is not passed into the task function. + +### this.flags / grunt.task.current.flags +An object generated from the arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.flags` would be `{foo: true, bar: true}`. In a multi task, the target name is not set as a flag. + +### this.errorCount / grunt.task.current.errorCount +The number of [grunt.log.error](api_log.md) calls that occurred during this task. This can be used to fail a task if errors occurred during the task. + + +## Inside Multi Tasks + +### this.target / grunt.task.current.target +In a multi task, this is the name of the target currently being iterated over. For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.target` would be `"foo"`. + +### this.data / grunt.task.current.data +In a multi task, this is the actual data stored in the grunt config object for the given target. For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.data` would be `"bar"`. + +### this.file / grunt.task.current.file +In a multi task, target data can be stored in two different formats. A relatively basic "compact" format and a much more flexible "full" format. When the compact format is used, that key and value are made available as `this.file.dest` and `this.file.src`, respectively. When the full format is used, the specified `src` and `dest` values are used for `this.file.dest` and `this.file.src`. + +Note that while grunt supports expanding [templates](api_template.md) for both `src` and `dest`, they only work for the `dest` file path when the _full_ format is used. + +```javascript +grunt.initConfig({ + concat: { + // This is the "compact" format. + 'dist/built.js': ['src/file1.js', 'src/file2.js'], + // This is the "full" format. + built: { + src: ['src/file1.js', 'src/file2.js'], + dest: 'dist/built.js' + } + } +}); +``` + + +## Loading Externally-Defined Tasks +For most projects, tasks and helpers will be defined in the [grunt.js gruntfile](getting_started.md). For larger projects, or in cases where tasks and helpers need to be shared across projects, tasks can be loaded from one or more external directories or Npm-installed grunt plugins. + +### grunt.task.loadTasks ☃ +Load task-related files from the specified directory, relative to the [grunt.js gruntfile](getting_started.md). This method can be used to load task-related files from a local grunt plugin by specifying the path to that plugin's "tasks" subdirectory. + +```javascript +grunt.task.loadTasks(tasksPath) +``` + +_This method is also available as [grunt.loadTasks](api.md)._ + + +### grunt.task.loadNpmTasks ☃ +Load tasks and helpers from the specified grunt plugin. This plugin must be installed locally via npm, and must be relative to the [grunt.js gruntfile](getting_started.md). Grunt plugins can be created by using the [gruntplugin init template](task_init.md). + +```javascript +grunt.task.loadNpmTasks(pluginName) +``` + +_This method is also available as [grunt.loadNpmTasks](api.md)._ + + +## Helpers +Helpers are utility functions that can be used by any task. + +For example, in the [min task](../tasks/min.js), the majority of the actual minification work is done in an `uglify` helper, so that other tasks can utilize that minification code if they want to. + +See the list of [built-in helpers](helpers_directives.md) for examples. + +### grunt.task.registerHelper ☃ +Register a helper function that can be used by any task. When called as a directive, `this.directive` will be true inside of the helper. + +```javascript +grunt.task.registerHelper(helperName, helperFunction) +``` + +In this example helper, the numbers `1` and `2` are passed in and the value `3` is returned. + +```javascript +grunt.task.registerHelper("add_two_nums", function(a, b) { + return a + b; +}); +``` + +_This method is also available as [grunt.registerHelper](api.md)._ + +### grunt.task.renameHelper ☃ +Rename a helper. This might be useful if you want to override the default behavior of a helper, while retaining the old name (to avoid having to completely recreate an already-made task just because you needed to override or extend a built-in helper). + +```javascript +grunt.task.renameHelper(oldname, newname) +``` + +_This method is also available as [grunt.renameHelper](api.md)._ + +### grunt.task.helper ☃ +Invoke a registered helper function. + +```javascript +grunt.task.helper(helperName [, arguments...]) +``` + +In this example, the previously defined `add_two_nums` helper is invoked. + +```javascript +grunt.task.helper("add_two_nums", 1, 2) // 3 +``` + +_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/gruntjs/grunt-init-jquery-sample/blob/master/grunt.js). + +See the list of [built-in directives](helpers_directives.md) for examples. + +### grunt.task.directive +Manually execute a helper based on the passed string directive, returning its value. Note that this only works for synchronous helpers. When called as a directive, `this.directive` will be true inside of the helper. + +```javascript +grunt.task.directive(directive) +``` + +In this example, note that the arguments passed into the helper must be coerced into numbers because all directive arguments are passed into the helper as strings. + +```javascript +grunt.task.registerHelper('add_two_numbers', function(a, b) { + return Number(a) + Number(b); +}); + +grunt.task.directive('') // 3 +``` + +### grunt.task.getDirectiveParts +Split a valid directive into its components. Returns `null` if the string can't be parsed as a directive or if the directive doesn't match an existing helper. + +```javascript +grunt.task.getDirectiveParts(directive) +``` + +In this example, the directive can't be parsed initially because the appropriate helper hasn't been defined. Once the helper has been defined, the directive can be parsed. + +```javascript +grunt.task.getDirectiveParts('') // null + +grunt.task.registerHelper('foo', function() {}); +grunt.task.getDirectiveParts('') // ['foo', 'bar', 'baz'] +``` + + +## Queueing Tasks +Grunt automatically enqueues and runs all tasks specified on the command line, but individual tasks can enqueue additional tasks to be run. + +### grunt.task.run +Enqueue one or more tasks. Every specified task in `taskList` will be run immediately after the current task completes, in the order specified. The task list can be a space-separated string, an array of task names, or individual task name arguments. + +```javascript +grunt.task.run(taskList) +``` + +See the [watch task source](../tasks/watch.js) for an example. + +### grunt.task.clearQueue +Empty the task queue completely. Unless additional tasks are enqueued, no more tasks will be run. + +```javascript +grunt.task.clearQueue() +``` + +See the [watch task source](../tasks/watch.js) for an example. + + +## Search Directories +For a given tasks file or related task "extra" file, these paths will be searched in this order, aka "task path order," until the first matching file is found. + +1. The grunt user tasks directory, ie. `grunt.file.userDir('tasks')`. +2. Npm-installed [grunt plugins](plugins.md) or tasks directories specified on the command-line via the `--tasks` option. +3. Npm-installed grunt plugins, tasks directories or individual tasks and helpers specified in the [grunt.js gruntfile](getting_started.md). +4. Task directories built-in to a Npm-installed grunt plugin run via its `grunt-` named binary. +5. The [built-in grunt tasks directory](../tasks). + +This allows referenced Npm-installed grunt plugins, tasks directories, the [grunt.js gruntfile](getting_started.md) and even the user to override grunt functionality as needed. + +For example, a grunt plugin may add a new "foo" task in its `tasks/foo.js`, completely override an existing task like the [concat task](task_concat.md) in its `tasks/concat.js` or add a new "bar" [init task](task_init.md) template with its `tasks/init/bar.js` and "extra" files in its `tasks/init/bar/` directory. In your personal user tasks directory, you can create your own "baz" init task template with a `tasks/init/baz.js` file or even override individual init template "extra" files like `tasks/init/jquery/root/README.md` just by creating them. + +**When defining project-specific tasks or "extra" files, it's always a good idea to include those files in a grunt plugin or tasks directory referenced in the [grunt.js gruntfile](getting_started.md), and committed with the project when possible. This will help to guarantee consistent grunt behavior for all contributors to that project.** + +### grunt.task.searchDirs +An array of directory paths that grunt uses to search for task-related files, in "task path order." This array is used by all task-specific file listing methods. + +```javascript +grunt.task.searchDirs +``` + + +## File Lists and Wildcards +Wildcard patterns are resolved using the [glob-whatev library](https://github.com/cowboy/node-glob-whatev). See the [minimatch](https://github.com/isaacs/minimatch) module documentation for more details on supported wildcard patterns. + +There are also a number of [generic file listing methods](api_file.md) that list files relative to the [grunt.js gruntfile](getting_started.md). + +### grunt.task.getFile +Search tasks directories in "task path order" (via `grunt.task.searchDirs`) for a given file path, returning the path of the first matching file. + +**This is the primary method used to locate tasks files and extras files.** + +_Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path._ + +```javascript +grunt.task.getFile(path1 [, path2 [, ...]]) +``` + +### grunt.task.expand +Search task "search directories" for the given wildcard pattern(s), returning a unique array of all matching file paths as "file objects" in `grunt.task.searchDirs` "task path order." This method accepts one or more comma separated wildcard patterns as well as an array of wildcard patterns. + +The `options` object supports all [minimatch](https://github.com/isaacs/minimatch) options. + +```javascript +grunt.task.expand([options, ] patterns) +``` + +Each "file object" item in the returned array has the following properties, and if coerced to string via `String(fileobj)` or `fileObj.toString()` returns the absolute file path value. In this way, `.map(String)` can be called on the resulting array to return an array of absolute file path strings. + +```javascript +var fileobj = { + // The absolute path of the matched file or directory. + abs: absolutePath, + // The path of the matched file or directory, relative to the search + // directory in which it was found. + rel: relativePath, + // The search directory in which this file was found. + base: basePath +} +``` + +### grunt.task.expandDirs +This method behaves the same as `grunt.task.expand` except it only returns directory paths. + +```javascript +grunt.task.expandDirs([options, ] patterns) +``` + +### grunt.task.expandFiles +This method behaves the same as `grunt.task.expand` except it only returns file paths. + +```javascript +grunt.task.expandFiles([options, ] patterns) +``` + +## JSON Defaults + +### grunt.task.readDefaults +Search tasks directories for a given JSON file, merging the parsed data objects in "task path order" and returning the final merged object. + +**This is the primary method used to load task-related JSON default data.** + +_Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path._ + +```javascript +grunt.task.readDefaults(path1 [, path2 [, ...]]) +``` 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 new file mode 100644 index 0000000..99810e9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_template.md @@ -0,0 +1,72 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.template + +Underscore.js template processing and other template-related methods. + +Template strings can be processed manually using the provided template functions. In addition, many tasks and helpers automatically expand `<% %>` style template strings specified inside the [grunt.js gruntfile](getting_started.md) when used as file paths and banners. + +See the [template lib source](../lib/grunt/template.js) for more information. + +## The template API + +### grunt.template.process +Process an [Underscore.js template](http://underscorejs.org/#template) string. If `data` is omitted, the entire [config object](api_config.md) is used. Templates are processed recursively until there are no more templates to process. + +Inside templates, the `grunt` object is exposed as `grunt` so that you can do things like `<%= grunt.template.today('yyyy') %>`. _Note that if the `data` object has a `grunt` property, it will prevent this from working._ + +If `mode` is omitted, `<% %>` style template delimiters will be used. If `mode` is "init", `{% %}` style template delimiters will be used (this is specifically used by the [init task](task_init.md)). + +```javascript +grunt.template.process(template, data, mode) +``` + +In this example, the `baz` property is processed recursively until there are no more `<% %>` templates to process. + +```javascript +var obj = { + foo: 'c', + bar: 'b<%= foo %>d', + baz: 'a<%= bar %>e' +}; +grunt.template.process('<%= baz %>', obj) // 'abcde' +``` + +### grunt.template.delimiters +Set [Underscore.js template](http://underscorejs.org/#template) delimiters manually, in case you need to use `grunt.utils._.template` manually. You probably won't need to call this, because you'll be using `grunt.template.process` which calls this internally. + +If `mode` is omitted, `<% %>` style template delimiters will be used. If `mode` is "init", `{% %}` style template delimiters will be used (this is specifically used by the [init task](task_init.md)). + +```javascript +grunt.template.delimiters(mode) +``` + +## Template Helpers + +### grunt.template.date +Format a date using the [dateformat](https://github.com/felixge/node-dateformat) library. + +```javascript +grunt.template.date(date, format) +``` + +In this example, a specific date is formatted as month/day/year. + +```javascript +grunt.template.date(847602000000, 'yyyy-mm-dd') // '1996-11-10' +``` + +### grunt.template.today +Format today's date using the [dateformat](https://github.com/felixge/node-dateformat) library. + +```javascript +grunt.template.today(format) +``` + +In this example, today's date is formatted as a 4-digit year. + +```javascript +grunt.template.today('yyyy') // '2012' +``` + +_(somebody remind me to update this date every year so the docs appear current)_ 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 new file mode 100644 index 0000000..78b0fe1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/api_utils.md @@ -0,0 +1,126 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# [The grunt API](api.md) / grunt.utils + +Miscellaneous utilities, including Underscore.js, Async and Hooker. + +See the [utils lib source](../lib/grunt/utils.js) for more information. + +## The utils API + +### grunt.utils.kindOf +Return the "kind" of a value. Like `typeof` but returns the internal `[[Class]]` value. Possible results are `"number"`, `"string"`, `"boolean"`, `"function"`, `"regexp"`, `"array"`, `"date"`, `"error"`, `"null"`, `"undefined"` and the catch-all `"object"`. + +```javascript +grunt.utils.kindOf(value) +``` + +### grunt.utils.linefeed +The linefeed character, normalized for the current operating system. (`\r\n` on Windows, `\n` otherwise) + +### grunt.utils.normalizelf +Given a string, return a new string with all the linefeeds normalized for the current operating system. (`\r\n` on Windows, `\n` otherwise) + +```javascript +grunt.utils.normalizelf(string) +``` + +### grunt.utils.recurse +Recurse through nested objects and arrays, executing `callbackFunction` for each non-object value. If `continueFunction` returns `false`, a given object or value will be skipped. + +```javascript +grunt.utils.recurse(object, callbackFunction, continueFunction) +``` + +See the [config lib source](../lib/grunt/config.js) for usage examples. + +### grunt.utils.repeat +Return string `str` repeated `n` times. + +```javascript +grunt.utils.repeat(n, str) +``` + +### grunt.utils.pluralize +Given `str` of `"a/b"`, If `n` is `1`, return `"a"` otherwise `"b"`. You can specify a custom separator if '/' doesn't work for you. + +```javascript +grunt.utils.pluralize(n, str, separator) +``` + +### grunt.utils.spawn +Spawn a child process, keeping track of its stdout, stderr and exit code. The method returns a reference to the spawned child. When the child exits, the done function is called. + +```javascript +grunt.utils.spawn(options, doneFunction) +``` + +The `options` object has these possible properties: + +```javascript +var options = { + // The command to execute. It should be in the system path. + cmd: commandToExecute, + // An array of arguments to pass to the command. + args: arrayOfArguments, + // Additional options for the Node.js child_process spawn method. + opts: nodeSpawnOptions, + // If this value is set and an error occurs, it will be used as the value + // and null will be passed as the error value. + fallback: fallbackValue +}; +``` + +The done function accepts these arguments: + +```javascript +function doneFunction(error, result, code) { + // If the exit code was non-zero and a fallback wasn't specified, the error + // object is the same as the result object. + error + // The result object is an object with the properties .stdout, .stderr, and + // .code (exit code). + result + // When result is coerced to a string, the value is stdout if the exit code + // was zero, the fallback if the exit code was non-zero and a fallback was + // specified, or stderr if the exit code was non-zero and a fallback was + // not specified. + String(result) + // The numeric exit code. + code +} +``` + +See the [init task source](../tasks/init.js) and the [qunit task source](../tasks/qunit.js) for usage examples. + + +### grunt.utils.toArray +Given an array or array-like object, return an array. Great for converting `arguments` objects into arrays. + +```javascript +grunt.utils.toArray(arrayLikeObject) +``` + +## Internal libraries + +### grunt.utils.namespace +An internal library for resolving deeply-nested properties in objects. + +### grunt.utils.task +An internal library for task running. + + +## External libraries + +### grunt.utils._ +[Underscore.js](http://underscorejs.org/) - Tons of super-useful array, function and object utility methods. +[Underscore.string](https://github.com/epeli/underscore.string) - Tons of string utility methods. + +Note that Underscore.string is mixed into `grunt.utils._` but is also available as `grunt.utils._.str` for methods that conflict with existing Underscore.js methods. + +### grunt.utils.async +[Async](https://github.com/caolan/async) - Async utilities for node and the browser. + +### grunt.utils.hooker +[JavaScript Hooker](https://github.com/cowboy/javascript-hooker) - Monkey-patch (hook) functions for debugging and stuff. + diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md b/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md new file mode 100644 index 0000000..ab5b1a9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/contributing.md @@ -0,0 +1,51 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# Contributing to grunt + +If you want to make contributions to grunt, by all means, please do so. "Patches welcome." + +## Discussing grunt + +Join the [freenode](http://freenode.net/) #grunt IRC channel. We've got a bot and everything. + +## 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/gruntjs/grunt/issues). If you'd like to chat directly, pop into IRC. + +## Cloning grunt + +first, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. + +Fork grunt in GitHub, and clone it locally: + +```bash +git clone git://github.com/YOURUSERNAME/grunt.git && cd grunt +``` + +To download grunt dependencies and add the development `grunt` bin script to your path: + +```bash +npm install && npm link +``` + +## Reverting back to the "live" grunt + +If, for some reason, you need to revert back to the current npm grunt release, just reinstall grunt globally via: + +```bash +npm install -g grunt +``` + +## Actually contributing + +In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Fork, tweak, and make pull requests.. but `grunt` grunt first: + +```bash +grunt +``` + +_(you shouldn't see any red or yellow when you do this)_ + +## One final note about contributing + +I'll be completely up-front: while you know that your idea is well-reasoned and executed, I might need to be convinced of the value of incorporating it into grunt, because it might not be immediately apparent to me. Don't lose hope! All I ask is that you include, along with your pull request, an explanation of how your code is going to improve grunt. Thanks! 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 new file mode 100644 index 0000000..c6818f7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/example_gruntfiles.md @@ -0,0 +1,14 @@ +[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/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) + +_(Do you have a really crazy gruntfile? Let me know by filing an issue, and I'll try to include it here._ 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 new file mode 100644 index 0000000..f980217 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/exit_codes.md @@ -0,0 +1,16 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# Grunt exit codes + +* `1` - Generic error +* `2` - Config file not found +* `3` - Task failure +* `10` - [UglifyJS](https://github.com/mishoo/UglifyJS) error +* `11` - Banner generation error +* `20` - Init error +* `90-99` - [Nodeunit](https://github.com/caolan/nodeunit) / [QUnit](http://docs.jquery.com/QUnit) error + +## Nodeunit / QUnit specific + +* `90` - Non assertion-specific error, like a timeout or JavaScript error. +* `91-99` - 91 = 1 assertion failed, 95 = 5 assertions failed, 99 = 9 or more assertions failed (you get the idea). diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md b/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md new file mode 100644 index 0000000..ef657a4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/faq.md @@ -0,0 +1,51 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# Frequently Asked Questions + +## When will I be able to use in-development feature 'X'? +While critical bug fixes are applied to both the latest stable release as well as the in-development version of grunt, new features are usually only added to the in-development version. + +If you want to install the latest bleeding-edge, in-development version, you can npm install `grunt@devel`. _This is something you do not want to do in a project_, as the in-development version of grunt is constantly evolving and a feature you've come to depend on may have changed between installs of `grunt@devel`, thus breaking your build. + +If you want to install an in-development version of grunt, locked in at a specific commit (totally fine for projects), follow the instructions for specifying a [git URL as a dependency](https://npmjs.org/doc/json.html#Git-URLs-as-Dependencies), and be sure to specify an actual commit SHA (not a branch name) as the `commit-ish`. + +Finally, it is preferable to specify grunt as a [devDependency](https://npmjs.org/doc/json.html#devDependencies) in your project's [package.json](https://npmjs.org/doc/json.html) and instruct users to do `npm install` than to have them install grunt explicitly with `npm install grunt`. This makes the task of installing grunt (and any other dev dependencies) much easier and less error-prone. + +## On Windows, why does my JS editor open when I try to run grunt? +If you're in the same directory as the [grunt.js gruntfile](getting_started.md), Windows tries to execute _that file_ when you type grunt. So you need to type `grunt.cmd` instead. + +An alternative would be to use the `DOSKEY` command to create a grunt macro, following [these directions](http://devblog.point2.com/2010/05/14/setup-persistent-aliases-macros-in-windows-command-prompt-cmd-exe-using-doskey/). That would allow you to use `grunt` instead of `grunt.cmd`. + +This is the `DOSKEY` command you'd use: + +``` +DOSKEY grunt=grunt.cmd $* +``` + +## Why does grunt complain that PhantomJS isn't installed? +In order for the [qunit task](task_qunit.md) 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) + +## Why doesn't my asynchronous task complete? +Chances are this is happening because you have forgotten to call the [this.async](api_task.md#thisasync--grunttaskcurrentasync) method to tell grunt that your task is asynchronous. For simplicity's sake, grunt uses a synchronous coding style, which can be switched to asynchronous by calling `this.async()` within the task body. + +Note that passing `false` to the `done()` function tells grunt that the task has failed. + +For example: + +```javascript +grunt.registerTask('asyncme', 'My asynchronous task.', function() { + var done = this.async(); + doSomethingAsync(done); +}); +``` 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 new file mode 100644 index 0000000..5b17cd5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/getting_started.md @@ -0,0 +1,138 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# Getting Started + +**If you're starting from scratch, [install grunt](../#installing-grunt) and then check out the [init task](task_init.md), which will set up a new grunt-based project for you. Even if you don't ultimately use the files that are generated, you can very quickly learn how grunt works.** + +## The grunt.js file, aka "gruntfile" +Each time grunt is run, it looks in the current directory for a file named `grunt.js`. If this file is not found, grunt continues looking in parent directories until that file is found. This file is typically placed in the root of your project repository, and is a valid JavaScript file comprised of these parts: + +* Project configuration +* Loading grunt plugins or tasks folders +* Tasks and helpers + +This is an example of a very basic sample `grunt.js` gruntfile that does all three of these things. + +```javascript +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + lint: { + all: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + jshint: { + options: { + browser: true + } + } + }); + + // Load tasks from "grunt-sample" grunt plugin installed via Npm. + grunt.loadNpmTasks('grunt-sample'); + + // Default task. + grunt.registerTask('default', 'lint sample'); + +}; +``` + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all future examples on this page, but it needs to be there. Like in the previous example. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +Each grunt task relies on configuration information defined in an object passed to the [grunt.initConfig](api.md) method. + +For example, this basic config defines a list of files to be linted when the [lint task](task_lint.md) is run on the command line via `grunt lint`. + +```javascript +// Project configuration. +grunt.initConfig({ + lint: { + all: ['lib/*.js', 'test/*.js', 'grunt.js'] + } +}); +``` + +_Note: the [lint task](task_lint.md) is an example of a [multi task](api.md). You can run all targets of any multi task by just specifying the name of the task. In this case, running `grunt lint` would automatically run the `all` target and any others that might exist under `lint` instead of you having to run `grunt lint:all` explicitly._ + +In another example, this very simple configuration saved in the root of a [jQuery repository](https://github.com/jquery/jquery) clone allows the jQuery QUnit unit tests to be run via grunt with `grunt qunit`. Note that even though jQuery's unit tests run in grunt doesn't mean they're going to actually pass. QUnit is running headless, after all! + +```javascript +// Project configuration. +grunt.initConfig({ + qunit: { + index: ['test/index.html'] + } +}); +``` + +You can store any arbitrary information inside of the configuration object, and as long as it doesn't conflict with a property one of your tasks is using, it will be ignored. Also, because this is JavaScript and not JSON, you can use any valid JavaScript here. This allows you to programatically generate the configuration object, if necessary. + +See the documentation [table of contents](toc.md) for a list of tasks whose documentation will explain their specific configuration requirements. + +_Also note that you don't need to specify configuration settings for tasks that you don't use._ + +```javascript +// Project configuration. +grunt.initConfig({ + // Project metadata, used by some directives, helpers and tasks. + meta: {}, + // Lists of files to be concatenated, used by the "concat" task. + concat: {}, + // Lists of files to be linted with JSHint, used by the "lint" task. + lint: {}, + // Lists of files to be minified with UglifyJS, used by the "min" task. + min: {}, + // Lists of files or URLs to be unit tested with QUnit, used by the "qunit" task. + qunit: {}, + // Configuration options for the "server" task. + server: {}, + // Lists of files to be unit tested with Nodeunit, used by the "test" task. + test: {}, + // Configuration options for the "watch" task. + watch: {}, + // Global configuration options for JSHint. + jshint: {}, + // Global configuration options for UglifyJS. + uglify: {} +}); +``` + +## Loading grunt plugins or tasks folders + +While you can define [tasks and helpers](api.md) in your project's gruntfile, you can also load tasks from external sources. + +```javascript +// Load tasks and helpers from the "tasks" directory, relative to grunt.js. +grunt.loadTasks('tasks'); + +// Load tasks and helpers from the "grunt-sample" Npm-installed grunt plugin. +grunt.loadNpmTasks('grunt-sample'); +``` + +_Note: loading externally defined tasks and helpers in this way is preferred to loading them via the analogous `--tasks` and `--npm` command-line options. This is because when tasks are created or loaded in the `grunt.js` gruntfile, the tasks effectively become part of the project and will always be used (provided they are available) whenever `grunt` is run._ + +## Tasks and helpers + +You aren't required to define tasks in your project gruntfile, because grunt provides a number of built-in tasks. That being said, until you define a `default` task, grunt won't know what to do when you run it just as `grunt` without specifying any tasks, because grunt doesn't provide a default `default` task. + +The easiest way to define the default task is to create an [alias task](api.md). + +In the following example, a default task is defined that, when invoked by specifying `grunt` or `grunt default` on the command line, will execute the `lint`, `qunit`, `concat` and `min` tasks in-order. It behaves exactly as if `grunt lint qunit concat min` was run on the command line. + +```javascript +// Default task. +grunt.registerTask('default', 'lint qunit concat min'); +``` + +_Note: choose the default tasks that make the most sense for your project. If you find yourself commonly executing other groups of tasks, create as many named aliases as you need!_ + +Take a look at the [example gruntfiles](example_gruntfiles.md) or check out the [init task](task_init.md) for more configuration examples. 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 new file mode 100644 index 0000000..fb816c3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/helpers_directives.md @@ -0,0 +1,27 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# Helpers and Directives + +## Built-in Helpers +EXPLAIN + +Take a look at the [built-in tasks source code](../tasks) for more examples. + +## Built-in Directives + +### `` +Expands to the value of the `prop.subprop` config property. This can be any number of objects deep, `prop.subprop.otherprop.whatever` is totally valid. Great for DRYing up file lists. + +### `` +Expand to the object parsed from file.json via [grunt.file.parseJSON](api_file.md). + +### `` +Expand to the string in config property `prop.subprop`, parsed via [grunt.template.process](api_template.md), using `<% %>` delimiters. If the config property isn't specified like ``, defaults to the `meta.banner` property. + +### `` +Expand to the given file, with any leading `/*...*/` banner (excluding `/*!...*/` comments) stripped. Flags can be passed to instruct which banners to strip. The `line` flag (eg. ``) will remove a continguous block of leading `//` line comments, while the `block` flag (eg. ``) will strip _all_ block comments. + +### `` +Expand to the given file, parsed as a template via [grunt.template.process](api_template.md), using `<% %>` delimiters. + +Take a look at the [api documentation](api.md) and [example gruntfiles](example_gruntfiles.md) for directive creation and usage examples. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md b/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md new file mode 100644 index 0000000..5201c40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/plugins.md @@ -0,0 +1,50 @@ +[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](/gruntjs/grunt/issues) and we'll work it all out! + +## Why create a grunt plugin? + +Publishing a "grunt plugin" to Npm gives you 3 possible things: + +1. An easily-included-in-your-project set of tasks that get referenced in `grunt.js` when run via `grunt`. +2. A custom global binary that is like "some version of grunt, plus your specific extra stuff." +3. Either 1 or 2, depending on whether the plugin was installed globally or locally via Npm. + +Other than that, it's not too much more than a specific directory structure, contain some number of task files. You load a plugin locally installed via Npm via [grunt.loadNpmTasks](api.md), and you load tasks from a directory via [grunt.loadTasks](api.md). + +## Plugin creation and development + +1. Run `grunt init:gruntplugin` in an empty directory. +2. Run `npm install` to install grunt locally. +3. Run `./node_modules/.bin/grunt` to run the plugin-specific grunt. Just `grunt` won't work. +4. When done, run `npm publish` to publish the grunt plugin to npm! + +## Two usage options + +### 1. Global install, where you run `grunt-yourplugin` + +1. Run `npm install -g grunt-yourplugin`. This installs the plugin globally, which contains its own internal grunt (the version specified in the plugin's package.json). +2. A new `grunt-yourplugin` binary should be globally available. +3. When run from that binary, the internal grunt runs, and provides grunt's internal tasks and helpers plus all the plugin's tasks and helpers. + +Notes: + +* When executed via the plugin binary, eg. `grunt-yourplugin`, the internally-specified grunt will be used. This allows you to "lock in" a specific version of grunt to your plugin. + +### 2. Local install, where you run `grunt` + +1. Grunt should already have been installed globally with `npm install -g grunt`. +2. In your project's root, next to the grunt.js gruntfile, run `npm install grunt-yourplugin`. +3. Add [grunt.loadNpmTasks('grunt-yourplugin')](api.md) into the project's grunt.js gruntfile. +2. Run `grunt` and all of the `grunt-yourplugin` tasks and helpers should be available in addition to those already provided by grunt.. + +Notes: + +* Multiple plugins, eg. `grunt-yourplugin` and `grunt-anotherplugin` can be installed locally via Npm. +* [grunt.loadNpmTasks('grunt-yourplugin')](api.md) should behave exactly the same as [grunt.loadTasks('./node_modules/grunt-yourplugin/tasks')](api.md) does. It's less to type though, which is awesome. + +## TODOS + +* More docs. 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 new file mode 100644 index 0000000..eb2ba9f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_concat.md @@ -0,0 +1,169 @@ +[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. + +## About + +This task is a [multi task](types_of_tasks.md), meaning that grunt will automatically iterate over all `concat` targets if a target is not specified. + +_Need some help getting started with grunt? Visit the [getting started](getting_started.md) page. And if you're creating your own tasks or helpers, be sure to check out the [types of tasks](types_of_tasks.md) page as well as the [API documentation](api.md)._ + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all examples on this page, but it needs to be there. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +This example shows a brief overview of the [grunt.js gruntfile](getting_started.md) config properties used by the `concat` task. For a more in-depth explanation, see the usage examples. + +```javascript +// Project configuration. +grunt.initConfig({ + // Project metadata, used by the directive. + meta: {}, + // Lists of files to be concatenated. + concat: {} +}); +``` + +## Usage examples + +### Concatenating multiple files + +In this example, running `grunt concat:dist` (or `grunt concat` because `concat` is a [multi task](types_of_tasks.md)) will simply concatenate the three specified source files, in order, writing the output to `dist/built.js`. + +```javascript +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/intro.js', 'src/project.js', 'src/outro.js'], + dest: 'dist/built.js' + } + } +}); +``` + +With a slight modification, running `grunt concat` will join the specified source files using `;` instead of the default newline character. + +```javascript +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/intro.js', 'src/project.js', 'src/outro.js'], + dest: 'dist/built.js', + separator: ';' + } + } +}); +``` + +### Banner comments + +In this example, running `grunt concat:dist` (or `grunt concat` because `concat` is a [multi task](types_of_tasks.md)) will first strip any preexisting banner comment from the `src/project.js` file, then concatenate the result with a newly-generated banner comment, writing the output to `dist/built.js`. + +This generated banner will be the contents of the `meta.banner` underscore template string interpolated with the config object. In this case, those properties are the values imported from the `package.json` file (which are available via the `pkg` config property) plus today's date. + +_Note: you don't have to use an external JSON file. It's completely valid to create the `pkg` object inline in the config. That being said, if you already have a JSON file, you might as well reference it. See the [directives](helpers_directives.md) page for more information on the `` and `` directives and their options._ + +```javascript +// Project configuration. +grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */' + }, + concat: { + dist: { + src: ['', ''], + dest: 'dist/built.js' + } + } +}); +``` + +### Multiple build targets + +In this example, running `grunt concat` will build two separate files. One "basic" version, with the main file essentially just copied to `dist/basic.js`, and another "with_extras" concatenated version written to `dist/with_extras.js`. + +While each concat target can be built individually by running `grunt concat:basic` or `grunt concat:extras`, running `grunt concat` will build all concat targets. This is because `concat` is a [multi task](types_of_tasks.md). + +```javascript +// Project configuration. +grunt.initConfig({ + concat: { + basic: { + src: ['src/main.js'], + dest: 'dist/basic.js' + }, + extras: { + src: ['src/main.js', 'src/extras.js'], + dest: 'dist/with_extras.js' + } + } +}); +``` + +### Dynamic filenames + +Filenames can be generated dynamically by using `<%= %>` delimited underscore templates as filenames. + +In this example, running `grunt concat:dist` generates a destination file whose name is generated from the `name` and `version` properties of the referenced `package.json` file (via the `pkg` config property). + +```javascript +// Project configuration. +grunt.initConfig({ + pkg: '', + concat: { + dist: { + src: ['src/main.js'], + dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js' + } + }, +}); +``` + +### Advanced dynamic filenames + +In this more involved example, running `grunt concat` will build two separate files (because `concat` is a [multi task](types_of_tasks.md)). The destination file paths will be expanded dynamically based on the specified underscore templates, recursively if necessary. + +For example, if the `package.json` file contained `{"name": "awesome", "version": "1.0.0"}`, the files `dist/awesome/1.0.0/basic.js` and `dist/awesome/1.0.0/with_extras.js` would be generated. + +```javascript +// Project configuration. +grunt.initConfig({ + pkg: '', + dirs: { + src: 'src/files', + dest: 'dist/<%= pkg.name %>/<%= pkg.version %>' + }, + concat: { + basic: { + src: ['<%= dirs.src %>/main.js'], + dest: '<%= dirs.dest %>/basic.js' + }, + extras: { + src: ['<%= dirs.src %>/main.js', '<%= dirs.src %>/extras.js'], + dest: '<%= dirs.dest %>/with_extras.js' + } + } +}); +``` + +## Helpers + +A generic `concat` helper is available for use in any other task where file and/or [directive](helpers_directives.md) concatenation might be useful. In this example, a `;` separator is specified, although it defaults to linefeed if omitted: + +```javascript +var fooPlusBar = grunt.helper('concat', ['foo.txt', 'bar.txt'], {separator: ';'}); +``` + +See the [concat task source](../tasks/concat.js) for more information. 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 new file mode 100644 index 0000000..885b114 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_init.md @@ -0,0 +1,186 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# init (built-in task) +Generate project scaffolding from a predefined template. + +## About + +The `init` task initializes a new project, based on the current environment and the answers to a few questions. Once complete, a [grunt.js configuration file](getting_started.md) will be generated along with a complete directory structure, including a basic readme, license, package.json, sample source files and unit tests (etc). + +The exact files and contents created depend on the template chosen along with the answers to the questions asked. + +Unlike other tasks, init should only ever be run once for a project. Typically, it is run at the very beginning before work has begun, but it can be run later. **Just keep in mind that new files are generated, so for existing projects, ensure that everything is already committed first.** + +## Usage examples + +Change to a new directory, and type in `grunt init:TEMPLATE` where TEMPLATE is one of the following templates. Answer the questions. Watch grunt do it's thing. Done. Now you have fully initialized project scaffolding that you can customize, `grunt` and publish. + +## Built-in templates + +The init task currently supports a number of built-in templates. + +### gruntfile +Generated via `grunt init:gruntfile`, this customizable template creates a single [grunt.js gruntfile](getting_started.md) based on the answers to a few questions and some highly advanced "fuzzy logic" that tries to determine source and unit test paths. This is the template you want to use to generate a gruntfile for an existing project. + +If your code is DOM-related, [QUnit unit tests](task_qunit.md) will be used, otherwise Nodeunit unit tests will be used. Where appropriate, predefined [lint](task_lint.md), [concat](task_concat.md) and [minification](task_min.md) tasks are generated. Also, depending on the library used, JSHint globals may be predefined (just `jQuery` for now). + +**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/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/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/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/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. + +For example, my `defaults.json` file looks like this, because I want to use a slightly different name than the default name, I want to exclude my email address, and I want to specify an author url automatically. + +```javascript +{ + "author_name": "\"Cowboy\" Ben Alman", + "author_email": "none", + "author_url": "http://benalman.com/" +} +``` + +_Note: until all the built-in prompts have been documented, you can find each prompt name by looking for the `prompt_for` helpers' argument in the [init templates' source .js files](../tasks/init)._ + +## Overriding template files +You can override any init template file, even the init template itself. + +For example, the "jquery" init template exists inside of grunt at this path: + +* [tasks/init/jquery.js](../tasks/init/jquery.js) + +A set of jquery-template-specific rename rules exists at this path: + +* [tasks/init/jquery/rename.json](../tasks/init/jquery/rename.json) + +And any files to be copied by this template (because the template uses the `init.filesToCopy` and `init.copyAndProcess` methods), exist here: + +* [tasks/init/jquery/root/](../tasks/init/jquery/root) + +_Any_ of these files can be overridden via a referenced [grunt plugin](plugins.md) or tasks directory, OR via your [grunt.file.userDir](api_file.md) which is `%USERPROFILE%\.grunt\` on Windows, and `~/.grunt/` on OS X or Linux. This directory structure mimics grunt's internal directory structure. + +So you can override any of the aforementioned things for a given init template `TEMPLATE` with these OS X / linux paths: + +* `~/.grunt/tasks/init/TEMPLATE.js` +* `~/.grunt/tasks/init/TEMPLATE/rename.json` +* `~/.grunt/tasks/init/TEMPLATE/root/` + +Or these Windows paths (`%USERPROFILE%` is generally your `Documents and Settings` directory): + +* `%USERPROFILE%\.grunt\tasks\init\TEMPLATE.js` +* `%USERPROFILE%\.grunt\tasks\init\TEMPLATE\rename.json` +* `%USERPROFILE%\.grunt\tasks\init\TEMPLATE\root\` + +If you wanted to change the `gruntfile` init template `grunt.js` file, you could copy grunt's own [tasks/init/gruntfile/root/grunt.js](../tasks/init/gruntfile/root/grunt.js) to `~/.grunt/tasks/init/gruntfile/root/grunt.js` (or the Windows equivalent), edit it as you see fit, and when you run `grunt init:gruntfile` grunt will use your file. + +Assuming the template uses the `init.filesToCopy` and `init.copyAndProcess` methods, you can add any additional files into that "root" folder, with any arbitrarily-nested directory structure, and those files will be copied to the current directory when the init template is run. + +For example, since the `gruntfile` init template is just two files, the [tasks/init/gruntfile.js](../tasks/init/gruntfile.js) template and the [tasks/init/gruntfile/root/grunt.js](../tasks/init/gruntfile/root/grunt.js) file-to-be-copied, you could completely change its behavior by overriding both of those files. + +## Renaming or excluding template files +If, for some reason, you want to rename or exclude files, you can edit the aforementioned `rename.json` which describes a map of `sourcepath` to `destpath` values. The `sourcepath` must be the path of the file-to-be-copied relative to the `root/` folder, but the `destpath` value can contain `{% %}` init templates, as in any init file, and describes what the destination path will be. See the `jquery` init template [rename.json](../tasks/init/jquery/rename.json) file for an example. + +A few notes about `rename.json`: + +* If `false` is specified for the `destpath` the file will not be copied. +* The `rename.json` file is _merged_ using `grunt.task.readDefaults` so it _overrides_ built-in values. + +## Creating custom templates +You create a custom template the exact same way you override init templates and their files, you just use a unique template name. in your userDir, just create a `~/.grunt/tasks/init/MYTEMPLATE.js` and any other relevant files. See the "Overriding template files" and "Renaming or excluding template files" sections for all the details. + +## Defining an init template + +### exports.description +This brief template description will be displayed along with the template name when the user runs `grunt init` or `grunt init:` to display a list of all available init templates. + +```javascript +exports.description = descriptionString; +``` + +### exports.notes +If specified, this optional extended description will be displayed before any prompts are displayed. This is a good place to give the user a little help explaining naming conventions, which prompts may be required or optional, etc. + +```javascript +exports.notes = notesString; +``` + +### exports.warnOn +If this optional (but recommended) wildcard pattern or array of wildcard patterns is matched, grunt will abort with a warning that the user can override with `--force`. This is very useful in cases where the init template could potentially override existing files. + +```javascript +exports.warnOn = wildcardPattern; +``` + +While the most common value will be `'*'`, matching any file or directory, the [minimatch](https://github.com/isaacs/minimatch) wildcard pattern syntax used allows for a lot of flexibility. For example: + +```javascript +exports.warnOn = 'grunt.js'; // Warn on a grunt.js file. +exports.warnOn = '*.js'; // Warn on any .js file. +exports.warnOn = '*'; // Warn on any non-dotfile or non-dotdir. +exports.warnOn = '.*'; // Warn on any dotfile or dotdir. +exports.warnOn = '{.*,*}'; // Warn on any file or dir (dot or non-dot). +exports.warnOn = '!*/**'; // Warn on any file (ignoring dirs). +exports.warnOn = '*.{png,gif,jpg}'; // Warn on any image file. + +// This is another way of writing the last example. +exports.warnOn = ['*.png', '*.gif', '*.jpg']; +``` + +### exports.template +While the `exports` properties are defined outside this function, all the actual init code is specified inside. Three arguments are passed into this function. The `grunt` argument is a reference to grunt, containing all the [grunt methods and libs](api.md). The `init` argument is an object containing methods and properties specific to this init template. The `done` argument is a function that must be called when the init template is done executing. + +```javascript +exports.template = function(grunt, init, done) { + // See the "Inside an init template" section. +}; +``` + +## Inside an init template +_(Documentation coming soon)_ + + + +## Built-in prompts +_(Documentation coming soon)_ + +See the [init task source](../tasks/init.js) for more information. 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 new file mode 100644 index 0000000..bb79a1a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_lint.md @@ -0,0 +1,188 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# lint (built-in task) +Validate files with [JSHint][jshint]. + +[jshint]: http://www.jshint.com/ + +## About + +This task is a [multi task](types_of_tasks.md), meaning that grunt will automatically iterate over all `lint` targets if a target is not specified. + +_Need some help getting started with grunt? Visit the [getting started](getting_started.md) page. And if you're creating your own tasks or helpers, be sure to check out the [types of tasks](types_of_tasks.md) page as well as the [API documentation](api.md)._ + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all examples on this page, but it needs to be there. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +This example shows a brief overview of the [config](api_config.md) properties used by the `lint` task. For a more in-depth explanation, see the usage examples. + +```javascript +// Project configuration. +grunt.initConfig({ + // Lists of files to be linted with JSHint. + lint: {} +}); +``` + +## Usage examples + +### Wildcards + +In this example, running `grunt lint` will lint the project's gruntfile as well as all JavaScript files in the `lib` and `test` directories, using the default JSHint `options` and `globals`. + +```javascript +// Project configuration. +grunt.initConfig({ + lint: { + files: ['grunt.js', 'lib/*.js', 'test/*.js'] + } +}); +``` + +With a slight modification, running `grunt lint` will also lint all JavaScript files in the `lib` and `test` directories _and all subdirectories_. See the [minimatch](https://github.com/isaacs/minimatch) module documentation for more details on wildcard patterns. + +```javascript +// Project configuration. +grunt.initConfig({ + lint: { + files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + } +}); +``` + +### Linting before and after concat + +In this example, running `grunt lint` will lint two separate sets of files using the default JSHint `options` and `globals`: one "beforeconcat" set, and one "afterconcat" set. Running `grunt lint` will lint both sets of files all at once, because lint is a [multi task](types_of_tasks.md). This is not ideal, because `dist/output.js` may get linted before it gets created via the [concat task](task_concat.md)! + +In this case, you should lint the "beforeconcat" set first, then concat, then lint the "afterconcat" set, by running `grunt lint:beforeconcat concat lint:afterconcat`. + +```javascript +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/foo.js', 'src/bar.js'], + dest: 'dist/output.js' + } + }, + lint: { + beforeconcat: ['src/foo.js', 'src/bar.js'], + afterconcat: ['dist/output.js'] + } +}); + +// Default task. +grunt.registerTask('default', 'lint:beforeconcat concat lint:afterconcat'); +``` + +_Note: in the above example, a default [alias task](types_of_tasks.md) was created that runs the 'lint:beforeconcat', 'concat' and 'lint:afterconcat' tasks. If you didn't want this to be the default grunt task, you could give it a different name._ + +### Dynamic filenames + +Building on the previous example, if you want to avoid duplication, you can use a [directive](helpers_directives.md) like `''` in place of `'dist/output.js'` in the `afterconcat` lint target. This allows you to generate the output filename dynamically. In this example, the `concat:dist` destination filename is generated from the `name` and `version` properties of the referenced `package.json` file through the `pkg` config property. + +```javascript +// Project configuration. +grunt.initConfig({ + pkg: '', + concat: { + dist: { + src: ['src/foo.js', 'src/bar.js'], + dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js' + } + }, + lint: { + beforeconcat: ['src/foo.js', 'src/bar.js'], + afterconcat: [''] + } +}); +``` + +### Specifying JSHint options and globals + +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*/`._ + +```javascript +// Project configuration. +grunt.initConfig({ + lint: { + files: ['grunt.js', 'src/**/*.js', 'test/**/*.js'] + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true + }, + globals: { + jQuery: true + } + }, +}); +``` + +#### Per-target JSHint options and globals + +For each `lint` target, grunt looks for a target-named object underneath the `jshint` config object. If this object is found, its `options` and `globals` sub-objects will be used instead of the global ones. this allows per-lint-target JSHint options/globals overrides. + +In this example, there are default JSHint settings, as well as per-target overrides: + +```javascript +// Project configuration. +grunt.initConfig({ + lint: { + src: 'src/*.js', + grunt: 'grunt.js', + tests: 'tests/unit/**/*.js' + }, + jshint: { + // Defaults. + options: {curly: true}, + globals: {}, + // Just for the lint:grunt target. + grunt: { + options: {node: true}, + globals: {task: true, config: true, file: true, log: true, template: true} + }, + // Just for the lint:src target. + src: { + options: {browser: true}, + globals: {jQuery: true} + }, + // Just for the lint:tests target. + tests: { + options: {jquery: true}, + globals: {module: true, test: true, ok: true, equal: true, deepEqual: true, QUnit: true} + } + } +}); +``` + +## Helpers + +A generic `lint` helper is available for use in any other task where file linting might be useful. For example: + +```javascript +var filename = 'example.js'; +var src = grunt.file.read(filename); +grunt.helper('lint', src, {browser: true}, {jQuery: true}, filename); +``` + +See the [lint task source](../tasks/lint.js) for more information. 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 new file mode 100644 index 0000000..c184cbd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_min.md @@ -0,0 +1,192 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# min (built-in task) +Minify files with [UglifyJS][uglify]. + +[uglify]: https://github.com/mishoo/UglifyJS/ + +## About + +This task is a [multi task](types_of_tasks.md), meaning that grunt will automatically iterate over all `min` targets if a target is not specified. + +_Need some help getting started with grunt? Visit the [getting started](getting_started.md) page. And if you're creating your own tasks or helpers, be sure to check out the [types of tasks](types_of_tasks.md) page as well as the [API documentation](api.md)._ + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all examples on this page, but it needs to be there. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +This example shows a brief overview of the [config](api_config.md) properties used by the `min` task. For a more in-depth explanation, see the usage examples. + +```javascript +// Project configuration. +grunt.initConfig({ + // Project metadata, used by the directive. + meta: {}, + // Lists of files to be minified with UglifyJS. + min: {} +}); +``` + +## Usage examples + +### Minifying individual files + +In this example, running `grunt min:dist` (or `grunt min` because `min` is a [multi task](types_of_tasks.md)) will minify the specified source file, writing the output to `dist/built.min.js`. + +_Note that UglifyJS strips all comments from the source, including banner comments. See the "Banner comments" example for instructions on how to add a banner to the generated source._ + +```javascript +// Project configuration. +grunt.initConfig({ + min: { + dist: { + src: ['dist/built.js'], + dest: 'dist/built.min.js' + } + } +}); +``` + +### Minifying while concatenating files + +In this example, running `grunt min:dist` (or `grunt min` because `min` is a [multi task](types_of_tasks.md)) will first concatenate the three specified source files, in order, minifying the result and writing the output to `dist/built.min.js`. + +_Note that UglifyJS strips all comments from the source, including banner comments. See the "Banner comments" example for instructions on how to add a banner to the generated source._ + +```javascript +// Project configuration. +grunt.initConfig({ + min: { + dist: { + src: ['src/intro.js', 'src/project.js', 'src/outro.js'], + dest: 'dist/built.min.js' + } + } +}); +``` + +With a slight modification, running `grunt min` will join the specified source files using `;` instead of the default newline character before minification. + +```javascript +// Project configuration. +grunt.initConfig({ + min: { + dist: { + src: ['src/intro.js', 'src/project.js', 'src/outro.js'], + dest: 'dist/built.min.js', + separator: ';' + } + } +}); +``` + +### Minifying and concatenating separately + +Often, it's desirable to create both unminified and minified distribution files. In these cases, the [concat task](task_concat.md) should be run first, followed by the `min` task. + +In this example, running `grunt concat:dist min:dist` (or `grunt concat min` because both `concat` and `min` are [multi tasks](types_of_tasks.md)) will first concatenate the three specified source files, in order, writing the output to `dist/built.js`. After that, grunt will minify the newly-created file, writing the output to `dist/built.min.js`. + +_Note that UglifyJS strips all comments from the source, including banner comments. See the "Banner comments" example for instructions on how to add a banner to the generated source._ + +```javascript +// Project configuration. +grunt.initConfig({ + concat: { + dist: { + src: ['src/intro.js', 'src/project.js', 'src/outro.js'], + dest: 'dist/built.js' + } + }, + min: { + dist: { + src: ['dist/built.js'], + dest: 'dist/built.min.js' + } + } +}); +``` + +### Banner comments + +In this example, running `grunt min:dist` (or `grunt min` because `min` is a [multi task](types_of_tasks.md)) will first strip any preexisting comments from the `src/project.js` file (because that's how UglifyJS works), then concatenate the result with a newly-generated banner comment, writing the output to `dist/built.js`. + +This generated banner will be the contents of the `meta.banner` underscore template string interpolated with the config object. In this case, those properties are the values imported from the `package.json` file (which are available via the `pkg` config property) plus today's date. + +_Note: you don't have to use an external JSON file. It's completely valid to create the `pkg` object inline in the config. That being said, if you already have a JSON file, you might as well reference it. See the [directives](helpers_directives.md) page for more information on the `` and `` directives and their options._ + +```javascript +// Project configuration. +grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */' + }, + min: { + dist: { + src: ['', 'dist/built.js'], + dest: 'dist/built.min.js' + } + } +}); +``` + +### Specifying UglifyJS options + +In this example, custom UglifyJS `mangle`, `squeeze` and `codegen` options are specified. The listed methods and their expected options are explained in the API section of the [UglifyJS documentation][uglify]: + +* The `mangle` object is passed into the `pro.ast_mangle` method. +* The `squeeze` object is passed into the `pro.ast_squeeze` method. +* The `codegen` object is passed into the `pro.gen_code` method. + +```javascript +// Project configuration. +grunt.initConfig({ + min: { + dist: { + src: ['dist/built.js'], + dest: 'dist/built.min.js' + } + }, + uglify: { + mangle: {toplevel: true}, + squeeze: {dead_code: false}, + codegen: {quote_keys: true} + } +}); +``` + +## Helpers + +A generic `uglify` helper is available for use in any other task where file minification might be useful. For example: + +```javascript +var src = grunt.file.read('example.js'); +var minSrc = grunt.helper('uglify', {mangle: {except: ['zomg']}}); +``` + +A generic `gzip` helper is available for use in any other task where gzipped text might be useful. For example: + +```javascript +var src = grunt.file.read('example.js'); +var gzipSrc = grunt.helper('gzip', src); +grunt.log.writeln('Original size: ' + src.length + ' bytes.'); +grunt.log.writeln('Gzipped size: ' + gzipSrc.length + ' bytes.'); +``` + +To this end, a specialized `min_max_info` helper is available for use in any other task where before-compression & after-compression sizes need to be logged. For example: + +```javascript +var src = grunt.file.read('example.js'); +var minSrc = grunt.helper('uglify', {mangle: {except: ['zomg']}}); +grunt.helper('min_max_info', minSrc, src); +``` + +See the [min task source](../tasks/min.js) for more information. 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 new file mode 100644 index 0000000..855f5a9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_qunit.md @@ -0,0 +1,118 @@ +[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. + +[qunit]: http://docs.jquery.com/QUnit +[phantom]: http://www.phantomjs.org/ + +## About + +This task is a [multi task](types_of_tasks.md), meaning that grunt will automatically iterate over all `qunit` targets if a target is not specified. + +_Need some help getting started with grunt? Visit the [getting started](getting_started.md) page. And if you're creating your own tasks or helpers, be sure to check out the [types of tasks](types_of_tasks.md) page as well as the [API documentation](api.md)._ + +### QUnit + +[QUnit][qunit] is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery project to test its code and plugins but is capable of testing any generic JavaScript code. + +### PhantomJS + +[PhantomJS](http://www.phantomjs.org/) is a headless WebKit with JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG. PhantomJS is required for the `qunit` task to work. + +See the [FAQ](faq.md) for instructions on installing PhantomJS. + + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all examples on this page, but it needs to be there. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +This example shows a brief overview of the [config](api_config.md) properties used by the `qunit` task. For a more in-depth explanation, see the usage examples. + +```javascript +// Project configuration. +grunt.initConfig({ + // Lists of files or URLs to be unit tested with QUnit. + qunit: {} +}); +``` + +## Usage examples + +### Wildcards + +In this example, `grunt qunit` will test all `.html` files in the test directory. First, the wildcard is expanded to match each individual file. Then, each matched filename is converted to the appropriate `file://` URI. Finally, [QUnit][qunit] is run for each URI. + +```javascript +// Project configuration. +grunt.initConfig({ + qunit: { + all: ['test/*.html'] + } +}); +``` + +With a slight modification, `grunt qunit` will test all `.html` files in the test directory _and all subdirectories_. See the [minimatch](https://github.com/isaacs/minimatch) module's documentation for more details on wildcard patterns. + +```javascript +// Project configuration. +grunt.initConfig({ + qunit: { + all: ['test/**/*.html'] + } +}); +``` + +### Testing via http:// or https:// + +In circumstances where running unit tests from `file://` URIs is inadequate, you can specify `http://` or `https://` URIs instead. If `http://` or `https://` URIs have been specified, those URIs will be passed directly into [QUnit][qunit] as-specified. + +In this example, `grunt qunit` will test two files, served from the server running at `localhost:8000`. + +```javascript +// Project configuration. +grunt.initConfig({ + qunit: { + all: ['http://localhost:8000/test/foo.html', 'http://localhost:8000/test/bar.html'] + } +}); +``` + +_Note: grunt does NOT start a server at `localhost:8000` automatically. While grunt DOES have a [server task](task_server.md) that can be run before the qunit task to serve files statically, it must be started manually..._ + +### Using the built-in static webserver + +If a web server isn't running at `localhost:8000`, running `grunt qunit` with `http://localhost:8000/` URIs will fail because grunt won't be able to load those URIs. This can be easily rectified by starting the built-in static web server via the [server task](task_server.md). + +In this example, running `grunt server qunit` will first start a static web server on `localhost:8000`, with its base path set to the gruntfile's directory. Then, the `qunit` task will be run, requesting the specified URIs from that server. + +```javascript +// Project configuration. +grunt.initConfig({ + qunit: { + all: ['http://localhost:8000/test/foo.html', 'http://localhost:8000/test/bar.html'] + }, + server: { + port: 8000, + base: '.' + } +}); + +// A convenient task alias. +grunt.registerTask('test', 'server qunit'); +``` + +_Note: in the above example, an [alias task](types_of_tasks.md) called `test` was created that runs both the `server` and `qunit` tasks._ + +## Debugging + +Running grunt with the `--debug` flag will output a lot of PhantomJS-specific debugging information. This can be very helpful in seeing what actual URIs are being requested and received by PhantomJS. + +See the [qunit task source](../tasks/qunit.js) for more information. 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 new file mode 100644 index 0000000..3ee0335 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/task_server.md @@ -0,0 +1,75 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) | [Documentation table of contents](toc.md) + +# server (built-in task) +Start a static web server. + +## About + +This task starts a static web server on a specified port, at a specified path, which runs as long as grunt is running. Once grunt's tasks have completed, the web server stops. + +_Need some help getting started with grunt? Visit the [getting started](getting_started.md) page. And if you're creating your own tasks or helpers, be sure to check out the [types of tasks](types_of_tasks.md) page as well as the [API documentation](api.md)._ + +## A Very Important Note +Your `grunt.js` gruntfile **must** contain this code, once and **only** once. If it doesn't, grunt won't work. For the sake of brevity, this "wrapper" code has been omitted from all examples on this page, but it needs to be there. + +```javascript +module.exports = function(grunt) { + // Your grunt code goes in here. +}; +``` + +## Project configuration + +This example shows a brief overview of the [config](api_config.md) properties used by the `server` task. For a more in-depth explanation, see the usage examples. + +```javascript +// Project configuration. +grunt.initConfig({ + // Configuration options. + server: {} +}); +``` + +## Usage examples + +### Basic Use + +In this example, `grunt server` will start a static web server at `http://localhost:8000/`, with its base path set to the gruntfile's directory. Of course, it will then immediately stop serving files, because grunt exits automatically when there are no more tasks to run. + +The `server` task is most useful when used in conjunction with another task, like the [qunit](task_qunit.md) task. + +```javascript +// Project configuration. +grunt.initConfig({ + server: { + port: 8000, + base: '.' + } +}); +``` + +### Roll Your Own + +Unlike the previous example, in this example the `grunt server` command will run a completely custom `server` task, because it has been overridden. This version is hard-coded to start a static web server at `http://localhost:1234/`, with its base path set to `www-root` subdirectory. + +Like the previous example, it will then immediately stop serving files, because grunt exits automatically when there are no more tasks to run, but you'll undoubtedly be running additional tasks after this one. + +```javascript +// Project configuration. +grunt.initConfig({ + // This custom server task doesn't care about config options! +}); + +// Of course, you need to have the "connect" Npm module installed locally +// for this to work. But that's just a matter of running: npm install connect +var connect = require('connect'); + +// Redefining the "server" task for this project. Note that the output +// displayed by --help will reflect the new task description. +grunt.registerTask('server', 'Start a custom static web server.', function() { + grunt.log.writeln('Starting static web server in "www-root" on port 1234.'); + connect(connect.static('www-root')).listen(1234); +}); +``` + +See the [server task source](../tasks/server.js) for more information. diff --git a/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md b/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md new file mode 100644 index 0000000..a2a8778 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/toc.md @@ -0,0 +1,42 @@ +[Grunt homepage](https://github.com/gruntjs/grunt) + +# Documentation table of contents + +## Getting started + +* [Getting started](getting_started.md) - A guide to configuring grunt for your project. +* [Example gruntfiles](example_gruntfiles.md) - A few samples, to help you get started. +* [The grunt API](api.md) - Complete API documentation here! +* [FAQ](faq.md) - Frequently asked questions, along with their answers. +* [Exit codes](exit_codes.md) - A list of all built-in grunt exit codes. + +## Built-in tasks + +* [concat](task_concat.md) - Concatenate files. +* [init](task_init.md) - Generate project scaffolding from a predefined template. +* [lint](task_lint.md) - Validate files with [JSHint][jshint]. +* [min](task_min.md) - Minify files with [UglifyJS][uglify]. +* [qunit](task_qunit.md) - Run [QUnit][qunit] unit tests in a headless [PhantomJS][phantom] instance. +* [server](task_server.md) - Start a static web server. +* _(more documentation coming soon)_ + + + +[jshint]: http://www.jshint.com/ +[uglify]: https://github.com/mishoo/UglifyJS/ +[nodeunit]: https://github.com/caolan/nodeunit +[qunit]: http://docs.jquery.com/QUnit +[phantom]: http://www.phantomjs.org/ + +## Other built-ins + +* [Helpers and Directives](helpers_directives.md) - Ones not specifically covered in other task documentation. + +## Development + +* [Contributing to grunt](contributing.md) - Development advice. + + 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 new file mode 100644 index 0000000..3a9f752 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/docs/types_of_tasks.md @@ -0,0 +1,252 @@ +[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).** + +# Types of Tasks + +Tasks are grunt's bread and butter. The stuff you do most often, like `concat` or `test`. Every time grunt is run, you specify one more more tasks, which tells grunt what you'd like it to do. + +_Note: if you don't specify a task, but a task named "default" has been defined, that task will run (unsurprisingly) by default._ + +Tasks can be created in a few ways. + +## Alias tasks + +```javascript +grunt.registerTask(taskName, [description, ] taskList); +``` + +_Note that for alias tasks, the description is optional. If omitted, a useful description will be added for you automatically._ + +In the following example, a `theworks` task is defined that, when invoked by `grunt theworks`, will execute the `lint`, `qunit`, `concat` and `min` tasks in-order. Running `grunt theworks` behaves exactly as if `grunt lint qunit concat min` was run on the command line. + +```javascript +grunt.registerTask('theworks', 'lint qunit concat min'); +``` + +In this example, a default task is defined that, when invoked by `grunt` or `grunt default`, will execute the `lint`, `qunit`, `concat` and `min` tasks in-order. It behaves exactly as if `grunt lint qunit concat min` was run on the command line. + +```javascript +grunt.registerTask('default', 'lint qunit concat min'); +``` + +_In case it's not obvious, defining a `default` task is helpful because it runs by default, whenever you run `grunt` without explicitly specifying tasks._ + +## Multi tasks +A multi task is a task that implicitly iterates over all of its targets if no target is specified. For example, in the following, while `grunt lint:test` or `grunt lint:lib` will lint only those specific sets of files, `grunt lint` will automatically run the `test`, `lib` and `grunt` targets for you. It's super convenient. + +_Note: multi tasks will ignore any config sub-properties beginning with `_` (underscore)._ + +```javascript +/*global config:true, task:true*/ +grunt.initConfig({ + lint: { + test: ['test/*.js'], + lib: ['lib/*.js'], + grunt: ['grunt.js'] + } +}); +``` + +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*/ +grunt.initConfig({ + logstuff: { + foo: [1, 2, 3], + bar: 'hello world', + baz: false + } +}); + +grunt.registerMultiTask('logstuff', 'This task logs stuff.', function() { + // this.target === the name of the target + // this.data === the target's value in the config object + // this.name === the task name + // this.args === an array of args specified after the target on the command-line + // this.flags === a map of flags specified after the target on the command-line + // this.file === file-specific .src and .dest properties + + // Log some stuff. + grunt.log.writeln(this.target + ': ' + this.data); + + // If data was falsy, abort!! + if (!this.data) { return false; } + grunt.log.writeln('Logging stuff succeeded.'); +}); +``` + +Sample grunt output from running `logstuff` targets individually: + +``` +$ grunt logstuff:foo +Running "logstuff:foo" (logstuff) task +foo: 1,2,3 +Logging stuff succeeded. + +Done, without errors. + +$ grunt logstuff:bar +Running "logstuff:bar" (logstuff) task +bar: hello world +Logging stuff succeeded. + +Done, without errors. + +$ grunt logstuff:baz +Running "logstuff:baz" (logstuff) task +baz: false + Task "logstuff:baz" failed. Use --force to continue. + +Aborted due to warnings. +``` + +Sample grunt output from running `logstuff` task: + +``` +$ grunt logstuff +Running "logstuff:foo" (logstuff) task +foo: 1,2,3 +Logging stuff succeeded. + +Running "logstuff:bar" (logstuff) task +bar: hello world +Logging stuff succeeded. + +Running "logstuff:baz" (logstuff) task +baz: false + Task "logstuff:baz" failed. Use --force to continue. + +Aborted due to warnings. +``` + +## Custom tasks +You can go crazy with tasks. If your tasks don't follow the "multi task" structure, use a custom task. + +```javascript +grunt.registerTask('default', 'My "default" task description.', function() { + grunt.log.writeln('Currently running the "default" task.'); +}); +``` + +Inside a task, you can run other tasks. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + // Enqueue "bar" and "baz" tasks, to run after "foo" finishes, in-order. + grunt.task.run('bar baz'); + // Or: + grunt.task.run(['bar', 'baz']); +}); +``` + +Tasks can be asynchronous. + +```javascript +grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() { + // Force task into async mode and grab a handle to the "done" function. + var done = this.async(); + // Run some sync stuff. + grunt.log.writeln('Processing task...'); + // And some async stuff. + setTimeout(function() { + grunt.log.writeln('All done!'); + done(); + }, 1000); +}); +``` + +Tasks can access their own name and arguments. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function(a, b) { + grunt.log.writeln(this.name, a, b); +}); + +// Usage: +// grunt foo foo:bar +// logs: "foo", undefined, undefined +// logs: "foo", "bar", undefined +// grunt foo:bar:baz +// logs: "foo", "bar", "baz" +``` + +Tasks can fail if any errors were logged. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + if (failureOfSomeKind) { + grunt.log.error('This is an error message.'); + } + + // Fail task if errors were logged. + if (task.hadErrors()) { return false; } + + grunt.log.writeln('This is the success message'); +}); +``` + +When tasks fail, all subsequent tasks will be aborted unless `--force` was specified. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + // Fail synchronously. + return false; +}); + +grunt.registerTask('bar', 'My "bar" task.', function() { + var done = this.async(); + setTimeout(function() { + // Fail asynchronously. + done(false); + }, 1000); +}); +``` + +Tasks can be dependent on the successful execution of other tasks. Note that `grunt.task.requires` won't actually RUN the other task(s). It'll just check to see that it has run and not failed. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + return false; +}); + +grunt.registerTask('bar', 'My "bar" task.', function() { + // Fail task if "foo" task failed or never ran. + grunt.task.requires('foo'); + // This code executes if the "foo" task ran successfully. + grunt.log.writeln('Hello, world.'); +}); + +// Usage: +// grunt foo bar +// doesn't log, because foo failed. +// grunt bar +// doesn't log, because foo never ran. +``` + +Tasks can fail if required configuration properties don't exist. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + // Fail task if "meta.name" config prop is missing. + grunt.config.requires('meta.name'); + // Also fails if "meta.name" config prop is missing. + grunt.config.requires(['meta', 'name']); + // Log... conditionally. + grunt.log.writeln('This will only log if meta.name is defined in the config.'); +}); +``` + +Tasks can access configuration properties. + +```javascript +grunt.registerTask('foo', 'My "foo" task.', function() { + // Log the property value. Returns null if the property is undefined. + grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name')); + // Also logs the property value. Returns null if the property is undefined. + grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name'])); +}); +``` + +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 new file mode 100644 index 0000000..bd6958d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/grunt.js @@ -0,0 +1,55 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + test: { + all: ['test/**/*.js'] + }, + lint: { + all: [ + 'grunt.js', + 'lib/**/*.js', + 'tasks/*.js', + 'tasks/*/*.js', + 'test/{grunt,tasks,util}/*.js' + ] + }, + watch: { + scripts: { + files: '', + tasks: 'lint test' + } + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + node: true, + es5: true, + strict: false + }, + globals: {} + } + }); + + // Default task. + grunt.registerTask('default', 'lint test'); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js new file mode 100644 index 0000000..79b4f36 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt.js @@ -0,0 +1,151 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Nodejs libs. +var path = require('path'); + +// The module to be exported. +var grunt = module.exports = {}; + +// Expose internal grunt libs. +function gRequire(name) { + return grunt[name] = require('./grunt/' + name); +} +var utils = gRequire('utils'); +var template = gRequire('template'); +var fail = gRequire('fail'); +var file = gRequire('file'); +var option = gRequire('option'); +var config = gRequire('config'); +var task = gRequire('task'); +var log = gRequire('log'); +var cli = gRequire('cli'); +var verbose = grunt.verbose = log.verbose; + +grunt.version = file.readJSON(path.join(__dirname, '../package.json')).version; + +// Expose specific grunt lib methods on grunt. +function gExpose(obj, methodName, newMethodName) { + grunt[newMethodName || methodName] = obj[methodName].bind(obj); +} +gExpose(task, 'registerTask'); +gExpose(task, 'registerMultiTask'); +gExpose(task, 'registerInitTask'); +gExpose(task, 'renameTask'); +gExpose(task, 'registerHelper'); +gExpose(task, 'renameHelper'); +gExpose(task, 'helper'); +gExpose(task, 'loadTasks'); +gExpose(task, 'registerTask'); +gExpose(task, 'loadNpmTasks'); +gExpose(config, 'init', 'initConfig'); +gExpose(fail, 'warn'); +gExpose(fail, 'fatal'); + +// Handle exceptions. +// process.on('uncaughtException', function (e) { +// fail.warn(e, 3); +// }); + +// Disable colors if --no-colors was passed. +function initColors() { + var methods = Object.keys(String.prototype); + // Requiring this here will modify String prototype everywhere. + require('colors'); + + // Disable colors. + if (option('no-color')) { + // Override "colors". + Object.keys(String.prototype).filter(function(method) { + // Filter out methods that existed before "colors" was required. + return methods.indexOf(method) === -1; + }).forEach(function(method) { + // Replace each new method with a function that just returns `this`. + String.prototype.__defineGetter__(method, function() { return this; }); + }); + + // Override console.log (nodeunit, maybe others). + console._log = console.log; + console.log = function() { + var args = utils.toArray(arguments).map(function(value) { + if (typeof value === 'string') { + return value.replace(/\033\[[\d;]+m/g, ''); + } + return value; + }); + console._log.apply(console, args); + }; + } +} + +// Expose the task interface. I've never called this manually, and have no idea +// how it will work. But it might. +grunt.tasks = function(tasks, options, done) { + // Update options with passed-in options. + option.init(options); + + // Init colors. + initColors(); + + if (option('help')) { + // Load and display help if the user did --help. + require('./grunt/help'); + } else if (option('version')) { + // Display the current grunt version if the user did --version. + log.writeln('grunt v' + grunt.version); + return; + } + + // A little header stuff. + verbose.header('Initializing').writeflags(option.flags(), 'Command-line options'); + + // Determine and output which tasks will be run. + var tasksSpecified = tasks && tasks.length > 0; + tasks = task.parseArgs([tasksSpecified ? tasks : 'default']); + + // Initialize tasks. + task.init(tasks); + + verbose.writeln(); + if (!tasksSpecified) { + verbose.writeln('No tasks specified, running default tasks.'); + } + verbose.writeflags(tasks, 'Running tasks'); + + // Report, etc when all tasks have completed. + task.options({ + error: function(e) { + fail.warn(e, 3); + }, + done: function() { + // Output a final fail / success report. + fail.report(); + + if (done) { + // Execute "done" function when done (only if passed, of course). + done(); + } else { + // Otherwise, explicitly exit. + process.exit(0); + } + } + }); + + // Execute all tasks, in order. Passing each task individually in a forEach + // allows the error callback to execute multiple times. + tasks.forEach(function(name) { task.run(name); }); + task.start(); +}; + +// Register one or more Npm-installed grunt plugins inside that plugin's bin. +grunt._npmTasks = []; +grunt.npmTasks = function(tasks) { + grunt._npmTasks = Array.isArray(tasks) ? tasks : [tasks]; + return grunt; +}; 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 new file mode 100644 index 0000000..2876c18 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/cli.js @@ -0,0 +1,115 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// Nodejs libs. +var path = require('path'); + +// External libs. +var nopt = require('nopt'); + +// This is only executed when run via command line. +var cli = module.exports = function(options, done) { + // CLI-parsed options override any passed-in "default" options. + if (options) { + // For each defult option... + Object.keys(options).forEach(function(key) { + if (!(key in cli.options)) { + // If this option doesn't exist in the parsed cli.options, add it in. + cli.options[key] = options[key]; + } else if (cli.optlist[key].type === Array) { + // If this option's type is Array, append it to any existing array + // (or create a new array). + [].push.apply(cli.options[key], options[key]); + } + }); + } + + // Run tasks. + grunt.tasks(cli.tasks, cli.options, done); +}; + +// Default options. +var optlist = cli.optlist = { + help: { + short: 'h', + info: 'Display this help text.', + type: Boolean + }, + base: { + info: 'Specify an alternate base path. By default, all file paths are relative to the "grunt.js" gruntfile. (grunt.file.setBase) *', + type: path + }, + color: { + info: 'Disable colored output.', + type: Boolean, + negate: true + }, + config: { + info: 'Specify an alternate "grunt.js" gruntfile.', + type: path + }, + debug: { + short: 'd', + info: 'Enable debugging mode for tasks that support it. For detailed error stack traces, specify --debug 9.', + type: Number + }, + force: { + short: 'f', + info: 'A way to force your way past warnings. Want a suggestion? Don\'t use this option, fix your code.', + type: Boolean + }, + tasks: { + info: 'Additional directory paths to scan for task and "extra" files. (grunt.loadTasks) *', + type: Array + }, + npm: { + info: 'Npm-installed grunt plugins to scan for task and "extra" files. (grunt.loadNpmTasks) *', + type: Array + }, + write: { + info: 'Disable writing files (dry run).', + type: Boolean, + negate: true + }, + verbose: { + short: 'v', + info: 'Verbose mode. A lot more information output.', + type: Boolean + }, + version: { + info: 'Print the grunt version.', + type: Boolean + } +}; + +// Parse `optlist` into a form that nopt can handle. +var aliases = {}; +var known = {}; + +Object.keys(optlist).forEach(function(key) { + var short = optlist[key].short; + if (short) { + aliases[short] = '--' + key; + } + known[key] = optlist[key].type; +}); + +var parsed = nopt(known, aliases, process.argv, 2); +cli.tasks = parsed.argv.remain; +cli.options = parsed; +delete parsed.argv; + +// Initialize any Array options that weren't initialized. +Object.keys(optlist).forEach(function(key) { + if (optlist[key].type === Array && !(key in cli.options)) { + cli.options[key] = []; + } +}); 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 new file mode 100644 index 0000000..134c115 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/config.js @@ -0,0 +1,129 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// The actual config data. +var data; + +// Get/set config data. If data hasn't been set, return null. If value was +// passed, set value. If props string wasn't passed, return all data. Otherwise, +// return the prop's value. +var config = module.exports = function(prop, value) { + if (arguments.length === 2) { + // Two arguments were passed, set the property's value. + return config.set(prop, value); + } else { + // Get the property's value (or the entire data object). + return config.get(prop); + } +}; + +// If prop is an array, convert it to a props string. +function getPropString(prop) { + if (grunt.utils.kindOf(prop) === 'array') { + return prop.map(config.escape).join('.'); + } + return prop; +} + +// Recursively expand config directives. +function processDirectives() { + // These directives should be processed now. + var toProcess = ['config', 'json']; + data = grunt.utils.recurse(data, function(value) { + if (typeof value !== 'string') { return value; } + var parts = grunt.task.getDirectiveParts(value) || []; + return toProcess.indexOf(parts[0]) !== -1 ? grunt.task.directive(value) : value; + }); +} + +// Get config data. +config.get = function(prop) { + // Abort if no config data exists. + if (!data) { return null; } + // If prop is an array, convert it to a prop string. + prop = getPropString(prop); + + if (prop) { + // A property string/array was passed, get that property's value. + return grunt.utils.namespace.get(data, prop); + } else { + // Nothing was passed. Return a shalow clone of the actual config data. + return grunt.utils._.clone(data); + } +}; + +// Set config data. +config.set = function(prop, value) { + // Abort if no config data exists. + if (!data) { return null; } + // If prop is an array, convert it to a prop string. + prop = getPropString(prop); + // Set the property's value. + var result = grunt.utils.namespace.set(data, prop, value); + // Process directives. + processDirectives(); + // Return result. + return result; +}; + +// Get config data, processing it as a template if necessary. +config.process = function(prop) { + return grunt.utils.recurse(config.get(prop), function(value) { + if (typeof value !== 'string') { return value; } + return grunt.template.process(value, data); + }); +}; + +// Initialize config data. +config.init = function(obj) { + grunt.verbose.write('Initializing config...').ok(); + // Initialize data. + data = obj || {}; + // Process directives. + processDirectives(); + // Return data. + return data; +}; + +// Escape any . in name with \. so dot-based namespacing works properly. +config.escape = function(str) { + return str.replace(/\./g, '\\.'); +}; + +// Test to see if required config params have been defined. If not, throw an +// exception (use this inside of a task). +config.requires = function() { + var p = grunt.utils.pluralize; + var props = grunt.utils.toArray(arguments).map(getPropString); + var msg = 'Verifying propert' + p(props.length, 'y/ies') + + ' ' + grunt.log.wordlist(props) + ' exist' + p(props.length, 's') + + ' in config...'; + grunt.verbose.write(msg); + var failProps = data && props.filter(function(prop) { + return config.get(prop) === undefined; + }).map(function(prop) { + return '"' + prop + '"'; + }); + if (data && failProps.length === 0) { + grunt.verbose.ok(); + return true; + } else { + grunt.verbose.or.write(msg); + grunt.log.error().error('Unable to process task.'); + if (!data) { + throw grunt.task.taskError('Unable to load config.'); + } else { + throw grunt.task.taskError('Required config propert' + + p(failProps.length, 'y/ies') + ' ' + failProps.join(', ') + + ' missing.'); + } + } +}; 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 new file mode 100644 index 0000000..45eb909 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/fail.js @@ -0,0 +1,85 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// The module to be exported. +var fail = module.exports = {}; + +// Error codes +// 1. Generic error. +// 2. Config file not found. +// 3. Generic task failed. +// 10. Uglify-JS error. +// 11. Banner generation error. +// 20. Init error. +// 90-99. Nodeunit/QUnit errors. + +// DRY it up! +function writeln(e, mode) { + grunt.log.muted = false; + // Pretty colors. + var tags = { + warn: ['<'.red + 'WARN'.yellow + '>'.red, ''.red], + fatal: ['<'.red + 'FATAL'.yellow + '>'.red, ''.red] + }; + var msg = String(e.message || e) + '\x07'; // Beep! + if (mode === 'warn') { + msg += ' ' + (grunt.option('force') ? 'Used --force, continuing.'.underline : 'Use --force to continue.'); + } + grunt.log.writeln([tags[mode][0], msg.yellow, tags[mode][1]].join(' ')); +} + +// A fatal error occured. Abort immediately. +fail.fatal = function(e, errcode) { + writeln(e, 'fatal'); + process.exit(typeof errcode === 'number' ? errcode : 1); +}; + +// Keep track of error and warning counts. +fail.errorcount = 0; +fail.warncount = 0; + +// Something (like the watch task) can override this to perform an alternate +// action to exiting on warn. +fail.warnAlternate = null; + +// A warning ocurred. Abort immediately unless -f or --force was used. +fail.warn = function(e, errcode) { + var message = typeof e === 'string' ? e : e.message; + fail.warncount++; + writeln(message, 'warn'); + // If -f or --force aren't used, stop script processing. + if (!grunt.option('force')) { + if (fail.warnAlternate) { + fail.warnAlternate(); + } else { + // If --debug is enabled, log the appropriate error stack (if it exists). + if (grunt.option('debug') >= 9) { + if (e.origError && e.origError.stack) { + console.log(e.origError.stack); + } else if (e.stack) { + console.log(e.stack); + } + } + // Log and exit. + grunt.log.writeln().fail('Aborted due to warnings.'); + process.exit(typeof errcode === 'number' ? errcode : 2); + } + } +}; + +// This gets called at the very end. +fail.report = function() { + if (fail.warncount > 0) { + grunt.log.writeln().fail('Done, but with warnings.'); + } else { + grunt.log.writeln().success('Done, without errors.'); + } +}; 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 new file mode 100644 index 0000000..4523cb1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/file.js @@ -0,0 +1,242 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// Nodejs libs. +var fs = require('fs'); +var path = require('path'); +// In Nodejs 0.8.0, existsSync moved from path -> fs. +var existsSync = fs.existsSync || path.existsSync; + +// The module to be exported. +var file = module.exports = {}; + +// External libs. +file.glob = require('glob-whatev'); +file.findup = require('../util/findup'); + +// Change the current base path (ie, CWD) to the specified path. +file.setBase = function() { + var dirpath = path.join.apply(path, arguments); + process.chdir(dirpath); +}; + +// Match a filepath against one or more wildcard patterns. Returns true if +// any of the patterns match. +file.isMatch = function(patterns, filepath) { + patterns = Array.isArray(patterns) ? patterns : [patterns]; + return patterns.some(function(pattern) { + return file.glob.minimatch(filepath, pattern, {matchBase: true}); + }); +}; + +// Return an array of all file paths that match the given wildcard patterns. +file.expand = function() { + var args = grunt.utils.toArray(arguments); + // If the first argument is an options object, save those options to pass + // into the file.glob.glob method for minimatch to use. + var options = grunt.utils.kindOf(args[0]) === 'object' ? args.shift() : {}; + // Use the first argument if it's an Array, otherwise convert the arguments + // object to an array and use that. + var patterns = Array.isArray(args[0]) ? args[0] : args; + // Generate a should-be-unique number. + var uid = +new Date(); + // Return a flattened, uniqued array of matching file paths. + return grunt.utils._(patterns).chain().flatten().map(function(pattern) { + // If pattern is a template, process it accordingly. + pattern = grunt.template.process(pattern); + // Just return the pattern if it's an internal directive. + if (grunt.task.getDirectiveParts(pattern)) { return pattern; } + // Otherwise, expand paths. + return file.glob.glob(pattern, options); + }).flatten().uniq(false, function(filepath) { + // Only unique file paths, but don't unique directives, in case + // they are repeated intentionally. + return grunt.task.getDirectiveParts(filepath) ? ++uid : filepath; + }).value(); +}; + +// Further filter file.expand. +function expandByType(type) { + var args = grunt.utils.toArray(arguments).slice(1); + return file.expand.apply(file, args).filter(function(filepath) { + // Just return the filepath if it's an internal directive. + if (grunt.task.getDirectiveParts(filepath)) { return filepath; } + try { + return fs.statSync(filepath)[type](); + } catch(e) { + throw grunt.task.taskError(e.message, e); + } + }); +} + +// A few type-specific file expansion methods. +file.expandDirs = expandByType.bind(file, 'isDirectory'); +file.expandFiles = expandByType.bind(file, 'isFile'); + +// Return an array of all file paths that match the given wildcard patterns, +// plus any URLs that were passed at the end. +file.expandFileURLs = function() { + // Use the first argument if it's an Array, otherwise convert the arguments + // object to an array and use that. + var patterns = Array.isArray(arguments[0]) ? arguments[0] : grunt.utils.toArray(arguments); + var urls = []; + // Filter all URLs out of patterns list and store them in a separate array. + patterns = patterns.filter(function(pattern) { + if (/^(?:file|https?):\/\//i.test(pattern)) { + // Push onto urls array. + urls.push(pattern); + // Remove from patterns array. + return false; + } + // Otherwise, keep pattern. + return true; + }); + // Return expanded filepaths with urls at end. + return file.expandFiles(patterns).map(function(filepath) { + var abspath = path.resolve(filepath); + // Convert C:\foo\bar style paths to /C:/foo/bar. + if (abspath.indexOf('/') !== 0) { + abspath = ('/' + abspath).replace(/\\/g, '/'); + } + return 'file://' + abspath; + }).concat(urls); +}; + +// Like mkdir -p. Create a directory and any intermediary directories. +file.mkdir = function(dirpath) { + if (grunt.option('no-write')) { return; } + dirpath.split(/[\/\\]/).reduce(function(parts, part) { + parts += part + '/'; + var subpath = path.resolve(parts); + if (!existsSync(subpath)) { + try { + fs.mkdirSync(subpath, '0755'); + } catch(e) { + throw grunt.task.taskError('Unable to create directory "' + subpath + '" (Error code: ' + e.code + ').', e); + } + } + return parts; + }, ''); +}; + +// Recurse into a directory, executing callback for each file. +file.recurse = function recurse(rootdir, callback, subdir) { + var abspath = subdir ? path.join(rootdir, subdir) : rootdir; + fs.readdirSync(abspath).forEach(function(filename) { + var filepath = path.join(abspath, filename); + if (fs.statSync(filepath).isDirectory()) { + recurse(rootdir, callback, path.join(subdir, filename)); + } else { + callback(path.join(rootdir, subdir, filename), rootdir, subdir, filename); + } + }); +}; + +// Is a given file path absolute? +file.isPathAbsolute = function() { + var filepath = path.join.apply(path, arguments); + return path.resolve(filepath) === filepath; +}; + +// Write a file. +file.write = function(filepath, contents) { + var nowrite = grunt.option('no-write'); + grunt.verbose.write((nowrite ? 'Not actually writing ' : 'Writing ') + filepath + '...'); + // Create path, if necessary. + file.mkdir(path.dirname(filepath)); + try { + if (!nowrite) { + // Actually write file. + fs.writeFileSync(filepath, contents); + } + grunt.verbose.ok(); + return true; + } catch(e) { + grunt.verbose.error(); + throw grunt.task.taskError('Unable to write "' + filepath + '" file (Error code: ' + e.code + ').', e); + } +}; + +// Read a file, return its contents. +file.read = function(filepath, encoding) { + var src; + grunt.verbose.write('Reading ' + filepath + '...'); + try { + src = fs.readFileSync(String(filepath), encoding ? null : 'utf8'); + grunt.verbose.ok(); + return src; + } catch(e) { + grunt.verbose.error(); + throw grunt.task.taskError('Unable to read "' + filepath + '" file (Error code: ' + e.code + ').', e); + } +}; + +// Read a file, optionally processing its content, then write the output. +file.copy = function(srcpath, destpath, options) { + if (!options) { options = {}; } + var src = file.read(srcpath, true); + if (options.process && options.noProcess !== true && + !(options.noProcess && file.isMatch(options.noProcess, srcpath))) { + grunt.verbose.write('Processing source...'); + try { + src = options.process(src.toString('utf8')); + grunt.verbose.ok(); + } catch(e) { + grunt.verbose.error(); + throw grunt.task.taskError('Error while processing "' + srcpath + '" file.', e); + } + } + // Abort copy if the process function returns false. + if (src === false) { + grunt.verbose.writeln('Write aborted.'); + } else { + file.write(destpath, src); + } +}; + +// Read a file, parse its contents, return an object. +file.readJSON = function(filepath) { + var src = this.read(String(filepath)); + var result; + grunt.verbose.write('Parsing ' + filepath + '...'); + try { + result = JSON.parse(src); + grunt.verbose.ok(); + return result; + } catch(e) { + grunt.verbose.error(); + throw grunt.task.taskError('Unable to parse "' + filepath + '" file (' + e.message + ').', e); + } +}; + +// Clear the require cache for all passed filepaths. +file.clearRequireCache = function() { + // If a non-string argument is passed, it's an array of filepaths, otherwise + // each filepath is passed individually. + var filepaths = typeof arguments[0] !== 'string' ? arguments[0] : grunt.utils.toArray(arguments); + // For each filepath, clear the require cache, if necessary. + filepaths.forEach(function(filepath) { + var abspath = path.resolve(filepath); + if (require.cache[abspath]) { + grunt.verbose.write('Clearing require cache for "' + filepath + '" file...').ok(); + delete require.cache[abspath]; + } + }); +}; + +// Access files in the user's ".grunt" folder. +file.userDir = function() { + var dirpath = path.join.apply(path, arguments); + var win32 = process.platform === 'win32'; + var homepath = process.env[win32 ? 'USERPROFILE' : 'HOME']; + dirpath = path.resolve(homepath, '.grunt', dirpath); + return existsSync(dirpath) ? dirpath : null; +}; 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 new file mode 100644 index 0000000..6164af3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/help.js @@ -0,0 +1,69 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// Nodejs libs. +var path = require('path'); + +// Initialize task system so that the tasks can be listed. +grunt.task.init([], {help: true}); + +// Build 2-column array for table view. +var col1len = 0; +var opts = Object.keys(grunt.cli.optlist).map(function(long) { + var o = grunt.cli.optlist[long]; + var col1 = '--' + (o.negate ? 'no-' : '') + long + (o.short ? ', -' + o.short : ''); + col1len = Math.max(col1len, col1.length); + return [col1, o.info]; +}); + +var tasks = Object.keys(grunt.task._tasks).map(function(name) { + col1len = Math.max(col1len, name.length); + var info = grunt.task._tasks[name].info; + if (grunt.task._tasks[name].multi) { + info += ' *'; + } + return [name, info]; +}); + +// Actually write out help screen. +grunt.log.writeln('grunt: a task-based command line build tool for JavaScript projects. (v' + grunt.version + ')'); + +grunt.log.header('Usage'); +grunt.log.writeln(' ' + path.basename(process.argv[1]) + ' [options] [task [task ...]]'); + +// Widths for options/tasks table output. +var widths = [1, col1len, 2, 76 - col1len]; + +grunt.log.header('Options'); +opts.forEach(function(a) { grunt.log.writetableln(widths, ['', grunt.utils._.pad(a[0], col1len), '', a[1]]); }); + +grunt.log.writeln().writelns( + 'Options marked with * have methods exposed via the grunt API and should ' + + 'instead be specified inside the "grunt.js" gruntfile wherever possible.' +); + +grunt.log.header('Available tasks'); +tasks.forEach(function(a) { grunt.log.writetableln(widths, ['', grunt.utils._.pad(a[0], col1len), '', a[1]]); }); + +grunt.log.writeln().writelns( + 'Tasks run in the order specified. Arguments may be passed to tasks that ' + + 'accept them by using semicolons, like "lint:files". Tasks marked with * ' + + 'are "multi tasks" and will iterate over all sub-targets if no argument is ' + + 'specified.' + + '\n\n' + + 'The list of available tasks may change based on tasks directories or ' + + 'grunt plugins specified in the "grunt.js" gruntfile or via command-line ' + + 'options.' + + '\n\n' + + '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 new file mode 100644 index 0000000..f7be8a0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/log.js @@ -0,0 +1,273 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// Nodejs libs. +var util = require('util'); + +// The module to be exported. +var log = module.exports = {}; + +// Temporarily suppress output. +var suppressOutput; + +// Allow external muting of output. +log.muted = false; + +// True once anything has actually been logged. +var hasLogged; + +// Parse certain markup in strings to be logged. +function markup(str) { + str = str || ''; + // Make _foo_ underline. + str = str.replace(/(\s|^)_([\s\S]+?)_(?=\s|$)/g, '$1' + '$2'.underline); + // Make *foo* bold. + str = str.replace(/(\s|^)\*([\s\S]+?)\*(?=\s|$)/g, '$1' + '$2'.bold); + return str; +} + +// Write output. +log.write = function(msg) { + // Actually write output. + if (!log.muted && !suppressOutput) { + hasLogged = true; + process.stdout.write(markup(msg)); + } + // Chainable! + return this; +}; + +// Write a line of output. +log.writeln = function(msg) { + // Actually write output. + this.write((msg || '') + '\n'); + // Chainable! + return this; +}; + +// Stuff. + +log.error = function(msg) { + if (msg) { + grunt.fail.errorcount++; + return this.writeln('>> '.red + grunt.utils._.trim(msg).replace(/\n/g, '\n>> '.red)); + } else { + return this.writeln('ERROR'.red); + } +}; +log.ok = function(msg) { + if (msg) { + return this.writeln('>> '.green + grunt.utils._.trim(msg).replace(/\n/g, '\n>> '.green)); + } else { + return this.writeln('OK'.green); + } +}; +log.errorlns = function(msg) { return this.error(log.wraptext(77, msg)); }; +log.oklns = function(msg) { return this.ok(log.wraptext(77, msg)); }; +log.success = function(msg) { return this.writeln(msg.green); }; +log.fail = function(msg) { return this.writeln(msg.red); }; +log.header = function(msg) { + // Skip line before header, but not if header is the very first line output. + if (hasLogged) { this.writeln(); } + return this.writeln(msg.underline); +}; +log.subhead = function(msg) { + // Skip line before subhead, but not if subhead is the very first line output. + if (hasLogged) { this.writeln(); } + return this.writeln(msg.bold); +}; +// For debugging. +log.debug = function() { + if (grunt.option('debug')) { + this.writeln(('[D] ' + util.format.apply(this, arguments)).magenta); + } + return this; +}; + +// Write a line of a table. +log.writetableln = function(widths, texts) { + return this.writeln(this.table(widths, texts)); +}; + +// Wrap a long line of text to 80 columns. +log.writelns = function(msg) { + return this.writeln(this.wraptext(80, msg)); +}; + +// Display flags in verbose mode. +log.writeflags = function(obj, prefix) { + var wordlist; + if (Array.isArray(obj)) { + wordlist = log.wordlist(obj); + } else if (typeof obj === 'object' && obj) { + wordlist = log.wordlist(Object.keys(obj).map(function(key) { + var val = obj[key]; + return key + (val === true ? '' : '=' + JSON.stringify(val)); + })); + } + return this.writeln((prefix || 'Flags') + ': ' + (wordlist || '(none)'.cyan)); +}; + +// Create explicit "verbose" and "notverbose" functions, one for each already- +// defined log function, that do the same thing but ONLY if -v or --verbose is +// specified (or not specified). +log.verbose = {}; +log.notverbose = {}; + +// Iterate over all exported functions. +Object.keys(log).filter(function(key) { + return typeof log[key] === 'function'; +}).forEach(function(key) { + // Like any other log function, but suppresses output if the "verbose" option + // IS NOT set. + log.verbose[key] = function() { + suppressOutput = !grunt.option('verbose'); + log[key].apply(this, arguments); + suppressOutput = false; + return this; + }; + // Like any other log function, but suppresses output if the "verbose" option + // IS set. + log.notverbose[key] = function() { + suppressOutput = grunt.option('verbose'); + log[key].apply(this, arguments); + suppressOutput = false; + return this; + }; +}); + +// A way to switch between verbose and notverbose modes. For example, this will +// write 'foo' if verbose logging is enabled, otherwise write 'bar': +// verbose.write('foo').or.write('bar'); +log.verbose.or = log.notverbose; +log.notverbose.or = log.verbose; + +// Static methods. + +// Pretty-format a word list. +log.wordlist = function(arr, separator) { + return arr.map(function(item) { + return item.cyan; + }).join(separator || ', '); +}; + +// Return a string, uncolored (suitable for testing .length, etc). +log.uncolor = function(str) { + return str.replace(/\x1B\[\d+m/g, ''); +}; + +// Word-wrap text to a given width, permitting ANSI color codes. +log.wraptext = function(width, text) { + // notes to self: + // grab 1st character or ansi code from string + // if ansi code, add to array and save for later, strip from front of string + // if character, add to array and increment counter, strip from front of string + // if width + 1 is reached and current character isn't space: + // slice off everything after last space in array and prepend it to string + // etc + + // This result array will be joined on \n. + var result = []; + var matches, color, tmp; + var captured = []; + var charlen = 0; + + while (matches = text.match(/(?:(\x1B\[\d+m)|\n|(.))([\s\S]*)/)) { + // Updated text to be everything not matched. + text = matches[3]; + + // Matched a color code? + if (matches[1]) { + // Save last captured color code for later use. + color = matches[1]; + // Capture color code. + captured.push(matches[1]); + continue; + + // Matched a non-newline character? + } else if (matches[2]) { + // If this is the first character and a previous color code was set, push + // that onto the captured array first. + if (charlen === 0 && color) { captured.push(color); } + // Push the matched character. + captured.push(matches[2]); + // Increment the current charlen. + charlen++; + // If not yet at the width limit or a space was matched, continue. + if (charlen <= width || matches[2] === ' ') { continue; } + // The current charlen exceeds the width and a space wasn't matched. + // "Roll everything back" until the last space character. + tmp = captured.lastIndexOf(' '); + text = captured.slice(tmp === -1 ? tmp : tmp + 1).join('') + text; + captured = captured.slice(0, tmp); + } + + // The limit has been reached. Push captured string onto result array. + result.push(captured.join('')); + + // Reset captured array and charlen. + captured = []; + charlen = 0; + } + + result.push(captured.join('')); + return result.join('\n'); +}; + +// todo: write unit tests +// +// function logs(text) { +// [4, 6, 10, 15, 20, 25, 30, 40].forEach(function(n) { +// log(n, text); +// }); +// } +// +// function log(n, text) { +// console.log(Array(n + 1).join('-')); +// console.log(wrap(n, text)); +// } +// +// var text = 'this is '.red + 'a simple'.yellow.inverse + ' test of'.green + ' ' + 'some wrapped'.blue + ' text over '.inverse.magenta + 'many lines'.red; +// logs(text); +// +// var text = 'foolish '.red.inverse + 'monkeys'.yellow + ' eating'.green + ' ' + 'delicious'.inverse.blue + ' bananas '.magenta + 'forever'.red; +// logs(text); +// +// var text = 'foolish monkeys eating delicious bananas forever'.rainbow; +// logs(text); + +// Format output into columns, wrapping words as-necessary. +log.table = function(widths, texts) { + var rows = []; + widths.forEach(function(width, i) { + var lines = log.wraptext(width, texts[i]).split('\n'); + lines.forEach(function(line, j) { + var row = rows[j]; + if (!row) { row = rows[j] = []; } + row[i] = line; + }); + }); + + var lines = []; + rows.forEach(function(row) { + var txt = ''; + var column; + for (var i = 0; i < row.length; i++) { + column = row[i] || ''; + txt += column; + var diff = widths[i] - log.uncolor(column).length; + if (diff > 0) { txt += grunt.utils.repeat(diff, ' '); } + } + lines.push(txt); + }); + + return lines.join('\n'); +}; 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 new file mode 100644 index 0000000..197f6dc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/option.js @@ -0,0 +1,40 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// The actual option data. +var data = {}; + +// Get or set an option value. +var option = module.exports = function(key, value) { + var no = key.match(/^no-(.+)$/); + if (arguments.length === 2) { + return (data[key] = value); + } else if (no) { + return data[no[1]] === false; + } else { + return data[key]; + } +}; + +// Initialize option data. +option.init = function(obj) { + return (data = obj || {}); +}; + +// List of options as flags. +option.flags = function() { + return Object.keys(data).filter(function(key) { + // Don't display empty arrays. + return !(Array.isArray(data[key]) && data[key].length === 0); + }).map(function(key) { + var val = data[key]; + return '--' + (val === false ? 'no-' : '') + key + + (typeof val === 'boolean' ? '' : '=' + val); + }); +}; 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 new file mode 100644 index 0000000..43ac8ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/task.js @@ -0,0 +1,415 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// Nodejs libs. +var path = require('path'); +var fs = require('fs'); +// In Nodejs 0.8.0, existsSync moved from path -> fs. +var existsSync = fs.existsSync || path.existsSync; + +// Extend generic "task" utils lib. +var parent = grunt.utils.task.create(); + +// The module to be exported. +var task = module.exports = Object.create(parent); + +// An internal registry of tasks and handlers. +var registry = {}; + +// Keep track of the number of log.error() calls. +var errorcount; + +// Override built-in registerTask. +task.registerTask = function(name, info, fn) { + // Add task to registry. + registry.tasks.push(name); + // Register task. + parent.registerTask.apply(task, arguments); + // This task, now that it's been registered. + var thisTask = task._tasks[name]; + // Override task function. + var _fn = thisTask.fn; + thisTask.fn = function(arg) { + // Initialize the errorcount for this task. + errorcount = grunt.fail.errorcount; + // Return the number of errors logged during this task. + this.__defineGetter__('errorCount', function() { + return grunt.fail.errorcount - errorcount; + }); + // Expose task.requires on `this`. + this.requires = task.requires.bind(task); + // Expose config.requires on `this`. + this.requiresConfig = grunt.config.requires; + // If this task was an alias or a multi task called without a target, + // only log if in verbose mode. + var logger = _fn.alias || (thisTask.multi && (!arg || arg === '*')) ? 'verbose' : 'log'; + // Actually log. + grunt[logger].header('Running "' + this.nameArgs + '"' + + (this.name !== this.nameArgs ? ' (' + this.name + ')' : '') + ' task'); + // Actually run the task. + return _fn.apply(this, arguments); + }; + return task; +}; + +// This is the most common "multi task" pattern. +task.registerMultiTask = function(name, info, fn) { + // Store a reference to the task object, in case the task gets renamed. + var thisTask; + task.registerTask(name, info, function(target) { + // Guaranteed to always be the actual task name. + var name = thisTask.name; + // If a target wasn't specified, run this task once for each target. + if (!target || target === '*') { + return task.runAllTargets(name, grunt.utils.toArray(arguments).slice(1)); + } + // Fail if any required config properties have been omitted. + this.requiresConfig([name, target]); + // Expose data on `this` (as well as task.current). + this.data = grunt.config([name, target]); + // Expose file object on `this` (as well as task.current). + this.file = {}; + // Handle data structured like either: + // 'prop': [srcfiles] + // {prop: {src: [srcfiles], dest: 'destfile'}}. + if (grunt.utils.kindOf(this.data) === 'object') { + if ('src' in this.data) { this.file.src = this.data.src; } + if ('dest' in this.data) { this.file.dest = this.data.dest; } + } else { + this.file.src = this.data; + this.file.dest = target; + } + // Process src as a template (recursively, if necessary). + if (this.file.src) { + this.file.src = grunt.utils.recurse(this.file.src, function(src) { + if (typeof src !== 'string') { return src; } + return grunt.template.process(src); + }); + } + // Process dest as a template. + if (this.file.dest) { + this.file.dest = grunt.template.process(this.file.dest); + } + // Expose the current target. + this.target = target; + // Remove target from args. + this.args = grunt.utils.toArray(arguments).slice(1); + // Recreate flags object so that the target isn't set as a flag. + this.flags = {}; + this.args.forEach(function(arg) { this.flags[arg] = true; }, this); + // Call original task function, passing in the target and any other args. + return fn.apply(this, this.args); + }); + thisTask = task._tasks[name]; + thisTask.multi = true; +}; + +// Init tasks don't require properties in config, and as such will preempt +// config loading errors. +task.registerInitTask = function(name, info, fn) { + task.registerTask(name, info, fn); + task._tasks[name].init = true; +}; + +// Override built-in registerHelper to use the registry. +task.registerHelper = function(name, fn) { + // Add task to registry. + registry.helpers.push(name); + // Actually register task. + return parent.registerHelper.apply(task, arguments); +}; + +// If a property wasn't passed, run all task targets in turn. +task.runAllTargets = function(taskname, args) { + // Get an array of sub-property keys under the given config object. + var targets = Object.keys(grunt.config(taskname) || {}); + // Fail if there are no actual properties to iterate over. + if (targets.length === 0) { + grunt.log.error('No "' + taskname + '" targets found.'); + return false; + } + // Iterate over all properties not starting with _, running a task for each. + targets.filter(function(target) { + return !/^_/.test(target); + }).forEach(function(target) { + // Be sure to pass in any additionally specified args. + task.run([taskname, target].concat(args || []).join(':')); + }); +}; + +// Load tasks and handlers from a given tasks file. +var loadTaskStack = []; +function loadTask(filepath) { + // In case this was called recursively, save registry for later. + loadTaskStack.push({tasks: registry.tasks, helpers: registry.helpers}); + // Reset registry. + registry.tasks = []; + registry.helpers = []; + var filename = path.basename(filepath); + var msg = 'Loading "' + filename + '" tasks and helpers...'; + var fn; + try { + // Load taskfile. + fn = require(path.resolve(filepath)); + if (typeof fn === 'function') { + fn.call(grunt, grunt); + } + grunt.verbose.write(msg).ok(); + if (registry.tasks.length === 0 && registry.helpers.length === 0) { + grunt.verbose.error('No new tasks or helpers found.'); + } else { + if (registry.tasks.length > 0) { + grunt.verbose.writeln('Tasks: ' + grunt.log.wordlist(registry.tasks)); + } + if (registry.helpers.length > 0) { + grunt.verbose.writeln('Helpers: ' + grunt.log.wordlist(registry.helpers)); + } + } + } catch(e) { + // Something went wrong. + grunt.log.write(msg).error().verbose.error(e.stack).or.error(e); + } + // Restore registry. + var obj = loadTaskStack.pop() || {}; + registry.tasks = obj.tasks || []; + registry.helpers = obj.helpers || []; +} + +// Log a message when loading tasks. +function loadTasksMessage(info) { + grunt.verbose.subhead('Registering ' + info + ' tasks.'); +} + +// Load tasks and handlers from a given directory. +function loadTasks(tasksdir) { + try { + fs.readdirSync(tasksdir).filter(function(filename) { + // Filter out non-.js files. + return path.extname(filename).toLowerCase() === '.js'; + }).forEach(function(filename) { + // Load task. + loadTask(path.join(tasksdir, filename)); + }); + } catch(e) { + grunt.log.verbose.error(e.stack).or.error(e); + } +} + +// Directories to be searched for tasks files and "extra" files. +task.searchDirs = []; + +// Return an array of all task-specific file paths that match the given +// wildcard patterns. Instead of returing a string for each file path, return +// an object with useful properties. When coerced to String, each object will +// yield its absolute path. +function expandByMethod(method) { + var args = grunt.utils.toArray(arguments).slice(1); + // If the first argument is an options object, remove and save it for later. + var options = grunt.utils.kindOf(args[0]) === 'object' ? args.shift() : {}; + // Use the first argument if it's an Array, otherwise convert the arguments + // object to an array and use that. + var patterns = Array.isArray(args[0]) ? args[0] : args; + var filepaths = {}; + // When any returned array item is used in a string context, return the + // absolute path. + var toString = function() { return this.abs; }; + // Iterate over all searchDirs. + task.searchDirs.forEach(function(dirpath) { + // Create an array of absolute patterns. + var args = patterns.map(function(pattern) { + return path.join(dirpath, pattern); + }); + // Add the options object back onto the beginning of the arguments array. + args.unshift(options); + // Expand the paths in case a wildcard was passed. + grunt.file[method].apply(null, args).forEach(function(abspath) { + var relpath = abspath.slice(dirpath.length + 1); + if (relpath in filepaths) { return; } + // Update object at this relpath only if it doesn't already exist. + filepaths[relpath] = { + abs: abspath, + rel: relpath, + base: abspath.slice(0, dirpath.length), + toString: toString + }; + }); + }); + // Return an array of objects. + return Object.keys(filepaths).map(function(relpath) { + return filepaths[relpath]; + }); +} + +// A few type-specific task expansion methods. These methods all return arrays +// of file objects. +task.expand = expandByMethod.bind(task, 'expand'); +task.expandDirs = expandByMethod.bind(task, 'expandDirs'); +task.expandFiles = expandByMethod.bind(task, 'expandFiles'); + +// Get a single task file path. +task.getFile = function() { + var filepath = path.join.apply(path, arguments); + var fileobj = task.expand(filepath)[0]; + return fileobj ? String(fileobj) : null; +}; + +// Read JSON defaults from task files (if they exist), merging them into one. +// data object. +var readDefaults = {}; +task.readDefaults = function() { + var filepath = path.join.apply(path, arguments); + var result = readDefaults[filepath]; + var filepaths; + if (!result) { + result = readDefaults[filepath] = {}; + // Find all matching taskfiles. + filepaths = task.searchDirs.map(function(dirpath) { + return path.join(dirpath, filepath); + }).filter(function(filepath) { + return existsSync(filepath) && fs.statSync(filepath).isFile(); + }); + // Load defaults data. + if (filepaths.length) { + grunt.verbose.subhead('Loading data from ' + filepath); + // Since extras path order goes from most-specific to least-specific, only + // add-in properties that don't already exist. + filepaths.forEach(function(filepath) { + grunt.utils._.defaults(result, grunt.file.readJSON(filepath)); + }); + } + } + return result; +}; + +// Load tasks and handlers from a given directory. +task.loadTasks = function(tasksdir) { + loadTasksMessage('"' + tasksdir + '"'); + if (existsSync(tasksdir)) { + task.searchDirs.unshift(tasksdir); + loadTasks(tasksdir); + } else { + grunt.log.error('Tasks directory "' + tasksdir + '" not found.'); + } +}; + +// Load tasks and handlers from a given locally-installed Npm module (installed +// relative to the base dir). +task.loadNpmTasks = function(name) { + loadTasksMessage('"' + name + '" local Npm module'); + var root = path.resolve('node_modules'); + var pkgfile = path.join(root, name, 'package.json'); + var pkg = existsSync(pkgfile) ? grunt.file.readJSON(pkgfile) : {}; + + // Process collection plugins. + if (pkg.keywords && pkg.keywords.indexOf('gruntcollection') !== -1) { + Object.keys(pkg.dependencies).forEach(function(depName) { + // Npm sometimes pulls dependencies out if they're shared, so find + // upwards if not found locally. + var filepath = grunt.file.findup(path.resolve('node_modules', name), + 'node_modules/' + depName); + if (filepath) { + // Load this task plugin recursively. + task.loadNpmTasks(path.relative(root, filepath)); + } + }); + return; + } + + // Process task plugins. + var tasksdir = path.join(root, name, 'tasks'); + if (existsSync(tasksdir)) { + task.searchDirs.unshift(tasksdir); + loadTasks(tasksdir); + } else { + grunt.log.error('Local Npm module "' + name + '" not found. Is it installed?'); + } +}; + +// Load tasks and handlers from a given Npm module, installed relative to the +// version of grunt being run. +function loadNpmTasksWithRequire(name) { + loadTasksMessage('"' + name + '" npm module'); + var dirpath; + try { + dirpath = require.resolve(name); + dirpath = path.resolve(path.join(path.dirname(dirpath), 'tasks')); + if (existsSync(dirpath)) { + task.searchDirs.unshift(dirpath); + loadTasks(dirpath); + return; + } + } catch (e) {} + + grunt.log.error('Npm module "' + name + '" not found. Is it installed?'); +} + +// Initialize tasks. +task.init = function(tasks, options) { + if (!options) { options = {}; } + + // Load all built-in tasks. + var tasksdir = path.resolve(__dirname, '../../tasks'); + task.searchDirs.unshift(tasksdir); + loadTasksMessage('built-in'); + loadTasks(tasksdir); + + // Grunt was loaded from a Npm-installed plugin bin script. Load any tasks + // that were specified via grunt.npmTasks. + grunt._npmTasks.forEach(loadNpmTasksWithRequire); + + // Were only init tasks specified? + var allInit = tasks.length > 0 && tasks.every(function(name) { + var obj = task._taskPlusArgs(name).task; + return obj && obj.init; + }); + + // Get any local configfile or tasks that might exist. Use --config override + // if specified, otherwise search the current directory or any parent. + var configfile = allInit ? null : grunt.option('config') || + grunt.file.findup(process.cwd(), 'grunt.js'); + + var msg = 'Reading "' + path.basename(configfile) + '" config file...'; + if (configfile && existsSync(configfile)) { + grunt.verbose.writeln().write(msg).ok(); + // Change working directory so that all paths are relative to the + // configfile's location (or the --base option, if specified). + process.chdir(grunt.option('base') || path.dirname(configfile)); + // Load local tasks, if the file exists. + loadTask(configfile); + } else if (options.help || allInit) { + // Don't complain about missing config file. + } else if (grunt.option('config')) { + // If --config override was specified and it doesn't exist, complain. + grunt.log.writeln().write(msg).error(); + grunt.fatal('Unable to find "' + configfile + '" config file.', 2); + } else if (!grunt.option('help')) { + grunt.verbose.writeln().write(msg).error(); + grunt.fatal('Unable to find "grunt.js" config file. Do you need any --help?', 2); + } + + // Load all user-specified --npm tasks. + (grunt.option('npm') || []).forEach(task.loadNpmTasks); + // Load all user-specified --tasks. + (grunt.option('tasks') || []).forEach(task.loadTasks); + + // Load user .grunt tasks. + tasksdir = grunt.file.userDir('tasks'); + if (tasksdir) { + task.searchDirs.unshift(tasksdir); + loadTasksMessage('user'); + loadTasks(tasksdir); + } + + // Search dirs should be unique and fully normalized absolute paths. + task.searchDirs = grunt.utils._.uniq(task.searchDirs).map(function(filepath) { + return path.resolve(filepath); + }); +}; 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 new file mode 100644 index 0000000..1d0786b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/template.js @@ -0,0 +1,80 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +var grunt = require('../grunt'); + +// The module to be exported. +var template = module.exports = {}; + +// External libs. +template.date = require('dateformat'); + +// Format today's date. +template.today = function(format) { + return template.date(new Date(), format); +}; + +// Set underscore template delimiters. +template.delimiters = function(mode) { + var modes = { + // The underscore default template syntax should be a pretty sane default. + default: { + // Used by grunt. + opener: '<%', + // Used by underscore. + evaluate: /<%([\s\S]+?)%>/g, + interpolate: /<%=([\s\S]+?)%>/g, + escape: /<%-([\s\S]+?)%>/g + }, + // The "init" task needs separate delimiters to avoid conflicts, so the <> + // are replaced with {}. Otherwise, they behave the same. + init: { + // Used by grunt. + opener: '{%', + // Used by underscore. + evaluate: /\{%([\s\S]+?)%\}/g, + interpolate: /\{%=([\s\S]+?)%\}/g, + escape: /\{%-([\s\S]+?)%\}/g + } + }; + var settings = modes[mode in modes ? mode : 'default']; + grunt.utils._.templateSettings = settings; + // Get opener character for grunt to use. + var opener = settings.opener; + // Remove it from the underscore object and return it. + delete settings.opener; + return opener; +}; + +// Process template + data with underscore. +template.process = function(template, data, mode) { + // Set delimiters, and get a opening match character. + var opener = grunt.template.delimiters(mode); + // Clone data, initializing to config data or empty object if omitted. + data = Object.create(data || grunt.config() || {}); + // Expose grunt so that grunt utilities can be accessed, but only if it + // doesn't conflict with an existing .grunt property. + if (!('grunt' in data)) { data.grunt = grunt; } + // Keep track of last change. + var last = template; + try { + // As long as template contains template tags, render it and get the result, + // otherwise just use the template string. + while (template.indexOf(opener) >= 0) { + template = grunt.utils._.template(template)(data); + // Abort if template didn't change - nothing left to process! + if (template === last) { break; } + last = template; + } + } catch (e) { + grunt.warn('An error occurred while processing a template (' + e.message + ').'); + } + // Normalize linefeeds and return. + return grunt.utils.normalizelf(template); +}; 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 new file mode 100644 index 0000000..155c617 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/grunt/utils.js @@ -0,0 +1,113 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Nodejs libs. +var spawn = require('child_process').spawn; + +// The module to be exported. +var utils = module.exports = {}; + +// A few internal utilites, exposed. +utils.task = require('../util/task'); +utils.namespace = require('../util/namespace'); + +// External libs. +utils.hooker = require('hooker'); +utils.async = require('async'); +var _ = utils._ = require('underscore'); + +// Mixin Underscore.string methods. +_.str = require('underscore.string'); +_.mixin(_.str.exports()); + +// The line feed char for the current system. +utils.linefeed = process.platform === 'win32' ? '\r\n' : '\n'; + +// Normalize linefeeds in a string. +utils.normalizelf = function(str) { + return str.replace(/\r\n|\n/g, utils.linefeed); +}; + +// What "kind" is a value? +// I really need to rework https://github.com/cowboy/javascript-getclass +var kindsOf = {}; +'Number String Boolean Function RegExp Array Date Error'.split(' ').forEach(function(k) { + kindsOf['[object ' + k + ']'] = k.toLowerCase(); +}); +utils.kindOf = function(value) { + // Null or undefined. + if (value == null) { return String(value); } + // Everything else. + return kindsOf[kindsOf.toString.call(value)] || 'object'; +}; + +// Coerce something to an Array. +utils.toArray = Function.call.bind(Array.prototype.slice); + +// Return the string `str` repeated `n` times. +utils.repeat = function(n, str) { + return new Array(n + 1).join(str || ' '); +}; + +// Given str of "a/b", If n is 1, return "a" otherwise "b". +utils.pluralize = function(n, str, separator) { + var parts = str.split(separator || '/'); + return n === 1 ? (parts[0] || '') : (parts[1] || ''); +}; + +// Recurse through objects and arrays, executing fn for each non-object. +utils.recurse = function recurse(value, fn, fnContinue) { + var obj; + if (fnContinue && fnContinue(value) === false) { + // Skip value if necessary. + return value; + } else if (utils.kindOf(value) === 'array') { + // If value is an array, recurse. + return value.map(function(value) { + return recurse(value, fn, fnContinue); + }); + } else if (utils.kindOf(value) === 'object') { + // If value is an object, recurse. + obj = {}; + Object.keys(value).forEach(function(key) { + obj[key] = recurse(value[key], fn, fnContinue); + }); + return obj; + } else { + // Otherwise pass value into fn and return. + return fn(value); + } +}; + +// Spawn a child process, capturing its stdout and stderr. +utils.spawn = function(opts, done) { + var child = spawn(opts.cmd, opts.args, opts.opts); + var stdout = ''; + var stderr = ''; + child.stdout.on('data', function(buf) { stdout += buf; }); + child.stderr.on('data', function(buf) { stderr += buf; }); + // Node 0.8 no longer waits for stdio pipes to be closed before emitting the + // exit event (grunt issue #322). + var eventName = process.version.split('.')[1] === '6' ? 'exit' : 'close'; + child.on(eventName, function(code) { + // Remove trailing whitespace (newline) + stdout = _.rtrim(stdout); + stderr = _.rtrim(stderr); + // To keep JSHint from complaining about using new String(). + var MyString = String; + // Create a new string... with properties. + var result = new MyString(code === 0 ? stdout : 'fallback' in opts ? opts.fallback : stderr); + result.stdout = stdout; + result.stderr = stderr; + result.code = code; + // On error, pass result object as error object. + done(code === 0 || 'fallback' in opts ? null: result, result, code); + }); + return child; +}; 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 new file mode 100644 index 0000000..c9f9444 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/findup.js @@ -0,0 +1,24 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Nodejs libs. +var path = require('path'); +var fs = require('fs'); +// In Nodejs 0.8.0, existsSync moved from path -> fs. +var existsSync = fs.existsSync || path.existsSync; + +// Search for a filename in the given directory or all parent directories. +module.exports = function findup(dirpath, filename) { + var filepath = path.join(dirpath, filename); + // Return file if found. + if (existsSync(filepath)) { return filepath; } + // If parentpath is the same as dirpath, we can't go any higher. + var parentpath = path.resolve(dirpath, '..'); + return parentpath === dirpath ? null : findup(parentpath, filename); +}; 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 new file mode 100644 index 0000000..7127980 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/namespace.js @@ -0,0 +1,61 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +(function(exports) { + + // Split strings on dot, but only if dot isn't preceded by a backslash. Since + // JavaScript doesn't support lookbehinds, use a placeholder for "\.", split + // on dot, then replace the placeholder character with a dot. + function getParts(str) { + return str.replace(/\\\./g, '\uffff').split('.').map(function(s) { + return s.replace(/\uffff/g, '.'); + }); + } + + // Get the value of a deeply-nested property exist in an object. + exports.get = function(obj, parts, create) { + if (typeof parts === 'string') { + parts = getParts(parts); + } + + var part; + while (typeof obj === 'object' && obj && parts.length) { + part = parts.shift(); + if (!(part in obj) && create) { + obj[part] = {}; + } + obj = obj[part]; + } + + return obj; + }; + + // Set a deeply-nested property in an object, creating intermediary objects + // as we go. + exports.set = function(obj, parts, value) { + parts = getParts(parts); + + var prop = parts.pop(); + obj = exports.get(obj, parts, true); + if (obj && typeof obj === 'object') { + return (obj[prop] = value); + } + }; + + // Does a deeply-nested property exist in an object? + exports.exists = function(obj, parts) { + parts = getParts(parts); + + var prop = parts.pop(); + obj = exports.get(obj, parts); + + return typeof obj === 'object' && obj && prop in obj; + }; + +}(typeof exports === 'object' && exports || this)); 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 new file mode 100644 index 0000000..398a605 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/lib/util/task.js @@ -0,0 +1,392 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +(function(exports) { + + // Construct-o-rama. + function Task() { + // Information about the currently-running task. + this.current = {}; + // Helpers. + this._helpers = {}; + // Tasks. + this._tasks = {}; + // Task queue. + this._queue = []; + // Queue placeholder (for dealing with nested tasks). + this._placeholder = {placeholder: true}; + // Queue marker (for clearing the queue programatically). + this._marker = {marker: true}; + // Options. + this._options = {}; + // Is the queue running? + this._running = false; + // Success status of completed tasks. + this._success = {}; + } + + // Expose the constructor function. + exports.Task = Task; + + // Create a new Task instance. + exports.create = function() { + return new Task(); + }; + + // Error constructors. + function TaskError(message) { + Error.captureStackTrace(this, TaskError); + this.message = message; + } + TaskError.prototype = Object.create(Error.prototype); + TaskError.prototype.name = 'TaskError'; + + function HelperError(message) { + Error.captureStackTrace(this, HelperError); + this.message = message; + } + HelperError.prototype = Object.create(Error.prototype); + HelperError.prototype.name = 'HelperError'; + + // Expose the ability to create a new taskError. + Task.prototype.taskError = function(message, e) { + var error = new TaskError(message); + error.origError = e; + return error; + }; + + // Register a new helper. + Task.prototype.registerHelper = function(name, fn) { + // Add task into cache. + this._helpers[name] = fn; + // Make chainable! + return this; + }; + + // Rename a helper. This might be useful if you want to override the default + // behavior of a helper, while retaining the old name (to avoid having to + // completely recreate an already-made task just because you needed to + // override or extend a built-in helper). + Task.prototype.renameHelper = function(oldname, newname) { + // Rename helper. + this._helpers[newname] = this._helpers[oldname]; + // Remove old name. + delete this._helpers[oldname]; + // Make chainable! + return this; + }; + + // If the task runner is running or an error handler is not defined, throw + // an exception. Otherwise, call the error handler directly. + Task.prototype._throwIfRunning = function(obj) { + if (this._running || !this._options.error) { + // Throw an exception that the task runner will catch. + throw obj; + } else { + // Not inside the task runner. Call the error handler and abort. + this._options.error.call({name: null}, obj); + } + }; + + // Execute a helper. + Task.prototype.helper = function(isDirective, name) { + var args = [].slice.call(arguments, 1); + if (isDirective !== true) { + name = isDirective; + isDirective = false; + } else { + args = args.slice(1); + } + var helper = this._helpers[name]; + if (!helper) { + // Helper not found. + this._throwIfRunning(new HelperError('Helper "' + name + '" not found.')); + return; + } + // Provide a few useful values on this. + var context = {args: args, flags: {}}; + // Maybe you want to use flags instead of positional args? + args.forEach(function(arg) { context.flags[arg] = true; }); + // Let the user know if it was used as a directive. + if (isDirective) { context.directive = true; } + // Invoke helper with any remaining arguments and return its value. + return helper.apply(context, args); + }; + + // If a directive is passed, return ["foo", "bar", "baz"], + // otherwise null. + var directiveRe = /^<(.*)>$/; + Task.prototype.getDirectiveParts = function(str) { + var matches = str.match(directiveRe); + // If the string doesn't look like a directive, return null. + if (!matches) { return null; } + // Split the name into parts. + var parts = matches[1].split(':'); + // If a matching helper was found, return the parts, otherwise null. + return this._helpers[parts[0]] ? parts : null; + }; + + // If value matches the format, and the specified handler + // exists, it's a directive. Execute the matching handler and return its + // value. If not, but an optional callback was passed, pass the value into + // the callback and return its result. If no callback was specified, return + // the value. + Task.prototype.directive = function(value, fn) { + // Get parts if a string was passed and it looks like a directive. + var directive = typeof value === 'string' ? this.getDirectiveParts(value) : null; + + if (directive) { + // If it looks like a directive and a matching helper exists, call the + // helper by applying all directive parts and return its value. + return this.helper.apply(this, [true].concat(directive)); + } else if (fn) { + // Not a directive, but a callback was passed. Pass the value into the + // callback and return its result. + return fn(value); + } + // A callback wasn't specified or a valid handler wasn't found, so just + // return the value. + return value; + }; + + // Register a new task. + Task.prototype.registerTask = function(name, info, fn) { + // If optional "info" string is omitted, shuffle arguments a bit. + if (fn == null) { + fn = info; + info = ''; + } + // String or array of strings was passed instead of fn. + var tasks; + if (typeof fn !== 'function') { + // Array of task names. + tasks = this.parseArgs([fn]); + // This task function just runs the specified tasks. + fn = this.run.bind(this, fn); + fn.alias = true; + // Generate an info string if one wasn't explicitly passed. + if (!info) { + info = 'Alias for "' + tasks.join(' ') + '" task' + + (tasks.length === 1 ? '' : 's') + '.'; + } + } + // Add task into cache. + this._tasks[name] = {name: name, info: info, fn: fn}; + // Make chainable! + return this; + }; + + // Is the specified task an alias? + Task.prototype.isTaskAlias = function(name) { + return !!this._tasks[name].fn.alias; + }; + + // Rename a task. This might be useful if you want to override the default + // behavior of a task, while retaining the old name. This is a billion times + // easier to implement than some kind of in-task "super" functionality. + Task.prototype.renameTask = function(oldname, newname) { + // Rename helper. + this._tasks[newname] = this._tasks[oldname]; + // Update name property of task. + this._tasks[newname].name = newname; + // Remove old name. + delete this._tasks[oldname]; + // Make chainable! + return this; + }; + + // Argument parsing helper. Supports these signatures: + // fn('foo') // ['foo'] + // fn('foo bar baz') // ['foo', 'bar', 'baz'] + // fn('foo', 'bar', 'baz') // ['foo', 'bar', 'baz'] + // fn(['foo', 'bar', 'baz']) // ['foo', 'bar', 'baz'] + Task.prototype.parseArgs = function(_arguments) { + // If there are multiple (or zero) arguments, convert the _arguments object + // into an array and return that. + return _arguments.length !== 1 ? [].slice.call(_arguments) : + // Return the first argument if it's an Array. + Array.isArray(_arguments[0]) ? _arguments[0] : + // Split the first argument on space. + typeof _arguments[0] === 'string' ? _arguments[0].split(/\s+/) : + // Just return an array containing the first argument. (todo: deprecate) + [_arguments[0]]; + }; + + // Given a task name, determine which actual task will be called, and what + // arguments will be passed into the task callback. "foo" -> task "foo", no + // args. "foo:bar:baz" -> task "foo:bar:baz" with no args (if "foo:bar:baz" + // task exists), otherwise task "foo:bar" with arg "baz" (if "foo:bar" task + // exists), otherwise task "foo" with args "bar" and "baz". + Task.prototype._taskPlusArgs = function(name) { + // Task name / argument parts. + var parts = name.split(':'); + // Start from the end, not the beginning! + var i = parts.length; + var task; + do { + // Get a task. + task = this._tasks[parts.slice(0, i).join(':')]; + // If the task doesn't exist, decrement `i`, and if `i` is greater than + // 0, repeat. + } while (!task && --i > 0); + // Just the args. + var args = parts.slice(i); + // Maybe you want to use them as flags instead of as positional args? + var flags = {}; + args.forEach(function(arg) { flags[arg] = true; }); + // The task to run and the args to run it with. + return {task: task, nameArgs: name, args: args, flags: flags}; + }; + + // Append things to queue in the correct spot. + Task.prototype._push = function(things) { + // Get current placeholder index. + var index = this._queue.indexOf(this._placeholder); + if (index === -1) { + // No placeholder, add task+args objects to end of queue. + this._queue = this._queue.concat(things); + } else { + // Placeholder exists, add task+args objects just before placeholder. + [].splice.apply(this._queue, [index, 0].concat(things)); + } + }; + + // Enqueue a task. + Task.prototype.run = function() { + // Parse arguments into an array, returning an array of task+args objects. + var things = this.parseArgs(arguments).map(this._taskPlusArgs, this); + // Throw an exception if any tasks weren't found. + var fails = things.filter(function(thing) { return !thing.task; }); + if (fails.length > 0) { + this._throwIfRunning(new TaskError('Task "' + fails[0].nameArgs + '" not found.')); + return this; + } + // Append things to queue in the correct spot. + this._push(things); + // Make chainable! + return this; + }; + + // Add a marker to the queue to facilitate clearing it programatically. + Task.prototype.mark = function() { + this._push(this._marker); + // Make chainable! + return this; + }; + + // Begin task queue processing. Ie. run all tasks. + Task.prototype.start = function() { + // Abort if already running. + if (this._running) { return false; } + // Actually process the next task. + var nextTask = function() { + // Async flag. + var async = false; + // Get next task+args object from queue. + var thing; + // Skip any placeholders or markers. + do { + thing = this._queue.shift(); + } while (thing === this._placeholder || thing === this._marker); + // If queue was empty, we're all done. + if (!thing) { + this._running = false; + if (this._options.done) { + this._options.done(); + } + return; + } + // Add a placeholder to the front of the queue. + this._queue.unshift(this._placeholder); + // Update the internal status object and run the next task. + var complete = function(status, errorObj) { + this.current = {}; + // A task has "failed" only if it returns false (async) or if the + // function returned by .async is passed false. + this._success[thing.nameArgs] = status !== false; + // If task failed, call error handler. + if (status === false && this._options.error) { + this._options.error.call({name: thing.task.name, nameArgs: thing.nameArgs}, errorObj || + new TaskError('Task "' + thing.nameArgs + '" failed.')); + } + // Run the next task. + nextTask(); + }.bind(this); + + // Expose some information about the currently-running task. + this.current = { + // The current task name plus args, as-passed. + nameArgs: thing.nameArgs, + // The current task name. + name: thing.task.name, + // The current task arguments. + args: thing.args, + // The current arguments, available as named flags. + flags: thing.flags, + // When called, sets the async flag and returns a function that can + // be used to continue processing the queue. + async: function() { + async = true; + return complete; + } + }; + + try { + // Get the current task and run it, setting `this` inside the task + // function to be something useful. + var status = thing.task.fn.apply(this.current, thing.args); + // If the async flag wasn't set, process the next task in the queue. + if (!async) { + complete(status); + } + } catch (e) { + if (e instanceof TaskError || e instanceof HelperError) { + complete(false, e); + } else { + throw e; + } + } + }.bind(this); + // Update flag. + this._running = true; + // Process the next task. + nextTask(); + }; + + // Clear remaining tasks from the queue. + Task.prototype.clearQueue = function(options) { + if (!options) { options = {}; } + if (options.untilMarker) { + this._queue.splice(0, this._queue.indexOf(this._marker) + 1); + } else { + this._queue = []; + } + // Make chainable! + return this; + }; + + // Test to see if all of the given tasks have succeeded. + Task.prototype.requires = function() { + this.parseArgs(arguments).forEach(function(name) { + var success = this._success[name]; + if (!success) { + throw new TaskError('Required task "' + name + + '" ' + (success === false ? 'failed' : 'missing') + '.'); + } + }.bind(this)); + }; + + // Override default options. + Task.prototype.options = function(options) { + Object.keys(options).forEach(function(name) { + this._options[name] = options[name]; + }.bind(this)); + }; + +}(typeof exports === 'object' && exports || this)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gunzip-js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gunzip-js new file mode 120000 index 0000000..0833f9f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gunzip-js @@ -0,0 +1 @@ +../gzip-js/bin/gunzip.js \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gzip-js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gzip-js new file mode 120000 index 0000000..5db6a5e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/gzip-js @@ -0,0 +1 @@ +../gzip-js/bin/gzip.js \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/jshint b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/jshint new file mode 120000 index 0000000..fca005f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/jshint @@ -0,0 +1 @@ +../jshint/bin/hint \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nodeunit b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nodeunit new file mode 120000 index 0000000..f31cdbe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nodeunit @@ -0,0 +1 @@ +../nodeunit/bin/nodeunit \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nopt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nopt new file mode 120000 index 0000000..6b6566e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/semver b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/semver new file mode 120000 index 0000000..317eb29 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/semver @@ -0,0 +1 @@ +../semver/bin/semver \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/uglifyjs b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.gitmodules b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.gitmodules new file mode 100644 index 0000000..a9aae98 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.gitmodules @@ -0,0 +1,9 @@ +[submodule "deps/nodeunit"] + path = deps/nodeunit + url = git://github.com/caolan/nodeunit.git +[submodule "deps/UglifyJS"] + path = deps/UglifyJS + url = https://github.com/mishoo/UglifyJS.git +[submodule "deps/nodelint"] + path = deps/nodelint + url = https://github.com/tav/nodelint.git diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.npmignore new file mode 100644 index 0000000..9bdfc97 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/.npmignore @@ -0,0 +1,4 @@ +deps +dist +test +nodelint.cfg \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/Makefile new file mode 100644 index 0000000..bad647c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/Makefile @@ -0,0 +1,25 @@ +PACKAGE = asyncjs +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) +CWD := $(shell pwd) +NODEUNIT = $(CWD)/node_modules/nodeunit/bin/nodeunit +UGLIFY = $(CWD)/node_modules/uglify-js/bin/uglifyjs +NODELINT = $(CWD)/node_modules/nodelint/nodelint + +BUILDDIR = dist + +all: clean test build + +build: $(wildcard lib/*.js) + mkdir -p $(BUILDDIR) + $(UGLIFY) lib/async.js > $(BUILDDIR)/async.min.js + +test: + $(NODEUNIT) test + +clean: + rm -rf $(BUILDDIR) + +lint: + $(NODELINT) --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/README.md new file mode 100644 index 0000000..1bbbc47 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/README.md @@ -0,0 +1,1021 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### forEachLimit(arr, limit, iterator, callback) + +The same as forEach only the iterator is applied to batches of items in the +array, in series. The next batch of iterators is only called once the current +one has completed processing. + +__Arguments__ + +* arr - An array to iterate over. +* limit - How many items should be in each batch. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // Assume documents is an array of JSON objects and requestApi is a + // function that interacts with a rate-limited REST api. + + async.forEachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error + }); +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equal to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + ); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ], function (err, result) { + // result now equals 'done' + }); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + // add some items to the queue (batch-wise) + + q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. If all tasks complete + successfully, it will receive an object containing their results. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/index.js new file mode 100644 index 0000000..8e23845 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/async'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/lib/async.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/lib/async.js new file mode 100644 index 0000000..7cc4f5e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/lib/async.js @@ -0,0 +1,692 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + async.forEachLimit = function (arr, limit, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed === arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed === arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _forEach(data, function(task) { + q.tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (q.saturated && q.tasks.length == concurrency) { + q.saturated(); + } + async.nextTick(q.process); + }); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if(q.empty && q.tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && q.tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + +}()); 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 new file mode 100644 index 0000000..71e56fd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/async/package.json @@ -0,0 +1,31 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "./index", + "author": { + "name": "Caolan McMahon" + }, + "version": "0.1.22", + "repository": { + "type": "git", + "url": "http://github.com/caolan/async.git" + }, + "bugs": { + "url": "http://github.com/caolan/async/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/async/raw/master/LICENSE" + } + ], + "devDependencies": { + "nodeunit": ">0.0.0", + "uglify-js": "1.2.x", + "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/MIT-LICENSE.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/MIT-LICENSE.txt new file mode 100644 index 0000000..7dca107 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/MIT-LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/ReadMe.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/ReadMe.md new file mode 100644 index 0000000..1c6b0d0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/ReadMe.md @@ -0,0 +1,77 @@ +# colors.js - get color and style in your node.js console ( and browser ) like what + + + + +## Installation + + npm install colors + +## colors and styles! + +- bold +- italic +- underline +- inverse +- yellow +- cyan +- white +- magenta +- green +- red +- grey +- blue +- rainbow +- zebra +- random + +## Usage + +``` js +var colors = require('./colors'); + +console.log('hello'.green); // outputs green text +console.log('i like cake and pies'.underline.red) // outputs red underlined text +console.log('inverse the color'.inverse); // inverses the color +console.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces) +``` + +# Creating Custom themes + +```js + +var require('colors'); + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); +``` + + +### Contributors + +Marak (Marak Squires) +Alexis Sellier (cloudhead) +mmalecki (Maciej Małecki) +nicoreed (Nico Reed) +morganrallen (Morgan Allen) +JustinCampbell (Justin Campbell) +ded (Dustin Diaz) + + +#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/colors.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/colors.js new file mode 100644 index 0000000..a7198f1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/colors.js @@ -0,0 +1,269 @@ +/* +colors.js + +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +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. + +*/ + +var isHeadless = false; + +if (typeof module !== 'undefined') { + isHeadless = true; +} + +if (!isHeadless) { + var exports = {}; + var module = {}; + var colors = exports; + exports.mode = "browser"; +} else { + exports.mode = "console"; +} + +// +// Prototypes the string object to have additional method calls that add terminal colors +// +var addProperty = function (color, func) { + var allowOverride = ['bold']; + exports[color] = function(str) { + return func.apply(str); + }; + String.prototype.__defineGetter__(color, func); +} + +// +// Iterate through all default styles and colors +// + +var x = ['bold', 'underline', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; +x.forEach(function (style) { + + // __defineGetter__ at the least works in more browsers + // http://robertnyman.com/javascript/javascript-getters-setters.html + // Object.defineProperty only works in Chrome + addProperty(style, function () { + return stylize(this, style); + }); +}); + +function sequencer(map) { + return function () { + if (!isHeadless) { + return this.replace(/( )/, '$1'); + } + var exploded = this.split(""); + var i = 0; + exploded = exploded.map(map); + return exploded.join(""); + } +} + +var rainbowMap = (function () { + var rainbowColors = ['red','yellow','green','blue','magenta']; //RoY G BiV + return function (letter, i, exploded) { + if (letter == " ") { + return letter; + } else { + return stylize(letter, rainbowColors[i++ % rainbowColors.length]); + } + } +})(); + +exports.addSequencer = function (name, map) { + addProperty(name, sequencer(map)); +} + +exports.addSequencer('rainbow', rainbowMap); +exports.addSequencer('zebra', function (letter, i, exploded) { + return i % 2 === 0 ? letter : letter.inverse; +}); + +exports.setTheme = function (theme) { + Object.keys(theme).forEach(function(prop){ + addProperty(prop, function(){ + return exports[theme[prop]](this); + }); + }); +} + +function stylize(str, style) { + + if (exports.mode == 'console') { + var styles = { + //styles + 'bold' : ['\033[1m', '\033[22m'], + 'italic' : ['\033[3m', '\033[23m'], + 'underline' : ['\033[4m', '\033[24m'], + 'inverse' : ['\033[7m', '\033[27m'], + //grayscale + 'white' : ['\033[37m', '\033[39m'], + 'grey' : ['\033[90m', '\033[39m'], + 'black' : ['\033[30m', '\033[39m'], + //colors + 'blue' : ['\033[34m', '\033[39m'], + 'cyan' : ['\033[36m', '\033[39m'], + 'green' : ['\033[32m', '\033[39m'], + 'magenta' : ['\033[35m', '\033[39m'], + 'red' : ['\033[31m', '\033[39m'], + 'yellow' : ['\033[33m', '\033[39m'] + }; + } else if (exports.mode == 'browser') { + var styles = { + //styles + 'bold' : ['', ''], + 'italic' : ['', ''], + 'underline' : ['', ''], + 'inverse' : ['', ''], + //grayscale + 'white' : ['', ''], + 'grey' : ['', ''], + 'black' : ['', ''], + //colors + 'blue' : ['', ''], + 'cyan' : ['', ''], + 'green' : ['', ''], + 'magenta' : ['', ''], + 'red' : ['', ''], + 'yellow' : ['', ''] + }; + } else if (exports.mode == 'none') { + return str; + } else { + console.log('unsupported mode, try "browser", "console" or "none"'); + } + return styles[style][0] + str + styles[style][1]; +}; + +// don't summon zalgo +addProperty('zalgo', function () { + return zalgo(this); +}); + +// please no +function zalgo(text, options) { + var soul = { + "up" : [ + '̍','̎','̄','̅', + '̿','̑','̆','̐', + '͒','͗','͑','̇', + '̈','̊','͂','̓', + '̈','͊','͋','͌', + '̃','̂','̌','͐', + '̀','́','̋','̏', + '̒','̓','̔','̽', + '̉','ͣ','ͤ','ͥ', + 'ͦ','ͧ','ͨ','ͩ', + 'ͪ','ͫ','ͬ','ͭ', + 'ͮ','ͯ','̾','͛', + '͆','̚' + ], + "down" : [ + '̖','̗','̘','̙', + '̜','̝','̞','̟', + '̠','̤','̥','̦', + '̩','̪','̫','̬', + '̭','̮','̯','̰', + '̱','̲','̳','̹', + '̺','̻','̼','ͅ', + '͇','͈','͉','͍', + '͎','͓','͔','͕', + '͖','͙','͚','̣' + ], + "mid" : [ + '̕','̛','̀','́', + '͘','̡','̢','̧', + '̨','̴','̵','̶', + '͜','͝','͞', + '͟','͠','͢','̸', + '̷','͡',' ҉' + ] + }, + all = [].concat(soul.up, soul.down, soul.mid), + zalgo = {}; + + function randomNumber(range) { + r = Math.floor(Math.random()*range); + return r; + }; + + function is_char(character) { + var bool = false; + all.filter(function(i){ + bool = (i == character); + }); + return bool; + } + + function heComes(text, options){ + result = ''; + options = options || {}; + options["up"] = options["up"] || true; + options["mid"] = options["mid"] || true; + options["down"] = options["down"] || true; + options["size"] = options["size"] || "maxi"; + var counts; + text = text.split(''); + for(var l in text){ + if(is_char(l)) { continue; } + result = result + text[l]; + + counts = {"up" : 0, "down" : 0, "mid" : 0}; + + switch(options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.min= randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.min = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down= randomNumber(8) + 1; + break; + } + + var arr = ["up", "mid", "down"]; + for(var d in arr){ + var index = arr[d]; + for (var i = 0 ; i <= counts[index]; i++) + { + if(options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + }; + return heComes(text); +} + +addProperty('stripColors', function() { + return ("" + this).replace(/\u001b\[\d+m/g,''); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.html new file mode 100644 index 0000000..ab95649 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.html @@ -0,0 +1,74 @@ + + + + + Colors Example + + + + + + \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.js new file mode 100644 index 0000000..3da2986 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/example.js @@ -0,0 +1,65 @@ +var colors = require('./colors'); + +//colors.mode = "browser"; + +var test = colors.red("hopefully colorless output"); +console.log('Rainbows are fun!'.rainbow); +console.log('So '.italic + 'are'.underline + ' styles! '.bold + 'inverse'.inverse); // styles not widely supported +console.log('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported +//console.log('zalgo time!'.zalgo); +console.log(test.stripColors); +console.log("a".grey + " b".black); + +console.log("Zebras are so fun!".zebra); + +console.log(colors.rainbow('Rainbows are fun!')); +console.log(colors.italic('So ') + colors.underline('are') + colors.bold(' styles! ') + colors.inverse('inverse')); // styles not widely supported +console.log(colors.bold(colors.italic(colors.underline(colors.red('Chains are also cool.'))))); // styles not widely supported +//console.log(colors.zalgo('zalgo time!')); +console.log(colors.stripColors(test)); +console.log(colors.grey("a") + colors.black(" b")); + +colors.addSequencer("america", function(letter, i, exploded) { + if(letter === " ") return letter; + switch(i%3) { + case 0: return letter.red; + case 1: return letter.white; + case 2: return letter.blue; + } +}); + +colors.addSequencer("random", (function() { + var available = ['bold', 'underline', 'italic', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; + + return function(letter, i, exploded) { + return letter === " " ? letter : letter[available[Math.round(Math.random() * (available.length - 1))]]; + }; +})()); + +console.log("AMERICA! F--K YEAH!".america); +console.log("So apparently I've been to Mars, with all the little green men. But you know, I don't recall.".random); + +// +// Custom themes +// + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); + + 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 new file mode 100644 index 0000000..4fda7d0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/package.json @@ -0,0 +1,20 @@ +{ + "name": "colors", + "description": "get colors in your node.js console like what", + "version": "0.6.0-1", + "author": { + "name": "Marak Squires" + }, + "repository": { + "type": "git", + "url": "http://github.com/Marak/colors.js.git" + }, + "engines": { + "node": ">=0.1.90" + }, + "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/colors/test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/test.js new file mode 100644 index 0000000..1c03d65 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/colors/test.js @@ -0,0 +1,65 @@ +var assert = require('assert'), + colors = require('./colors'); + +// +// This is a pretty nice example on how tests shouldn't be written. However, +// it's more about API stability than about really testing it (although it's +// a pretty complete test suite). +// + +var s = 'string'; + +function a(s, code) { + return '\033[' + code.toString() + 'm' + s + '\033[39m'; +} + +function aE(s, color, code) { + assert.equal(s[color], a(s, code)); + assert.equal(colors[color](s), a(s, code)); + assert.equal(s[color], colors[color](s)); + assert.equal(s[color].stripColors, s); + assert.equal(s[color].stripColors, colors.stripColors(s)); +} + +function h(s, color) { + return '' + s + ''; + // that's pretty dumb approach to testing it +} + +var stylesColors = ['white', 'grey', 'black', 'blue', 'cyan', 'green', 'magenta', 'red', 'yellow']; +var stylesAll = stylesColors.concat(['bold', 'italic', 'underline', 'inverse', 'rainbow']); + +colors.mode = 'console'; +assert.equal(s.bold, '\033[1m' + s + '\033[22m'); +assert.equal(s.italic, '\033[3m' + s + '\033[23m'); +assert.equal(s.underline, '\033[4m' + s + '\033[24m'); +assert.equal(s.inverse, '\033[7m' + s + '\033[27m'); +assert.ok(s.rainbow); +aE(s, 'white', 37); +aE(s, 'grey', 90); +aE(s, 'black', 30); +aE(s, 'blue', 34); +aE(s, 'cyan', 36); +aE(s, 'green', 32); +aE(s, 'magenta', 35); +aE(s, 'red', 31); +aE(s, 'yellow', 33); +assert.equal(s, 'string'); + +colors.mode = 'browser'; +assert.equal(s.bold, '' + s + ''); +assert.equal(s.italic, '' + s + ''); +assert.equal(s.underline, '' + s + ''); +assert.equal(s.inverse, '' + s + ''); +assert.ok(s.rainbow); +stylesColors.forEach(function (color) { + assert.equal(s[color], h(s, color)); + assert.equal(colors[color](s), h(s, color)); +}); + +colors.mode = 'none'; +stylesAll.forEach(function (style) { + assert.equal(s[style], s); + assert.equal(colors[style](s), s); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.npmignore new file mode 100644 index 0000000..9046dde --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.npmignore @@ -0,0 +1,12 @@ +*.markdown +*.md +.git* +Makefile +benchmarks/ +docs/ +examples/ +install.sh +support/ +test/ +.DS_Store +coverage.html diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.travis.yml new file mode 100644 index 0000000..8111245 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/LICENSE new file mode 100644 index 0000000..0c5d22d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/Readme.md new file mode 100644 index 0000000..58d282e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/Readme.md @@ -0,0 +1,133 @@ +[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect) +# Connect + + Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance "plugins" known as _middleware_. + + Connect is bundled with over _20_ commonly used middleware, including + a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/). + +```js +var connect = require('connect') + , http = require('http'); + +var app = connect() + .use(connect.favicon()) + .use(connect.logger('dev')) + .use(connect.static('public')) + .use(connect.directory('public')) + .use(connect.cookieParser()) + .use(connect.session({ secret: 'my secret here' })) + .use(function(req, res){ + res.end('Hello from Connect!\n'); + }); + +http.createServer(app).listen(3000); +``` + +## Middleware + + - csrf + - basicAuth + - bodyParser + - json + - multipart + - urlencoded + - cookieParser + - directory + - compress + - errorHandler + - favicon + - limit + - logger + - methodOverride + - query + - responseTime + - session + - static + - staticCache + - vhost + - subdomains + - cookieSession + +## Running Tests + +first: + + $ npm install -d + +then: + + $ make test + +## Authors + + Below is the output from [git-summary](http://github.com/visionmedia/git-extras). + + + project: connect + commits: 2033 + active : 301 days + files : 171 + authors: + 1414 Tj Holowaychuk 69.6% + 298 visionmedia 14.7% + 191 Tim Caswell 9.4% + 51 TJ Holowaychuk 2.5% + 10 Ryan Olds 0.5% + 8 Astro 0.4% + 5 Nathan Rajlich 0.2% + 5 Jakub Nešetřil 0.2% + 3 Daniel Dickison 0.1% + 3 David Rio Deiros 0.1% + 3 Alexander Simmerl 0.1% + 3 Andreas Lind Petersen 0.1% + 2 Aaron Heckmann 0.1% + 2 Jacques Crocker 0.1% + 2 Fabian Jakobs 0.1% + 2 Brian J Brennan 0.1% + 2 Adam Malcontenti-Wilson 0.1% + 2 Glen Mailer 0.1% + 2 James Campos 0.1% + 1 Trent Mick 0.0% + 1 Troy Kruthoff 0.0% + 1 Wei Zhu 0.0% + 1 comerc 0.0% + 1 darobin 0.0% + 1 nateps 0.0% + 1 Marco Sanson 0.0% + 1 Arthur Taylor 0.0% + 1 Aseem Kishore 0.0% + 1 Bart Teeuwisse 0.0% + 1 Cameron Howey 0.0% + 1 Chad Weider 0.0% + 1 Craig Barnes 0.0% + 1 Eran Hammer-Lahav 0.0% + 1 Gregory McWhirter 0.0% + 1 Guillermo Rauch 0.0% + 1 Jae Kwon 0.0% + 1 Jakub Nesetril 0.0% + 1 Joshua Peek 0.0% + 1 Jxck 0.0% + 1 AJ ONeal 0.0% + 1 Michael Hemesath 0.0% + 1 Morten Siebuhr 0.0% + 1 Samori Gorse 0.0% + 1 Tom Jensen 0.0% + +## Node Compatibility + + Connect `< 1.x` is compatible with node 0.2.x + + + Connect `1.x` is compatible with node 0.4.x + + + Connect (_master_) `2.x` is compatible with node 0.6.x + +## CLA + + [http://sencha.com/cla](http://sencha.com/cla) + +## License + +View the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/). diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/index.js new file mode 100644 index 0000000..23240ee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.CONNECT_COV + ? require('./lib-cov/connect') + : require('./lib/connect'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/cache.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/cache.js new file mode 100644 index 0000000..052fcdb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/cache.js @@ -0,0 +1,81 @@ + +/*! + * Connect - Cache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Expose `Cache`. + */ + +module.exports = Cache; + +/** + * LRU cache store. + * + * @param {Number} limit + * @api private + */ + +function Cache(limit) { + this.store = {}; + this.keys = []; + this.limit = limit; +} + +/** + * Touch `key`, promoting the object. + * + * @param {String} key + * @param {Number} i + * @api private + */ + +Cache.prototype.touch = function(key, i){ + this.keys.splice(i,1); + this.keys.push(key); +}; + +/** + * Remove `key`. + * + * @param {String} key + * @api private + */ + +Cache.prototype.remove = function(key){ + delete this.store[key]; +}; + +/** + * Get the object stored for `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.get = function(key){ + return this.store[key]; +}; + +/** + * Add a cache `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.add = function(key){ + // initialize store + var len = this.keys.push(key); + + // limit reached, invalidate LRU + if (len > this.limit) this.remove(this.keys.shift()); + + var arr = this.store[key] = []; + arr.createdAt = new Date; + return arr; +}; 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 new file mode 100644 index 0000000..19b4502 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/connect.js @@ -0,0 +1,93 @@ + +/*! + * Connect + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , proto = require('./proto') + , utils = require('./utils') + , path = require('path') + , basename = path.basename + , fs = require('fs'); + +// node patches + +require('./patch'); + +// expose createServer() as the module + +exports = module.exports = createServer; + +/** + * Framework version. + */ + +exports.version = '2.4.6'; + +/** + * Expose mime module. + */ + +exports.mime = require('./middleware/static').mime; + +/** + * Expose the prototype. + */ + +exports.proto = proto; + +/** + * Auto-load middleware getters. + */ + +exports.middleware = {}; + +/** + * Expose utilities. + */ + +exports.utils = utils; + +/** + * Create a new connect server. + * + * @return {Function} + * @api public + */ + +function createServer() { + function app(req, res){ app.handle(req, res); } + utils.merge(app, proto); + utils.merge(app, EventEmitter.prototype); + app.route = '/'; + app.stack = []; + for (var i = 0; i < arguments.length; ++i) { + app.use(arguments[i]); + } + return app; +}; + +/** + * Support old `.createServer()` method. + */ + +createServer.createServer = createServer; + +/** + * Auto-load bundled middleware with getters. + */ + +fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ + if (!/\.js$/.test(filename)) return; + var name = basename(filename, '.js'); + function load(){ return require('./middleware/' + name); } + exports.middleware.__defineGetter__(name, load); + exports.__defineGetter__(name, load); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/index.js new file mode 100644 index 0000000..a2602ee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/index.js @@ -0,0 +1,49 @@ + +/** + * Connect is a middleware framework for node, + * shipping with over 18 bundled middleware and a rich selection of + * 3rd-party middleware. + * + * var app = connect() + * .use(connect.logger('dev')) + * .use(connect.static('public')) + * .use(function(req, res){ + * res.end('hello world\n'); + * }) + * .listen(3000); + * + * Installation: + * + * $ npm install connect + * + * Middleware: + * + * - [logger](logger.html) request logger with custom format support + * - [csrf](csrf.html) Cross-site request forgery protection + * - [compress](compress.html) Gzip compression middleware + * - [basicAuth](basicAuth.html) basic http authentication + * - [bodyParser](bodyParser.html) extensible request body parser + * - [json](json.html) application/json parser + * - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser + * - [multipart](multipart.html) multipart/form-data parser + * - [cookieParser](cookieParser.html) cookie parser + * - [session](session.html) session management support with bundled MemoryStore + * - [cookieSession](cookieSession.html) cookie-based session support + * - [methodOverride](methodOverride.html) faux HTTP method support + * - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time + * - [staticCache](staticCache.html) memory cache layer for the static() middleware + * - [static](static.html) streaming static file server supporting `Range` and more + * - [directory](directory.html) directory listing middleware + * - [vhost](vhost.html) virtual host sub-domain mapping middleware + * - [favicon](favicon.html) efficient favicon server (with default icon) + * - [limit](limit.html) limit the bytesize of request bodies + * - [query](query.html) automatic querystring parser, populating `req.query` + * - [errorHandler](errorHandler.html) flexible error handler + * + * Links: + * + * - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware + * - GitHub [repository](http://github.com/senchalabs/connect) + * - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md) + * + */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/basicAuth.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/basicAuth.js new file mode 100644 index 0000000..fbd26f2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/basicAuth.js @@ -0,0 +1,101 @@ + +/*! + * Connect - basicAuth + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , unauthorized = utils.unauthorized; + +/** + * Basic Auth: + * + * Enfore basic authentication by providing a `callback(user, pass)`, + * which must return `true` in order to gain access. Alternatively an async + * method is provided as well, invoking `callback(user, pass, callback)`. Populates + * `req.user`. The final alternative is simply passing username / password + * strings. + * + * Simple username and password + * + * connect(connect.basicAuth('username', 'password')); + * + * Callback verification + * + * connect() + * .use(connect.basicAuth(function(user, pass){ + * return 'tj' == user & 'wahoo' == pass; + * })) + * + * Async callback verification, accepting `fn(err, user)`. + * + * connect() + * .use(connect.basicAuth(function(user, pass, fn){ + * User.authenticate({ user: user, pass: pass }, fn); + * })) + * + * @param {Function|String} callback or username + * @param {String} realm + * @api public + */ + +module.exports = function basicAuth(callback, realm) { + var username, password; + + // user / pass strings + if ('string' == typeof callback) { + username = callback; + password = realm; + if ('string' != typeof password) throw new Error('password argument required'); + realm = arguments[2]; + callback = function(user, pass){ + return user == username && pass == password; + } + } + + realm = realm || 'Authorization Required'; + + return function(req, res, next) { + var authorization = req.headers.authorization; + + if (req.user) return next(); + if (!authorization) return unauthorized(res, realm); + + var parts = authorization.split(' ') + + if (parts.length !== 2) return next(utils.error(400)); + + var scheme = parts[0] + , credentials = new Buffer(parts[1], 'base64').toString().split(':') + , user = credentials[0] + , pass = credentials[1]; + + if ('Basic' != scheme) return next(utils.error(400)); + + // async + if (callback.length >= 3) { + var pause = utils.pause(req); + callback(user, pass, function(err, user){ + if (err || !user) return unauthorized(res, realm); + req.user = req.remoteUser = user; + next(); + pause.resume(); + }); + // sync + } else { + if (callback(user, pass)) { + req.user = req.remoteUser = user; + next(); + } else { + unauthorized(res, realm); + } + } + } +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/bodyParser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/bodyParser.js new file mode 100644 index 0000000..9f692cd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/bodyParser.js @@ -0,0 +1,61 @@ + +/*! + * Connect - bodyParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var multipart = require('./multipart') + , urlencoded = require('./urlencoded') + , json = require('./json'); + +/** + * Body parser: + * + * Parse request bodies, supports _application/json_, + * _application/x-www-form-urlencoded_, and _multipart/form-data_. + * + * This is equivalent to: + * + * app.use(connect.json()); + * app.use(connect.urlencoded()); + * app.use(connect.multipart()); + * + * Examples: + * + * connect() + * .use(connect.bodyParser()) + * .use(function(req, res) { + * res.end('viewing user ' + req.body.user.name); + * }); + * + * $ curl -d 'user[name]=tj' http://local/ + * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/ + * + * View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function bodyParser(options){ + var _urlencoded = urlencoded(options) + , _multipart = multipart(options) + , _json = json(options); + + return function bodyParser(req, res, next) { + _json(req, res, function(err){ + if (err) return next(err); + _urlencoded(req, res, function(err){ + if (err) return next(err); + _multipart(req, res, next); + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/compress.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/compress.js new file mode 100644 index 0000000..5e954c4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/compress.js @@ -0,0 +1,142 @@ +/*! + * Connect - compress + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var zlib = require('zlib'); + +/** + * Supported content-encoding methods. + */ + +exports.methods = { + gzip: zlib.createGzip + , deflate: zlib.createDeflate +}; + +/** + * Default filter function. + */ + +exports.filter = function(req, res){ + return /json|text|javascript/.test(res.getHeader('Content-Type')); +}; + +/** + * Compress: + * + * Compress response data with gzip/deflate. + * + * Filter: + * + * A `filter` callback function may be passed to + * replace the default logic of: + * + * exports.filter = function(req, res){ + * return /json|text|javascript/.test(res.getHeader('Content-Type')); + * }; + * + * Options: + * + * All remaining options are passed to the gzip/deflate + * creation functions. Consult node's docs for additional details. + * + * - `chunkSize` (default: 16*1024) + * - `windowBits` + * - `level`: 0-9 where 0 is no compression, and 9 is slow but best compression + * - `memLevel`: 1-9 low is slower but uses less memory, high is fast but uses more + * - `strategy`: compression strategy + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function compress(options) { + var options = options || {} + , names = Object.keys(exports.methods) + , filter = options.filter || exports.filter; + + return function(req, res, next){ + var accept = req.headers['accept-encoding'] + , write = res.write + , end = res.end + , stream + , method; + + // vary + res.setHeader('Vary', 'Accept-Encoding'); + + // proxy + + res.write = function(chunk, encoding){ + if (!this.headerSent) this._implicitHeader(); + return stream + ? stream.write(new Buffer(chunk, encoding)) + : write.call(res, chunk, encoding); + }; + + res.end = function(chunk, encoding){ + if (chunk) this.write(chunk, encoding); + return stream + ? stream.end() + : end.call(res); + }; + + res.on('header', function(){ + // default request filter + if (!filter(req, res)) return; + + // SHOULD use identity + if (!accept) return; + + // head + if ('HEAD' == req.method) return; + + // default to gzip + if ('*' == accept.trim()) method = 'gzip'; + + // compression method + if (!method) { + for (var i = 0, len = names.length; i < len; ++i) { + if (~accept.indexOf(names[i])) { + method = names[i]; + break; + } + } + } + + // compression method + if (!method) return; + + // compression stream + stream = exports.methods[method](options); + + // header fields + res.setHeader('Content-Encoding', method); + res.removeHeader('Content-Length'); + + // compression + + stream.on('data', function(chunk){ + write.call(res, chunk); + }); + + stream.on('end', function(){ + end.call(res); + }); + + stream.on('drain', function() { + res.emit('drain'); + }); + }); + + next(); + }; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieParser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieParser.js new file mode 100644 index 0000000..876b5d2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieParser.js @@ -0,0 +1,62 @@ + +/*! + * Connect - cookieParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , cookie = require('cookie'); + +/** + * Cookie parser: + * + * Parse _Cookie_ header and populate `req.cookies` + * with an object keyed by the cookie names. Optionally + * you may enabled signed cookie support by passing + * a `secret` string, which assigns `req.secret` so + * it may be used by other middleware. + * + * Examples: + * + * connect() + * .use(connect.cookieParser('optional secret string')) + * .use(function(req, res, next){ + * res.end(JSON.stringify(req.cookies)); + * }) + * + * @param {String} secret + * @return {Function} + * @api public + */ + +module.exports = function cookieParser(secret){ + return function cookieParser(req, res, next) { + if (req.cookies) return next(); + var cookies = req.headers.cookie; + + req.secret = secret; + req.cookies = {}; + req.signedCookies = {}; + + if (cookies) { + try { + req.cookies = cookie.parse(cookies); + if (secret) { + req.signedCookies = utils.parseSignedCookies(req.cookies, secret); + var obj = utils.parseJSONCookies(req.signedCookies); + req.signedCookies = obj; + } + req.cookies = utils.parseJSONCookies(req.cookies); + } catch (err) { + return next(err); + } + } + next(); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieSession.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieSession.js new file mode 100644 index 0000000..24d6495 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/cookieSession.js @@ -0,0 +1,118 @@ + +/*! + * Connect - cookieSession + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , Cookie = require('./session/cookie') + , debug = require('debug')('connect:cookieSession') + , crc16 = require('crc').crc16; + +// environment + +var env = process.env.NODE_ENV; + +/** + * Cookie Session: + * + * Cookie session middleware. + * + * var app = connect(); + * app.use(connect.cookieParser()); + * app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }})); + * + * Options: + * + * - `key` cookie name defaulting to `connect.sess` + * - `secret` prevents cookie tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Clearing sessions: + * + * To clear the session simply set its value to `null`, + * `cookieSession()` will then respond with a 1970 Set-Cookie. + * + * req.session = null; + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function cookieSession(options){ + // TODO: utilize Session/Cookie to unify API + var options = options || {} + , key = options.key || 'connect.sess' + , trustProxy = options.proxy; + + return function cookieSession(req, res, next) { + + // req.secret is for backwards compatibility + var secret = options.secret || req.secret; + if (!secret) throw new Error('`secret` option required for cookie sessions'); + + // default session + req.session = {}; + var cookie = req.session.cookie = new Cookie(options.cookie); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path)) return next(); + + // cookieParser secret + if (!options.secret && req.secret) { + req.session = req.signedCookies[key] || {}; + } else { + // TODO: refactor + var rawCookie = req.cookies[key]; + if (rawCookie) { + var unsigned = utils.parseSignedCookie(rawCookie, secret); + if (unsigned) { + var originalHash = crc16(unsigned); + req.session = utils.parseJSONCookie(unsigned) || {}; + } + } + } + + res.on('header', function(){ + // removed + if (!req.session) { + debug('clear session'); + cookie.expires = new Date(0); + res.setHeader('Set-Cookie', cookie.serialize(key, '')); + return; + } + + delete req.session.cookie; + + // check security + var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto) + , secured = cookie.secure && tls; + + // only send secure cookies via https + if (cookie.secure && !secured) return debug('not secured'); + + // serialize + debug('serializing %j', req.session); + var val = 'j:' + JSON.stringify(req.session); + + // compare hashes, no need to set-cookie if unchanged + if (originalHash == crc16(val)) return debug('unmodified session'); + + // set-cookie + val = 's:' + utils.sign(val, secret); + val = cookie.serialize(key, val); + debug('set-cookie %j', cookie); + res.setHeader('Set-Cookie', val); + }); + + next(); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/csrf.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/csrf.js new file mode 100644 index 0000000..d7a5e05 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/csrf.js @@ -0,0 +1,73 @@ +/*! + * Connect - csrf + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Anti CSRF: + * + * CRSF protection middleware. + * + * By default this middleware generates a token named "_csrf" + * which should be added to requests which mutate + * state, within a hidden form field, query-string etc. This + * token is validated against the visitor's `req.session._csrf` + * property. + * + * The default `value` function checks `req.body` generated + * by the `bodyParser()` middleware, `req.query` generated + * by `query()`, and the "X-CSRF-Token" header field. + * + * This middleware requires session support, thus should be added + * somewhere _below_ `session()` and `cookieParser()`. + * + * Options: + * + * - `value` a function accepting the request, returning the token + * + * @param {Object} options + * @api public + */ + +module.exports = function csrf(options) { + var options = options || {} + , value = options.value || defaultValue; + + return function(req, res, next){ + // generate CSRF token + var token = req.session._csrf || (req.session._csrf = utils.uid(24)); + + // ignore these methods + if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); + + // determine value + var val = value(req); + + // check + if (val != token) return next(utils.error(403)); + + next(); + } +}; + +/** + * Default value function, checking the `req.body` + * and `req.query` for the CSRF token. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +function defaultValue(req) { + return (req.body && req.body._csrf) + || (req.query && req.query._csrf) + || (req.headers['x-csrf-token']); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/directory.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/directory.js new file mode 100644 index 0000000..1c925a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/directory.js @@ -0,0 +1,229 @@ + +/*! + * Connect - directory + * Copyright(c) 2011 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +// TODO: icon / style for directories +// TODO: arrow key navigation +// TODO: make icons extensible + +/** + * Module dependencies. + */ + +var fs = require('fs') + , parse = require('url').parse + , utils = require('../utils') + , path = require('path') + , normalize = path.normalize + , extname = path.extname + , join = path.join; + +/*! + * Icon cache. + */ + +var cache = {}; + +/** + * Directory: + * + * Serve directory listings with the given `root` path. + * + * Options: + * + * - `hidden` display hidden (dot) files. Defaults to false. + * - `icons` display icons. Defaults to false. + * - `filter` Apply this filter function to files. Defaults to false. + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function directory(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('directory() root path required'); + var hidden = options.hidden + , icons = options.icons + , filter = options.filter + , root = normalize(root); + + return function directory(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + + var accept = req.headers.accept || 'text/plain' + , url = parse(req.url) + , dir = decodeURIComponent(url.pathname) + , path = normalize(join(root, dir)) + , originalUrl = parse(req.originalUrl) + , originalDir = decodeURIComponent(originalUrl.pathname) + , showUp = path != root && path != root + '/'; + + // null byte(s), bad request + if (~path.indexOf('\0')) return next(utils.error(400)); + + // malicious path, forbidden + if (0 != path.indexOf(root)) return next(utils.error(403)); + + // check if we have a directory + fs.stat(path, function(err, stat){ + if (err) return 'ENOENT' == err.code + ? next() + : next(err); + + if (!stat.isDirectory()) return next(); + + // fetch files + fs.readdir(path, function(err, files){ + if (err) return next(err); + if (!hidden) files = removeHidden(files); + if (filter) files = files.filter(filter); + files.sort(); + + // content-negotiation + for (var key in exports) { + if (~accept.indexOf(key) || ~accept.indexOf('*/*')) { + exports[key](req, res, files, next, originalDir, showUp, icons); + return; + } + } + + // not acceptable + next(utils.error(406)); + }); + }); + }; +}; + +/** + * Respond with text/html. + */ + +exports.html = function(req, res, files, next, dir, showUp, icons){ + fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){ + if (err) return next(err); + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){ + if (err) return next(err); + if (showUp) files.unshift('..'); + str = str + .replace('{style}', style) + .replace('{files}', html(files, dir, icons)) + .replace('{directory}', dir) + .replace('{linked-path}', htmlPath(dir)); + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Content-Length', str.length); + res.end(str); + }); + }); +}; + +/** + * Respond with application/json. + */ + +exports.json = function(req, res, files){ + files = JSON.stringify(files); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Respond with text/plain. + */ + +exports.plain = function(req, res, files){ + files = files.join('\n') + '\n'; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Map html `dir`, returning a linked path. + */ + +function htmlPath(dir) { + var curr = []; + return dir.split('/').map(function(part){ + curr.push(part); + return '' + part + ''; + }).join(' / '); +} + +/** + * Map html `files`, returning an html unordered list. + */ + +function html(files, dir, useIcons) { + return '
      ' + files.map(function(file){ + var icon = '' + , classes = []; + + if (useIcons && '..' != file) { + icon = icons[extname(file)] || icons.default; + icon = ''; + classes.push('icon'); + } + + return '
    • ' + + icon + file + '
    • '; + + }).join('\n') + '
    '; +} + +/** + * Load and cache the given `icon`. + * + * @param {String} icon + * @return {String} + * @api private + */ + +function load(icon) { + if (cache[icon]) return cache[icon]; + return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64'); +} + +/** + * Filter "hidden" `files`, aka files + * beginning with a `.`. + * + * @param {Array} files + * @return {Array} + * @api private + */ + +function removeHidden(files) { + return files.filter(function(file){ + return '.' != file[0]; + }); +} + +/** + * Icon map. + */ + +var icons = { + '.js': 'page_white_code_red.png' + , '.c': 'page_white_c.png' + , '.h': 'page_white_h.png' + , '.cc': 'page_white_cplusplus.png' + , '.php': 'page_white_php.png' + , '.rb': 'page_white_ruby.png' + , '.cpp': 'page_white_cplusplus.png' + , '.swf': 'page_white_flash.png' + , '.pdf': 'page_white_acrobat.png' + , 'default': 'page_white.png' +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/errorHandler.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/errorHandler.js new file mode 100644 index 0000000..b62aab7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/errorHandler.js @@ -0,0 +1,87 @@ +/*! + * Connect - errorHandler + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , url = require('url') + , fs = require('fs'); + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Error handler: + * + * Development error handler, providing stack traces + * and error message responses for requests accepting text, html, + * or json. + * + * Text: + * + * By default, and when _text/plain_ is accepted a simple stack trace + * or error message will be returned. + * + * JSON: + * + * When _application/json_ is accepted, connect will respond with + * an object in the form of `{ "error": error }`. + * + * HTML: + * + * When accepted connect will output a nice html stack trace. + * + * @return {Function} + * @api public + */ + +exports = module.exports = function errorHandler(){ + return function errorHandler(err, req, res, next){ + if (err.status) res.statusCode = err.status; + if (res.statusCode < 400) res.statusCode = 500; + if ('test' != env) console.error(err.stack); + var accept = req.headers.accept || ''; + // html + if (~accept.indexOf('html')) { + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){ + fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){ + var stack = (err.stack || '') + .split('\n').slice(1) + .map(function(v){ return '
  • ' + v + '
  • '; }).join(''); + html = html + .replace('{style}', style) + .replace('{stack}', stack) + .replace('{title}', exports.title) + .replace('{statusCode}', res.statusCode) + .replace(/\{error\}/g, utils.escape(err.toString())); + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end(html); + }); + }); + // json + } else if (~accept.indexOf('json')) { + var error = { message: err.message, stack: err.stack }; + for (var prop in err) error[prop] = err[prop]; + var json = JSON.stringify({ error: error }); + res.setHeader('Content-Type', 'application/json'); + res.end(json); + // plain text + } else { + res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' }); + res.end(err.stack); + } + }; +}; + +/** + * Template title, framework authors may override this value. + */ + +exports.title = 'Connect'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/favicon.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/favicon.js new file mode 100644 index 0000000..c57bf34 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/favicon.js @@ -0,0 +1,81 @@ + +/*! + * Connect - favicon + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , utils = require('../utils'); + +/** + * Favicon: + * + * By default serves the connect favicon, or the favicon + * located by the given `path`. + * + * Options: + * + * - `maxAge` cache-control max-age directive, defaulting to 1 day + * + * Examples: + * + * Serve default favicon: + * + * connect() + * .use(connect.favicon()) + * + * Serve favicon before logging for brevity: + * + * connect() + * .use(connect.favicon()) + * .use(connect.logger('dev')) + * + * Serve custom favicon: + * + * connect() + * .use(connect.favicon('public/favicon.ico)) + * + * @param {String} path + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function favicon(path, options){ + var options = options || {} + , path = path || __dirname + '/../public/favicon.ico' + , maxAge = options.maxAge || 86400000 + , icon; // favicon cache + + return function favicon(req, res, next){ + if ('/favicon.ico' == req.url) { + if (icon) { + res.writeHead(200, icon.headers); + res.end(icon.body); + } else { + fs.readFile(path, function(err, buf){ + if (err) return next(err); + icon = { + headers: { + 'Content-Type': 'image/x-icon' + , 'Content-Length': buf.length + , 'ETag': '"' + utils.md5(buf) + '"' + , 'Cache-Control': 'public, max-age=' + (maxAge / 1000) + }, + body: buf + }; + res.writeHead(200, icon.headers); + res.end(icon.body); + }); + } + } else { + next(); + } + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/json.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/json.js new file mode 100644 index 0000000..1659cf8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/json.js @@ -0,0 +1,80 @@ + +/*! + * Connect - json + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * JSON: + * + * Parse JSON request bodies, providing the + * parsed object as `req.body`. + * + * Options: + * + * - `strict` when `false` anything `JSON.parse()` accepts will be parsed + * - `reviver` used as the second "reviver" argument for JSON.parse + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + var options = options || {} + , strict = options.strict === false + ? false + : true; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function json(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + // check Content-Type + if ('application/json' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + if (strict && '{' != buf[0] && '[' != buf[0]) return next(utils.error(400, 'invalid json')); + try { + req.body = JSON.parse(buf, options.reviver); + next(); + } catch (err){ + err.body = buf; + err.status = 400; + next(err); + } + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/limit.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/limit.js new file mode 100644 index 0000000..8233b4d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/limit.js @@ -0,0 +1,55 @@ + +/*! + * Connect - limit + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Limit: + * + * Limit request bodies to the given size in `bytes`. + * + * A string representation of the bytesize may also be passed, + * for example "5mb", "200kb", "1gb", etc. + * + * connect() + * .use(connect.limit('5.5mb')) + * .use(handleImageUpload) + * + * @param {Number|String} bytes + * @return {Function} + * @api public + */ + +module.exports = function limit(bytes){ + if ('string' == typeof bytes) bytes = utils.parseBytes(bytes); + if ('number' != typeof bytes) throw new Error('limit() bytes required'); + return function limit(req, res, next){ + var received = 0 + , len = req.headers['content-length'] + ? parseInt(req.headers['content-length'], 10) + : null; + + // self-awareness + if (req._limit) return next(); + req._limit = true; + + // limit by content-length + if (len && len > bytes) return next(utils.error(413)); + + // limit + req.on('data', function(chunk){ + received += chunk.length; + if (received > bytes) req.destroy(); + }); + + next(); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/logger.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/logger.js new file mode 100644 index 0000000..ccf08a0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/logger.js @@ -0,0 +1,336 @@ +/*! + * Connect - logger + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var bytes = require('bytes'); + +/*! + * Log buffer. + */ + +var buf = []; + +/*! + * Default log buffer duration. + */ + +var defaultBufferDuration = 1000; + +/** + * Logger: + * + * Log requests with the given `options` or a `format` string. + * + * Options: + * + * - `format` Format string, see below for tokens + * - `stream` Output stream, defaults to _stdout_ + * - `buffer` Buffer duration, defaults to 1000ms when _true_ + * - `immediate` Write log line on request instead of response (for response times) + * + * Tokens: + * + * - `:req[header]` ex: `:req[Accept]` + * - `:res[header]` ex: `:res[Content-Length]` + * - `:http-version` + * - `:response-time` + * - `:remote-addr` + * - `:date` + * - `:method` + * - `:url` + * - `:referrer` + * - `:user-agent` + * - `:status` + * + * Formats: + * + * Pre-defined formats that ship with connect: + * + * - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"' + * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms' + * - `tiny` ':method :url :status :res[content-length] - :response-time ms' + * - `dev` concise output colored by response status for development use + * + * Examples: + * + * connect.logger() // default + * connect.logger('short') + * connect.logger('tiny') + * connect.logger({ immediate: true, format: 'dev' }) + * connect.logger(':method :url - :referrer') + * connect.logger(':req[content-type] -> :res[content-type]') + * connect.logger(function(req, res){ return 'some format string' }) + * + * Defining Tokens: + * + * To define a token, simply invoke `connect.logger.token()` with the + * name and a callback function. The value returned is then available + * as ":type" in this case. + * + * connect.logger.token('type', function(req, res){ return req.headers['content-type']; }) + * + * Defining Formats: + * + * All default formats are defined this way, however it's public API as well: + * + * connect.logger.format('name', 'string or function') + * + * @param {String|Function|Object} format or options + * @return {Function} + * @api public + */ + +exports = module.exports = function logger(options) { + if ('object' == typeof options) { + options = options || {}; + } else if (options) { + options = { format: options }; + } else { + options = {}; + } + + // output on request instead of response + var immediate = options.immediate; + + // format name + var fmt = exports[options.format] || options.format || exports.default; + + // compile format + if ('function' != typeof fmt) fmt = compile(fmt); + + // options + var stream = options.stream || process.stdout + , buffer = options.buffer; + + // buffering support + if (buffer) { + var realStream = stream + , interval = 'number' == typeof buffer + ? buffer + : defaultBufferDuration; + + // flush interval + setInterval(function(){ + if (buf.length) { + realStream.write(buf.join(''), 'ascii'); + buf.length = 0; + } + }, interval); + + // swap the stream + stream = { + write: function(str){ + buf.push(str); + } + }; + } + + return function logger(req, res, next) { + req._startTime = new Date; + + // immediate + if (immediate) { + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n', 'ascii'); + // proxy end to output logging + } else { + var end = res.end; + res.end = function(chunk, encoding){ + res.end = end; + res.end(chunk, encoding); + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n', 'ascii'); + }; + } + + + next(); + }; +}; + +/** + * Compile `fmt` into a function. + * + * @param {String} fmt + * @return {Function} + * @api private + */ + +function compile(fmt) { + fmt = fmt.replace(/"/g, '\\"'); + var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){ + return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "'; + }) + '";' + return new Function('tokens, req, res', js); +}; + +/** + * Define a token function with the given `name`, + * and callback `fn(req, res)`. + * + * @param {String} name + * @param {Function} fn + * @return {Object} exports for chaining + * @api public + */ + +exports.token = function(name, fn) { + exports[name] = fn; + return this; +}; + +/** + * Define a `fmt` with the given `name`. + * + * @param {String} name + * @param {String|Function} fmt + * @return {Object} exports for chaining + * @api public + */ + +exports.format = function(name, str){ + exports[name] = str; + return this; +}; + +/** + * Default format. + */ + +exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'); + +/** + * Short format. + */ + +exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'); + +/** + * Tiny format. + */ + +exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms'); + +/** + * dev (colored) + */ + +exports.format('dev', function(tokens, req, res){ + var status = res.statusCode + , len = parseInt(res.getHeader('Content-Length'), 10) + , color = 32; + + if (status >= 500) color = 31 + else if (status >= 400) color = 33 + else if (status >= 300) color = 36; + + len = isNaN(len) + ? '' + : len = ' - ' + bytes(len); + + return '\033[90m' + req.method + + ' ' + req.originalUrl + ' ' + + '\033[' + color + 'm' + res.statusCode + + ' \033[90m' + + (new Date - req._startTime) + + 'ms' + len + + '\033[0m'; +}); + +/** + * request url + */ + +exports.token('url', function(req){ + return req.originalUrl || req.url; +}); + +/** + * request method + */ + +exports.token('method', function(req){ + return req.method; +}); + +/** + * response time in milliseconds + */ + +exports.token('response-time', function(req){ + return new Date - req._startTime; +}); + +/** + * UTC date + */ + +exports.token('date', function(){ + return new Date().toUTCString(); +}); + +/** + * response status code + */ + +exports.token('status', function(req, res){ + return res.statusCode; +}); + +/** + * normalized referrer + */ + +exports.token('referrer', function(req){ + return req.headers['referer'] || req.headers['referrer']; +}); + +/** + * remote address + */ + +exports.token('remote-addr', function(req){ + return req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)); +}); + +/** + * HTTP version + */ + +exports.token('http-version', function(req){ + return req.httpVersionMajor + '.' + req.httpVersionMinor; +}); + +/** + * UA string + */ + +exports.token('user-agent', function(req){ + return req.headers['user-agent']; +}); + +/** + * request header + */ + +exports.token('req', function(req, res, field){ + return req.headers[field.toLowerCase()]; +}); + +/** + * response header + */ + +exports.token('res', function(req, res, field){ + return (res._headers || {})[field.toLowerCase()]; +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/methodOverride.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/methodOverride.js new file mode 100644 index 0000000..aaf4014 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/methodOverride.js @@ -0,0 +1,40 @@ + +/*! + * Connect - methodOverride + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Method Override: + * + * Provides faux HTTP method support. + * + * Pass an optional `key` to use when checking for + * a method override, othewise defaults to _\_method_. + * The original method is available via `req.originalMethod`. + * + * @param {String} key + * @return {Function} + * @api public + */ + +module.exports = function methodOverride(key){ + key = key || "_method"; + return function methodOverride(req, res, next) { + req.originalMethod = req.originalMethod || req.method; + + // req.body + if (req.body && key in req.body) { + req.method = req.body[key].toUpperCase(); + delete req.body[key]; + // check X-HTTP-Method-Override + } else if (req.headers['x-http-method-override']) { + req.method = req.headers['x-http-method-override'].toUpperCase(); + } + + next(); + }; +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/multipart.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/multipart.js new file mode 100644 index 0000000..2bf10ac --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/multipart.js @@ -0,0 +1,120 @@ +/*! + * Connect - multipart + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var formidable = require('formidable') + , _limit = require('./limit') + , utils = require('../utils') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Multipart: + * + * Parse multipart/form-data request bodies, + * providing the parsed object as `req.body` + * and `req.files`. + * + * Configuration: + * + * The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s + * `IncomingForm` object, allowing you to configure the upload directory, + * size limits, etc. For example if you wish to change the upload dir do the following. + * + * app.use(connect.multipart({ uploadDir: path })); + * + * Options: + * + * - `limit` byte limit defaulting to none + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function multipart(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + req.files = req.files || {}; + + // ignore GET + if ('GET' == req.method || 'HEAD' == req.method) return next(); + + // check Content-Type + if ('multipart/form-data' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + + var form = new formidable.IncomingForm + , data = {} + , files = {} + , done; + + Object.keys(options).forEach(function(key){ + form[key] = options[key]; + }); + + function ondata(name, val, data){ + if (Array.isArray(data[name])) { + data[name].push(val); + } else if (data[name]) { + data[name] = [data[name], val]; + } else { + data[name] = val; + } + } + + form.on('field', function(name, val){ + ondata(name, val, data); + }); + + form.on('file', function(name, val){ + ondata(name, val, files); + }); + + form.on('error', function(err){ + next(err); + done = true; + }); + + form.on('end', function(){ + if (done) return; + try { + req.body = qs.parse(data); + req.files = qs.parse(files); + next(); + } catch (err) { + next(err); + } + }); + + form.parse(req); + }); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/query.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/query.js new file mode 100644 index 0000000..93fc5d3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/query.js @@ -0,0 +1,46 @@ +/*! + * Connect - query + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var qs = require('qs') + , parse = require('../utils').parseUrl; + +/** + * Query: + * + * Automatically parse the query-string when available, + * populating the `req.query` object. + * + * Examples: + * + * connect() + * .use(connect.query()) + * .use(function(req, res){ + * res.end(JSON.stringify(req.query)); + * }); + * + * The `options` passed are provided to qs.parse function. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options){ + return function query(req, res, next){ + if (!req.query) { + req.query = ~req.url.indexOf('?') + ? qs.parse(parse(req).query, options) + : {}; + } + + next(); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/responseTime.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/responseTime.js new file mode 100644 index 0000000..57858f6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/responseTime.js @@ -0,0 +1,32 @@ + +/*! + * Connect - responseTime + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Reponse time: + * + * Adds the `X-Response-Time` header displaying the response + * duration in milliseconds. + * + * @return {Function} + * @api public + */ + +module.exports = function responseTime(){ + return function(req, res, next){ + var start = new Date; + + if (res._responseTime) return next(); + res._responseTime = true; + + res.on('header', function(header){ + var duration = new Date - start; + res.setHeader('X-Response-time', duration + 'ms'); + }); + + next(); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session.js new file mode 100644 index 0000000..af57b8f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session.js @@ -0,0 +1,352 @@ + +/*! + * Connect - session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Session = require('./session/session') + , debug = require('debug')('connect:session') + , MemoryStore = require('./session/memory') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + , utils = require('./../utils') + , parse = utils.parseUrl + , crc16 = require('crc').crc16 + , crypto = require('crypto'); + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + */ + +var warning = 'Warning: connection.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Session: + * + * Setup session store with the given `options`. + * + * Session data is _not_ saved in the cookie itself, however + * cookies are used, so we must use the [cookieParser()](cookieParser.html) + * middleware _before_ `session()`. + * + * Examples: + * + * connect() + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }})) + * + * Options: + * + * - `key` cookie name defaulting to `connect.sid` + * - `store` session store instance + * - `secret` session cookie is signed with this secret to prevent tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Cookie option: + * + * By default `cookie.maxAge` is `null`, meaning no "expires" parameter is set + * so the cookie becomes a browser-session cookie. When the user closes the + * browser the cookie (and session) will be removed. + * + * ## req.session + * + * To store or access session data, simply use the request property `req.session`, + * which is (generally) serialized as JSON by the store, so nested objects + * are typically fine. For example below is a user-specific view counter: + * + * connect() + * .use(connect.favicon()) + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})) + * .use(function(req, res, next){ + * var sess = req.session; + * if (sess.views) { + * res.setHeader('Content-Type', 'text/html'); + * res.write('

    views: ' + sess.views + '

    '); + * res.write('

    expires in: ' + (sess.cookie.maxAge / 1000) + 's

    '); + * res.end(); + * sess.views++; + * } else { + * sess.views = 1; + * res.end('welcome to the session demo. refresh!'); + * } + * } + * )).listen(3000); + * + * ## Session#regenerate() + * + * To regenerate the session simply invoke the method, once complete + * a new SID and `Session` instance will be initialized at `req.session`. + * + * req.session.regenerate(function(err){ + * // will have a new session here + * }); + * + * ## Session#destroy() + * + * Destroys the session, removing `req.session`, will be re-generated next request. + * + * req.session.destroy(function(err){ + * // cannot access session here + * }); + * + * ## Session#reload() + * + * Reloads the session data. + * + * req.session.reload(function(err){ + * // session updated + * }); + * + * ## Session#save() + * + * Save the session. + * + * req.session.save(function(err){ + * // session saved + * }); + * + * ## Session#touch() + * + * Updates the `.maxAge` property. Typically this is + * not necessary to call, as the session middleware does this for you. + * + * ## Session#cookie + * + * Each session has a unique cookie object accompany it. This allows + * you to alter the session cookie per visitor. For example we can + * set `req.session.cookie.expires` to `false` to enable the cookie + * to remain for only the duration of the user-agent. + * + * ## Session#maxAge + * + * Alternatively `req.session.cookie.maxAge` will return the time + * remaining in milliseconds, which we may also re-assign a new value + * to adjust the `.expires` property appropriately. The following + * are essentially equivalent + * + * var hour = 3600000; + * req.session.cookie.expires = new Date(Date.now() + hour); + * req.session.cookie.maxAge = hour; + * + * For example when `maxAge` is set to `60000` (one minute), and 30 seconds + * has elapsed it will return `30000` until the current request has completed, + * at which time `req.session.touch()` is called to reset `req.session.maxAge` + * to its original value. + * + * req.session.cookie.maxAge; + * // => 30000 + * + * Session Store Implementation: + * + * Every session store _must_ implement the following methods + * + * - `.get(sid, callback)` + * - `.set(sid, session, callback)` + * - `.destroy(sid, callback)` + * + * Recommended methods include, but are not limited to: + * + * - `.length(callback)` + * - `.clear(callback)` + * + * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +function session(options){ + var options = options || {} + , key = options.key || 'connect.sid' + , store = options.store || new MemoryStore + , cookie = options.cookie || {} + , trustProxy = options.proxy + , storeReady = true; + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = utils.uid(24); + req.session = new Session(req); + req.session.cookie = new Cookie(cookie); + }; + + store.on('disconnect', function(){ storeReady = false; }); + store.on('connect', function(){ storeReady = true; }); + + return function session(req, res, next) { + // self-awareness + if (req.session) return next(); + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) return next(); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next(); + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secret = options.secret || req.secret; + + // ensure secret is available or bail + if (!secret) throw new Error('`secret` option required for sessions'); + + // parse url + var url = parse(req) + , path = url.pathname + , originalHash; + + // expose store + req.sessionStore = store; + + // grab the session cookie value and check the signature + var rawCookie = req.cookies[key]; + + // get signedCookies for backwards compat with signed cookies + var unsignedCookie = req.signedCookies[key]; + + if (!unsignedCookie && rawCookie) { + unsignedCookie = utils.parseSignedCookie(rawCookie, secret); + } + + // set-cookie + res.on('header', function(){ + if (!req.session) return; + var cookie = req.session.cookie + , proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto) + , secured = cookie.secure && tls + , isNew = unsignedCookie != req.sessionID; + + // only send secure cookies via https + if (cookie.secure && !secured) return debug('not secured'); + + // browser-session length cookie + if (null == cookie.expires) { + if (!isNew) return debug('already set browser-session cookie'); + // compare hashes + } else if (originalHash == hash(req.session)) { + return debug('unmodified session'); + } + + var val = 's:' + utils.sign(req.sessionID, secret); + val = cookie.serialize(key, val); + debug('set-cookie %s', val); + res.setHeader('Set-Cookie', val); + }); + + // proxy end() to commit the session + var end = res.end; + res.end = function(data, encoding){ + res.end = end; + if (!req.session) return res.end(data, encoding); + debug('saving'); + req.session.resetMaxAge(); + req.session.save(function(){ + debug('saved'); + res.end(data, encoding); + }); + }; + + // generate the session + function generate() { + store.generate(req); + } + + // get the sessionID from the cookie + req.sessionID = unsignedCookie; + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + var pause = utils.pause(req); + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // proxy to resume() events + var _next = next; + next = function(err){ + _next(err); + pause.resume(); + } + + // error handling + if (err) { + debug('error'); + if ('ENOENT' == err.code) { + generate(); + next(); + } else { + next(err); + } + // no session + } else if (!sess) { + debug('no session found'); + generate(); + next(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalHash = hash(sess); + next(); + } + }); + }; +}; + +/** + * Hash the given `sess` object omitting changes + * to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @api private + */ + +function hash(sess) { + return crc16(JSON.stringify(sess, function(key, val){ + if ('cookie' != key) return val; + })); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/cookie.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/cookie.js new file mode 100644 index 0000000..e8ff862 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/cookie.js @@ -0,0 +1,128 @@ + +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) utils.merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + } + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/memory.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/memory.js new file mode 100644 index 0000000..ec569f5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/memory.js @@ -0,0 +1,131 @@ + +/*! + * Connect - session - MemoryStore + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Store = require('./store') + , utils = require('../../utils') + , Session = require('./session'); + +/** + * Initialize a new `MemoryStore`. + * + * @api public + */ + +var MemoryStore = module.exports = function MemoryStore() { + this.sessions = {}; +}; + +/** + * Inherit from `Store.prototype`. + */ + +MemoryStore.prototype.__proto__ = Store.prototype; + +/** + * Attempt to fetch session by the given `sid`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.get = function(sid, fn){ + var self = this; + process.nextTick(function(){ + var expires + , sess = self.sessions[sid]; + if (sess) { + sess = JSON.parse(sess); + expires = 'string' == typeof sess.cookie.expires + ? new Date(sess.cookie.expires) + : sess.cookie.expires; + if (!expires || new Date < expires) { + fn(null, sess); + } else { + self.destroy(sid, fn); + } + } else { + fn(); + } + }); +}; + +/** + * Commit the given `sess` object associated with the given `sid`. + * + * @param {String} sid + * @param {Session} sess + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.set = function(sid, sess, fn){ + var self = this; + process.nextTick(function(){ + self.sessions[sid] = JSON.stringify(sess); + fn && fn(); + }); +}; + +/** + * Destroy the session associated with the given `sid`. + * + * @param {String} sid + * @api public + */ + +MemoryStore.prototype.destroy = function(sid, fn){ + var self = this; + process.nextTick(function(){ + delete self.sessions[sid]; + fn && fn(); + }); +}; + +/** + * Invoke the given callback `fn` with all active sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.all = function(fn){ + var arr = [] + , keys = Object.keys(this.sessions); + for (var i = 0, len = keys.length; i < len; ++i) { + arr.push(this.sessions[keys[i]]); + } + fn(null, arr); +}; + +/** + * Clear all sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.clear = function(fn){ + this.sessions = {}; + fn && fn(); +}; + +/** + * Fetch number of sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.length = function(fn){ + fn(null, Object.keys(this.sessions).length); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/session.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/session.js new file mode 100644 index 0000000..0dd4b40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/session.js @@ -0,0 +1,116 @@ + +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils'); + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +var Session = module.exports = function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + if ('object' == typeof data) utils.merge(this, data); +}; + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.touch = function(){ + return this.resetMaxAge(); +}; + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.resetMaxAge = function(){ + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}; + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.save = function(fn){ + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}; + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.reload = function(fn){ + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}; + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.destroy = function(fn){ + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}; + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.regenerate = function(fn){ + this.req.sessionStore.regenerate(this.req, fn); + return this; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/store.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/store.js new file mode 100644 index 0000000..7d6f1cb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/session/store.js @@ -0,0 +1,86 @@ + +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , Session = require('./session') + , Cookie = require('./cookie') + , utils = require('../../utils'); + +/** + * Initialize abstract `Store`. + * + * @api private + */ + +var Store = module.exports = function Store(options){}; + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + sess = self.createSession(req, sess); + fn(null, sess); + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge + , update = null == update ? true : false; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/static.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/static.js new file mode 100644 index 0000000..281a783 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/static.js @@ -0,0 +1,94 @@ + +/*! + * Connect - static + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var send = require('send') + , utils = require('../utils') + , parse = utils.parseUrl + , url = require('url'); + +/** + * Static: + * + * Static file server with the given `root` path. + * + * Examples: + * + * var oneDay = 86400000; + * + * connect() + * .use(connect.static(__dirname + '/public')) + * + * connect() + * .use(connect.static(__dirname + '/public', { maxAge: oneDay })) + * + * Options: + * + * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0 + * - `hidden` Allow transfer of hidden files. defaults to false + * - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function static(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('static() root path required'); + + // default redirect + var redirect = false === options.redirect ? false : true; + + return function static(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + var path = parse(req).pathname; + var pause = utils.pause(req); + + function resume() { + next(); + pause.resume(); + } + + function directory() { + if (!redirect) return resume(); + var pathname = url.parse(req.originalUrl).pathname; + res.statusCode = 301; + res.setHeader('Location', pathname + '/'); + res.end('Redirecting to ' + utils.escape(pathname) + '/'); + } + + function error(err) { + if (404 == err.status) return resume(); + next(err); + } + + send(req, path) + .maxage(options.maxAge || 0) + .root(root) + .hidden(options.hidden) + .on('error', error) + .on('directory', directory) + .pipe(res); + }; +}; + +/** + * Expose mime module. + * + * If you wish to extend the mime table use this + * reference to the "mime" module in the npm registry. + */ + +exports.mime = send.mime; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/staticCache.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/staticCache.js new file mode 100644 index 0000000..54ccc98 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/staticCache.js @@ -0,0 +1,234 @@ + +/*! + * Connect - staticCache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('../utils') + , Cache = require('../cache') + , fresh = require('fresh') + , url = require('url') + , fs = require('fs'); + +/** + * Static cache: + * + * Enables a memory cache layer on top of + * the `static()` middleware, serving popular + * static files. + * + * By default a maximum of 128 objects are + * held in cache, with a max of 256k each, + * totalling ~32mb. + * + * A Least-Recently-Used (LRU) cache algo + * is implemented through the `Cache` object, + * simply rotating cache objects as they are + * hit. This means that increasingly popular + * objects maintain their positions while + * others get shoved out of the stack and + * garbage collected. + * + * Benchmarks: + * + * static(): 2700 rps + * node-static: 5300 rps + * static() + staticCache(): 7500 rps + * + * Options: + * + * - `maxObjects` max cache objects [128] + * - `maxLength` max cache object length 256kb + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function staticCache(options){ + var options = options || {} + , cache = new Cache(options.maxObjects || 128) + , maxlen = options.maxLength || 1024 * 256; + + console.warn('connect.staticCache() is deprecated and will be removed in 3.0'); + console.warn('use varnish or similar reverse proxy caches.'); + + return function staticCache(req, res, next){ + var key = cacheKey(req) + , ranges = req.headers.range + , hasCookies = req.headers.cookie + , hit = cache.get(key); + + // cache static + // TODO: change from staticCache() -> cache() + // and make this work for any request + req.on('static', function(stream){ + var headers = res._headers + , cc = utils.parseCacheControl(headers['cache-control'] || '') + , contentLength = headers['content-length'] + , hit; + + // dont cache set-cookie responses + if (headers['set-cookie']) return hasCookies = true; + + // dont cache when cookies are present + if (hasCookies) return; + + // ignore larger files + if (!contentLength || contentLength > maxlen) return; + + // don't cache partial files + if (headers['content-range']) return; + + // dont cache items we shouldn't be + // TODO: real support for must-revalidate / no-cache + if ( cc['no-cache'] + || cc['no-store'] + || cc['private'] + || cc['must-revalidate']) return; + + // if already in cache then validate + if (hit = cache.get(key)){ + if (headers.etag == hit[0].etag) { + hit[0].date = new Date; + return; + } else { + cache.remove(key); + } + } + + // validation notifiactions don't contain a steam + if (null == stream) return; + + // add the cache object + var arr = []; + + // store the chunks + stream.on('data', function(chunk){ + arr.push(chunk); + }); + + // flag it as complete + stream.on('end', function(){ + var cacheEntry = cache.add(key); + delete headers['x-cache']; // Clean up (TODO: others) + cacheEntry.push(200); + cacheEntry.push(headers); + cacheEntry.push.apply(cacheEntry, arr); + }); + }); + + if (req.method == 'GET' || req.method == 'HEAD') { + if (ranges) { + next(); + } else if (!hasCookies && hit && !mustRevalidate(req, hit)) { + res.setHeader('X-Cache', 'HIT'); + respondFromCache(req, res, hit); + } else { + res.setHeader('X-Cache', 'MISS'); + next(); + } + } else { + next(); + } + } +}; + +/** + * Respond with the provided cached value. + * TODO: Assume 200 code, that's iffy. + * + * @param {Object} req + * @param {Object} res + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function respondFromCache(req, res, cacheEntry) { + var status = cacheEntry[0] + , headers = utils.merge({}, cacheEntry[1]) + , content = cacheEntry.slice(2); + + headers.age = (new Date - new Date(headers.date)) / 1000 || 0; + + switch (req.method) { + case 'HEAD': + res.writeHead(status, headers); + res.end(); + break; + case 'GET': + if (utils.conditionalGET(req) && fresh(req.headers, headers)) { + headers['content-length'] = 0; + res.writeHead(304, headers); + res.end(); + } else { + res.writeHead(status, headers); + + function write() { + while (content.length) { + if (false === res.write(content.shift())) { + res.once('drain', write); + return; + } + } + res.end(); + } + + write(); + } + break; + default: + // This should never happen. + res.writeHead(500, ''); + res.end(); + } +} + +/** + * Determine whether or not a cached value must be revalidated. + * + * @param {Object} req + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function mustRevalidate(req, cacheEntry) { + var cacheHeaders = cacheEntry[1] + , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '') + , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '') + , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0; + + if ( cacheCC['no-cache'] + || cacheCC['must-revalidate'] + || cacheCC['proxy-revalidate']) return true; + + if (reqCC['no-cache']) return true + + if (null != reqCC['max-age']) return reqCC['max-age'] < cacheAge; + + if (null != cacheCC['max-age']) return cacheCC['max-age'] < cacheAge; + + return false; +} + +/** + * The key to use in the cache. For now, this is the URL path and query. + * + * 'http://example.com?key=value' -> '/?key=value' + * + * @param {Object} req + * @return {String} + * @api private + */ + +function cacheKey(req) { + return utils.parseUrl(req).path; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/timeout.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/timeout.js new file mode 100644 index 0000000..372963f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/timeout.js @@ -0,0 +1,45 @@ + +/*! + * Connect - timeout + * Ported from https://github.com/LearnBoost/connect-timeout + * MIT Licensed + */ + +/** + * Timeout: + * + * Times out the request in `ms`, defaulting to `5000`. The + * method `req.clearTimeout()` is added to revert this behaviour + * programmatically within your application's middleware, routes, etc. + * + * @param {Number} ms + * @return {Function} + * @api public + */ + +module.exports = function timeout(ms) { + ms = ms || 5000; + + return function(req, res, next) { + var id = setTimeout(function(){ + req.emit('timeout', ms); + }, ms); + + req.on('timeout', function(){ + if (req.headerSent) return; + var err = new Error('Request timeout'); + res.statusCode = 408; + res.end('Request timeout'); + }); + + req.clearTimeout = function(){ + clearTimeout(id); + }; + + res.on('header', function(){ + clearTimeout(id); + }); + + next(); + }; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/urlencoded.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/urlencoded.js new file mode 100644 index 0000000..011c8c0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/urlencoded.js @@ -0,0 +1,76 @@ + +/*! + * Connect - urlencoded + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Urlencoded: + * + * Parse x-ww-form-urlencoded request bodies, + * providing the parsed object as `req.body`. + * + * Options: + * + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function urlencoded(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + // check Content-Type + if ('application/x-www-form-urlencoded' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + try { + req.body = buf.length + ? qs.parse(buf, options) + : {}; + next(); + } catch (err){ + err.body = buf; + next(err); + } + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/vhost.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/vhost.js new file mode 100644 index 0000000..897a9d8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/middleware/vhost.js @@ -0,0 +1,40 @@ + +/*! + * Connect - vhost + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Vhost: + * + * Setup vhost for the given `hostname` and `server`. + * + * connect() + * .use(connect.vhost('foo.com', fooApp)) + * .use(connect.vhost('bar.com', barApp)) + * .use(connect.vhost('*.com', mainApp)) + * + * The `server` may be a Connect server or + * a regular Node `http.Server`. + * + * @param {String} hostname + * @param {Server} server + * @return {Function} + * @api public + */ + +module.exports = function vhost(hostname, server){ + if (!hostname) throw new Error('vhost hostname required'); + if (!server) throw new Error('vhost server required'); + var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$', 'i'); + if (server.onvhost) server.onvhost(hostname); + return function vhost(req, res, next){ + if (!req.headers.host) return next(); + var host = req.headers.host.split(':')[0]; + if (!regexp.test(host)) return next(); + if ('function' == typeof server) return server(req, res, next); + server.emit('request', req, res); + }; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/patch.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/patch.js new file mode 100644 index 0000000..7cf0012 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/patch.js @@ -0,0 +1,79 @@ + +/*! + * Connect + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , res = http.ServerResponse.prototype + , setHeader = res.setHeader + , _renderHeaders = res._renderHeaders + , writeHead = res.writeHead; + +// apply only once + +if (!res._hasConnectPatch) { + + /** + * Provide a public "header sent" flag + * until node does. + * + * @return {Boolean} + * @api public + */ + + res.__defineGetter__('headerSent', function(){ + return this._header; + }); + + /** + * Set header `field` to `val`, special-casing + * the `Set-Cookie` field for multiple support. + * + * @param {String} field + * @param {String} val + * @api public + */ + + res.setHeader = function(field, val){ + var key = field.toLowerCase() + , prev; + + // special-case Set-Cookie + if (this._headers && 'set-cookie' == key) { + if (prev = this.getHeader(field)) { + val = Array.isArray(prev) + ? prev.concat(val) + : [prev, val]; + } + // charset + } else if ('content-type' == key && this.charset) { + val += '; charset=' + this.charset; + } + + return setHeader.call(this, field, val); + }; + + /** + * Proxy to emit "header" event. + */ + + res._renderHeaders = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return _renderHeaders.call(this); + }; + + res.writeHead = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return writeHead.apply(this, arguments); + }; + + res._hasConnectPatch = true; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/proto.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/proto.js new file mode 100644 index 0000000..bca6ec4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/proto.js @@ -0,0 +1,230 @@ + +/*! + * Connect - HTTPServer + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , debug = require('debug')('connect:dispatcher'); + +// prototype + +var app = module.exports = {}; + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Utilize the given middleware `handle` to the given `route`, + * defaulting to _/_. This "route" is the mount-point for the + * middleware, when given a value other than _/_ the middleware + * is only effective when that segment is present in the request's + * pathname. + * + * For example if we were to mount a function at _/admin_, it would + * be invoked on _/admin_, and _/admin/settings_, however it would + * not be invoked for _/_, or _/posts_. + * + * Examples: + * + * var app = connect(); + * app.use(connect.favicon()); + * app.use(connect.logger()); + * app.use(connect.static(__dirname + '/public')); + * + * If we wanted to prefix static files with _/public_, we could + * "mount" the `static()` middleware: + * + * app.use('/public', connect.static(__dirname + '/public')); + * + * This api is chainable, so the following is valid: + * + * connect + * .use(connect.favicon()) + * .use(connect.logger()) + * .use(connect.static(__dirname + '/public')) + * .listen(3000); + * + * @param {String|Function|Server} route, callback or server + * @param {Function|Server} callback or server + * @return {Server} for chaining + * @api public + */ + +app.use = function(route, fn){ + // default route to '/' + if ('string' != typeof route) { + fn = route; + route = '/'; + } + + // wrap sub-apps + if ('function' == typeof fn.handle) { + var server = fn; + fn.route = route; + fn = function(req, res, next){ + server.handle(req, res, next); + }; + } + + // wrap vanilla http.Servers + if (fn instanceof http.Server) { + fn = fn.listeners('request')[0]; + } + + // strip trailing slash + if ('/' == route[route.length - 1]) { + route = route.slice(0, -1); + } + + // add the middleware + debug('use %s %s', route || '/', fn.name || 'anonymous'); + this.stack.push({ route: route, handle: fn }); + + return this; +}; + +/** + * Handle server requests, punting them down + * the middleware stack. + * + * @api private + */ + +app.handle = function(req, res, out) { + var stack = this.stack + , fqdn = ~req.url.indexOf('://') + , removed = '' + , slashAdded = false + , index = 0; + + function next(err) { + var layer, path, status, c; + + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + req.url = removed + req.url; + req.originalUrl = req.originalUrl || req.url; + removed = ''; + + // next callback + layer = stack[index++]; + + // all done + if (!layer || res.headerSent) { + // delegate to parent + if (out) return out(err); + + // unhandled error + if (err) { + // default to 500 + if (res.statusCode < 400) res.statusCode = 500; + debug('default %s', res.statusCode); + + // respect err.status + if (err.status) res.statusCode = err.status; + + // production gets a basic error message + var msg = 'production' == env + ? http.STATUS_CODES[res.statusCode] + : err.stack || err.toString(); + + // log to stderr in a non-test env + if ('test' != env) console.error(err.stack || err.toString()); + if (res.headerSent) return req.socket.destroy(); + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', Buffer.byteLength(msg)); + if ('HEAD' == req.method) return res.end(); + res.end(msg); + } else { + debug('default 404'); + res.statusCode = 404; + res.setHeader('Content-Type', 'text/plain'); + if ('HEAD' == req.method) return res.end(); + res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl)); + } + return; + } + + try { + path = utils.parseUrl(req).pathname; + if (undefined == path) path = '/'; + + // skip this layer if the route doesn't match. + if (0 != path.indexOf(layer.route)) return next(err); + + c = path[layer.route.length]; + if (c && '/' != c && '.' != c) return next(err); + + // Call the layer handler + // Trim off the part of the url that matches the route + removed = layer.route; + req.url = req.url.substr(removed.length); + + // Ensure leading slash + if (!fqdn && '/' != req.url[0]) { + req.url = '/' + req.url; + slashAdded = true; + } + + debug('%s', layer.handle.name || 'anonymous'); + var arity = layer.handle.length; + if (err) { + if (arity === 4) { + layer.handle(err, req, res, next); + } else { + next(err); + } + } else if (arity < 4) { + layer.handle(req, res, next); + } else { + next(); + } + } catch (e) { + next(e); + } + } + next(); +}; + +/** + * Listen for connections. + * + * This method takes the same arguments + * as node's `http.Server#listen()`. + * + * HTTP and HTTPS: + * + * If you run your application both as HTTP + * and HTTPS you may wrap them individually, + * since your Connect "server" is really just + * a JavaScript `Function`. + * + * var connect = require('connect') + * , http = require('http') + * , https = require('https'); + * + * var app = connect(); + * + * http.createServer(app).listen(80); + * https.createServer(options, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/directory.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/directory.html new file mode 100644 index 0000000..15164bb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/directory.html @@ -0,0 +1,75 @@ + + + listing directory {directory} + + + + + +
    +

    {linked-path}

    + {files} +
    + + \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/error.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/error.html new file mode 100644 index 0000000..c5ae73a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/error.html @@ -0,0 +1,13 @@ + + + {error} + + + +
    +

    {title}

    +

    {statusCode} {error}

    +
      {stack}
    +
    + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/favicon.ico b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/favicon.ico new file mode 100644 index 0000000..895fc96 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/favicon.ico differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_add.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_add.png new file mode 100644 index 0000000..d5bfa07 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_add.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_attach.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_attach.png new file mode 100644 index 0000000..89ee2da Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_attach.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_code.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_code.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_copy.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_copy.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_delete.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_delete.png new file mode 100644 index 0000000..3141467 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_delete.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_edit.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_edit.png new file mode 100644 index 0000000..046811e Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_edit.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_error.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_error.png new file mode 100644 index 0000000..f07f449 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_error.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_excel.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_excel.png new file mode 100644 index 0000000..eb6158e Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_excel.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_find.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_find.png new file mode 100644 index 0000000..2f19388 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_find.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_gear.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_gear.png new file mode 100644 index 0000000..8e83281 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_gear.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_go.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_go.png new file mode 100644 index 0000000..80fe1ed Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_go.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_green.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_green.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_key.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_key.png new file mode 100644 index 0000000..d6626cb Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_key.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_lightning.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_lightning.png new file mode 100644 index 0000000..7e56870 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_lightning.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_link.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_link.png new file mode 100644 index 0000000..312eab0 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_link.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paintbrush.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paintbrush.png new file mode 100644 index 0000000..246a2f0 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paintbrush.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paste.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paste.png new file mode 100644 index 0000000..968f073 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_paste.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_red.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_red.png new file mode 100644 index 0000000..0b18247 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_red.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_refresh.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_refresh.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_refresh.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_save.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_save.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_acrobat.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_acrobat.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_actionscript.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_actionscript.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_add.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_add.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_c.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_c.png new file mode 100644 index 0000000..34a05cc Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_c.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_camera.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_camera.png new file mode 100644 index 0000000..f501a59 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_camera.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cd.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cd.png new file mode 100644 index 0000000..848bdaf Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cd.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code_red.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code_red.png new file mode 100644 index 0000000..87a6914 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_code_red.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_coldfusion.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000..c66011f Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_coldfusion.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_compressed.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_compressed.png new file mode 100644 index 0000000..2b6b100 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_compressed.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_copy.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_copy.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cplusplus.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cplusplus.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_csharp.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_csharp.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cup.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_cup.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_database.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_database.png new file mode 100644 index 0000000..bddba1f Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_database.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_delete.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_delete.png new file mode 100644 index 0000000..af1ecaf Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_delete.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_dvd.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_dvd.png new file mode 100644 index 0000000..4cc537a Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_dvd.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_edit.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_edit.png new file mode 100644 index 0000000..b93e776 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_edit.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_error.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_error.png new file mode 100644 index 0000000..9fc5a0a Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_error.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_excel.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_excel.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_find.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_find.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_flash.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_flash.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_freehand.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_freehand.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_gear.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_gear.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_gear.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_get.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_get.png new file mode 100644 index 0000000..e4a1ecb Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_get.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_go.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_go.png new file mode 100644 index 0000000..7e62a92 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_go.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_h.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_h.png new file mode 100644 index 0000000..e902abb Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_h.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_horizontal.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_horizontal.png new file mode 100644 index 0000000..1d2d0a4 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_horizontal.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_key.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_key.png new file mode 100644 index 0000000..d616484 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_key.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_lightning.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_lightning.png new file mode 100644 index 0000000..7215d1e Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_lightning.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_link.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_link.png new file mode 100644 index 0000000..bf7bd1c Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_link.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_magnify.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_magnify.png new file mode 100644 index 0000000..f6b74cc Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_magnify.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_medal.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_medal.png new file mode 100644 index 0000000..d3fffb6 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_medal.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_office.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_office.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paint.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paint.png new file mode 100644 index 0000000..23a37b8 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paint.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paintbrush.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paintbrush.png new file mode 100644 index 0000000..f907e44 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paintbrush.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paste.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_paste.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_php.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_php.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_picture.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_picture.png new file mode 100644 index 0000000..134b669 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_picture.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_powerpoint.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000..c4eff03 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_powerpoint.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_put.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_put.png new file mode 100644 index 0000000..884ffd6 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_put.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_ruby.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_ruby.png new file mode 100644 index 0000000..f59b7c4 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_ruby.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_stack.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_stack.png new file mode 100644 index 0000000..44084ad Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_stack.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_star.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_star.png new file mode 100644 index 0000000..3a1441c Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_star.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_swoosh.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_swoosh.png new file mode 100644 index 0000000..e770829 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_swoosh.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text_width.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text_width.png new file mode 100644 index 0000000..d9cf132 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_text_width.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_tux.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_tux.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_vector.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_vector.png new file mode 100644 index 0000000..4a05955 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_vector.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_visualstudio.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_visualstudio.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_width.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_width.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_word.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_word.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_world.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_world.png new file mode 100644 index 0000000..6ed2490 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_world.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_wrench.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_wrench.png new file mode 100644 index 0000000..fecadd0 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_wrench.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_zip.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_white_zip.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_word.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_word.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_world.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_world.png new file mode 100644 index 0000000..b8895dd Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/icons/page_world.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/style.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/style.css new file mode 100644 index 0000000..32b6507 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/public/style.css @@ -0,0 +1,141 @@ +body { + margin: 0; + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + margin: 0; + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul { + margin: 0; + padding: 0; +} +ul li { + margin: 5px 0; + padding: 3px 8px; + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 500px; +} +ul#files li { + padding: 0; +} +ul#files li img { + position: absolute; + top: 5px; + left: 5px; +} +ul#files li a { + position: relative; + display: block; + margin: 1px; + width: 30%; + height: 25px; + line-height: 25px; + text-indent: 8px; + float: left; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + text-overflow: ellipsis; +} +ul#files li a.icon { + text-indent: 25px; +} +ul#files li a:focus, +ul#files li a:hover { + outline: none; + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/utils.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/utils.js new file mode 100644 index 0000000..3ebd4a6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/lib/utils.js @@ -0,0 +1,373 @@ + +/*! + * Connect - utils + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , crypto = require('crypto') + , parse = require('url').parse + , Path = require('path') + , fs = require('fs'); + +/** + * Extract the mime type from the given request's + * _Content-Type_ header. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +exports.mime = function(req) { + var str = req.headers['content-type'] || ''; + return str.split(';')[0]; +}; + +/** + * Generate an `Error` from the given status `code` + * and optional `msg`. + * + * @param {Number} code + * @param {String} msg + * @return {Error} + * @api private + */ + +exports.error = function(code, msg){ + var err = new Error(msg || http.STATUS_CODES[code]); + err.status = code; + return err; +}; + +/** + * Return md5 hash of the given string and optional encoding, + * defaulting to hex. + * + * utils.md5('wahoo'); + * // => "e493298061761236c96b02ea6aa8a2ad" + * + * @param {String} str + * @param {String} encoding + * @return {String} + * @api private + */ + +exports.md5 = function(str, encoding){ + return crypto + .createHash('md5') + .update(str) + .digest(encoding || 'hex'); +}; + +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * utils.merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api private + */ + +exports.merge = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + + +/** + * Return a unique identifier with the given `len`. + * + * utils.uid(10); + * // => "FDaS435D2z" + * + * @param {Number} len + * @return {String} + * @api private + */ + +exports.uid = function(len) { + return crypto.randomBytes(Math.ceil(len * 3 / 4)) + .toString('base64') + .slice(0, len); +}; + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val + ? str + : false; +}; + +/** + * Parse signed cookies, returning an object + * containing the decoded key/value pairs, + * while removing the signed key from `obj`. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseSignedCookies = function(obj, secret){ + var ret = {}; + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + if (0 == val.indexOf('s:')) { + val = exports.unsign(val.slice(2), secret); + if (val) { + ret[key] = val; + delete obj[key]; + } + } + }); + return ret; +}; + +/** + * Parse a signed cookie string, return the decoded value + * + * @param {String} str signed cookie string + * @param {String} secret + * @return {String} decoded value + * @api private + */ + +exports.parseSignedCookie = function(str, secret){ + return 0 == str.indexOf('s:') + ? exports.unsign(str.slice(2), secret) + : str; +}; + +/** + * Parse JSON cookies. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseJSONCookies = function(obj){ + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + var res = exports.parseJSONCookie(val); + if (res) obj[key] = res; + }); + return obj; +}; + +/** + * Parse JSON cookie string + * + * @param {String} str + * @return {Object} Parsed object or null if not json cookie + * @api private + */ + +exports.parseJSONCookie = function(str) { + if (0 == str.indexOf('j:')) { + try { + return JSON.parse(str.slice(2)); + } catch (err) { + // no op + } + } +} + +/** + * Pause `data` and `end` events on the given `obj`. + * Middleware performing async tasks _should_ utilize + * this utility (or similar), to re-emit data once + * the async operation has completed, otherwise these + * events may be lost. + * + * var pause = utils.pause(req); + * fs.readFile(path, function(){ + * next(); + * pause.resume(); + * }); + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.pause = require('pause'); + +/** + * Strip `Content-*` headers from `res`. + * + * @param {ServerResponse} res + * @api private + */ + +exports.removeContentHeaders = function(res){ + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Check if `req` is a conditional GET request. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.conditionalGET = function(req) { + return req.headers['if-modified-since'] + || req.headers['if-none-match']; +}; + +/** + * Respond with 401 "Unauthorized". + * + * @param {ServerResponse} res + * @param {String} realm + * @api private + */ + +exports.unauthorized = function(res, realm) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); + res.end('Unauthorized'); +}; + +/** + * Respond with 304 "Not Modified". + * + * @param {ServerResponse} res + * @param {Object} headers + * @api private + */ + +exports.notModified = function(res) { + exports.removeContentHeaders(res); + res.statusCode = 304; + res.end(); +}; + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * Parse the given Cache-Control `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.parseCacheControl = function(str){ + var directives = str.split(',') + , obj = {}; + + for(var i = 0, len = directives.length; i < len; i++) { + var parts = directives[i].split('=') + , key = parts.shift().trim() + , val = parseInt(parts.shift(), 10); + + obj[key] = isNaN(val) ? true : val; + } + + return obj; +}; + +/** + * Parse the `req` url with memoization. + * + * @param {ServerRequest} req + * @return {Object} + * @api private + */ + +exports.parseUrl = function(req){ + var parsed = req._parsedUrl; + if (parsed && parsed.href == req.url) { + return parsed; + } else { + return req._parsedUrl = parse(req.url); + } +}; + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api private + */ + +exports.parseBytes = require('bytes'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/History.md new file mode 100644 index 0000000..db1f759 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/History.md @@ -0,0 +1,5 @@ + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Readme.md new file mode 100644 index 0000000..9325d5b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/Readme.md @@ -0,0 +1,51 @@ +# node-bytes + + Byte string parser / formatter. + +## Example: + +```js +bytes('1kb') +// => 1024 + +bytes('2mb') +// => 2097152 + +bytes('1gb') +// => 1073741824 + +bytes(1073741824) +// => 1gb +``` + +## Installation + +``` +$ npm install bytes +$ component install visionmedia/bytes.js +``` + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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/connect/node_modules/bytes/component.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/component.json new file mode 100644 index 0000000..76a6057 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/component.json @@ -0,0 +1,7 @@ +{ + "name": "bytes", + "description": "byte size string parser / serializer", + "keywords": ["bytes", "utility"], + "version": "0.1.0", + "scripts": ["index.js"] +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/index.js new file mode 100644 index 0000000..3eaafc7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/index.js @@ -0,0 +1,39 @@ + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api public + */ + +module.exports = function(size) { + if ('number' == typeof size) return convert(size); + var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/) + , n = parseFloat(parts[1]) + , type = parts[2]; + + var map = { + kb: 1 << 10 + , mb: 1 << 20 + , gb: 1 << 30 + }; + + return map[type] * n; +}; + +/** + * convert bytes into string. + * + * @param {Number} b - bytes to convert + * @return {String}i + * @api public + */ + +function convert (b) { + var gb = 1 << 30, mb = 1 << 20, kb = 1 << 10; + if (b >= gb) return (Math.round(b / gb * 100) / 100) + 'gb'; + if (b >= mb) return (Math.round(b / mb * 100) / 100) + 'mb'; + if (b >= kb) return (Math.round(b / kb * 100) / 100) + 'kb'; + return b; +} \ No newline at end of file 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 new file mode 100644 index 0000000..b284b09 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/bytes/package.json @@ -0,0 +1,25 @@ +{ + "name": "bytes", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "byte size string parser / serializer", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "bytes": "index.js" + } + }, + "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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/.travis.yml new file mode 100644 index 0000000..bced151 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/README.md new file mode 100644 index 0000000..5187ed1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/README.md @@ -0,0 +1,44 @@ +# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) # + +cookie 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. + +See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies. + +## how? + +``` +npm install cookie +``` + +```javascript +var cookie = require('cookie'); + +var hdr = cookie.serialize('foo', 'bar'); +// hdr = 'foo=bar'; + +var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff'); +// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' }; +``` + +## more + +The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values. + +### path +> cookie path + +### expires +> absolute expiration date for the cookie (Date object) + +### maxAge +> relative max age of the cookie from when the client receives it (seconds) + +### domain +> domain for the cookie + +### secure +> true or false + +### httpOnly +> true or false + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/index.js new file mode 100644 index 0000000..ce6c926 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/index.js @@ -0,0 +1,57 @@ + +/// Serialize the a name value pair into a cookie string suitable for +/// http headers. An optional options object specified cookie parameters +/// +/// serialize('foo', 'bar', { httpOnly: true }) +/// => "foo=bar; httpOnly" +/// +/// @param {String} name +/// @param {String} val +/// @param {Object} options +/// @return {String} +var serialize = function(name, val, opt){ + var pairs = [name + '=' + encode(val)]; + opt = opt || {}; + + if (opt.maxAge) pairs.push('Max-Age=' + opt.maxAge); + if (opt.domain) pairs.push('Domain=' + opt.domain); + if (opt.path) pairs.push('Path=' + opt.path); + if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString()); + if (opt.httpOnly) pairs.push('HttpOnly'); + if (opt.secure) pairs.push('Secure'); + + return pairs.join('; '); +}; + +/// Parse the given cookie header string into an object +/// The object has the various cookies as keys(names) => values +/// @param {String} str +/// @return {Object} +var parse = function(str) { + var obj = {} + var pairs = str.split(/[;,] */); + + pairs.forEach(function(pair) { + var eq_idx = pair.indexOf('=') + var key = pair.substr(0, eq_idx).trim() + var val = pair.substr(++eq_idx, pair.length).trim(); + + // quoted values + if ('"' == val[0]) { + val = val.slice(1, -1); + } + + // only assign once + if (undefined == obj[key]) { + obj[key] = decode(val); + } + }); + + return obj; +}; + +var encode = encodeURIComponent; +var decode = decodeURIComponent; + +module.exports.serialize = serialize; +module.exports.parse = parse; 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 new file mode 100644 index 0000000..e169b94 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/package.json @@ -0,0 +1,33 @@ +{ + "author": { + "name": "Roman Shtylman", + "email": "shtylman@gmail.com" + }, + "name": "cookie", + "description": "cookie parsing and serialization", + "version": "0.0.4", + "repository": { + "type": "git", + "url": "git://github.com/shtylman/node-cookie.git" + }, + "keywords": [ + "cookie", + "cookies" + ], + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "1.x.x" + }, + "optionalDependencies": {}, + "engines": { + "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/cookie/test/mocha.opts b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/mocha.opts new file mode 100644 index 0000000..e2bfcc5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/mocha.opts @@ -0,0 +1 @@ +--ui qunit diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/parse.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/parse.js new file mode 100644 index 0000000..4b98a20 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/parse.js @@ -0,0 +1,25 @@ + +var assert = require('assert'); + +var cookie = require('..'); + +suite('parse'); + +test('basic', function() { + assert.deepEqual({ foo: 'bar' }, cookie.parse('foo=bar')); + assert.deepEqual({ foo: '123' }, cookie.parse('foo=123')); +}); + +test('ignore spaces', function() { + assert.deepEqual({ FOO: 'bar', baz: 'raz' }, + cookie.parse('FOO = bar; baz = raz')); +}); + +test('escaping', function() { + assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' }, + cookie.parse('foo="bar=123456789&name=Magic+Mouse"')); + + assert.deepEqual({ email: ' ",;/' }, + cookie.parse('email=%20%22%2c%3b%2f')); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/serialize.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/serialize.js new file mode 100644 index 0000000..d38768d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/cookie/test/serialize.js @@ -0,0 +1,59 @@ +// builtin +var assert = require('assert'); + +var cookie = require('..'); + +suite('serialize'); + +test('basic', function() { + assert.equal('foo=bar', cookie.serialize('foo', 'bar')); + assert.equal('foo=bar%20baz', cookie.serialize('foo', 'bar baz')); +}); + +test('path', function() { + assert.equal('foo=bar; Path=/', cookie.serialize('foo', 'bar', { + path: '/' + })); +}); + +test('secure', function() { + assert.equal('foo=bar; Secure', cookie.serialize('foo', 'bar', { + secure: true + })); + + assert.equal('foo=bar', cookie.serialize('foo', 'bar', { + secure: false + })); +}); + +test('domain', function() { + assert.equal('foo=bar; Domain=example.com', cookie.serialize('foo', 'bar', { + domain: 'example.com' + })); +}); + +test('httpOnly', function() { + assert.equal('foo=bar; HttpOnly', cookie.serialize('foo', 'bar', { + httpOnly: true + })); +}); + +test('maxAge', function() { + assert.equal('foo=bar; Max-Age=1000', cookie.serialize('foo', 'bar', { + maxAge: 1000 + })); +}); + +test('escaping', function() { + assert.deepEqual('cat=%2B%20', cookie.serialize('cat', '+ ')); +}); + +test('parse->serialize', function() { + + assert.deepEqual({ cat: 'foo=123&name=baz five' }, cookie.parse( + cookie.serialize('cat', 'foo=123&name=baz five'))); + + assert.deepEqual({ cat: ' ";/' }, cookie.parse( + cookie.serialize('cat', ' ";/'))); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.gitmodules b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.gitmodules new file mode 100644 index 0000000..2319e18 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tests/nodeunit"] + path = tests/nodeunit + url = git://github.com/caolan/nodeunit.git diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/Makefile new file mode 100644 index 0000000..720bf85 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/README.md new file mode 100644 index 0000000..26ce22f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/README.md @@ -0,0 +1,31 @@ +# JavaScript CRC 8, 16 and 32. + +This 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". + +Original code is taken from http://www.digsys.se/JavaScript/CRC.aspx + +## Functions + +The following functions are implemented: + + crc8(String) #=> Number + crcArc(String) #=> Number + crc16(String) #=> Number + fcs16(String) #=> Number + crc32(String) #=> Number + hex8(Number) #=> String + hex16(Number) #=> String + hex32(Number) #=> String + +## Installation + + git clone git://github.com/alexgorbatchev/node-crc.git + +or + + npm install crc + +## Running tests + + $ npm install + $ make test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/lib/crc.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/lib/crc.js new file mode 100644 index 0000000..8feb542 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/lib/crc.js @@ -0,0 +1,403 @@ +(function() +{ + // CRC-8 in table form + // + // Copyright (c) 1989 AnDan Software. You may use this program, or + // code or tables extracted from it, as long as this notice is not + // removed or changed. + var CRC8_TAB = new Array( + // C/C++ language: + // + // unsigned char CRC8_TAB[] = {...}; + 0x00,0x1B,0x36,0x2D,0x6C,0x77,0x5A,0x41,0xD8,0xC3,0xEE,0xF5,0xB4,0xAF,0x82,0x99,0xD3,0xC8,0xE5, + 0xFE,0xBF,0xA4,0x89,0x92,0x0B,0x10,0x3D,0x26,0x67,0x7C,0x51,0x4A,0xC5,0xDE,0xF3,0xE8,0xA9,0xB2, + 0x9F,0x84,0x1D,0x06,0x2B,0x30,0x71,0x6A,0x47,0x5C,0x16,0x0D,0x20,0x3B,0x7A,0x61,0x4C,0x57,0xCE, + 0xD5,0xF8,0xE3,0xA2,0xB9,0x94,0x8F,0xE9,0xF2,0xDF,0xC4,0x85,0x9E,0xB3,0xA8,0x31,0x2A,0x07,0x1C, + 0x5D,0x46,0x6B,0x70,0x3A,0x21,0x0C,0x17,0x56,0x4D,0x60,0x7B,0xE2,0xF9,0xD4,0xCF,0x8E,0x95,0xB8, + 0xA3,0x2C,0x37,0x1A,0x01,0x40,0x5B,0x76,0x6D,0xF4,0xEF,0xC2,0xD9,0x98,0x83,0xAE,0xB5,0xFF,0xE4, + 0xC9,0xD2,0x93,0x88,0xA5,0xBE,0x27,0x3C,0x11,0x0A,0x4B,0x50,0x7D,0x66,0xB1,0xAA,0x87,0x9C,0xDD, + 0xC6,0xEB,0xF0,0x69,0x72,0x5F,0x44,0x05,0x1E,0x33,0x28,0x62,0x79,0x54,0x4F,0x0E,0x15,0x38,0x23, + 0xBA,0xA1,0x8C,0x97,0xD6,0xCD,0xE0,0xFB,0x74,0x6F,0x42,0x59,0x18,0x03,0x2E,0x35,0xAC,0xB7,0x9A, + 0x81,0xC0,0xDB,0xF6,0xED,0xA7,0xBC,0x91,0x8A,0xCB,0xD0,0xFD,0xE6,0x7F,0x64,0x49,0x52,0x13,0x08, + 0x25,0x3E,0x58,0x43,0x6E,0x75,0x34,0x2F,0x02,0x19,0x80,0x9B,0xB6,0xAD,0xEC,0xF7,0xDA,0xC1,0x8B, + 0x90,0xBD,0xA6,0xE7,0xFC,0xD1,0xCA,0x53,0x48,0x65,0x7E,0x3F,0x24,0x09,0x12,0x9D,0x86,0xAB,0xB0, + 0xF1,0xEA,0xC7,0xDC,0x45,0x5E,0x73,0x68,0x29,0x32,0x1F,0x04,0x4E,0x55,0x78,0x63,0x22,0x39,0x14, + 0x0F,0x96,0x8D,0xA0,0xBB,0xFA,0xE1,0xCC,0xD7 + ); + + function crc8Add(crc,c) + // 'crc' should be initialized to 0x00. + { + return CRC8_TAB[(crc^c)&0xFF]; + }; + // C/C++ language: + // + // inline unsigned char crc8Add(unsigned char crc, unsigned char c) + // { + // return CRC8_TAB[crc^c]; + // } + + // CRC-16 (as it is in SEA's ARC) in table form + // + // The logic for this method of calculating the CRC 16 bit polynomial + // is taken from an article by David Schwaderer in the April 1985 + // issue of PC Tech Journal. + var CRC_ARC_TAB = new Array( + // C/C++ language: + // + // unsigned short CRC_ARC_TAB[] = {...}; + 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,0x0500, + 0xC5C1,0xC481,0x0440,0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,0x0A00,0xCAC1, + 0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81, + 0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,0x1400,0xD4C1,0xD581,0x1540, + 0xD701,0x17C0,0x1680,0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,0xF001, + 0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0, + 0x3480,0xF441,0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,0xFA01,0x3AC0,0x3B80, + 0xFB41,0x3900,0xF9C1,0xF881,0x3840,0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41, + 0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,0xE401,0x24C0,0x2580,0xE541,0x2700, + 0xE7C1,0xE681,0x2640,0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,0xA001,0x60C0, + 0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480, + 0xA441,0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,0x6B80,0xAB41, + 0x6900,0xA9C1,0xA881,0x6840,0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,0xBE01, + 0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1, + 0xB681,0x7640,0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,0x5000,0x90C1,0x9181, + 0x5140,0x9301,0x53C0,0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440, + 0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,0x9901, + 0x59C0,0x5880,0x9841,0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,0x4E00,0x8EC1, + 0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680, + 0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 + ); + + function crcArcAdd(crc,c) + // 'crc' should be initialized to 0x0000. + { + return CRC_ARC_TAB[(crc^c)&0xFF]^((crc>>8)&0xFF); + }; + // C/C++ language: + // + // inline unsigned short crcArcAdd(unsigned short crc, unsigned char c) + // { + // return CRC_ARC_TAB[(unsigned char)crc^c]^(unsigned short)(crc>>8); + // } + + // CRC-16 (as it is in ZMODEM) in table form + // + // Copyright (c) 1989 AnDan Software. You may use this program, or + // code or tables extracted from it, as long as this notice is not + // removed or changed. + var CRC16_TAB = new Array( + // C/C++ language: + // + // unsigned short CRC16_TAB[] = {...}; + 0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,0x8108,0x9129,0xA14A,0xB16B,0xC18C, + 0xD1AD,0xE1CE,0xF1EF,0x1231,0x0210,0x3273,0x2252,0x52B5,0x4294,0x72F7,0x62D6,0x9339,0x8318, + 0xB37B,0xA35A,0xD3BD,0xC39C,0xF3FF,0xE3DE,0x2462,0x3443,0x0420,0x1401,0x64E6,0x74C7,0x44A4, + 0x5485,0xA56A,0xB54B,0x8528,0x9509,0xE5EE,0xF5CF,0xC5AC,0xD58D,0x3653,0x2672,0x1611,0x0630, + 0x76D7,0x66F6,0x5695,0x46B4,0xB75B,0xA77A,0x9719,0x8738,0xF7DF,0xE7FE,0xD79D,0xC7BC,0x48C4, + 0x58E5,0x6886,0x78A7,0x0840,0x1861,0x2802,0x3823,0xC9CC,0xD9ED,0xE98E,0xF9AF,0x8948,0x9969, + 0xA90A,0xB92B,0x5AF5,0x4AD4,0x7AB7,0x6A96,0x1A71,0x0A50,0x3A33,0x2A12,0xDBFD,0xCBDC,0xFBBF, + 0xEB9E,0x9B79,0x8B58,0xBB3B,0xAB1A,0x6CA6,0x7C87,0x4CE4,0x5CC5,0x2C22,0x3C03,0x0C60,0x1C41, + 0xEDAE,0xFD8F,0xCDEC,0xDDCD,0xAD2A,0xBD0B,0x8D68,0x9D49,0x7E97,0x6EB6,0x5ED5,0x4EF4,0x3E13, + 0x2E32,0x1E51,0x0E70,0xFF9F,0xEFBE,0xDFDD,0xCFFC,0xBF1B,0xAF3A,0x9F59,0x8F78,0x9188,0x81A9, + 0xB1CA,0xA1EB,0xD10C,0xC12D,0xF14E,0xE16F,0x1080,0x00A1,0x30C2,0x20E3,0x5004,0x4025,0x7046, + 0x6067,0x83B9,0x9398,0xA3FB,0xB3DA,0xC33D,0xD31C,0xE37F,0xF35E,0x02B1,0x1290,0x22F3,0x32D2, + 0x4235,0x5214,0x6277,0x7256,0xB5EA,0xA5CB,0x95A8,0x8589,0xF56E,0xE54F,0xD52C,0xC50D,0x34E2, + 0x24C3,0x14A0,0x0481,0x7466,0x6447,0x5424,0x4405,0xA7DB,0xB7FA,0x8799,0x97B8,0xE75F,0xF77E, + 0xC71D,0xD73C,0x26D3,0x36F2,0x0691,0x16B0,0x6657,0x7676,0x4615,0x5634,0xD94C,0xC96D,0xF90E, + 0xE92F,0x99C8,0x89E9,0xB98A,0xA9AB,0x5844,0x4865,0x7806,0x6827,0x18C0,0x08E1,0x3882,0x28A3, + 0xCB7D,0xDB5C,0xEB3F,0xFB1E,0x8BF9,0x9BD8,0xABBB,0xBB9A,0x4A75,0x5A54,0x6A37,0x7A16,0x0AF1, + 0x1AD0,0x2AB3,0x3A92,0xFD2E,0xED0F,0xDD6C,0xCD4D,0xBDAA,0xAD8B,0x9DE8,0x8DC9,0x7C26,0x6C07, + 0x5C64,0x4C45,0x3CA2,0x2C83,0x1CE0,0x0CC1,0xEF1F,0xFF3E,0xCF5D,0xDF7C,0xAF9B,0xBFBA,0x8FD9, + 0x9FF8,0x6E17,0x7E36,0x4E55,0x5E74,0x2E93,0x3EB2,0x0ED1,0x1EF0 + ); + + function crc16Add(crc,c) + // 'crc' should be initialized to 0x0000. + { + return CRC16_TAB[((crc>>8)^c)&0xFF]^((crc<<8)&0xFFFF); + }; + // C/C++ language: + // + // inline unsigned short crc16Add(unsigned short crc, unsigned char c) + // { + // return CRC16_TAB[(unsigned char)(crc>>8)^c]^(unsigned short)(crc<<8); + // } + + // FCS-16 (as it is in PPP) in table form + // + // Described in RFC-1662 by William Allen Simpson, see RFC-1662 for references. + // + // Modified by Anders Danielsson, March 10, 2006. + var FCS_16_TAB = new Array( + // C/C++ language: + // + // unsigned short FCS_16_TAB[256] = {...}; + 0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF,0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C, + 0xDBE5,0xE97E,0xF8F7,0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E,0x9CC9,0x8D40, + 0xBFDB,0xAE52,0xDAED,0xCB64,0xF9FF,0xE876,0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434, + 0x55BD,0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E,0xFAE7,0xC87C,0xD9F5,0x3183,0x200A,0x1291,0x0318, + 0x77A7,0x662E,0x54B5,0x453C,0xBDCB,0xAC42,0x9ED9,0x8F50,0xFBEF,0xEA66,0xD8FD,0xC974,0x4204, + 0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB,0xCE4C,0xDFC5,0xED5E,0xFCD7,0x8868,0x99E1, + 0xAB7A,0xBAF3,0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A,0xDECD,0xCF44,0xFDDF, + 0xEC56,0x98E9,0x8960,0xBBFB,0xAA72,0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9, + 0xEF4E,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1,0x7387,0x620E,0x5095,0x411C,0x35A3, + 0x242A,0x16B1,0x0738,0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70,0x8408,0x9581, + 0xA71A,0xB693,0xC22C,0xD3A5,0xE13E,0xF0B7,0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76, + 0x7CFF,0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324,0xF1BF,0xE036,0x18C1,0x0948,0x3BD3,0x2A5A, + 0x5EE5,0x4F6C,0x7DF7,0x6C7E,0xA50A,0xB483,0x8618,0x9791,0xE32E,0xF2A7,0xC03C,0xD1B5,0x2942, + 0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD,0xB58B,0xA402,0x9699,0x8710,0xF3AF,0xE226, + 0xD0BD,0xC134,0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C,0xC60C,0xD785,0xE51E, + 0xF497,0x8028,0x91A1,0xA33A,0xB2B3,0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB, + 0xD68D,0xC704,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232,0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1, + 0x0D68,0x3FF3,0x2E7A,0xE70E,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1,0x6B46,0x7ACF, + 0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9,0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9, + 0x8330,0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1,0x0F78 + ); + + function fcs16Add(fcs,c) + // 'fcs' should be initialized to 0xFFFF and after the computation it should be + // complemented (inverted). + // + // If the FCS-16 is calculated over the data and over the complemented FCS-16, the + // result will always be 0xF0B8 (without the complementation). + { + return FCS_16_TAB[(fcs^c)&0xFF]^((fcs>>8)&0xFF); + }; + + // C/C++ language: + // + // inline unsigned short fcs16Add(unsigned short fcs, unsigned char c) + // { + // return FCS_16_TAB[(unsigned char)fcs^c]^(unsigned short)(fcs>>8); + // } + + // + // CRC-32 (as it is in ZMODEM) in table form + // + // Copyright (C) 1986 Gary S. Brown. You may use this program, or + // code or tables extracted from it, as desired without restriction. + // + // Modified by Anders Danielsson, February 5, 1989 and March 10, 2006. + // + // This is also known as FCS-32 (as it is in PPP), described in + // RFC-1662 by William Allen Simpson, see RFC-1662 for references. + // + var CRC32_TAB = new Array( /* CRC polynomial 0xEDB88320 */ + // C/C++ language: + // + // unsigned long CRC32_TAB[] = {...}; + 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, + 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, + 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, + 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, + 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B, + 0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, + 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, + 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, + 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, + 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, + 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, + 0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, + 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB, + 0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, + 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, + 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, + 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683, + 0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, + 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7, + 0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, + 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, + 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, + 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F, + 0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, + 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, + 0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, + 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, + 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, + 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB, + 0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, + 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF, + 0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D + ); + + function crc32Add(crc,c) + // 'crc' should be initialized to 0xFFFFFFFF and after the computation it should be + // complemented (inverted). + // + // CRC-32 is also known as FCS-32. + // + // If the FCS-32 is calculated over the data and over the complemented FCS-32, the + // result will always be 0xDEBB20E3 (without the complementation). + { + return CRC32_TAB[(crc^c)&0xFF]^((crc>>8)&0xFFFFFF); + }; + // + // C/C++ language: + // + // inline unsigned long crc32Add(unsigned long crc, unsigned char c) + // { + // return CRC32_TAB[(unsigned char)crc^c]^(crc>>8); + // } + // + + function crc8(str) + { + var n, + len = str.length, + crc = 0 + ; + + for(var i = 0; i < len; i++) + crc = crc8Add(crc, str.charCodeAt(i)); + + return crc; + }; + + function crc8Buffer(buf) + { + var crc = 0; + + for (var i = 0, len = buf.length; i < len; ++i) + { + crc = crc8Add(crc, buf[i]); + } + + return crc; + } + + function crcArc(str) + { + var i, + len = str.length, + crc = 0 + ; + + for(i = 0; i < len; i++) + crc = crcArcAdd(crc, str.charCodeAt(i)); + + return crc; + }; + + function crc16(str) + { + var i, + len = str.length, + crc = 0 + ; + + for(i = 0; i < len; i++) + crc = crc16Add(crc, str.charCodeAt(i)); + + return crc; + }; + + function crc16Buffer(buf) + { + var crc = 0; + + for (var i = 0, len = buf.length; i < len; ++i) + { + crc = crc16Add(crc, buf[i]); + } + + return crc; + } + + function fcs16(str) + { + var i, + len = str.length, + fcs = 0xFFFF + ; + + for(i = 0; i < len; i++) + fcs = fcs16Add(fcs,str.charCodeAt(i)); + + return fcs^0xFFFF; + }; + + function crc32(str) + { + var i, + len = str.length, + crc = 0xFFFFFFFF + ; + + for(i = 0; i < len; i++) + crc = crc32Add(crc, str.charCodeAt(i)); + + return crc^0xFFFFFFFF; + }; + + function crc32Buffer(buf) + { + var crc = 0xFFFFFFFF; + + for (var i = 0, len = buf.length; i < len; ++i) + { + crc = crc32Add(crc, buf[i]); + } + + return crc ^ 0xFFFFFFFF; + } + + /** + * Convert value as 8-bit unsigned integer to 2 digit hexadecimal number. + */ + function hex8(val) + { + var n = val & 0xFF, + str = n.toString(16).toUpperCase() + ; + + while(str.length < 2) + str = "0" + str; + + return str; + }; + + /** + * Convert value as 16-bit unsigned integer to 4 digit hexadecimal number. + */ + function hex16(val) + { + return hex8(val >> 8) + hex8(val); + }; + + /** + * Convert value as 32-bit unsigned integer to 8 digit hexadecimal number. + */ + function hex32(val) + { + return hex16(val >> 16) + hex16(val); + }; + + var target, property; + + if(typeof(window) == 'undefined') + { + target = module; + property = 'exports'; + } + else + { + target = window; + property = 'crc'; + } + + target[property] = { + 'crc8' : crc8, + 'crcArc' : crcArc, + 'crc16' : crc16, + 'fcs16' : fcs16, + 'crc32' : crc32, + 'hex8' : hex8, + 'hex16' : hex16, + 'hex32' : hex32, + 'buffer' : { + crc8 : crc8Buffer, + crc16 : crc16Buffer, + crc32 : crc32Buffer + } + }; +})(); 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 new file mode 100644 index 0000000..b16c89e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/package.json @@ -0,0 +1,25 @@ +{ + "name": "crc", + "version": "0.2.0", + "description": "CRC JavaScript implementation", + "author": { + "name": "Alex Gorbatchev", + "email": "alex.gorbatchev@gmail.com" + }, + "contributors": [], + "main": "./lib/crc.js", + "scripts": {}, + "directories": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "repository": { + "type": "git", + "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/crc/test/crc.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/test/crc.js new file mode 100755 index 0000000..faf2d1d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/crc/test/crc.js @@ -0,0 +1,63 @@ +#!/usr/bin/env ./nodeunit/bin/nodeunit + +var crc = require('../lib/crc'); + +describe('crc8()', function(){ + it('should work with strings', function(){ + crc.crc8('hello world').should.equal(64); + }) + + it('should work with Buffers', function(){ + crc.buffer.crc8(new Buffer('hello world')).should.equal(64); + }) +}) + +describe('crc16()', function(){ + it('should work with strings', function(){ + crc.crc16('hello world').should.equal(15332); + }) + + it('should work with Buffers', function(){ + crc.buffer.crc16(new Buffer('hello world')).should.equal(15332); + }) +}) + +describe('crc32()', function(){ + it('should work with strings', function(){ + crc.crc32('hello world').should.equal(222957957); + }) + + it('should work with Buffers', function(){ + crc.buffer.crc32(new Buffer('hello world')).should.equal(222957957); + }) +}) + +describe('crcArc()', function(){ + it('should work with strings', function(){ + crc.crcArc('hello world').should.equal(14785); + }) +}) + +describe('fcs16()', function(){ + it('should work with strings', function(){ + crc.fcs16('hello world').should.equal(44550); + }) +}) + +describe('hex8()', function(){ + it('should work with strings', function(){ + crc.hex8(64).should.equal('40'); + }) +}) + +describe('hex16()', function(){ + it('should work with strings', function(){ + crc.hex16(15332).should.equal('3BE4'); + }) +}) + +describe('hex32()', function(){ + it('should work with strings', function(){ + crc.hex32(222957957).should.equal('0D4A1185'); + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/History.md new file mode 100644 index 0000000..2220632 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/History.md @@ -0,0 +1,47 @@ + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Makefile new file mode 100644 index 0000000..692f2c1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Makefile @@ -0,0 +1,4 @@ + +debug.component.js: head.js debug.js tail.js + cat $^ > $@ + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Readme.md new file mode 100644 index 0000000..419fcdf --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/Readme.md @@ -0,0 +1,130 @@ + +# debug + + tiny node.js debugging utility. + +## Installation + +``` +$ npm install debug +``` + +## Example + + 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: + +```js +var debug; +if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) { + debug = function(x) { + var prefix = process.pid + ',' + + (process.env.NODE_WORKER_ID ? 'Worker' : 'Master'); + console.error(prefix, x); + }; +} else { + debug = function() { }; +} +``` + + 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. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + + ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) + + ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + + ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:". + +## Browser support + + Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + a('doing some work'); +}, 1200); +``` + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.component.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.component.js new file mode 100644 index 0000000..e6e9dbf --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.component.js @@ -0,0 +1,120 @@ +;(function(){ + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + if (!debug.enabled(name)) return function(){}; + + return function(fmt){ + var curr = new Date; + var ms = curr - (debug[name] || curr); + debug[name] = curr; + + fmt = name + + ' ' + + fmt + + ' +' + debug.humanize(ms); + + // This hackery is required for IE8 + // where `console.log` doesn't have 'apply' + window.console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } +} + +/** + * The currently active debug mode names. + */ + +debug.names = []; +debug.skips = []; + +/** + * Enables a debug mode by name. This can include modes + * separated by a colon and wildcards. + * + * @param {String} name + * @api public + */ + +debug.enable = function(name) { + localStorage.debug = name; + + var split = (name || '').split(/[\s,]+/) + , len = split.length; + + for (var i = 0; i < len; i++) { + name = split[i].replace('*', '.*?'); + if (name[0] === '-') { + debug.skips.push(new RegExp('^' + name.substr(1) + '$')); + } + else { + debug.names.push(new RegExp('^' + name + '$')); + } + } +}; + +/** + * Disable debug output. + * + * @api public + */ + +debug.disable = function(){ + debug.enable(''); +}; + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +debug.humanize = function(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +}; + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +debug.enabled = function(name) { + for (var i = 0, len = debug.skips.length; i < len; i++) { + if (debug.skips[i].test(name)) { + return false; + } + } + for (var i = 0, len = debug.names.length; i < len; i++) { + if (debug.names[i].test(name)) { + return true; + } + } + return false; +}; + +// persist + +if (window.localStorage) debug.enable(localStorage.debug); + module.exports = debug; + +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.js new file mode 100644 index 0000000..905fbd4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/debug.js @@ -0,0 +1,116 @@ + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + if (!debug.enabled(name)) return function(){}; + + return function(fmt){ + var curr = new Date; + var ms = curr - (debug[name] || curr); + debug[name] = curr; + + fmt = name + + ' ' + + fmt + + ' +' + debug.humanize(ms); + + // This hackery is required for IE8 + // where `console.log` doesn't have 'apply' + window.console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } +} + +/** + * The currently active debug mode names. + */ + +debug.names = []; +debug.skips = []; + +/** + * Enables a debug mode by name. This can include modes + * separated by a colon and wildcards. + * + * @param {String} name + * @api public + */ + +debug.enable = function(name) { + localStorage.debug = name; + + var split = (name || '').split(/[\s,]+/) + , len = split.length; + + for (var i = 0; i < len; i++) { + name = split[i].replace('*', '.*?'); + if (name[0] === '-') { + debug.skips.push(new RegExp('^' + name.substr(1) + '$')); + } + else { + debug.names.push(new RegExp('^' + name + '$')); + } + } +}; + +/** + * Disable debug output. + * + * @api public + */ + +debug.disable = function(){ + debug.enable(''); +}; + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +debug.humanize = function(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +}; + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +debug.enabled = function(name) { + for (var i = 0, len = debug.skips.length; i < len; i++) { + if (debug.skips[i].test(name)) { + return false; + } + } + for (var i = 0, len = debug.names.length; i < len; i++) { + if (debug.names[i].test(name)) { + return true; + } + } + return false; +}; + +// persist + +if (window.localStorage) debug.enable(localStorage.debug); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/app.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/app.js new file mode 100644 index 0000000..05374d9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/app.js @@ -0,0 +1,19 @@ + +var debug = require('../')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/browser.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/browser.html new file mode 100644 index 0000000..7510eee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/browser.html @@ -0,0 +1,24 @@ + + + debug() + + + + + + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/wildcards.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/wildcards.js new file mode 100644 index 0000000..1fdac20 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/wildcards.js @@ -0,0 +1,10 @@ + +var debug = { + foo: require('../')('test:foo'), + bar: require('../')('test:bar'), + baz: require('../')('test:baz') +}; + +debug.foo('foo') +debug.bar('bar') +debug.baz('baz') \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/worker.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/worker.js new file mode 100644 index 0000000..7f6d288 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/example/worker.js @@ -0,0 +1,22 @@ + +// DEBUG=* node example/worker +// DEBUG=worker:* node example/worker +// DEBUG=worker:a node example/worker +// DEBUG=worker:b node example/worker + +var a = require('../')('worker:a') + , b = require('../')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/head.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/head.js new file mode 100644 index 0000000..55d3817 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/head.js @@ -0,0 +1 @@ +;(function(){ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/index.js new file mode 100644 index 0000000..ee54454 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/debug'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/lib/debug.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/lib/debug.js new file mode 100644 index 0000000..969d122 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/lib/debug.js @@ -0,0 +1,135 @@ + +/** + * Module dependencies. + */ + +var tty = require('tty'); + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Enabled debuggers. + */ + +var names = [] + , skips = []; + +(process.env.DEBUG || '') + .split(/[\s,]+/) + .forEach(function(name){ + name = name.replace('*', '.*?'); + if (name[0] === '-') { + skips.push(new RegExp('^' + name.substr(1) + '$')); + } else { + names.push(new RegExp('^' + name + '$')); + } + }); + +/** + * Colors. + */ + +var colors = [6, 2, 3, 4, 5, 1]; + +/** + * Previous debug() call. + */ + +var prev = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Is stdout a TTY? Colored output is disabled when `true`. + */ + +var isatty = tty.isatty(2); + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function color() { + return colors[prevColor++ % colors.length]; +} + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +function humanize(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +} + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + function disabled(){} + disabled.enabled = false; + + var match = skips.some(function(re){ + return re.test(name); + }); + + if (match) return disabled; + + match = names.some(function(re){ + return re.test(name); + }); + + if (!match) return disabled; + var c = color(); + + function colored(fmt) { + var curr = new Date; + var ms = curr - (prev[name] || curr); + prev[name] = curr; + + fmt = ' \033[9' + c + 'm' + name + ' ' + + '\033[3' + c + 'm\033[90m' + + fmt + '\033[3' + c + 'm' + + ' +' + humanize(ms) + '\033[0m'; + + console.error.apply(this, arguments); + } + + function plain(fmt) { + fmt = new Date().toUTCString() + + ' ' + name + ' ' + fmt; + console.error.apply(this, arguments); + } + + colored.enabled = plain.enabled = true; + + return isatty + ? colored + : plain; +} 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 new file mode 100644 index 0000000..abc581e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/package.json @@ -0,0 +1,32 @@ +{ + "name": "debug", + "version": "0.7.0", + "description": "small debugging utility", + "keywords": [ + "debug", + "log", + "debugger" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*" + }, + "main": "index", + "browserify": "debug.component.js", + "engines": { + "node": "*" + }, + "component": { + "scripts": { + "debug": "debug.component.js" + } + }, + "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/debug/tail.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/tail.js new file mode 100644 index 0000000..5bf3fd3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/debug/tail.js @@ -0,0 +1,4 @@ + + module.exports = debug; + +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.npmignore new file mode 100644 index 0000000..4fbabb3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.npmignore @@ -0,0 +1,4 @@ +/test/tmp/ +*.upload +*.un~ +*.http diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/.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/connect/node_modules/formidable/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/Makefile new file mode 100644 index 0000000..8945872 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/Makefile @@ -0,0 +1,14 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +build: npm test + +npm: + npm install . + +clean: + rm test/tmp/* + +.PHONY: test clean build diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/Readme.md new file mode 100644 index 0000000..a5ca104 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/Readme.md @@ -0,0 +1,311 @@ +# Formidable + +[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable) + +## Purpose + +A node.js module for parsing form data, especially file uploads. + +## Current status + +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from +a large variety of clients and is considered production-ready. + +## Features + +* Fast (~500mb/sec), non-buffering multipart parser +* Automatically writing file uploads to disk +* Low memory footprint +* Graceful error handling +* Very high test coverage + +## Changelog + +### v1.0.9 + +* Emit progress when content length header parsed (Tim Koschützki) +* Fix Readme syntax due to GitHub changes (goob) +* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara) + +### v1.0.8 + +* Strip potentially unsafe characters when using `keepExtensions: true`. +* Switch to utest / urun for testing +* Add travis build + +### v1.0.7 + +* Remove file from package that was causing problems when installing on windows. (#102) +* Fix typos in Readme (Jason Davies). + +### v1.0.6 + +* Do not default to the default to the field name for file uploads where + filename="". + +### v1.0.5 + +* Support filename="" in multipart parts +* Explain unexpected end() errors in parser better + +**Note:** Starting with this version, formidable emits 'file' events for empty +file input fields. Previously those were incorrectly emitted as regular file +input fields with value = "". + +### v1.0.4 + +* Detect a good default tmp directory regardless of platform. (#88) + +### v1.0.3 + +* Fix problems with utf8 characters (#84) / semicolons in filenames (#58) +* Small performance improvements +* New test suite and fixture system + +### v1.0.2 + +* Exclude node\_modules folder from git +* Implement new `'aborted'` event +* Fix files in example folder to work with recent node versions +* Make gently a devDependency + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2) + +### v1.0.1 + +* Fix package.json to refer to proper main directory. (#68, Dean Landolt) + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1) + +### v1.0.0 + +* Add support for multipart boundaries that are quoted strings. (Jeff Craig) + +This marks the beginning of development on version 2.0 which will include +several architectural improvements. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0) + +### v0.9.11 + +* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki) +* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class + +**Important:** The old property names of the File class will be removed in a +future release. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11) + +### Older releases + +These releases were done before starting to maintain the above Changelog: + +* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10) +* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9) +* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8) +* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7) +* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6) +* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5) +* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4) +* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3) +* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2) +* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0) + +## Installation + +Via [npm](http://github.com/isaacs/npm): + + npm install formidable@latest + +Manually: + + git clone git://github.com/felixge/node-formidable.git formidable + vim my.js + # var formidable = require('./formidable'); + +Note: 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. + +## Example + +Parse an incoming file upload. + + var formidable = require('formidable'), + http = require('http'), + + util = require('util'); + + http.createServer(function(req, res) { + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { + // parse a file upload + var form = new formidable.IncomingForm(); + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received upload:\n\n'); + res.end(util.inspect({fields: fields, files: files})); + }); + return; + } + + // show a file upload form + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '' + ); + }).listen(80); + +## API + +### formidable.IncomingForm + +__new formidable.IncomingForm()__ + +Creates a new incoming form. + +__incomingForm.encoding = 'utf-8'__ + +The encoding to use for incoming form fields. + +__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__ + +The directory for placing file uploads in. You can move them later on using +`fs.rename()`. The default directory is picked at module load time depending on +the first existing directory from those listed above. + +__incomingForm.keepExtensions = false__ + +If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`. + +__incomingForm.type__ + +Either 'multipart' or 'urlencoded' depending on the incoming request. + +__incomingForm.maxFieldsSize = 2 * 1024 * 1024__ + +Limits the amount of memory a field (not file) can allocate in bytes. +If this value is exceeded, an `'error'` event is emitted. The default +size is 2MB. + +__incomingForm.hash = false__ + +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. + +__incomingForm.bytesReceived__ + +The amount of bytes received for this form so far. + +__incomingForm.bytesExpected__ + +The expected number of bytes in this form. + +__incomingForm.parse(request, [cb])__ + +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback: + + incomingForm.parse(req, function(err, fields, files) { + // ... + }); + +__incomingForm.onPart(part)__ + +You 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. + + incomingForm.onPart = function(part) { + part.addListener('data', function() { + // ... + }); + } + +If you want to use formidable to only handle certain parts for you, you can do so: + + incomingForm.onPart = function(part) { + if (!part.filename) { + // let formidable handle all non-file parts + incomingForm.handlePart(part); + } + } + +Check the code in this method for further inspiration. + +__Event: 'progress' (bytesReceived, bytesExpected)__ + +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. + +__Event: 'field' (name, value)__ + +Emitted whenever a field / value pair has been received. + +__Event: 'fileBegin' (name, file)__ + +Emitted whenever a new file is detected in the upload stream. Use this even if +you want to stream the file to somewhere else while buffering the upload on +the file system. + +__Event: 'file' (name, file)__ + +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. + +__Event: 'error' (err)__ + +Emitted 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. + +__Event: 'aborted'__ + +Emitted 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). + +__Event: 'end' ()__ + +Emitted 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. + +### formidable.File + +__file.size = 0__ + +The 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. + +__file.path = null__ + +The path this file is being written to. You can modify this in the `'fileBegin'` event in +case you are unhappy with the way formidable generates a temporary path for your files. + +__file.name = null__ + +The name this file had according to the uploading client. + +__file.type = null__ + +The mime type of this file, according to the uploading client. + +__file.lastModifiedDate = null__ + +A date object (or `null`) containing the time this file was last written to. Mostly +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). + +__file.hash = null__ + +If hash calculation was set, you can read the hex digest out of this var. + +## License + +Formidable is licensed under the MIT license. + +## Ports + +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable + +## Credits + +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/TODO b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/TODO new file mode 100644 index 0000000..e1107f2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/TODO @@ -0,0 +1,3 @@ +- Better bufferMaxSize handling approach +- Add tests for JSON parser pull request and merge it +- Implement QuerystringParser the same way as MultipartParser diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js new file mode 100644 index 0000000..bff41f1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js @@ -0,0 +1,70 @@ +require('../test/common'); +var multipartParser = require('../lib/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + Buffer = require('buffer').Buffer, + boundary = '-----------------------------168072824752491622650073', + mb = 100, + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), + callbacks = + { partBegin: -1, + partEnd: -1, + headerField: -1, + headerValue: -1, + partData: -1, + end: -1, + }; + + +parser.initWithBoundary(boundary); +parser.onHeaderField = function() { + callbacks.headerField++; +}; + +parser.onHeaderValue = function() { + callbacks.headerValue++; +}; + +parser.onPartBegin = function() { + callbacks.partBegin++; +}; + +parser.onPartData = function() { + callbacks.partData++; +}; + +parser.onPartEnd = function() { + callbacks.partEnd++; +}; + +parser.onEnd = function() { + callbacks.end++; +}; + +var start = +new Date(), + nparsed = parser.write(buffer), + duration = +new Date - start, + mbPerSec = (mb / (duration / 1000)).toFixed(2); + +console.log(mbPerSec+' mb/sec'); + +assert.equal(nparsed, buffer.length); + +function createMultipartBuffer(boundary, size) { + var head = + '--'+boundary+'\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + , tail = '\r\n--'+boundary+'--\r\n' + , buffer = new Buffer(size); + + buffer.write(head, 'ascii', 0); + buffer.write(tail, 'ascii', buffer.length - tail.length); + return buffer; +} + +process.on('exit', function() { + for (var k in callbacks) { + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/post.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/post.js new file mode 100644 index 0000000..f6c15a6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/post.js @@ -0,0 +1,43 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '' + ); + } else if (req.url == '/post') { + var form = new formidable.IncomingForm(), + fields = []; + + form + .on('error', function(err) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + }) + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/upload.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/upload.js new file mode 100644 index 0000000..050cdd9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/example/upload.js @@ -0,0 +1,48 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '' + ); + } else if (req.url == '/upload') { + var form = new formidable.IncomingForm(), + files = [], + fields = []; + + form.uploadDir = TEST_TMP; + + form + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('file', function(field, file) { + console.log(field, file); + files.push([field, file]); + }) + .on('end', function() { + console.log('-> upload done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received fields:\n\n '+util.inspect(fields)); + res.write('\n\n'); + res.end('received files:\n\n '+util.inspect(files)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/index.js new file mode 100644 index 0000000..be41032 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/formidable'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/file.js new file mode 100644 index 0000000..dad8d5f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/file.js @@ -0,0 +1,73 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var util = require('./util'), + WriteStream = require('fs').WriteStream, + EventEmitter = require('events').EventEmitter, + crypto = require('crypto'); + +function File(properties) { + EventEmitter.call(this); + + this.size = 0; + this.path = null; + this.name = null; + this.type = null; + this.hash = null; + this.lastModifiedDate = null; + + this._writeStream = null; + + for (var key in properties) { + this[key] = properties[key]; + } + + if(typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } + + this._backwardsCompatibility(); +} +module.exports = File; +util.inherits(File, EventEmitter); + +// @todo Next release: Show error messages when accessing these +File.prototype._backwardsCompatibility = function() { + var self = this; + this.__defineGetter__('length', function() { + return self.size; + }); + this.__defineGetter__('filename', function() { + return self.name; + }); + this.__defineGetter__('mime', function() { + return self.type; + }); +}; + +File.prototype.open = function() { + this._writeStream = new WriteStream(this.path); +}; + +File.prototype.write = function(buffer, cb) { + var self = this; + this._writeStream.write(buffer, function() { + if(self.hash) { + self.hash.update(buffer); + } + self.lastModifiedDate = new Date(); + self.size += buffer.length; + self.emit('progress', self.size); + cb(); + }); +}; + +File.prototype.end = function(cb) { + var self = this; + this._writeStream.end(function() { + if(self.hash) { + self.hash = self.hash.digest('hex'); + } + self.emit('end'); + cb(); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/incoming_form.js new file mode 100644 index 0000000..060eac2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/incoming_form.js @@ -0,0 +1,384 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var fs = require('fs'); +var util = require('./util'), + path = require('path'), + File = require('./file'), + MultipartParser = require('./multipart_parser').MultipartParser, + QuerystringParser = require('./querystring_parser').QuerystringParser, + StringDecoder = require('string_decoder').StringDecoder, + EventEmitter = require('events').EventEmitter, + Stream = require('stream').Stream; + +function IncomingForm(opts) { + if (!(this instanceof IncomingForm)) return new IncomingForm; + EventEmitter.call(this); + + opts=opts||{}; + + this.error = null; + this.ended = false; + + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; + this.keepExtensions = opts.keepExtensions || false; + this.uploadDir = opts.uploadDir || IncomingForm.UPLOAD_DIR; + this.encoding = opts.encoding || 'utf-8'; + this.headers = null; + this.type = null; + this.hash = false; + + this.bytesReceived = null; + this.bytesExpected = null; + + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; +}; +util.inherits(IncomingForm, EventEmitter); +exports.IncomingForm = IncomingForm; + +IncomingForm.UPLOAD_DIR = (function() { + var dirs = [process.env.TMP, '/tmp', process.cwd()]; + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var isDirectory = false; + + try { + isDirectory = fs.statSync(dir).isDirectory(); + } catch (e) {} + + if (isDirectory) return dir; + } +})(); + +IncomingForm.prototype.parse = function(req, cb) { + this.pause = function() { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + return true; + }; + + this.resume = function() { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + + return true; + }; + + this.writeHeaders(req.headers); + + var self = this; + req + .on('error', function(err) { + self._error(err); + }) + .on('aborted', function() { + self.emit('aborted'); + }) + .on('data', function(buffer) { + self.write(buffer); + }) + .on('end', function() { + if (self.error) { + return; + } + + var err = self._parser.end(); + if (err) { + self._error(err); + } + }); + + if (cb) { + var fields = {}, files = {}; + this + .on('field', function(name, value) { + fields[name] = value; + }) + .on('file', function(name, file) { + files[name] = file; + }) + .on('error', function(err) { + cb(err, fields, files); + }) + .on('end', function() { + cb(null, fields, files); + }); + } + + return this; +}; + +IncomingForm.prototype.writeHeaders = function(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); +}; + +IncomingForm.prototype.write = function(buffer) { + if (!this._parser) { + this._error(new Error('unintialized parser')); + return; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); + + var bytesParsed = this._parser.write(buffer); + if (bytesParsed !== buffer.length) { + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); + } + + return bytesParsed; +}; + +IncomingForm.prototype.pause = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.resume = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.onPart = function(part) { + // this method can be overwritten by the user + this.handlePart(part); +}; + +IncomingForm.prototype.handlePart = function(part) { + var self = this; + + if (part.filename === undefined) { + var value = '' + , decoder = new StringDecoder(this.encoding); + + part.on('data', function(buffer) { + self._fieldsSize += buffer.length; + if (self._fieldsSize > self.maxFieldsSize) { + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); + return; + } + value += decoder.write(buffer); + }); + + part.on('end', function() { + self.emit('field', part.name, value); + }); + return; + } + + this._flushing++; + + var file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: self.hash + }); + + this.emit('fileBegin', part.name, file); + + file.open(); + + part.on('data', function(buffer) { + self.pause(); + file.write(buffer, function() { + self.resume(); + }); + }); + + part.on('end', function() { + file.end(function() { + self._flushing--; + self.emit('file', part.name, file); + self._maybeEnd(); + }); + }); +}; + +IncomingForm.prototype._parseContentType = function() { + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); + return; + } + + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } + + if (this.headers['content-type'].match(/multipart/i)) { + var m; + if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) { + this._initMultipart(m[1] || m[2]); + } else { + this._error(new Error('bad content-type header, no multipart boundary')); + } + return; + } + + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); +}; + +IncomingForm.prototype._error = function(err) { + if (this.error) { + return; + } + + this.error = err; + this.pause(); + this.emit('error', err); +}; + +IncomingForm.prototype._parseContentLength = function() { + if (this.headers['content-length']) { + this.bytesReceived = 0; + this.bytesExpected = parseInt(this.headers['content-length'], 10); + this.emit('progress', this.bytesReceived, this.bytesExpected); + } +}; + +IncomingForm.prototype._newParser = function() { + return new MultipartParser(); +}; + +IncomingForm.prototype._initMultipart = function(boundary) { + this.type = 'multipart'; + + var parser = new MultipartParser(), + self = this, + headerField, + headerValue, + part; + + parser.initWithBoundary(boundary); + + parser.onPartBegin = function() { + part = new Stream(); + part.readable = true; + part.headers = {}; + part.name = null; + part.filename = null; + part.mime = null; + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString(self.encoding, start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString(self.encoding, start, end); + }; + + parser.onHeaderEnd = function() { + headerField = headerField.toLowerCase(); + part.headers[headerField] = headerValue; + + var m; + if (headerField == 'content-disposition') { + if (m = headerValue.match(/name="([^"]+)"/i)) { + part.name = m[1]; + } + + part.filename = self._fileName(headerValue); + } else if (headerField == 'content-type') { + part.mime = headerValue; + } + + headerField = ''; + headerValue = ''; + }; + + parser.onHeadersEnd = function() { + self.onPart(part); + }; + + parser.onPartData = function(b, start, end) { + part.emit('data', b.slice(start, end)); + }; + + parser.onPartEnd = function() { + part.emit('end'); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._fileName = function(headerValue) { + var m = headerValue.match(/filename="(.*?)"($|; )/i) + if (!m) return; + + var filename = m[1].substr(m[1].lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { + return String.fromCharCode(code); + }); + return filename; +}; + +IncomingForm.prototype._initUrlencoded = function() { + this.type = 'urlencoded'; + + var parser = new QuerystringParser() + , self = this; + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._uploadPath = function(filename) { + var name = ''; + for (var i = 0; i < 32; i++) { + name += Math.floor(Math.random() * 16).toString(16); + } + + if (this.keepExtensions) { + var ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/, '$1') + + name += ext; + } + + return path.join(this.uploadDir, name); +}; + +IncomingForm.prototype._maybeEnd = function() { + if (!this.ended || this._flushing) { + return; + } + + this.emit('end'); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/index.js new file mode 100644 index 0000000..7a6e3e1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/index.js @@ -0,0 +1,3 @@ +var IncomingForm = require('./incoming_form').IncomingForm; +IncomingForm.IncomingForm = IncomingForm; +module.exports = IncomingForm; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/multipart_parser.js new file mode 100644 index 0000000..9ca567c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/multipart_parser.js @@ -0,0 +1,312 @@ +var Buffer = require('buffer').Buffer, + s = 0, + S = + { PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++, + }, + + f = 1, + F = + { PART_BOUNDARY: f, + LAST_BOUNDARY: f *= 2, + }, + + LF = 10, + CR = 13, + SPACE = 32, + HYPHEN = 45, + COLON = 58, + A = 97, + Z = 122, + + lower = function(c) { + return c | 0x20; + }; + +for (var s in S) { + exports[s] = S[s]; +} + +function MultipartParser() { + this.boundary = null; + this.boundaryChars = null; + this.lookbehind = null; + this.state = S.PARSER_UNINITIALIZED; + + this.index = null; + this.flags = 0; +}; +exports.MultipartParser = MultipartParser; + +MultipartParser.stateToString = function(stateNumber) { + for (var state in S) { + var number = S[state]; + if (number === stateNumber) return state; + } +}; + +MultipartParser.prototype.initWithBoundary = function(str) { + this.boundary = new Buffer(str.length+4); + this.boundary.write('\r\n--', 'ascii', 0); + this.boundary.write(str, 'ascii', 4); + this.lookbehind = new Buffer(this.boundary.length+8); + this.state = S.START; + + this.boundaryChars = {}; + for (var i = 0; i < this.boundary.length; i++) { + this.boundaryChars[this.boundary[i]] = true; + } +}; + +MultipartParser.prototype.write = function(buffer) { + var self = this, + i = 0, + len = buffer.length, + prevIndex = this.index, + index = this.index, + state = this.state, + flags = this.flags, + lookbehind = this.lookbehind, + boundary = this.boundary, + boundaryChars = this.boundaryChars, + boundaryLength = this.boundary.length, + boundaryEnd = boundaryLength - 1, + bufferLength = buffer.length, + c, + cl, + + mark = function(name) { + self[name+'Mark'] = i; + }, + clear = function(name) { + delete self[name+'Mark']; + }, + callback = function(name, buffer, start, end) { + if (start !== undefined && start === end) { + return; + } + + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](buffer, start, end); + } + }, + dataCallback = function(name, clear) { + var markSymbol = name+'Mark'; + if (!(markSymbol in self)) { + return; + } + + if (!clear) { + callback(name, buffer, self[markSymbol], buffer.length); + self[markSymbol] = 0; + } else { + callback(name, buffer, self[markSymbol], i); + delete self[markSymbol]; + } + }; + + for (i = 0; i < len; i++) { + c = buffer[i]; + switch (state) { + case S.PARSER_UNINITIALIZED: + return i; + case S.START: + index = 0; + state = S.START_BOUNDARY; + case S.START_BOUNDARY: + if (index == boundary.length - 2) { + if (c != CR) { + return i; + } + index++; + break; + } else if (index - 1 == boundary.length - 2) { + if (c != LF) { + return i; + } + index = 0; + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + + if (c != boundary[index+2]) { + return i; + } + index++; + break; + case S.HEADER_FIELD_START: + state = S.HEADER_FIELD; + mark('headerField'); + index = 0; + case S.HEADER_FIELD: + if (c == CR) { + clear('headerField'); + state = S.HEADERS_ALMOST_DONE; + break; + } + + index++; + if (c == HYPHEN) { + break; + } + + if (c == COLON) { + if (index == 1) { + // empty header field + return i; + } + dataCallback('headerField', true); + state = S.HEADER_VALUE_START; + break; + } + + cl = lower(c); + if (cl < A || cl > Z) { + return i; + } + break; + case S.HEADER_VALUE_START: + if (c == SPACE) { + break; + } + + mark('headerValue'); + state = S.HEADER_VALUE; + case S.HEADER_VALUE: + if (c == CR) { + dataCallback('headerValue', true); + callback('headerEnd'); + state = S.HEADER_VALUE_ALMOST_DONE; + } + break; + case S.HEADER_VALUE_ALMOST_DONE: + if (c != LF) { + return i; + } + state = S.HEADER_FIELD_START; + break; + case S.HEADERS_ALMOST_DONE: + if (c != LF) { + return i; + } + + callback('headersEnd'); + state = S.PART_DATA_START; + break; + case S.PART_DATA_START: + state = S.PART_DATA + mark('partData'); + case S.PART_DATA: + prevIndex = index; + + if (index == 0) { + // boyer-moore derrived algorithm to safely skip non-boundary data + i += boundaryEnd; + while (i < bufferLength && !(buffer[i] in boundaryChars)) { + i += boundaryLength; + } + i -= boundaryEnd; + c = buffer[i]; + } + + if (index < boundary.length) { + if (boundary[index] == c) { + if (index == 0) { + dataCallback('partData', true); + } + index++; + } else { + index = 0; + } + } else if (index == boundary.length) { + index++; + if (c == CR) { + // CR = part boundary + flags |= F.PART_BOUNDARY; + } else if (c == HYPHEN) { + // HYPHEN = end boundary + flags |= F.LAST_BOUNDARY; + } else { + index = 0; + } + } else if (index - 1 == boundary.length) { + if (flags & F.PART_BOUNDARY) { + index = 0; + if (c == LF) { + // unset the PART_BOUNDARY flag + flags &= ~F.PART_BOUNDARY; + callback('partEnd'); + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + } else if (flags & F.LAST_BOUNDARY) { + if (c == HYPHEN) { + callback('partEnd'); + callback('end'); + state = S.END; + } else { + index = 0; + } + } else { + index = 0; + } + } + + if (index > 0) { + // when matching a possible boundary, keep a lookbehind reference + // in case it turns out to be a false lead + lookbehind[index-1] = c; + } else if (prevIndex > 0) { + // if our boundary turned out to be rubbish, the captured lookbehind + // belongs to partData + callback('partData', lookbehind, 0, prevIndex); + prevIndex = 0; + mark('partData'); + + // reconsider the current character even so it interrupted the sequence + // it could be the beginning of a new sequence + i--; + } + + break; + case S.END: + break; + default: + return i; + } + } + + dataCallback('headerField'); + dataCallback('headerValue'); + dataCallback('partData'); + + this.index = index; + this.state = state; + this.flags = flags; + + return len; +}; + +MultipartParser.prototype.end = function() { + if (this.state != S.END) { + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); + } +}; + +MultipartParser.prototype.explain = function() { + return 'state = ' + MultipartParser.stateToString(this.state); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/querystring_parser.js new file mode 100644 index 0000000..63f109e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/querystring_parser.js @@ -0,0 +1,25 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +// This is a buffering parser, not quite as nice as the multipart one. +// If I find time I'll rewrite this to be fully streaming as well +var querystring = require('querystring'); + +function QuerystringParser() { + this.buffer = ''; +}; +exports.QuerystringParser = QuerystringParser; + +QuerystringParser.prototype.write = function(buffer) { + this.buffer += buffer.toString('ascii'); + return buffer.length; +}; + +QuerystringParser.prototype.end = function() { + var fields = querystring.parse(this.buffer); + for (var field in fields) { + this.onField(field, fields[field]); + } + this.buffer = ''; + + this.onEnd(); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/util.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/util.js new file mode 100644 index 0000000..e9493e9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/lib/util.js @@ -0,0 +1,6 @@ +// Backwards compatibility ... +try { + module.exports = require('util'); +} catch (e) { + module.exports = require('sys'); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Makefile new file mode 100644 index 0000000..01f7140 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Makefile @@ -0,0 +1,4 @@ +test: + @find test/simple/test-*.js | xargs -n 1 -t node + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Readme.md new file mode 100644 index 0000000..f8f0c66 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/Readme.md @@ -0,0 +1,167 @@ +# Gently + +## Purpose + +A node.js module that helps with stubbing and behavior verification. It allows you to test the most remote and nested corners of your code while keeping being fully unobtrusive. + +## Features + +* Overwrite and stub individual object functions +* Verify that all expected calls have been made in the expected order +* Restore stubbed functions to their original behavior +* Detect object / class names from obj.constructor.name and obj.toString() +* Hijack any required module function or class constructor + +## Installation + +Via [npm](http://github.com/isaacs/npm): + + npm install gently@latest + +## Example + +Make sure your dog is working properly: + + function Dog() {} + + Dog.prototype.seeCat = function() { + this.bark('whuf, whuf'); + this.run(); + } + + Dog.prototype.bark = function(bark) { + require('sys').puts(bark); + } + + var gently = new (require('gently')) + , assert = require('assert') + , dog = new Dog(); + + gently.expect(dog, 'bark', function(bark) { + assert.equal(bark, 'whuf, whuf'); + }); + gently.expect(dog, 'run'); + + dog.seeCat(); + +You can also easily test event emitters with this, for example a simple sequence of 2 events emitted by `fs.WriteStream`: + + var gently = new (require('gently')) + , stream = new (require('fs').WriteStream)('my_file.txt'); + + gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'open'); + }); + + gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'drain'); + }); + +For a full read world example, check out this test case: [test-incoming-form.js](http://github.com/felixge/node-formidable/blob/master/test/simple/test-incoming-form.js) (in [node-formdiable](http://github.com/felixge/node-formidable)). + +## API + +### Gently + +#### new Gently() + +Creates a new gently instance. It listens to the process `'exit'` event to make sure all expectations have been verified. + +#### gently.expect(obj, method, [[count], stubFn]) + +Creates an expectation for an objects method to be called. You can optionally specify the call `count` you are expecting, as well as `stubFn` function that will run instead of the original function. + +Returns a reference to the function that is getting overwritten. + +#### gently.expect([count], stubFn) + +Returns a function that is supposed to be executed `count` times, delegating any calls to the provided `stubFn` function. Naming your stubFn closure will help to properly diagnose errors that are being thrown: + + childProcess.exec('ls', gently.expect(function lsCallback(code) { + assert.equal(0, code); + })); + +#### gently.restore(obj, method) + +Restores an object method that has been previously overwritten using `gently.expect()`. + +#### gently.hijack(realRequire) + +Returns a new require functions that catches a reference to all required modules into `gently.hijacked`. + +To use this function, include a line like this in your `'my-module.js'`. + + if (global.GENTLY) require = GENTLY.hijack(require); + + var sys = require('sys'); + exports.hello = function() { + sys.log('world'); + }; + +Now you can write a test for the module above: + + var gently = global.GENTLY = new (require('gently')) + , myModule = require('./my-module'); + + gently.expect(gently.hijacked.sys, 'log', function(str) { + assert.equal(str, 'world'); + }); + + myModule.hello(); + +#### gently.stub(location, [exportsName]) + +Returns a stub class that will be used instead of the real class from the module at `location` with the given `exportsName`. + +This allows to test an OOP version of the previous example, where `'my-module.js'`. + + if (global.GENTLY) require = GENTLY.hijack(require); + + var World = require('./world'); + + exports.hello = function() { + var world = new World(); + world.hello(); + } + +And `world.js` looks like this: + + var sys = require('sys'); + + function World() { + + } + module.exports = World; + + World.prototype.hello = function() { + sys.log('world'); + }; + +Testing `'my-module.js'` can now easily be accomplished: + + var gently = global.GENTLY = new (require('gently')) + , WorldStub = gently.stub('./world') + , myModule = require('./my-module') + , WORLD; + + gently.expect(WorldStub, 'new', function() { + WORLD = this; + }); + + gently.expect(WORLD, 'hello'); + + myModule.hello(); + +#### gently.hijacked + +An object that holds the references to all hijacked modules. + +#### gently.verify([msg]) + +Verifies that all expectations of this gently instance have been satisfied. If not called manually, this method is called when the process `'exit'` event is fired. + +If `msg` is given, it will appear in any error that might be thrown. + +## License + +Gently is licensed under the MIT license. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/dog.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/dog.js new file mode 100644 index 0000000..022fae0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/dog.js @@ -0,0 +1,22 @@ +require('../test/common'); +function Dog() {} + +Dog.prototype.seeCat = function() { + this.bark('whuf, whuf'); + this.run(); +} + +Dog.prototype.bark = function(bark) { + require('sys').puts(bark); +} + +var gently = new (require('gently')) + , assert = require('assert') + , dog = new Dog(); + +gently.expect(dog, 'bark', function(bark) { + assert.equal(bark, 'whuf, whuf'); +}); +gently.expect(dog, 'run'); + +dog.seeCat(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js new file mode 100644 index 0000000..7def134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js @@ -0,0 +1,11 @@ +require('../test/common'); +var gently = new (require('gently')) + , stream = new (require('fs').WriteStream)('my_file.txt'); + +gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'open'); +}); + +gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'drain'); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/index.js new file mode 100644 index 0000000..69122bd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/gently'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js new file mode 100644 index 0000000..8af0e1e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js @@ -0,0 +1,184 @@ +var path = require('path'); + +function Gently() { + this.expectations = []; + this.hijacked = {}; + + var self = this; + process.addListener('exit', function() { + self.verify('process exit'); + }); +}; +module.exports = Gently; + +Gently.prototype.stub = function(location, exportsName) { + function Stub() { + return Stub['new'].apply(this, arguments); + }; + + Stub['new'] = function () {}; + + var stubName = 'require('+JSON.stringify(location)+')'; + if (exportsName) { + stubName += '.'+exportsName; + } + + Stub.prototype.toString = Stub.toString = function() { + return stubName; + }; + + var exports = this.hijacked[location] || {}; + if (exportsName) { + exports[exportsName] = Stub; + } else { + exports = Stub; + } + + this.hijacked[location] = exports; + return Stub; +}; + +Gently.prototype.hijack = function(realRequire) { + var self = this; + return function(location) { + return self.hijacked[location] = (self.hijacked[location]) + ? self.hijacked[location] + : realRequire(location); + }; +}; + +Gently.prototype.expect = function(obj, method, count, stubFn) { + if (typeof obj != 'function' && typeof obj != 'object' && typeof obj != 'number') { + throw new Error + ( 'Bad 1st argument for gently.expect(), ' + + 'object, function, or number expected, got: '+(typeof obj) + ); + } else if (typeof obj == 'function' && (typeof method != 'string')) { + // expect(stubFn) interface + stubFn = obj; + obj = null; + method = null; + count = 1; + } else if (typeof method == 'function') { + // expect(count, stubFn) interface + count = obj; + stubFn = method; + obj = null; + method = null; + } else if (typeof count == 'function') { + // expect(obj, method, stubFn) interface + stubFn = count; + count = 1; + } else if (count === undefined) { + // expect(obj, method) interface + count = 1; + } + + var name = this._name(obj, method, stubFn); + this.expectations.push({obj: obj, method: method, stubFn: stubFn, name: name, count: count}); + + var self = this; + function delegate() { + return self._stubFn(this, obj, method, name, Array.prototype.slice.call(arguments)); + } + + if (!obj) { + return delegate; + } + + var original = (obj[method]) + ? obj[method]._original || obj[method] + : undefined; + + obj[method] = delegate; + return obj[method]._original = original; +}; + +Gently.prototype.restore = function(obj, method) { + if (!obj[method] || !obj[method]._original) { + throw new Error(this._name(obj, method)+' is not gently stubbed'); + } + obj[method] = obj[method]._original; +}; + +Gently.prototype.verify = function(msg) { + if (!this.expectations.length) { + return; + } + + var validExpectations = []; + for (var i = 0, l = this.expectations.length; i < l; i++) { + var expectation = this.expectations[i]; + + if (expectation.count > 0) { + validExpectations.push(expectation); + } + } + + this.expectations = []; // reset so that no duplicate verification attempts are made + + if (!validExpectations.length) { + return; + } + + var expectation = validExpectations[0]; + + throw new Error + ( 'Expected call to '+expectation.name+' did not happen' + + ( (msg) + ? ' ('+msg+')' + : '' + ) + ); +}; + +Gently.prototype._stubFn = function(self, obj, method, name, args) { + var expectation = this.expectations[0], obj, method; + + if (!expectation) { + throw new Error('Unexpected call to '+name+', no call was expected'); + } + + if (expectation.obj !== obj || expectation.method !== method) { + throw new Error('Unexpected call to '+name+', expected call to '+ expectation.name); + } + + expectation.count -= 1; + if (expectation.count === 0) { + this.expectations.shift(); + + // autorestore original if its not a closure + // and no more expectations on that object + var has_more_expectations = this.expectations.reduce(function (memo, expectation) { + return memo || (expectation.obj === obj && expectation.method === method); + }, false); + if (obj !== null && method !== null && !has_more_expectations) { + if (typeof obj[method]._original !== 'undefined') { + obj[method] = obj[method]._original; + delete obj[method]._original; + } else { + delete obj[method]; + } + } + } + + if (expectation.stubFn) { + return expectation.stubFn.apply(self, args); + } +}; + +Gently.prototype._name = function(obj, method, stubFn) { + if (obj) { + var objectName = obj.toString(); + if (objectName == '[object Object]' && obj.constructor.name) { + objectName = '['+obj.constructor.name+']'; + } + return (objectName)+'.'+method+'()'; + } + + if (stubFn.name) { + return stubFn.name+'()'; + } + + return '>> '+stubFn.toString()+' <<'; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js new file mode 100644 index 0000000..64c1977 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js @@ -0,0 +1 @@ +module.exports = require('./gently'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/package.json new file mode 100644 index 0000000..9c1b7a0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/package.json @@ -0,0 +1,14 @@ +{ + "name": "gently", + "version": "0.9.2", + "directories": { + "lib": "./lib/gently" + }, + "main": "./lib/gently/index", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "optionalDependencies": {} +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/common.js new file mode 100644 index 0000000..978b5c5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/common.js @@ -0,0 +1,8 @@ +var path = require('path') + , sys = require('sys'); + +require.paths.unshift(path.dirname(__dirname)+'/lib'); + +global.puts = sys.puts; +global.p = function() {sys.error(sys.inspect.apply(null, arguments))};; +global.assert = require('assert'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js new file mode 100644 index 0000000..4f8fe2d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js @@ -0,0 +1,348 @@ +require('../common'); +var Gently = require('gently') + , gently; + +function test(test) { + process.removeAllListeners('exit'); + gently = new Gently(); + test(); +} + +test(function constructor() { + assert.deepEqual(gently.expectations, []); + assert.deepEqual(gently.hijacked, {}); + assert.equal(gently.constructor.name, 'Gently'); +}); + +test(function expectBadArgs() { + var BAD_ARG = 'oh no'; + try { + gently.expect(BAD_ARG); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Bad 1st argument for gently.expect(), object, function, or number expected, got: '+(typeof BAD_ARG)); + } +}); + +test(function expectObjMethod() { + var OBJ = {}, NAME = 'foobar'; + OBJ.foo = function(x) { + return x; + }; + + gently._name = function() { + return NAME; + }; + + var original = OBJ.foo + , stubFn = function() {}; + + (function testAddOne() { + assert.strictEqual(gently.expect(OBJ, 'foo', stubFn), original); + + assert.equal(gently.expectations.length, 1); + var expectation = gently.expectations[0]; + assert.strictEqual(expectation.obj, OBJ); + assert.strictEqual(expectation.method, 'foo'); + assert.strictEqual(expectation.stubFn, stubFn); + assert.strictEqual(expectation.name, NAME); + assert.strictEqual(OBJ.foo._original, original); + })(); + + (function testAddTwo() { + gently.expect(OBJ, 'foo', 2, stubFn); + assert.equal(gently.expectations.length, 2); + assert.strictEqual(OBJ.foo._original, original); + })(); + + (function testAddOneWithoutMock() { + gently.expect(OBJ, 'foo'); + assert.equal(gently.expectations.length, 3); + })(); + + var stubFnCalled = 0, SELF = {}; + gently._stubFn = function(self, obj, method, name, args) { + stubFnCalled++; + assert.strictEqual(self, SELF); + assert.strictEqual(obj, OBJ); + assert.strictEqual(method, 'foo'); + assert.strictEqual(name, NAME); + assert.deepEqual(args, [1, 2]); + return 23; + }; + assert.equal(OBJ.foo.apply(SELF, [1, 2]), 23); + assert.equal(stubFnCalled, 1); +}); + +test(function expectClosure() { + var NAME = 'MY CLOSURE'; + function closureFn() {}; + + gently._name = function() { + return NAME; + }; + + var fn = gently.expect(closureFn); + assert.equal(gently.expectations.length, 1); + var expectation = gently.expectations[0]; + assert.strictEqual(expectation.obj, null); + assert.strictEqual(expectation.method, null); + assert.strictEqual(expectation.stubFn, closureFn); + assert.strictEqual(expectation.name, NAME); + + var stubFnCalled = 0, SELF = {}; + gently._stubFn = function(self, obj, method, name, args) { + stubFnCalled++; + assert.strictEqual(self, SELF); + assert.strictEqual(obj, null); + assert.strictEqual(method, null); + assert.strictEqual(name, NAME); + assert.deepEqual(args, [1, 2]); + return 23; + }; + assert.equal(fn.apply(SELF, [1, 2]), 23); + assert.equal(stubFnCalled, 1); +}); + +test(function expectClosureCount() { + var stubFnCalled = 0; + function closureFn() {stubFnCalled++}; + + var fn = gently.expect(2, closureFn); + assert.equal(gently.expectations.length, 1); + fn(); + assert.equal(gently.expectations.length, 1); + fn(); + assert.equal(stubFnCalled, 2); +}); + +test(function restore() { + var OBJ = {}, NAME = '[my object].myFn()'; + OBJ.foo = function(x) { + return x; + }; + + gently._name = function() { + return NAME; + }; + + var original = OBJ.foo; + gently.expect(OBJ, 'foo'); + gently.restore(OBJ, 'foo'); + assert.strictEqual(OBJ.foo, original); + + (function testError() { + try { + gently.restore(OBJ, 'foo'); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, NAME+' is not gently stubbed'); + } + })(); +}); + +test(function _stubFn() { + var OBJ1 = {toString: function() {return '[OBJ 1]'}} + , OBJ2 = {toString: function() {return '[OBJ 2]'}, foo: function () {return 'bar';}} + , SELF = {}; + + gently.expect(OBJ1, 'foo', function(x) { + assert.strictEqual(this, SELF); + return x * 2; + }); + + assert.equal(gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]), 10); + + (function testAutorestore() { + assert.equal(OBJ2.foo(), 'bar'); + + gently.expect(OBJ2, 'foo', function() { + return 'stubbed foo'; + }); + + gently.expect(OBJ2, 'foo', function() { + return "didn't restore yet"; + }); + + assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), 'stubbed foo'); + assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), "didn't restore yet"); + assert.equal(OBJ2.foo(), 'bar'); + assert.deepEqual(gently.expectations, []); + })(); + + (function testNoMoreCallExpected() { + try { + gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Unexpected call to dummy_name, no call was expected'); + } + })(); + + (function testDifferentCallExpected() { + gently.expect(OBJ2, 'bar'); + try { + gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Unexpected call to dummy_name, expected call to '+gently._name(OBJ2, 'bar')); + } + + assert.equal(gently.expectations.length, 1); + })(); + + (function testNoMockCallback() { + OBJ2.bar(); + assert.equal(gently.expectations.length, 0); + })(); +}); + +test(function stub() { + var LOCATION = './my_class'; + + (function testRegular() { + var Stub = gently.stub(LOCATION); + assert.ok(Stub instanceof Function); + assert.strictEqual(gently.hijacked[LOCATION], Stub); + assert.ok(Stub['new'] instanceof Function); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+')'); + + (function testConstructor() { + var newCalled = 0 + , STUB + , ARGS = ['foo', 'bar']; + + Stub['new'] = function(a, b) { + assert.equal(a, ARGS[0]); + assert.equal(b, ARGS[1]); + newCalled++; + STUB = this; + }; + + var stub = new Stub(ARGS[0], ARGS[1]); + assert.strictEqual(stub, STUB); + assert.equal(newCalled, 1); + assert.equal(stub.toString(), 'require('+JSON.stringify(LOCATION)+')'); + })(); + + (function testUseReturnValueAsInstance() { + var R = {}; + + Stub['new'] = function() { + return R; + }; + + var stub = new Stub(); + assert.strictEqual(stub, R); + + })(); + })(); + + var EXPORTS_NAME = 'MyClass'; + test(function testExportsName() { + var Stub = gently.stub(LOCATION, EXPORTS_NAME); + assert.strictEqual(gently.hijacked[LOCATION][EXPORTS_NAME], Stub); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME); + + (function testConstructor() { + var stub = new Stub(); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME); + })(); + }); +}); + +test(function hijack() { + var LOCATION = './foo' + , REQUIRE_CALLS = 0 + , EXPORTS = {} + , REQUIRE = function() { + REQUIRE_CALLS++; + return EXPORTS; + }; + + var hijackedRequire = gently.hijack(REQUIRE); + hijackedRequire(LOCATION); + assert.strictEqual(gently.hijacked[LOCATION], EXPORTS); + + assert.equal(REQUIRE_CALLS, 1); + + // make sure we are caching the hijacked module + hijackedRequire(LOCATION); + assert.equal(REQUIRE_CALLS, 1); +}); + +test(function verify() { + var OBJ = {toString: function() {return '[OBJ]'}}; + gently.verify(); + + gently.expect(OBJ, 'foo'); + try { + gently.verify(); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen'); + } + + try { + gently.verify('foo'); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen (foo)'); + } +}); + +test(function processExit() { + var verifyCalled = 0; + gently.verify = function(msg) { + verifyCalled++; + assert.equal(msg, 'process exit'); + }; + + process.emit('exit'); + assert.equal(verifyCalled, 1); +}); + +test(function _name() { + (function testNamedClass() { + function Foo() {}; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), '[Foo].bar()'); + })(); + + (function testToStringPreference() { + function Foo() {}; + Foo.prototype.toString = function() { + return '[Superman 123]'; + }; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), '[Superman 123].bar()'); + })(); + + (function testUnamedClass() { + var Foo = function() {}; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), foo.toString()+'.bar()'); + })(); + + (function testNamedClosure() { + function myClosure() {}; + assert.equal(gently._name(null, null, myClosure), myClosure.name+'()'); + })(); + + (function testUnamedClosure() { + var myClosure = function() {2+2 == 5}; + assert.equal(gently._name(null, null, myClosure), '>> '+myClosure.toString()+' <<'); + })(); +}); + +test(function verifyExpectNone() { + var OBJ = {toString: function() {return '[OBJ]'}}; + gently.verify(); + + gently.expect(OBJ, 'foo', 0); + try { + gently.verify(); + } catch (e) { + assert.fail('Exception should not have been thrown'); + } +}); \ No newline at end of file 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 new file mode 100644 index 0000000..1fd45c7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/package.json @@ -0,0 +1,28 @@ +{ + "name": "formidable", + "version": "1.0.11", + "dependencies": {}, + "devDependencies": { + "gently": "0.8.0", + "findit": "0.1.1", + "hashish": "0.0.4", + "urun": "0.0.4", + "utest": "0.0.3" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/index", + "scripts": { + "test": "make test" + }, + "engines": { + "node": "*" + }, + "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/formidable/test/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/common.js new file mode 100644 index 0000000..eb432ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/common.js @@ -0,0 +1,19 @@ +var mysql = require('..'); +var path = require('path'); + +var root = path.join(__dirname, '../'); +exports.dir = { + root : root, + lib : root + '/lib', + fixture : root + '/test/fixture', + tmp : root + '/test/tmp', +}; + +exports.port = 13532; + +exports.formidable = require('..'); +exports.assert = require('assert'); + +exports.require = function(lib) { + return require(exports.dir.lib + '/' + lib); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt new file mode 100644 index 0000000..e7a4785 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt @@ -0,0 +1 @@ +I am a text file with a funky name! diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt new file mode 100644 index 0000000..9b6903e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt @@ -0,0 +1 @@ +I am a plain text file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md new file mode 100644 index 0000000..3c9dbe3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md @@ -0,0 +1,3 @@ +* Opera does not allow submitting this file, it shows a warning to the + user that the file could not be found instead. Tested in 9.8, 11.51 on OSX. + Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com). diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js new file mode 100644 index 0000000..0bae449 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js @@ -0,0 +1,3 @@ +module.exports['generic.http'] = [ + {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt'}, +]; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js new file mode 100644 index 0000000..eb76fdc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js @@ -0,0 +1,21 @@ +var properFilename = 'funkyfilename.txt'; + +function expect(filename) { + return [ + {type: 'field', name: 'title', value: 'Weird filename'}, + {type: 'file', name: 'upload', filename: filename, fixture: properFilename}, + ]; +}; + +var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; +var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; + +module.exports = { + 'osx-chrome-13.http' : expect(webkit), + 'osx-firefox-3.6.http' : expect(ffOrIe), + 'osx-safari-5.http' : expect(webkit), + 'xp-chrome-12.http' : expect(webkit), + 'xp-ie-7.http' : expect(ffOrIe), + 'xp-ie-8.http' : expect(ffOrIe), + 'xp-safari-5.http' : expect(webkit), +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/multipart.js new file mode 100644 index 0000000..a476169 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/fixture/multipart.js @@ -0,0 +1,72 @@ +exports['rfc1867'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['noTrailing\r\n'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['emptyHeader'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + ': foo\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + expectError: true, + }; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js new file mode 100644 index 0000000..66ad259 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js @@ -0,0 +1,89 @@ +var hashish = require('hashish'); +var fs = require('fs'); +var findit = require('findit'); +var path = require('path'); +var http = require('http'); +var net = require('net'); +var assert = require('assert'); + +var common = require('../common'); +var formidable = common.formidable; + +var server = http.createServer(); +server.listen(common.port, findFixtures); + +function findFixtures() { + var fixtures = []; + findit + .sync(common.dir.fixture + '/js') + .forEach(function(jsPath) { + if (!/\.js$/.test(jsPath)) return; + + var group = path.basename(jsPath, '.js'); + hashish.forEach(require(jsPath), function(fixture, name) { + fixtures.push({ + name : group + '/' + name, + fixture : fixture, + }); + }); + }); + + testNext(fixtures); +} + +function testNext(fixtures) { + var fixture = fixtures.shift(); + if (!fixture) return server.close(); + + var name = fixture.name; + var fixture = fixture.fixture; + + uploadFixture(name, function(err, parts) { + if (err) throw err; + + fixture.forEach(function(expectedPart, i) { + var parsedPart = parts[i]; + assert.equal(parsedPart.type, expectedPart.type); + assert.equal(parsedPart.name, expectedPart.name); + + if (parsedPart.type === 'file') { + var filename = parsedPart.value.name; + assert.equal(filename, expectedPart.filename); + } + }); + + testNext(fixtures); + }); +}; + +function uploadFixture(name, cb) { + server.once('request', function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.parse(req); + + function callback() { + var realCallback = cb; + cb = function() {}; + realCallback.apply(null, arguments); + } + + var parts = []; + form + .on('error', callback) + .on('fileBegin', function(name, value) { + parts.push({type: 'file', name: name, value: value}); + }) + .on('field', function(name, value) { + parts.push({type: 'field', name: name, value: value}); + }) + .on('end', function() { + callback(null, parts); + }); + }); + + var socket = net.createConnection(common.port); + var file = fs.createReadStream(common.dir.fixture + '/http/' + name); + + file.pipe(socket); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/common.js new file mode 100644 index 0000000..2b98598 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/common.js @@ -0,0 +1,24 @@ +var path = require('path'), + fs = require('fs'); + +try { + global.Gently = require('gently'); +} catch (e) { + throw new Error('this test suite requires node-gently'); +} + +exports.lib = path.join(__dirname, '../../lib'); + +global.GENTLY = new Gently(); + +global.assert = require('assert'); +global.TEST_PORT = 13532; +global.TEST_FIXTURES = path.join(__dirname, '../fixture'); +global.TEST_TMP = path.join(__dirname, '../tmp'); + +// Stupid new feature in node that complains about gently attaching too many +// listeners to process 'exit'. This is a workaround until I can think of a +// better way to deal with this. +if (process.setMaxListeners) { + process.setMaxListeners(10000); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js new file mode 100644 index 0000000..75232aa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js @@ -0,0 +1,80 @@ +var common = require('../common'); +var CHUNK_LENGTH = 10, + multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + fixtures = require(TEST_FIXTURES + '/multipart'), + Buffer = require('buffer').Buffer; + +Object.keys(fixtures).forEach(function(name) { + var fixture = fixtures[name], + buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')), + offset = 0, + chunk, + nparsed, + + parts = [], + part = null, + headerField, + headerValue, + endCalled = ''; + + parser.initWithBoundary(fixture.boundary); + parser.onPartBegin = function() { + part = {headers: {}, data: ''}; + parts.push(part); + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString('ascii', start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString('ascii', start, end); + } + + parser.onHeaderEnd = function() { + part.headers[headerField] = headerValue; + headerField = ''; + headerValue = ''; + }; + + parser.onPartData = function(b, start, end) { + var str = b.toString('ascii', start, end); + part.data += b.slice(start, end); + } + + parser.onEnd = function() { + endCalled = true; + } + + buffer.write(fixture.raw, 'binary', 0); + + while (offset < buffer.length) { + if (offset + CHUNK_LENGTH < buffer.length) { + chunk = buffer.slice(offset, offset+CHUNK_LENGTH); + } else { + chunk = buffer.slice(offset, buffer.length); + } + offset = offset + CHUNK_LENGTH; + + nparsed = parser.write(chunk); + if (nparsed != chunk.length) { + if (fixture.expectError) { + return; + } + puts('-- ERROR --'); + p(chunk.toString('ascii')); + throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); + } + } + + if (fixture.expectError) { + throw new Error('expected parse error did not happen'); + } + + assert.ok(endCalled); + assert.deepEqual(parts, fixture.parts); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js new file mode 100644 index 0000000..52ceedb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js @@ -0,0 +1,104 @@ +var common = require('../common'); +var WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); + +var File = require(common.lib + '/file'), + EventEmitter = require('events').EventEmitter, + file, + gently; + +function test(test) { + gently = new Gently(); + file = new File(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.ok(file instanceof EventEmitter); + assert.strictEqual(file.size, 0); + assert.strictEqual(file.path, null); + assert.strictEqual(file.name, null); + assert.strictEqual(file.type, null); + assert.strictEqual(file.lastModifiedDate, null); + + assert.strictEqual(file._writeStream, null); + + (function testSetProperties() { + var file2 = new File({foo: 'bar'}); + assert.equal(file2.foo, 'bar'); + })(); +}); + +test(function open() { + var WRITE_STREAM; + file.path = '/foo'; + + gently.expect(WriteStreamStub, 'new', function (path) { + WRITE_STREAM = this; + assert.strictEqual(path, file.path); + }); + + file.open(); + assert.strictEqual(file._writeStream, WRITE_STREAM); +}); + +test(function write() { + var BUFFER = {length: 10}, + CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'write', function (buffer, cb) { + assert.strictEqual(buffer, BUFFER); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.ok(file.lastModifiedDate instanceof Date); + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 10); + }); + + cb(); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 20); + }); + + cb(); + }); + + file.write(BUFFER, CB); +}); + +test(function end() { + var CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'end', function (cb) { + gently.expect(file, 'emit', function (event) { + assert.equal(event, 'end'); + }); + + CB_STUB = gently.expect(function endCb() { + }); + + cb(); + }); + + file.end(CB); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js new file mode 100644 index 0000000..84de439 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js @@ -0,0 +1,727 @@ +var common = require('../common'); +var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'), + QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'), + EventEmitterStub = GENTLY.stub('events', 'EventEmitter'), + StreamStub = GENTLY.stub('stream', 'Stream'), + FileStub = GENTLY.stub('./file'); + +var formidable = require(common.lib + '/index'), + IncomingForm = formidable.IncomingForm, + events = require('events'), + fs = require('fs'), + path = require('path'), + Buffer = require('buffer').Buffer, + fixtures = require(TEST_FIXTURES + '/multipart'), + form, + gently; + +function test(test) { + gently = new Gently(); + gently.expect(EventEmitterStub, 'call'); + form = new IncomingForm(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.strictEqual(form.error, null); + assert.strictEqual(form.ended, false); + assert.strictEqual(form.type, null); + assert.strictEqual(form.headers, null); + assert.strictEqual(form.keepExtensions, false); + assert.strictEqual(form.uploadDir, '/tmp'); + assert.strictEqual(form.encoding, 'utf-8'); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024); + assert.strictEqual(form._parser, null); + assert.strictEqual(form._flushing, 0); + assert.strictEqual(form._fieldsSize, 0); + assert.ok(form instanceof EventEmitterStub); + assert.equal(form.constructor.name, 'IncomingForm'); + + (function testSimpleConstructor() { + gently.expect(EventEmitterStub, 'call'); + var form = IncomingForm(); + assert.ok(form instanceof IncomingForm); + })(); + + (function testSimpleConstructorShortcut() { + gently.expect(EventEmitterStub, 'call'); + var form = formidable(); + assert.ok(form instanceof IncomingForm); + })(); +}); + +test(function parse() { + var REQ = {headers: {}} + , emit = {}; + + gently.expect(form, 'writeHeaders', function(headers) { + assert.strictEqual(headers, REQ.headers); + }); + + var events = ['error', 'aborted', 'data', 'end']; + gently.expect(REQ, 'on', events.length, function(event, fn) { + assert.equal(event, events.shift()); + emit[event] = fn; + return this; + }); + + form.parse(REQ); + + (function testPause() { + gently.expect(REQ, 'pause'); + assert.strictEqual(form.pause(), true); + })(); + + (function testPauseCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testPauseHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testResume() { + gently.expect(REQ, 'resume'); + assert.strictEqual(form.resume(), true); + })(); + + (function testResumeCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testResumeHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testEmitError() { + var ERR = new Error('something bad happened'); + gently.expect(form, '_error',function(err) { + assert.strictEqual(err, ERR); + }); + emit.error(ERR); + })(); + + (function testEmitAborted() { + gently.expect(form, 'emit',function(event) { + assert.equal(event, 'aborted'); + }); + + emit.aborted(); + })(); + + + (function testEmitData() { + var BUFFER = [1, 2, 3]; + gently.expect(form, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + }); + emit.data(BUFFER); + })(); + + (function testEmitEnd() { + form._parser = {}; + + (function testWithError() { + var ERR = new Error('haha'); + gently.expect(form._parser, 'end', function() { + return ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + emit.end(); + })(); + + (function testWithoutError() { + gently.expect(form._parser, 'end'); + emit.end(); + })(); + + (function testAfterError() { + form.error = true; + emit.end(); + })(); + })(); + + (function testWithCallback() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(), + REQ = {headers: {}}, + parseCalled = 0; + + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + gently.expect(form, 'on', 4, function(event, fn) { + if (event == 'field') { + fn('field1', 'foo'); + fn('field1', 'bar'); + fn('field2', 'nice'); + } + + if (event == 'file') { + fn('file1', '1'); + fn('file1', '2'); + fn('file2', '3'); + } + + if (event == 'end') { + fn(); + } + return this; + }); + + form.parse(REQ, gently.expect(function parseCbOk(err, fields, files) { + assert.deepEqual(fields, {field1: 'bar', field2: 'nice'}); + assert.deepEqual(files, {file1: '2', file2: '3'}); + })); + + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + var ERR = new Error('test'); + gently.expect(form, 'on', 3, function(event, fn) { + if (event == 'field') { + fn('foo', 'bar'); + } + + if (event == 'error') { + fn(ERR); + gently.expect(form, 'on'); + } + return this; + }); + + form.parse(REQ, gently.expect(function parseCbErr(err, fields, files) { + assert.strictEqual(err, ERR); + assert.deepEqual(fields, {foo: 'bar'}); + })); + })(); +}); + +test(function pause() { + assert.strictEqual(form.pause(), false); +}); + +test(function resume() { + assert.strictEqual(form.resume(), false); +}); + + +test(function writeHeaders() { + var HEADERS = {}; + gently.expect(form, '_parseContentLength'); + gently.expect(form, '_parseContentType'); + + form.writeHeaders(HEADERS); + assert.strictEqual(form.headers, HEADERS); +}); + +test(function write() { + var parser = {}, + BUFFER = [1, 2, 3]; + + form._parser = parser; + form.bytesExpected = 523423; + + (function testBasic() { + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, BUFFER.length); + assert.equal(bytesExpected, form.bytesExpected); + }); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length; + }); + + assert.equal(form.write(BUFFER), BUFFER.length); + assert.equal(form.bytesReceived, BUFFER.length); + })(); + + (function testParserError() { + gently.expect(form, 'emit'); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length - 1; + }); + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/parser error/i)); + }); + + assert.equal(form.write(BUFFER), BUFFER.length - 1); + assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length); + })(); + + (function testUninitialized() { + delete form._parser; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unintialized parser/i)); + }); + form.write(BUFFER); + })(); +}); + +test(function parseContentType() { + var HEADERS = {}; + + form.headers = {'content-type': 'application/x-www-form-urlencoded'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + // accept anything that has 'urlencoded' in it + form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + var BOUNDARY = '---------------------------57814261102167618332366269'; + form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + + (function testQuotedBoundary() { + form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + })(); + + (function testNoBoundary() { + form.headers = {'content-type': 'multipart/form-data'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no multipart boundary/i)); + }); + form._parseContentType(); + })(); + + (function testNoContentType() { + form.headers = {}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no content-type/i)); + }); + form._parseContentType(); + })(); + + (function testUnknownContentType() { + form.headers = {'content-type': 'invalid'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unknown content-type/i)); + }); + form._parseContentType(); + })(); +}); + +test(function parseContentLength() { + var HEADERS = {}; + + form.headers = {}; + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + + form.headers['content-length'] = '8'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, 0); + assert.strictEqual(form.bytesExpected, 8); + + // JS can be evil, lets make sure we are not + form.headers['content-length'] = '08'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesExpected, 8); +}); + +test(function _initMultipart() { + var BOUNDARY = '123', + PARSER; + + gently.expect(MultipartParserStub, 'new', function() { + PARSER = this; + }); + + gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + + form._initMultipart(BOUNDARY); + assert.equal(form.type, 'multipart'); + assert.strictEqual(form._parser, PARSER); + + (function testRegularField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.strictEqual(part, PART); + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field1"' + , 'foo': 'bar' + } + ); + assert.equal(part.name, 'field1'); + + var strings = ['hello', ' world']; + gently.expect(part, 'emit', 2, function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), strings.shift()); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10); + PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('foo'), 0, 3); + PARSER.onHeaderValue(new Buffer('bar'), 0, 3); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('hello world'), 0, 5); + PARSER.onPartData(new Buffer('hello world'), 5, 11); + PARSER.onPartEnd(); + })(); + + (function testFileField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"' + , 'content-type': 'text/plain' + } + ); + assert.equal(part.name, 'field2'); + assert.equal(part.filename, 'Sun"et.jpg'); + assert.equal(part.mime, 'text/plain'); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), '... contents of file1.txt ...'); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12); + PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29); + PARSER.onPartEnd(); + })(); + + (function testEnd() { + gently.expect(form, '_maybeEnd'); + PARSER.onEnd(); + assert.ok(form.ended); + })(); +}); + +test(function _fileName() { + // TODO + return; +}); + +test(function _initUrlencoded() { + var PARSER; + + gently.expect(QuerystringParserStub, 'new', function() { + PARSER = this; + }); + + form._initUrlencoded(); + assert.equal(form.type, 'urlencoded'); + assert.strictEqual(form._parser, PARSER); + + (function testOnField() { + var KEY = 'KEY', VAL = 'VAL'; + gently.expect(form, 'emit', function(field, key, val) { + assert.equal(field, 'field'); + assert.equal(key, KEY); + assert.equal(val, VAL); + }); + + PARSER.onField(KEY, VAL); + })(); + + (function testOnEnd() { + gently.expect(form, '_maybeEnd'); + + PARSER.onEnd(); + assert.equal(form.ended, true); + })(); +}); + +test(function _error() { + var ERR = new Error('bla'); + + gently.expect(form, 'pause'); + gently.expect(form, 'emit', function(event, err) { + assert.equal(event, 'error'); + assert.strictEqual(err, ERR); + }); + + form._error(ERR); + assert.strictEqual(form.error, ERR); + + // make sure _error only does its thing once + form._error(ERR); +}); + +test(function onPart() { + var PART = {}; + gently.expect(form, 'handlePart', function(part) { + assert.strictEqual(part, PART); + }); + + form.onPart(PART); +}); + +test(function handlePart() { + (function testUtf8Field() { + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field'); + assert.equal(value, 'hello world: €'); + }); + + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testBinaryField() { + var PART = new events.EventEmitter(); + PART.name = 'my_field2'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field2'); + assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary')); + }); + + form.encoding = 'binary'; + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testFieldSize() { + form.maxFieldsSize = 8; + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, '_error', function(err) { + assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data'); + }); + + form.handlePart(PART); + form._fieldsSize = 1; + PART.emit('data', new Buffer(7)); + PART.emit('data', new Buffer(1)); + })(); + + (function testFilePart() { + var PART = new events.EventEmitter(), + FILE = new events.EventEmitter(), + PATH = '/foo/bar'; + + PART.name = 'my_file'; + PART.filename = 'sweet.txt'; + PART.mime = 'sweet.txt'; + + gently.expect(form, '_uploadPath', function(filename) { + assert.equal(filename, PART.filename); + return PATH; + }); + + gently.expect(FileStub, 'new', function(properties) { + assert.equal(properties.path, PATH); + assert.equal(properties.name, PART.filename); + assert.equal(properties.type, PART.mime); + FILE = this; + + gently.expect(form, 'emit', function (event, field, file) { + assert.equal(event, 'fileBegin'); + assert.strictEqual(field, PART.name); + assert.strictEqual(file, FILE); + }); + + gently.expect(FILE, 'open'); + }); + + form.handlePart(PART); + assert.equal(form._flushing, 1); + + var BUFFER; + gently.expect(form, 'pause'); + gently.expect(FILE, 'write', function(buffer, cb) { + assert.strictEqual(buffer, BUFFER); + gently.expect(form, 'resume'); + // @todo handle cb(new Err) + cb(); + }); + + PART.emit('data', BUFFER = new Buffer('test')); + + gently.expect(FILE, 'end', function(cb) { + gently.expect(form, 'emit', function(event, field, file) { + assert.equal(event, 'file'); + assert.strictEqual(file, FILE); + }); + + gently.expect(form, '_maybeEnd'); + + cb(); + assert.equal(form._flushing, 0); + }); + + PART.emit('end'); + })(); +}); + +test(function _uploadPath() { + (function testUniqueId() { + var UUID_A, UUID_B; + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + assert.equal(uploadDir, form.uploadDir); + UUID_A = uuid; + }); + form._uploadPath(); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + UUID_B = uuid; + }); + form._uploadPath(); + + assert.notEqual(UUID_A, UUID_B); + })(); + + (function testFileExtension() { + form.keepExtensions = true; + var FILENAME = 'foo.jpg', + EXT = '.bar'; + + gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { + assert.equal(filename, FILENAME); + gently.restore(path, 'extname'); + + return EXT; + }); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) { + assert.equal(path.extname(name), EXT); + }); + form._uploadPath(FILENAME); + })(); +}); + +test(function _maybeEnd() { + gently.expect(form, 'emit', 0); + form._maybeEnd(); + + form.ended = true; + form._flushing = 1; + form._maybeEnd(); + + gently.expect(form, 'emit', function(event) { + assert.equal(event, 'end'); + }); + + form.ended = true; + form._flushing = 0; + form._maybeEnd(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js new file mode 100644 index 0000000..d8dc968 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js @@ -0,0 +1,50 @@ +var common = require('../common'); +var multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + events = require('events'), + Buffer = require('buffer').Buffer, + parser; + +function test(test) { + parser = new MultipartParser(); + test(); +} + +test(function constructor() { + assert.equal(parser.boundary, null); + assert.equal(parser.state, 0); + assert.equal(parser.flags, 0); + assert.equal(parser.boundaryChars, null); + assert.equal(parser.index, null); + assert.equal(parser.lookbehind, null); + assert.equal(parser.constructor.name, 'MultipartParser'); +}); + +test(function initWithBoundary() { + var boundary = 'abc'; + parser.initWithBoundary(boundary); + assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); + assert.equal(parser.state, multipartParser.START); + + assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); +}); + +test(function parserError() { + var boundary = 'abc', + buffer = new Buffer(5); + + parser.initWithBoundary(boundary); + buffer.write('--ad', 'ascii', 0); + assert.equal(parser.write(buffer), 3); +}); + +test(function end() { + (function testError() { + assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain()); + })(); + + (function testRegular() { + parser.state = multipartParser.END; + assert.strictEqual(parser.end(), undefined); + })(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js new file mode 100644 index 0000000..54d3e2d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser, + Buffer = require('buffer').Buffer, + gently, + parser; + +function test(test) { + gently = new Gently(); + parser = new QuerystringParser(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.equal(parser.buffer, ''); + assert.equal(parser.constructor.name, 'QuerystringParser'); +}); + +test(function write() { + var a = new Buffer('a=1'); + assert.equal(parser.write(a), a.length); + + var b = new Buffer('&b=2'); + parser.write(b); + assert.equal(parser.buffer, a + b); +}); + +test(function end() { + var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; + + gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { + assert.equal(str, parser.buffer); + return FIELDS; + }); + + gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { + assert.deepEqual(FIELDS[key], val); + }); + + gently.expect(parser, 'onEnd'); + + parser.buffer = 'my buffer'; + parser.end(); + assert.equal(parser.buffer, ''); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js new file mode 100644 index 0000000..479e46d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js @@ -0,0 +1,75 @@ +var common = require('../common'); +var BOUNDARY = '---------------------------10102754414578508781458777923', + FIXTURE = TEST_FIXTURES+'/multi_video.upload', + fs = require('fs'), + util = require(common.lib + '/util'), + http = require('http'), + formidable = require(common.lib + '/index'), + server = http.createServer(); + +server.on('request', function(req, res) { + var form = new formidable.IncomingForm(), + uploads = {}; + + form.uploadDir = TEST_TMP; + form.hash = 'sha1'; + form.parse(req); + + form + .on('fileBegin', function(field, file) { + assert.equal(field, 'upload'); + + var tracker = {file: file, progress: [], ended: false}; + uploads[file.filename] = tracker; + file + .on('progress', function(bytesReceived) { + tracker.progress.push(bytesReceived); + assert.equal(bytesReceived, file.length); + }) + .on('end', function() { + tracker.ended = true; + }); + }) + .on('field', function(field, value) { + assert.equal(field, 'title'); + assert.equal(value, ''); + }) + .on('file', function(field, file) { + assert.equal(field, 'upload'); + assert.strictEqual(uploads[file.filename].file, file); + }) + .on('end', function() { + assert.ok(uploads['shortest_video.flv']); + assert.ok(uploads['shortest_video.flv'].ended); + assert.ok(uploads['shortest_video.flv'].progress.length > 3); + assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a'); + assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.length); + assert.ok(uploads['shortest_video.mp4']); + assert.ok(uploads['shortest_video.mp4'].ended); + assert.ok(uploads['shortest_video.mp4'].progress.length > 3); + assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f'); + + server.close(); + res.writeHead(200); + res.end('good'); + }); +}); + +server.listen(TEST_PORT, function() { + var client = http.createClient(TEST_PORT), + stat = fs.statSync(FIXTURE), + headers = { + 'content-type': 'multipart/form-data; boundary='+BOUNDARY, + 'content-length': stat.size, + } + request = client.request('POST', '/', headers), + fixture = new fs.ReadStream(FIXTURE); + + fixture + .on('data', function(b) { + request.write(b); + }) + .on('end', function() { + request.end(); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/run.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/run.js new file mode 100755 index 0000000..50b2361 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/run.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('urun')(__dirname) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js new file mode 100644 index 0000000..fe2ac1c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js @@ -0,0 +1,63 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var IncomingForm = common.require('incoming_form').IncomingForm; +var path = require('path'); + +var form; +test('IncomingForm', { + before: function() { + form = new IncomingForm(); + }, + + '#_fileName with regular characters': function() { + var filename = 'foo.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'foo.txt'); + }, + + '#_fileName with unescaped quote': function() { + var filename = 'my".txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with escaped quote': function() { + var filename = 'my%22.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with bad quote and additional sub-header': function() { + var filename = 'my".txt'; + var header = makeHeader(filename) + '; foo="bar"'; + assert.equal(form._fileName(header), filename); + }, + + '#_fileName with semicolon': function() { + var filename = 'my;.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my;.txt'); + }, + + '#_fileName with utf8 character': function() { + var filename = 'my☃.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt'); + }, + + '#_uploadPath strips harmful characters from extension when keepExtensions': function() { + form.keepExtensions = true; + + var ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); + assert.equal(ext, '.jpg'); + + var ext = path.extname(form._uploadPath('fine?foo=bar')); + assert.equal(ext, ''); + + var ext = path.extname(form._uploadPath('super.cr2+dsad')); + assert.equal(ext, '.cr2'); + + var ext = path.extname(form._uploadPath('super.bar')); + assert.equal(ext, '.bar'); + }, +}); + +function makeHeader(filename) { + return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"'; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/tool/record.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/tool/record.js new file mode 100644 index 0000000..9f1cef8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/formidable/tool/record.js @@ -0,0 +1,47 @@ +var http = require('http'); +var fs = require('fs'); +var connections = 0; + +var server = http.createServer(function(req, res) { + var socket = req.socket; + console.log('Request: %s %s -> %s', req.method, req.url, socket.filename); + + req.on('end', function() { + if (req.url !== '/') { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + filename: socket.filename, + })); + return; + } + + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '' + ); + }); +}); + +server.on('connection', function(socket) { + connections++; + + socket.id = connections; + socket.filename = 'connection-' + socket.id + '.http'; + socket.file = fs.createWriteStream(socket.filename); + socket.pipe(socket.file); + + console.log('--> %s', socket.filename); + socket.on('close', function() { + console.log('<-- %s', socket.filename); + }); +}); + +var port = process.env.PORT || 8080; +server.listen(port, function() { + console.log('Recording connections on port %s', port); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Readme.md new file mode 100644 index 0000000..273130d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/Readme.md @@ -0,0 +1,32 @@ + +# node-fresh + + HTTP response freshness testing + +## fresh(req, res) + + Check freshness of `req` and `res` headers. + + When the cache is "fresh" __true__ is returned, + otherwise __false__ is returned to indicate that + the cache is now stale. + +## Example: + +```js +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'luna' }; +fresh(req, res); +// => false + +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'tobi' }; +fresh(req, res); +// => true +``` + +## Installation + +``` +$ npm install fresh +``` \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/index.js new file mode 100644 index 0000000..b2f4d41 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/index.js @@ -0,0 +1,49 @@ + +/** + * Expose `fresh()`. + */ + +module.exports = fresh; + +/** + * Check freshness of `req` and `res` headers. + * + * When the cache is "fresh" __true__ is returned, + * otherwise __false__ is returned to indicate that + * the cache is now stale. + * + * @param {Object} req + * @param {Object} res + * @return {Boolean} + * @api public + */ + +function fresh(req, res) { + // defaults + var etagMatches = true; + var notModified = true; + + // fields + var modifiedSince = req['if-modified-since']; + var noneMatch = req['if-none-match']; + var lastModified = res['last-modified']; + var etag = res['etag']; + + // unconditional request + if (!modifiedSince && !noneMatch) return false; + + // parse if-none-match + if (noneMatch) noneMatch = noneMatch.split(/ *, */); + + // if-none-match + if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0]; + + // if-modified-since + if (modifiedSince) { + modifiedSince = new Date(modifiedSince); + lastModified = new Date(lastModified); + notModified = lastModified <= modifiedSince; + } + + return !! (etagMatches && notModified); +} \ No newline at end of file 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 new file mode 100644 index 0000000..d9fddb2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/fresh/package.json @@ -0,0 +1,20 @@ +{ + "name": "fresh", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "HTTP response freshness testing", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/History.md new file mode 100644 index 0000000..c8aa68f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/History.md @@ -0,0 +1,5 @@ + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Readme.md new file mode 100644 index 0000000..1cdd68a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/Readme.md @@ -0,0 +1,29 @@ + +# pause + + Pause streams... + +## License + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/index.js new file mode 100644 index 0000000..1b7b379 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/index.js @@ -0,0 +1,29 @@ + +module.exports = function(obj){ + var onData + , onEnd + , events = []; + + // buffer data + obj.on('data', onData = function(data, encoding){ + events.push(['data', data, encoding]); + }); + + // buffer end + obj.on('end', onEnd = function(data, encoding){ + events.push(['end', data, encoding]); + }); + + return { + end: function(){ + obj.removeListener('data', onData); + obj.removeListener('end', onEnd); + }, + resume: function(){ + this.end(); + for (var i = 0, len = events.length; i < len; ++i) { + obj.emit.apply(obj, events[i]); + } + } + }; +}; \ No newline at end of file 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 new file mode 100644 index 0000000..73cfe40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/pause/package.json @@ -0,0 +1,20 @@ +{ + "name": "pause", + "version": "0.0.1", + "description": "Pause streams...", + "keywords": [], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "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/.gitmodules b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.travis.yml new file mode 100644 index 0000000..2c0a8f6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.4 \ No newline at end of file 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 new file mode 100644 index 0000000..1feef45 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/History.md @@ -0,0 +1,83 @@ + +0.5.1 / 2012-09-18 +================== + + * fix encoded `=`. Closes #43 + +0.5.0 / 2012-05-04 +================== + + * Added component support + +0.4.2 / 2012-02-08 +================== + + * Fixed: ensure objects are created when appropriate not arrays [aheckmann] + +0.4.1 / 2012-01-26 +================== + + * Fixed stringify()ing numbers. Closes #23 + +0.4.0 / 2011-11-21 +================== + + * Allow parsing of an existing object (for `bodyParser()`) [jackyz] + * Replaced expresso with mocha + +0.3.2 / 2011-11-08 +================== + + * Fixed global variable leak + +0.3.1 / 2011-08-17 +================== + + * Added `try/catch` around malformed uri components + * Add test coverage for Array native method bleed-though + +0.3.0 / 2011-07-19 +================== + + * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart] + +0.2.0 / 2011-06-29 +================== + + * Added `qs.stringify()` [Cory Forsyth] + +0.1.0 / 2011-04-13 +================== + + * Added jQuery-ish array support + +0.0.7 / 2011-03-13 +================== + + * Fixed; handle empty string and `== null` in `qs.parse()` [dmit] + allows for convenient `qs.parse(url.parse(str).query)` + +0.0.6 / 2011-02-14 +================== + + * Fixed; support for implicit arrays + +0.0.4 / 2011-02-09 +================== + + * Fixed `+` as a space + +0.0.3 / 2011-02-08 +================== + + * Fixed case when right-hand value contains "]" + +0.0.2 / 2011-02-07 +================== + + * Fixed "=" presence in key + +0.0.1 / 2011-02-07 +================== + + * Initial release \ No newline at end of file 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 new file mode 100644 index 0000000..0a21cf7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Makefile @@ -0,0 +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 \ + --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 new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/benchmark.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/benchmark.js new file mode 100644 index 0000000..97e2c93 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/benchmark.js @@ -0,0 +1,17 @@ + +var qs = require('./'); + +var times = 100000 + , start = new Date + , n = times; + +console.log('times: %d', times); + +while (n--) qs.parse('foo=bar'); +console.log('simple: %dms', new Date - start); + +var start = new Date + , n = times; + +while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log('nested: %dms', new Date - start); \ No newline at end of file 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/examples.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/examples.js new file mode 100644 index 0000000..27617b7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/examples.js @@ -0,0 +1,51 @@ + +/** + * Module dependencies. + */ + +var qs = require('./'); + +var obj = qs.parse('foo'); +console.log(obj) + +var obj = qs.parse('foo=bar=baz'); +console.log(obj) + +var obj = qs.parse('users[]'); +console.log(obj) + +var obj = qs.parse('name=tj&email=tj@vision-media.ca'); +console.log(obj) + +var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('a=a&a=b&a=c'); +console.log(obj) + +var obj = qs.parse('user[tj]=tj&user[tj]=TJ'); +console.log(obj) + +var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[1]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[foo]=TJ'); +console.log(obj) + +var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}); +console.log(str); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/index.js new file mode 100644 index 0000000..d177d20 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/querystring'); \ 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 new file mode 100644 index 0000000..d3689bb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/lib/querystring.js @@ -0,0 +1,262 @@ + +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = {}; + var t = {}; + for (var i in parent[key]) t[i] = parent[key][i]; + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (Array.isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (Array.isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[Object.keys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~part.indexOf(']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~key.indexOf(']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && Array.isArray(parent.base)) { + var t = {}; + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + Object.keys(obj).forEach(function(name){ + merge(ret, name, obj[name]); + }); + return ret.base; +} + +/** + * Parse the given str. + */ + +function parseString(str){ + return String(str) + .split('&') + .reduce(function(ret, pair){ + var eql = pair.indexOf('=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(val.indexOf('=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + + return merge(ret, decode(key), decode(val)); + }, { base: {} }).base; +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (Array.isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + 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; + } +} + +/** + * 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 new file mode 100644 index 0000000..233d5e4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/connect/node_modules/qs/package.json @@ -0,0 +1,36 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.5.1", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "component": { + "scripts": { + "querystring": "querystring.js" + } + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <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 + + +

    DEFLATE Test Page

    +

    Enter text into the first text box to encode it, or enter base64 encoded deflate-encoded text into the second to decode

    +
    +
    Inflated + Base64-Decoded (Original Text):
    +
    +
    Deflated + Base64-Encoded (Compressed Output):
    +
    +
    + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/main.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/main.js new file mode 100644 index 0000000..5ff21d7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/main.js @@ -0,0 +1,46 @@ +(function () { + 'use strict'; + + var inflate = require('../lib/rawinflate.js'), + deflate = require('../lib/rawdeflate.js'), + ender = require('ender'); + + ender.domReady(function () { + ender('#inflated').bind('keyup', function () { + var self = this, dst = ender('#deflated'); + + setTimeout(function(){ + var arr, + str; + + arr = Array.prototype.map.call(self.value, function (char) { + return char.charCodeAt(0); + }); + + str = deflate(arr).map(function (byte) { + return String.fromCharCode(byte); + }).join(''); + + dst.val(btoa(str)); + },0); + }); + ender('#deflated').bind('keyup', function () { + var self = this, dst = ender('#inflated'); + + setTimeout(function(){ + var str, + arr; + + arr = Array.prototype.map.call(atob(self.value), function (char) { + return char.charCodeAt(0); + }); + + str = inflate(arr).map(function (byte) { + return String.fromCharCode(byte); + }).join(''); + + dst.val(str); + }, 0); + }); + }); +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/package.json new file mode 100644 index 0000000..1ed4f98 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/examples/package.json @@ -0,0 +1,11 @@ +{ + "author": "T. Jameson Little", + "name": "test", + "version": "0.1.0", + "main": "./main.js", + "repository": {}, + "engines": {}, + "dependencies": { + "jeesh": "*" + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/index.js new file mode 100644 index 0000000..72519f6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/index.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + module.exports = { + 'inflate': require('./lib/rawinflate.js'), + 'deflate': require('./lib/rawdeflate.js') + }; +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawdeflate.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawdeflate.js new file mode 100644 index 0000000..12516cd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawdeflate.js @@ -0,0 +1,1696 @@ +/* + * $Id: rawdeflate.js,v 0.3 2009/03/01 19:05:05 dankogai Exp dankogai $ + * + * Original: + * http://www.onicos.com/staff/iz/amuse/javascript/expert/deflate.txt + */ + +/* Copyright (C) 1999 Masanao Izumo + * Version: 1.0.1 + * LastModified: Dec 25 1999 + */ + +/* Interface: + * data = deflate(src); + */ + +(function () { + /* constant parameters */ + var WSIZE = 32768, // Sliding Window size + STORED_BLOCK = 0, + STATIC_TREES = 1, + DYN_TREES = 2, + + /* for deflate */ + DEFAULT_LEVEL = 6, + FULL_SEARCH = false, + INBUFSIZ = 32768, // Input buffer size + //INBUF_EXTRA = 64, // Extra buffer + OUTBUFSIZ = 1024 * 8, + window_size = 2 * WSIZE, + MIN_MATCH = 3, + MAX_MATCH = 258, + BITS = 16, + // for SMALL_MEM + LIT_BUFSIZE = 0x2000, +// HASH_BITS = 13, + //for MEDIUM_MEM + // LIT_BUFSIZE = 0x4000, + // HASH_BITS = 14, + // for BIG_MEM + // LIT_BUFSIZE = 0x8000, + HASH_BITS = 15, + DIST_BUFSIZE = LIT_BUFSIZE, + HASH_SIZE = 1 << HASH_BITS, + HASH_MASK = HASH_SIZE - 1, + WMASK = WSIZE - 1, + NIL = 0, // Tail of hash chains + TOO_FAR = 4096, + MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1, + MAX_DIST = WSIZE - MIN_LOOKAHEAD, + SMALLEST = 1, + MAX_BITS = 15, + MAX_BL_BITS = 7, + LENGTH_CODES = 29, + LITERALS = 256, + END_BLOCK = 256, + L_CODES = LITERALS + 1 + LENGTH_CODES, + D_CODES = 30, + BL_CODES = 19, + REP_3_6 = 16, + REPZ_3_10 = 17, + REPZ_11_138 = 18, + HEAP_SIZE = 2 * L_CODES + 1, + H_SHIFT = parseInt((HASH_BITS + MIN_MATCH - 1) / MIN_MATCH, 10), + + /* variables */ + free_queue, + qhead, + qtail, + initflag, + outbuf = null, + outcnt, + outoff, + complete, + window, + d_buf, + l_buf, + prev, + bi_buf, + bi_valid, + block_start, + ins_h, + hash_head, + prev_match, + match_available, + match_length, + prev_length, + strstart, + match_start, + eofile, + lookahead, + max_chain_length, + max_lazy_match, + compr_level, + good_match, + nice_match, + dyn_ltree, + dyn_dtree, + static_ltree, + static_dtree, + bl_tree, + l_desc, + d_desc, + bl_desc, + bl_count, + heap, + heap_len, + heap_max, + depth, + length_code, + dist_code, + base_length, + base_dist, + flag_buf, + last_lit, + last_dist, + last_flags, + flags, + flag_bit, + opt_len, + static_len, + deflate_data, + deflate_pos; + + if (LIT_BUFSIZE > INBUFSIZ) { + console.error("error: INBUFSIZ is too small"); + } + if ((WSIZE << 1) > (1 << BITS)) { + console.error("error: WSIZE is too large"); + } + if (HASH_BITS > BITS - 1) { + console.error("error: HASH_BITS is too large"); + } + if (HASH_BITS < 8 || MAX_MATCH !== 258) { + console.error("error: Code too clever"); + } + + /* objects (deflate) */ + + function DeflateCT() { + this.fc = 0; // frequency count or bit string + this.dl = 0; // father node in Huffman tree or length of bit string + } + + function DeflateTreeDesc() { + this.dyn_tree = null; // the dynamic tree + this.static_tree = null; // corresponding static tree or NULL + this.extra_bits = null; // extra bits for each code or NULL + this.extra_base = 0; // base index for extra_bits + this.elems = 0; // max number of elements in the tree + this.max_length = 0; // max bit length for the codes + this.max_code = 0; // largest code with non zero frequency + } + + /* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + function DeflateConfiguration(a, b, c, d) { + this.good_length = a; // reduce lazy search above this match length + this.max_lazy = b; // do not perform lazy search above this match length + this.nice_length = c; // quit search above this match length + this.max_chain = d; + } + + function DeflateBuffer() { + this.next = null; + this.len = 0; + this.ptr = []; // new Array(OUTBUFSIZ); // ptr.length is never read + this.off = 0; + } + + /* constant tables */ + var extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; + var extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; + var extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]; + var bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + var configuration_table = [ + new DeflateConfiguration(0, 0, 0, 0), + new DeflateConfiguration(4, 4, 8, 4), + new DeflateConfiguration(4, 5, 16, 8), + new DeflateConfiguration(4, 6, 32, 32), + new DeflateConfiguration(4, 4, 16, 16), + new DeflateConfiguration(8, 16, 32, 32), + new DeflateConfiguration(8, 16, 128, 128), + new DeflateConfiguration(8, 32, 128, 256), + new DeflateConfiguration(32, 128, 258, 1024), + new DeflateConfiguration(32, 258, 258, 4096) + ]; + + + /* routines (deflate) */ + + function deflate_start(level) { + var i; + + if (!level) { + level = DEFAULT_LEVEL; + } else if (level < 1) { + level = 1; + } else if (level > 9) { + level = 9; + } + + compr_level = level; + initflag = false; + eofile = false; + if (outbuf !== null) { + return; + } + + free_queue = qhead = qtail = null; + outbuf = []; // new Array(OUTBUFSIZ); // outbuf.length never called + window = []; // new Array(window_size); // window.length never called + d_buf = []; // new Array(DIST_BUFSIZE); // d_buf.length never called + l_buf = []; // new Array(INBUFSIZ + INBUF_EXTRA); // l_buf.length never called + prev = []; // new Array(1 << BITS); // prev.length never called + + dyn_ltree = []; + for (i = 0; i < HEAP_SIZE; i++) { + dyn_ltree[i] = new DeflateCT(); + } + dyn_dtree = []; + for (i = 0; i < 2 * D_CODES + 1; i++) { + dyn_dtree[i] = new DeflateCT(); + } + static_ltree = []; + for (i = 0; i < L_CODES + 2; i++) { + static_ltree[i] = new DeflateCT(); + } + static_dtree = []; + for (i = 0; i < D_CODES; i++) { + static_dtree[i] = new DeflateCT(); + } + bl_tree = []; + for (i = 0; i < 2 * BL_CODES + 1; i++) { + bl_tree[i] = new DeflateCT(); + } + l_desc = new DeflateTreeDesc(); + d_desc = new DeflateTreeDesc(); + bl_desc = new DeflateTreeDesc(); + bl_count = []; // new Array(MAX_BITS+1); // bl_count.length never called + heap = []; // new Array(2*L_CODES+1); // heap.length never called + depth = []; // new Array(2*L_CODES+1); // depth.length never called + length_code = []; // new Array(MAX_MATCH-MIN_MATCH+1); // length_code.length never called + dist_code = []; // new Array(512); // dist_code.length never called + base_length = []; // new Array(LENGTH_CODES); // base_length.length never called + base_dist = []; // new Array(D_CODES); // base_dist.length never called + flag_buf = []; // new Array(parseInt(LIT_BUFSIZE / 8, 10)); // flag_buf.length never called + } + + function deflate_end() { + free_queue = qhead = qtail = null; + outbuf = null; + window = null; + d_buf = null; + l_buf = null; + prev = null; + dyn_ltree = null; + dyn_dtree = null; + static_ltree = null; + static_dtree = null; + bl_tree = null; + l_desc = null; + d_desc = null; + bl_desc = null; + bl_count = null; + heap = null; + depth = null; + length_code = null; + dist_code = null; + base_length = null; + base_dist = null; + flag_buf = null; + } + + function reuse_queue(p) { + p.next = free_queue; + free_queue = p; + } + + function new_queue() { + var p; + + if (free_queue !== null) { + p = free_queue; + free_queue = free_queue.next; + } else { + p = new DeflateBuffer(); + } + p.next = null; + p.len = p.off = 0; + + return p; + } + + function head1(i) { + return prev[WSIZE + i]; + } + + function head2(i, val) { + return (prev[WSIZE + i] = val); + } + + /* put_byte is used for the compressed output, put_ubyte for the + * uncompressed output. However unlzw() uses window for its + * suffix table instead of its output buffer, so it does not use put_ubyte + * (to be cleaned up). + */ + function put_byte(c) { + outbuf[outoff + outcnt++] = c; + if (outoff + outcnt === OUTBUFSIZ) { + qoutbuf(); + } + } + + /* Output a 16 bit value, lsb first */ + function put_short(w) { + w &= 0xffff; + if (outoff + outcnt < OUTBUFSIZ - 2) { + outbuf[outoff + outcnt++] = (w & 0xff); + outbuf[outoff + outcnt++] = (w >>> 8); + } else { + put_byte(w & 0xff); + put_byte(w >>> 8); + } + } + + /* ========================================================================== + * Insert string s in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of s are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ + function INSERT_STRING() { + ins_h = ((ins_h << H_SHIFT) ^ (window[strstart + MIN_MATCH - 1] & 0xff)) & HASH_MASK; + hash_head = head1(ins_h); + prev[strstart & WMASK] = hash_head; + head2(ins_h, strstart); + } + + /* Send a code of the given tree. c and tree must not have side effects */ + function SEND_CODE(c, tree) { + send_bits(tree[c].fc, tree[c].dl); + } + + /* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + function D_CODE(dist) { + return (dist < 256 ? dist_code[dist] : dist_code[256 + (dist >> 7)]) & 0xff; + } + + /* ========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + function SMALLER(tree, n, m) { + return tree[n].fc < tree[m].fc || (tree[n].fc === tree[m].fc && depth[n] <= depth[m]); + } + + /* ========================================================================== + * read string data + */ + function read_buff(buff, offset, n) { + var i; + for (i = 0; i < n && deflate_pos < deflate_data.length; i++) { + buff[offset + i] = deflate_data[deflate_pos++] & 0xff; + } + return i; + } + + /* ========================================================================== + * Initialize the "longest match" routines for a new file + */ + function lm_init() { + var j; + + // Initialize the hash table. */ + for (j = 0; j < HASH_SIZE; j++) { + // head2(j, NIL); + prev[WSIZE + j] = 0; + } + // prev will be initialized on the fly */ + + // Set the default configuration parameters: + max_lazy_match = configuration_table[compr_level].max_lazy; + good_match = configuration_table[compr_level].good_length; + if (!FULL_SEARCH) { + nice_match = configuration_table[compr_level].nice_length; + } + max_chain_length = configuration_table[compr_level].max_chain; + + strstart = 0; + block_start = 0; + + lookahead = read_buff(window, 0, 2 * WSIZE); + if (lookahead <= 0) { + eofile = true; + lookahead = 0; + return; + } + eofile = false; + // Make sure that we always have enough lookahead. This is important + // if input comes from a device such as a tty. + while (lookahead < MIN_LOOKAHEAD && !eofile) { + fill_window(); + } + + // If lookahead < MIN_MATCH, ins_h is garbage, but this is + // not important since only literal bytes will be emitted. + ins_h = 0; + for (j = 0; j < MIN_MATCH - 1; j++) { + // UPDATE_HASH(ins_h, window[j]); + ins_h = ((ins_h << H_SHIFT) ^ (window[j] & 0xff)) & HASH_MASK; + } + } + + /* ========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + */ + function longest_match(cur_match) { + var chain_length = max_chain_length; // max hash chain length + var scanp = strstart; // current string + var matchp; // matched string + var len; // length of current match + var best_len = prev_length; // best match length so far + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + var limit = (strstart > MAX_DIST ? strstart - MAX_DIST : NIL); + + var strendp = strstart + MAX_MATCH; + var scan_end1 = window[scanp + best_len - 1]; + var scan_end = window[scanp + best_len]; + + var i, broke; + + // Do not waste too much time if we already have a good match: */ + if (prev_length >= good_match) { + chain_length >>= 2; + } + + // Assert(encoder->strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); + + do { + // Assert(cur_match < encoder->strstart, "no future"); + matchp = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[matchp + best_len] !== scan_end || + window[matchp + best_len - 1] !== scan_end1 || + window[matchp] !== window[scanp] || + window[++matchp] !== window[scanp + 1]) { + continue; + } + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scanp += 2; + matchp++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + while (scanp < strendp) { + broke = false; + for (i = 0; i < 8; i += 1) { + scanp += 1; + matchp += 1; + if (window[scanp] !== window[matchp]) { + broke = true; + break; + } + } + + if (broke) { + break; + } + } + + len = MAX_MATCH - (strendp - scanp); + scanp = strendp - MAX_MATCH; + + if (len > best_len) { + match_start = cur_match; + best_len = len; + if (FULL_SEARCH) { + if (len >= MAX_MATCH) { + break; + } + } else { + if (len >= nice_match) { + break; + } + } + + scan_end1 = window[scanp + best_len - 1]; + scan_end = window[scanp + best_len]; + } + } while ((cur_match = prev[cur_match & WMASK]) > limit && --chain_length !== 0); + + return best_len; + } + + /* ========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead, and sets eofile if end of input file. + * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 + * OUT assertions: at least one byte has been read, or eofile is set; + * file reads are performed for at least two bytes (required for the + * translate_eol option). + */ + function fill_window() { + var n, m; + + // Amount of free space at the end of the window. + var more = window_size - lookahead - strstart; + + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + if (more === -1) { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + } else if (strstart >= WSIZE + MAX_DIST) { + // By the IN assertion, the window is not empty so we can't confuse + // more == 0 with more == 64K on a 16 bit machine. + // Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); + + // System.arraycopy(window, WSIZE, window, 0, WSIZE); + for (n = 0; n < WSIZE; n++) { + window[n] = window[n + WSIZE]; + } + + match_start -= WSIZE; + strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ + block_start -= WSIZE; + + for (n = 0; n < HASH_SIZE; n++) { + m = head1(n); + head2(n, m >= WSIZE ? m - WSIZE : NIL); + } + for (n = 0; n < WSIZE; n++) { + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + m = prev[n]; + prev[n] = (m >= WSIZE ? m - WSIZE : NIL); + } + more += WSIZE; + } + // At this point, more >= 2 + if (!eofile) { + n = read_buff(window, strstart + lookahead, more); + if (n <= 0) { + eofile = true; + } else { + lookahead += n; + } + } + } + + /* ========================================================================== + * Processes a new input file and return its compressed length. This + * function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + function deflate_fast() { + while (lookahead !== 0 && qhead === null) { + var flush; // set if current block must be flushed + + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + INSERT_STRING(); + + // Find the longest match, discarding those <= prev_length. + // At this point we have always match_length < MIN_MATCH + if (hash_head !== NIL && strstart - hash_head <= MAX_DIST) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + match_length = longest_match(hash_head); + // longest_match() sets match_start */ + if (match_length > lookahead) { + match_length = lookahead; + } + } + if (match_length >= MIN_MATCH) { + // check_match(strstart, match_start, match_length); + + flush = ct_tally(strstart - match_start, match_length - MIN_MATCH); + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if (match_length <= max_lazy_match) { + match_length--; // string at strstart already in hash table + do { + strstart++; + INSERT_STRING(); + // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + // these bytes are garbage, but it does not matter since + // the next lookahead bytes will be emitted as literals. + } while (--match_length !== 0); + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart] & 0xff; + // UPDATE_HASH(ins_h, window[strstart + 1]); + ins_h = ((ins_h << H_SHIFT) ^ (window[strstart + 1] & 0xff)) & HASH_MASK; + + //#if MIN_MATCH !== 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + + } + } else { + // No match, output a literal byte */ + flush = ct_tally(0, window[strstart] & 0xff); + lookahead--; + strstart++; + } + if (flush) { + flush_block(0); + block_start = strstart; + } + + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + while (lookahead < MIN_LOOKAHEAD && !eofile) { + fill_window(); + } + } + } + + function deflate_better() { + // Process the input block. */ + while (lookahead !== 0 && qhead === null) { + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + INSERT_STRING(); + + // Find the longest match, discarding those <= prev_length. + prev_length = match_length; + prev_match = match_start; + match_length = MIN_MATCH - 1; + + if (hash_head !== NIL && prev_length < max_lazy_match && strstart - hash_head <= MAX_DIST) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + match_length = longest_match(hash_head); + // longest_match() sets match_start */ + if (match_length > lookahead) { + match_length = lookahead; + } + + // Ignore a length 3 match if it is too distant: */ + if (match_length === MIN_MATCH && strstart - match_start > TOO_FAR) { + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length--; + } + } + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if (prev_length >= MIN_MATCH && match_length <= prev_length) { + var flush; // set if current block must be flushed + + // check_match(strstart - 1, prev_match, prev_length); + flush = ct_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. + lookahead -= prev_length - 1; + prev_length -= 2; + do { + strstart++; + INSERT_STRING(); + // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + // these bytes are garbage, but it does not matter since the + // next lookahead bytes will always be emitted as literals. + } while (--prev_length !== 0); + match_available = false; + match_length = MIN_MATCH - 1; + strstart++; + if (flush) { + flush_block(0); + block_start = strstart; + } + } else if (match_available) { + // If there was no match at the previous position, output a + // single literal. If there was a match but the current match + // is longer, truncate the previous match to a single literal. + if (ct_tally(0, window[strstart - 1] & 0xff)) { + flush_block(0); + block_start = strstart; + } + strstart++; + lookahead--; + } else { + // There is no previous match to compare with, wait for + // the next step to decide. + match_available = true; + strstart++; + lookahead--; + } + + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + while (lookahead < MIN_LOOKAHEAD && !eofile) { + fill_window(); + } + } + } + + function init_deflate() { + if (eofile) { + return; + } + bi_buf = 0; + bi_valid = 0; + ct_init(); + lm_init(); + + qhead = null; + outcnt = 0; + outoff = 0; + + if (compr_level <= 3) { + prev_length = MIN_MATCH - 1; + match_length = 0; + } else { + match_length = MIN_MATCH - 1; + match_available = false; + } + + complete = false; + } + + /* ========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + function deflate_internal(buff, off, buff_size) { + var n; + + if (!initflag) { + init_deflate(); + initflag = true; + if (lookahead === 0) { // empty + complete = true; + return 0; + } + } + + n = qcopy(buff, off, buff_size); + if (n === buff_size) { + return buff_size; + } + + if (complete) { + return n; + } + + if (compr_level <= 3) { + // optimized for speed + deflate_fast(); + } else { + deflate_better(); + } + + if (lookahead === 0) { + if (match_available) { + ct_tally(0, window[strstart - 1] & 0xff); + } + flush_block(1); + complete = true; + } + + return n + qcopy(buff, n + off, buff_size - n); + } + + function qcopy(buff, off, buff_size) { + var n, i, j; + + n = 0; + while (qhead !== null && n < buff_size) { + i = buff_size - n; + if (i > qhead.len) { + i = qhead.len; + } + // System.arraycopy(qhead.ptr, qhead.off, buff, off + n, i); + for (j = 0; j < i; j++) { + buff[off + n + j] = qhead.ptr[qhead.off + j]; + } + + qhead.off += i; + qhead.len -= i; + n += i; + if (qhead.len === 0) { + var p; + p = qhead; + qhead = qhead.next; + reuse_queue(p); + } + } + + if (n === buff_size) { + return n; + } + + if (outoff < outcnt) { + i = buff_size - n; + if (i > outcnt - outoff) { + i = outcnt - outoff; + } + // System.arraycopy(outbuf, outoff, buff, off + n, i); + for (j = 0; j < i; j++) { + buff[off + n + j] = outbuf[outoff + j]; + } + outoff += i; + n += i; + if (outcnt === outoff) { + outcnt = outoff = 0; + } + } + return n; + } + + /* ========================================================================== + * Allocate the match buffer, initialize the various tables and save the + * location of the internal file attribute (ascii/binary) and method + * (DEFLATE/STORE). + */ + function ct_init() { + var n; // iterates over tree elements + var bits; // bit counter + var length; // length value + var code; // code value + var dist; // distance index + + if (static_dtree[0].dl !== 0) { + return; // ct_init already called + } + + l_desc.dyn_tree = dyn_ltree; + l_desc.static_tree = static_ltree; + l_desc.extra_bits = extra_lbits; + l_desc.extra_base = LITERALS + 1; + l_desc.elems = L_CODES; + l_desc.max_length = MAX_BITS; + l_desc.max_code = 0; + + d_desc.dyn_tree = dyn_dtree; + d_desc.static_tree = static_dtree; + d_desc.extra_bits = extra_dbits; + d_desc.extra_base = 0; + d_desc.elems = D_CODES; + d_desc.max_length = MAX_BITS; + d_desc.max_code = 0; + + bl_desc.dyn_tree = bl_tree; + bl_desc.static_tree = null; + bl_desc.extra_bits = extra_blbits; + bl_desc.extra_base = 0; + bl_desc.elems = BL_CODES; + bl_desc.max_length = MAX_BL_BITS; + bl_desc.max_code = 0; + + // Initialize the mapping length (0..255) -> length code (0..28) + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < (1 << extra_lbits[code]); n++) { + length_code[length++] = code; + } + } + // Assert (length === 256, "ct_init: length !== 256"); + + // Note that the length 255 (match length 258) can be represented + // in two different ways: code 284 + 5 bits or code 285, so we + // overwrite length_code[255] to use the best encoding: + length_code[length - 1] = code; + + // Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1 << extra_dbits[code]); n++) { + dist_code[dist++] = code; + } + } + // Assert (dist === 256, "ct_init: dist !== 256"); + // from now on, all distances are divided by 128 + for (dist >>= 7; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { + dist_code[256 + dist++] = code; + } + } + // Assert (dist === 256, "ct_init: 256+dist !== 512"); + + // Construct the codes of the static literal tree + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + n = 0; + while (n <= 143) { + static_ltree[n++].dl = 8; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n++].dl = 9; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n++].dl = 7; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n++].dl = 8; + bl_count[8]++; + } + // Codes 286 and 287 do not exist, but we must include them in the + // tree construction to get a canonical Huffman tree (longest code + // all ones) + gen_codes(static_ltree, L_CODES + 1); + + // The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].dl = 5; + static_dtree[n].fc = bi_reverse(n, 5); + } + + // Initialize the first block of the first file: + init_block(); + } + + /* ========================================================================== + * Initialize a new block. + */ + function init_block() { + var n; // iterates over tree elements + + // Initialize the trees. + for (n = 0; n < L_CODES; n++) { + dyn_ltree[n].fc = 0; + } + for (n = 0; n < D_CODES; n++) { + dyn_dtree[n].fc = 0; + } + for (n = 0; n < BL_CODES; n++) { + bl_tree[n].fc = 0; + } + + dyn_ltree[END_BLOCK].fc = 1; + opt_len = static_len = 0; + last_lit = last_dist = last_flags = 0; + flags = 0; + flag_bit = 1; + } + + /* ========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + * + * @param tree- tree to restore + * @param k- node to move down + */ + function pqdownheap(tree, k) { + var v = heap[k], + j = k << 1; // left son of k + + while (j <= heap_len) { + // Set j to the smallest of the two sons: + if (j < heap_len && SMALLER(tree, heap[j + 1], heap[j])) { + j++; + } + + // Exit if v is smaller than both sons + if (SMALLER(tree, v, heap[j])) { + break; + } + + // Exchange v with the smallest son + heap[k] = heap[j]; + k = j; + + // And continue down the tree, setting j to the left son of k + j <<= 1; + } + heap[k] = v; + } + + /* ========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + function gen_bitlen(desc) { // the tree descriptor + var tree = desc.dyn_tree; + var extra = desc.extra_bits; + var base = desc.extra_base; + var max_code = desc.max_code; + var max_length = desc.max_length; + var stree = desc.static_tree; + var h; // heap index + var n, m; // iterate over the tree elements + var bits; // bit length + var xbits; // extra bits + var f; // frequency + var overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[heap[heap_max]].dl = 0; // root of the heap + + for (h = heap_max + 1; h < HEAP_SIZE; h++) { + n = heap[h]; + bits = tree[tree[n].dl].dl + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n].dl = bits; + // We overwrite tree[n].dl which is no longer needed + + if (n > max_code) { + continue; // not a leaf node + } + + bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n].fc; + opt_len += f * (bits + xbits); + if (stree !== null) { + static_len += f * (stree[n].dl + xbits); + } + } + if (overflow === 0) { + return; + } + + // This happens for example on obj2 and pic of the Calgary corpus + + // Find the first bit length which could increase: + do { + bits = max_length - 1; + while (bl_count[bits] === 0) { + bits--; + } + bl_count[bits]--; // move one leaf down the tree + bl_count[bits + 1] += 2; // move one overflow item as its brother + bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } while (overflow > 0); + + // Now recompute all bit lengths, scanning in increasing frequency. + // h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + // lengths instead of fixing only the wrong ones. This idea is taken + // from 'ar' written by Haruhiko Okumura.) + for (bits = max_length; bits !== 0; bits--) { + n = bl_count[bits]; + while (n !== 0) { + m = heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m].dl !== bits) { + opt_len += (bits - tree[m].dl) * tree[m].fc; + tree[m].fc = bits; + } + n--; + } + } + } + + /* ========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + * @param tree- the tree to decorate + * @param max_code- largest code with non-zero frequency + */ + function gen_codes(tree, max_code) { + var next_code = []; // new Array(MAX_BITS + 1); // next code value for each bit length + var code = 0; // running code value + var bits; // bit index + var n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + for (bits = 1; bits <= MAX_BITS; bits++) { + code = ((code + bl_count[bits - 1]) << 1); + next_code[bits] = code; + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + // Assert (code + encoder->bl_count[MAX_BITS]-1 === (1<> 1; n >= 1; n--) { + pqdownheap(tree, n); + } + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + do { + n = heap[SMALLEST]; + heap[SMALLEST] = heap[heap_len--]; + pqdownheap(tree, SMALLEST); + + m = heap[SMALLEST]; // m = node of next least frequency + + // keep the nodes sorted by frequency + heap[--heap_max] = n; + heap[--heap_max] = m; + + // Create a new node father of n and m + tree[node].fc = tree[n].fc + tree[m].fc; + // depth[node] = (char)(MAX(depth[n], depth[m]) + 1); + if (depth[n] > depth[m] + 1) { + depth[node] = depth[n]; + } else { + depth[node] = depth[m] + 1; + } + tree[n].dl = tree[m].dl = node; + + // and insert the new node in the heap + heap[SMALLEST] = node++; + pqdownheap(tree, SMALLEST); + + } while (heap_len >= 2); + + heap[--heap_max] = heap[SMALLEST]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + gen_bitlen(desc); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code); + } + + /* ========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. Updates opt_len to take into account the repeat + * counts. (The contribution of the bit length codes will be added later + * during the construction of bl_tree.) + * + * @param tree- the tree to be scanned + * @param max_code- and its largest code of non zero frequency + */ + function scan_tree(tree, max_code) { + var n, // iterates over all tree elements + prevlen = -1, // last emitted length + curlen, // length of current code + nextlen = tree[0].dl, // length of next code + count = 0, // repeat count of the current code + max_count = 7, // max repeat count + min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[max_code + 1].dl = 0xffff; // guard + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + bl_tree[curlen].fc += count; + } else if (curlen !== 0) { + if (curlen !== prevlen) { + bl_tree[curlen].fc++; + } + bl_tree[REP_3_6].fc++; + } else if (count <= 10) { + bl_tree[REPZ_3_10].fc++; + } else { + bl_tree[REPZ_11_138].fc++; + } + count = 0; prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + + /* ========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + * + * @param tree- the tree to be scanned + * @param max_code- and its largest code of non zero frequency + */ + function send_tree(tree, max_code) { + var n; // iterates over all tree elements + var prevlen = -1; // last emitted length + var curlen; // length of current code + var nextlen = tree[0].dl; // length of next code + var count = 0; // repeat count of the current code + var max_count = 7; // max repeat count + var min_count = 4; // min repeat count + + // tree[max_code+1].dl = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + do { + SEND_CODE(curlen, bl_tree); + } while (--count !== 0); + } else if (curlen !== 0) { + if (curlen !== prevlen) { + SEND_CODE(curlen, bl_tree); + count--; + } + // Assert(count >= 3 && count <= 6, " 3_6?"); + SEND_CODE(REP_3_6, bl_tree); + send_bits(count - 3, 2); + } else if (count <= 10) { + SEND_CODE(REPZ_3_10, bl_tree); + send_bits(count - 3, 3); + } else { + SEND_CODE(REPZ_11_138, bl_tree); + send_bits(count - 11, 7); + } + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } + + /* ========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + function build_bl_tree() { + var max_blindex; // index of last bit length code of non zero freq + + // Determine the bit length frequencies for literal and distance trees + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); + + // Build the bit length tree: + build_tree(bl_desc); + // opt_len now includes the length of the tree representations, except + // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + + // Determine the number of bit length codes to send. The pkzip format + // requires that at least 4 bit length codes be sent. (appnote.txt says + // 3 but the actual value used is 4.) + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (bl_tree[bl_order[max_blindex]].dl !== 0) { + break; + } + } + // Update opt_len to include the bit length tree and counts */ + opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + // Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + return max_blindex; + } + + /* ========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + function send_all_trees(lcodes, dcodes, blcodes) { // number of codes for each tree + var rank; // index in bl_order + + // Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + // Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); + // Tracev((stderr, "\nbl counts: ")); + send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes - 1, 5); + send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + // Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(bl_tree[bl_order[rank]].dl, 3); + } + + // send the literal tree + send_tree(dyn_ltree, lcodes - 1); + + // send the distance tree + send_tree(dyn_dtree, dcodes - 1); + } + + /* ========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + function flush_block(eof) { // true if this is the last block for a file + var opt_lenb, static_lenb, // opt_len and static_len in bytes + max_blindex, // index of last bit length code of non zero freq + stored_len, // length of input block + i; + + stored_len = strstart - block_start; + flag_buf[last_flags] = flags; // Save the flags for the last 8 items + + // Construct the literal and distance trees + build_tree(l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + build_tree(d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex = build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb = (opt_len + 3 + 7) >> 3; + static_lenb = (static_len + 3 + 7) >> 3; + + // Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", opt_lenb, encoder->opt_len, static_lenb, encoder->static_len, stored_len, encoder->last_lit, encoder->last_dist)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + if (stored_len + 4 <= opt_lenb && block_start >= 0) { // 4: two words for the lengths + // The test buf !== NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ + bi_windup(); /* align on byte boundary */ + put_short(stored_len); + put_short(~stored_len); + + // copy block + /* + p = &window[block_start]; + for (i = 0; i < stored_len; i++) { + put_byte(p[i]); + } + */ + for (i = 0; i < stored_len; i++) { + put_byte(window[block_start + i]); + } + } else if (static_lenb === opt_lenb) { + send_bits((STATIC_TREES << 1) + eof, 3); + compress_block(static_ltree, static_dtree); + } else { + send_bits((DYN_TREES << 1) + eof, 3); + send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); + compress_block(dyn_ltree, dyn_dtree); + } + + init_block(); + + if (eof !== 0) { + bi_windup(); + } + } + + /* ========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + * + * @param dist- distance of matched string + * @param lc- (match length - MIN_MATCH) or unmatched char (if dist === 0) + */ + function ct_tally(dist, lc) { + l_buf[last_lit++] = lc; + if (dist === 0) { + // lc is the unmatched char + dyn_ltree[lc].fc++; + } else { + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + // Assert((ush)dist < (ush)MAX_DIST && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)D_CODE(dist) < (ush)D_CODES, "ct_tally: bad match"); + + dyn_ltree[length_code[lc] + LITERALS + 1].fc++; + dyn_dtree[D_CODE(dist)].fc++; + + d_buf[last_dist++] = dist; + flags |= flag_bit; + } + flag_bit <<= 1; + + // Output the flags if they fill a byte + if ((last_lit & 7) === 0) { + flag_buf[last_flags++] = flags; + flags = 0; + flag_bit = 1; + } + // Try to guess if it is profitable to stop the current block here + if (compr_level > 2 && (last_lit & 0xfff) === 0) { + // Compute an upper bound for the compressed length + var out_length = last_lit * 8; + var in_length = strstart - block_start; + var dcode; + + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += dyn_dtree[dcode].fc * (5 + extra_dbits[dcode]); + } + out_length >>= 3; + // Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", encoder->last_lit, encoder->last_dist, in_length, out_length, 100L - out_length*100L/in_length)); + if (last_dist < parseInt(last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) { + return true; + } + } + return (last_lit === LIT_BUFSIZE - 1 || last_dist === DIST_BUFSIZE); + // We avoid equality with LIT_BUFSIZE because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + /* ========================================================================== + * Send the block data compressed using the given Huffman trees + * + * @param ltree- literal tree + * @param dtree- distance tree + */ + function compress_block(ltree, dtree) { + var dist; // distance of matched string + var lc; // match length or unmatched char (if dist === 0) + var lx = 0; // running index in l_buf + var dx = 0; // running index in d_buf + var fx = 0; // running index in flag_buf + var flag = 0; // current flags + var code; // the code to send + var extra; // number of extra bits to send + + if (last_lit !== 0) { + do { + if ((lx & 7) === 0) { + flag = flag_buf[fx++]; + } + lc = l_buf[lx++] & 0xff; + if ((flag & 1) === 0) { + SEND_CODE(lc, ltree); /* send a literal byte */ + // Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + // Here, lc is the match length - MIN_MATCH + code = length_code[lc]; + SEND_CODE(code + LITERALS + 1, ltree); // send the length code + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist = d_buf[dx++]; + // Here, dist is the match distance - 1 + code = D_CODE(dist); + // Assert (code < D_CODES, "bad d_code"); + + SEND_CODE(code, dtree); // send the distance code + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + flag >>= 1; + } while (lx < last_lit); + } + + SEND_CODE(END_BLOCK, ltree); + } + + /* ========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + * + * @param value- value to send + * @param length- number of bits + */ + var Buf_size = 16; // bit size of bi_buf + function send_bits(value, length) { + // If not enough room in bi_buf, use (valid) bits from bi_buf and + // (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + // unused bits in value. + if (bi_valid > Buf_size - length) { + bi_buf |= (value << bi_valid); + put_short(bi_buf); + bi_buf = (value >> (Buf_size - bi_valid)); + bi_valid += length - Buf_size; + } else { + bi_buf |= value << bi_valid; + bi_valid += length; + } + } + + /* ========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + * + * @param code- the value to invert + * @param len- its bit length + */ + function bi_reverse(code, len) { + var res = 0; + do { + res |= code & 1; + code >>= 1; + res <<= 1; + } while (--len > 0); + return res >> 1; + } + + /* ========================================================================== + * Write out any remaining bits in an incomplete byte. + */ + function bi_windup() { + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte(bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + function qoutbuf() { + var q, i; + if (outcnt !== 0) { + q = new_queue(); + if (qhead === null) { + qhead = qtail = q; + } else { + qtail = qtail.next = q; + } + q.len = outcnt - outoff; + // System.arraycopy(outbuf, outoff, q.ptr, 0, q.len); + for (i = 0; i < q.len; i++) { + q.ptr[i] = outbuf[outoff + i]; + } + outcnt = outoff = 0; + } + } + + function deflate(arr, level) { + var i, j, buff; + + deflate_data = arr; + deflate_pos = 0; + if (typeof level === "undefined") { + level = DEFAULT_LEVEL; + } + deflate_start(level); + + buff = []; + + do { + i = deflate_internal(buff, buff.length, 1024); + } while (i > 0); + + deflate_data = null; // G.C. + return buff; + } + + module.exports = deflate; + module.exports.DEFAULT_LEVEL = DEFAULT_LEVEL; +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawinflate.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawinflate.js new file mode 100644 index 0000000..56f1f10 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/lib/rawinflate.js @@ -0,0 +1,812 @@ +/* + * $Id: rawinflate.js,v 0.2 2009/03/01 18:32:24 dankogai Exp $ + * + * original: + * http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt + */ + +/* Copyright (C) 1999 Masanao Izumo + * Version: 1.0.0.1 + * LastModified: Dec 25 1999 + */ + +/* Interface: + * data = inflate(src); + */ + +(function () { + /* constant parameters */ + var WSIZE = 32768, // Sliding Window size + STORED_BLOCK = 0, + STATIC_TREES = 1, + DYN_TREES = 2, + + /* for inflate */ + lbits = 9, // bits in base literal/length lookup table + dbits = 6, // bits in base distance lookup table + + /* variables (inflate) */ + slide, + wp, // current position in slide + fixed_tl = null, // inflate static + fixed_td, // inflate static + fixed_bl, // inflate static + fixed_bd, // inflate static + bit_buf, // bit buffer + bit_len, // bits in bit buffer + method, + eof, + copy_leng, + copy_dist, + tl, // literal length decoder table + td, // literal distance decoder table + bl, // number of bits decoded by tl + bd, // number of bits decoded by td + + inflate_data, + inflate_pos, + + +/* constant tables (inflate) */ + MASK_BITS = [ + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff + ], + // Tables for deflate from PKZIP's appnote.txt. + // Copy lengths for literal codes 257..285 + cplens = [ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + ], +/* note: see note #13 above about the 258 in this list. */ + // Extra bits for literal codes 257..285 + cplext = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 // 99==invalid + ], + // Copy offsets for distance codes 0..29 + cpdist = [ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + ], + // Extra bits for distance codes + cpdext = [ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + ], + // Order of the bit length code lengths + border = [ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + ]; + /* objects (inflate) */ + + function HuftList() { + this.next = null; + this.list = null; + } + + function HuftNode() { + this.e = 0; // number of extra bits or operation + this.b = 0; // number of bits in this code or subcode + + // union + this.n = 0; // literal, length base, or distance base + this.t = null; // (HuftNode) pointer to next level of table + } + + /* + * @param b- code lengths in bits (all assumed <= BMAX) + * @param n- number of codes (assumed <= N_MAX) + * @param s- number of simple-valued codes (0..s-1) + * @param d- list of base values for non-simple codes + * @param e- list of extra bits for non-simple codes + * @param mm- maximum lookup bits + */ + function HuftBuild(b, n, s, d, e, mm) { + this.BMAX = 16; // maximum bit length of any code + this.N_MAX = 288; // maximum number of codes in any set + this.status = 0; // 0: success, 1: incomplete table, 2: bad input + this.root = null; // (HuftList) starting table + this.m = 0; // maximum lookup bits, returns actual + + /* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. + The code with value 256 is special, and the tables are constructed + so that no bits beyond that code are fetched when that code is + decoded. */ + var a; // counter for codes of length k + var c = []; + var el; // length of EOB code (value 256) + var f; // i repeats in table every f entries + var g; // maximum code length + var h; // table level + var i; // counter, current code + var j; // counter + var k; // number of bits in current code + var lx = []; + var p; // pointer into c[], b[], or v[] + var pidx; // index of p + var q; // (HuftNode) points to current table + var r = new HuftNode(); // table entry for structure assignment + var u = []; + var v = []; + var w; + var x = []; + var xp; // pointer into x or c + var y; // number of dummy codes added + var z; // number of entries in current table + var o; + var tail; // (HuftList) + + tail = this.root = null; + + // bit length count table + for (i = 0; i < this.BMAX + 1; i++) { + c[i] = 0; + } + // stack of bits per table + for (i = 0; i < this.BMAX + 1; i++) { + lx[i] = 0; + } + // HuftNode[BMAX][] table stack + for (i = 0; i < this.BMAX; i++) { + u[i] = null; + } + // values in order of bit length + for (i = 0; i < this.N_MAX; i++) { + v[i] = 0; + } + // bit offsets, then code stack + for (i = 0; i < this.BMAX + 1; i++) { + x[i] = 0; + } + + // Generate counts for each bit length + el = n > 256 ? b[256] : this.BMAX; // set length of EOB code, if any + p = b; pidx = 0; + i = n; + do { + c[p[pidx]]++; // assume all entries <= BMAX + pidx++; + } while (--i > 0); + if (c[0] === n) { // null input--all zero length codes + this.root = null; + this.m = 0; + this.status = 0; + return; + } + + // Find minimum and maximum length, bound *m by those + for (j = 1; j <= this.BMAX; j++) { + if (c[j] !== 0) { + break; + } + } + k = j; // minimum code length + if (mm < j) { + mm = j; + } + for (i = this.BMAX; i !== 0; i--) { + if (c[i] !== 0) { + break; + } + } + g = i; // maximum code length + if (mm > i) { + mm = i; + } + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1) { + if ((y -= c[j]) < 0) { + this.status = 2; // bad input: more codes than bits + this.m = mm; + return; + } + } + if ((y -= c[i]) < 0) { + this.status = 2; + this.m = mm; + return; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = c; + pidx = 1; + xp = 2; + while (--i > 0) { // note that i == g from above + x[xp++] = (j += p[pidx++]); + } + + // Make a table of values in order of bit lengths + p = b; pidx = 0; + i = 0; + do { + if ((j = p[pidx++]) !== 0) { + v[x[j]++] = i; + } + } while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = v; pidx = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = lx[0] = 0; // no bits decoded yet + q = null; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (null; k <= g; k++) { + a = c[k]; + while (a-- > 0) { + // here i is the Huffman code of length k bits for value p[pidx] + // make tables up to required level + while (k > w + lx[1 + h]) { + w += lx[1 + h]; // add bits already decoded + h++; + + // compute minimum size table less than or equal to *m bits + z = (z = g - w) > mm ? mm : z; // upper limit + if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + while (++j < z) { // try smaller tables up to z bits + if ((f <<= 1) <= c[++xp]) { + break; // enough codes to use up j bits + } + f -= c[xp]; // else deduct codes from patterns + } + } + if (w + j > el && w < el) { + j = el - w; // make EOB code end at table + } + z = 1 << j; // table entries for j-bit table + lx[1 + h] = j; // set table size in stack + + // allocate and link in new table + q = []; + for (o = 0; o < z; o++) { + q[o] = new HuftNode(); + } + + if (!tail) { + tail = this.root = new HuftList(); + } else { + tail = tail.next = new HuftList(); + } + tail.next = null; + tail.list = q; + u[h] = q; // table starts after link + + /* connect to last table, if there is one */ + if (h > 0) { + x[h] = i; // save pattern for backing up + r.b = lx[h]; // bits to dump before this table + r.e = 16 + j; // bits in this table + r.t = q; // pointer to this table + j = (i & ((1 << w) - 1)) >> (w - lx[h]); + u[h - 1][j].e = r.e; + u[h - 1][j].b = r.b; + u[h - 1][j].n = r.n; + u[h - 1][j].t = r.t; + } + } + + // set up table entry in r + r.b = k - w; + if (pidx >= n) { + r.e = 99; // out of values--invalid code + } else if (p[pidx] < s) { + r.e = (p[pidx] < 256 ? 16 : 15); // 256 is end-of-block code + r.n = p[pidx++]; // simple code is just the value + } else { + r.e = e[p[pidx] - s]; // non-simple--look up in lists + r.n = d[p[pidx++] - s]; + } + + // fill code-like entries with r // + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) { + q[j].e = r.e; + q[j].b = r.b; + q[j].n = r.n; + q[j].t = r.t; + } + + // backwards increment the k-bit code i + for (j = 1 << (k - 1); (i & j) !== 0; j >>= 1) { + i ^= j; + } + i ^= j; + + // backup over finished tables + while ((i & ((1 << w) - 1)) !== x[h]) { + w -= lx[h]; // don't need to update q + h--; + } + } + } + + /* return actual size of base table */ + this.m = lx[1]; + + /* Return true (1) if we were given an incomplete table */ + this.status = ((y !== 0 && g !== 1) ? 1 : 0); + } + + + /* routines (inflate) */ + + function GET_BYTE() { + if (inflate_data.length === inflate_pos) { + return -1; + } + return inflate_data[inflate_pos++] & 0xff; + } + + function NEEDBITS(n) { + while (bit_len < n) { + bit_buf |= GET_BYTE() << bit_len; + bit_len += 8; + } + } + + function GETBITS(n) { + return bit_buf & MASK_BITS[n]; + } + + function DUMPBITS(n) { + bit_buf >>= n; + bit_len -= n; + } + + function inflate_codes(buff, off, size) { + // inflate (decompress) the codes in a deflated (compressed) block. + // Return an error code or zero if it all goes ok. + var e; // table entry flag/number of extra bits + var t; // (HuftNode) pointer to table entry + var n; + + if (size === 0) { + return 0; + } + + // inflate the coded data + n = 0; + for (;;) { // do until end of block + NEEDBITS(bl); + t = tl.list[GETBITS(bl)]; + e = t.e; + while (e > 16) { + if (e === 99) { + return -1; + } + DUMPBITS(t.b); + e -= 16; + NEEDBITS(e); + t = t.t[GETBITS(e)]; + e = t.e; + } + DUMPBITS(t.b); + + if (e === 16) { // then it's a literal + wp &= WSIZE - 1; + buff[off + n++] = slide[wp++] = t.n; + if (n === size) { + return size; + } + continue; + } + + // exit if end of block + if (e === 15) { + break; + } + + // it's an EOB or a length + + // get length of block to copy + NEEDBITS(e); + copy_leng = t.n + GETBITS(e); + DUMPBITS(e); + + // decode distance of block to copy + NEEDBITS(bd); + t = td.list[GETBITS(bd)]; + e = t.e; + + while (e > 16) { + if (e === 99) { + return -1; + } + DUMPBITS(t.b); + e -= 16; + NEEDBITS(e); + t = t.t[GETBITS(e)]; + e = t.e; + } + DUMPBITS(t.b); + NEEDBITS(e); + copy_dist = wp - t.n - GETBITS(e); + DUMPBITS(e); + + // do the copy + while (copy_leng > 0 && n < size) { + copy_leng--; + copy_dist &= WSIZE - 1; + wp &= WSIZE - 1; + buff[off + n++] = slide[wp++] = slide[copy_dist++]; + } + + if (n === size) { + return size; + } + } + + method = -1; // done + return n; + } + + function inflate_stored(buff, off, size) { + /* "decompress" an inflated type 0 (stored) block. */ + var n; + + // go to byte boundary + n = bit_len & 7; + DUMPBITS(n); + + // get the length and its complement + NEEDBITS(16); + n = GETBITS(16); + DUMPBITS(16); + NEEDBITS(16); + if (n !== ((~bit_buf) & 0xffff)) { + return -1; // error in compressed data + } + DUMPBITS(16); + + // read and output the compressed data + copy_leng = n; + + n = 0; + while (copy_leng > 0 && n < size) { + copy_leng--; + wp &= WSIZE - 1; + NEEDBITS(8); + buff[off + n++] = slide[wp++] = GETBITS(8); + DUMPBITS(8); + } + + if (copy_leng === 0) { + method = -1; // done + } + return n; + } + + function inflate_fixed(buff, off, size) { + // decompress an inflated type 1 (fixed Huffman codes) block. We should + // either replace this with a custom decoder, or at least precompute the + // Huffman tables. + + // if first time, set up tables for fixed blocks + if (!fixed_tl) { + var i; // temporary variable + var l = []; // 288 length list for huft_build (initialized below) + var h; // HuftBuild + + // literal table + for (i = 0; i < 144; i++) { + l[i] = 8; + } + for (null; i < 256; i++) { + l[i] = 9; + } + for (null; i < 280; i++) { + l[i] = 7; + } + for (null; i < 288; i++) { // make a complete, but wrong code set + l[i] = 8; + } + fixed_bl = 7; + + h = new HuftBuild(l, 288, 257, cplens, cplext, fixed_bl); + if (h.status !== 0) { + console.error("HufBuild error: " + h.status); + return -1; + } + fixed_tl = h.root; + fixed_bl = h.m; + + // distance table + for (i = 0; i < 30; i++) { // make an incomplete code set + l[i] = 5; + } + fixed_bd = 5; + + h = new HuftBuild(l, 30, 0, cpdist, cpdext, fixed_bd); + if (h.status > 1) { + fixed_tl = null; + console.error("HufBuild error: " + h.status); + return -1; + } + fixed_td = h.root; + fixed_bd = h.m; + } + + tl = fixed_tl; + td = fixed_td; + bl = fixed_bl; + bd = fixed_bd; + return inflate_codes(buff, off, size); + } + + function inflate_dynamic(buff, off, size) { + // decompress an inflated type 2 (dynamic Huffman codes) block. + var i; // temporary variables + var j; + var l; // last length + var n; // number of lengths to get + var t; // (HuftNode) literal/length code table + var nb; // number of bit length codes + var nl; // number of literal/length codes + var nd; // number of distance codes + var ll = []; + var h; // (HuftBuild) + + // literal/length and distance code lengths + for (i = 0; i < 286 + 30; i++) { + ll[i] = 0; + } + + // read in table lengths + NEEDBITS(5); + nl = 257 + GETBITS(5); // number of literal/length codes + DUMPBITS(5); + NEEDBITS(5); + nd = 1 + GETBITS(5); // number of distance codes + DUMPBITS(5); + NEEDBITS(4); + nb = 4 + GETBITS(4); // number of bit length codes + DUMPBITS(4); + if (nl > 286 || nd > 30) { + return -1; // bad lengths + } + + // read in bit-length-code lengths + for (j = 0; j < nb; j++) { + NEEDBITS(3); + ll[border[j]] = GETBITS(3); + DUMPBITS(3); + } + for (null; j < 19; j++) { + ll[border[j]] = 0; + } + + // build decoding table for trees--single level, 7 bit lookup + bl = 7; + h = new HuftBuild(ll, 19, 19, null, null, bl); + if (h.status !== 0) { + return -1; // incomplete code set + } + + tl = h.root; + bl = h.m; + + // read in literal and distance code lengths + n = nl + nd; + i = l = 0; + while (i < n) { + NEEDBITS(bl); + t = tl.list[GETBITS(bl)]; + j = t.b; + DUMPBITS(j); + j = t.n; + if (j < 16) { // length of code in bits (0..15) + ll[i++] = l = j; // save last length in l + } else if (j === 16) { // repeat last length 3 to 6 times + NEEDBITS(2); + j = 3 + GETBITS(2); + DUMPBITS(2); + if (i + j > n) { + return -1; + } + while (j-- > 0) { + ll[i++] = l; + } + } else if (j === 17) { // 3 to 10 zero length codes + NEEDBITS(3); + j = 3 + GETBITS(3); + DUMPBITS(3); + if (i + j > n) { + return -1; + } + while (j-- > 0) { + ll[i++] = 0; + } + l = 0; + } else { // j === 18: 11 to 138 zero length codes + NEEDBITS(7); + j = 11 + GETBITS(7); + DUMPBITS(7); + if (i + j > n) { + return -1; + } + while (j-- > 0) { + ll[i++] = 0; + } + l = 0; + } + } + + // build the decoding tables for literal/length and distance codes + bl = lbits; + h = new HuftBuild(ll, nl, 257, cplens, cplext, bl); + if (bl === 0) { // no literals or lengths + h.status = 1; + } + if (h.status !== 0) { + if (h.status !== 1) { + return -1; // incomplete code set + } + // **incomplete literal tree** + } + tl = h.root; + bl = h.m; + + for (i = 0; i < nd; i++) { + ll[i] = ll[i + nl]; + } + bd = dbits; + h = new HuftBuild(ll, nd, 0, cpdist, cpdext, bd); + td = h.root; + bd = h.m; + + if (bd === 0 && nl > 257) { // lengths but no distances + // **incomplete distance tree** + return -1; + } +/* + if (h.status === 1) { + // **incomplete distance tree** + } +*/ + if (h.status !== 0) { + return -1; + } + + // decompress until an end-of-block code + return inflate_codes(buff, off, size); + } + + function inflate_start() { + if (!slide) { + slide = []; // new Array(2 * WSIZE); // slide.length is never called + } + wp = 0; + bit_buf = 0; + bit_len = 0; + method = -1; + eof = false; + copy_leng = copy_dist = 0; + tl = null; + } + + function inflate_internal(buff, off, size) { + // decompress an inflated entry + var n, i; + + n = 0; + while (n < size) { + if (eof && method === -1) { + return n; + } + + if (copy_leng > 0) { + if (method !== STORED_BLOCK) { + // STATIC_TREES or DYN_TREES + while (copy_leng > 0 && n < size) { + copy_leng--; + copy_dist &= WSIZE - 1; + wp &= WSIZE - 1; + buff[off + n++] = slide[wp++] = slide[copy_dist++]; + } + } else { + while (copy_leng > 0 && n < size) { + copy_leng--; + wp &= WSIZE - 1; + NEEDBITS(8); + buff[off + n++] = slide[wp++] = GETBITS(8); + DUMPBITS(8); + } + if (copy_leng === 0) { + method = -1; // done + } + } + if (n === size) { + return n; + } + } + + if (method === -1) { + if (eof) { + break; + } + + // read in last block bit + NEEDBITS(1); + if (GETBITS(1) !== 0) { + eof = true; + } + DUMPBITS(1); + + // read in block type + NEEDBITS(2); + method = GETBITS(2); + DUMPBITS(2); + tl = null; + copy_leng = 0; + } + + switch (method) { + case STORED_BLOCK: + i = inflate_stored(buff, off + n, size - n); + break; + + case STATIC_TREES: + if (tl) { + i = inflate_codes(buff, off + n, size - n); + } else { + i = inflate_fixed(buff, off + n, size - n); + } + break; + + case DYN_TREES: + if (tl) { + i = inflate_codes(buff, off + n, size - n); + } else { + i = inflate_dynamic(buff, off + n, size - n); + } + break; + + default: // error + i = -1; + break; + } + + if (i === -1) { + if (eof) { + return 0; + } + return -1; + } + n += i; + } + return n; + } + + function inflate(arr) { + var buff = [], i; + + inflate_start(); + inflate_data = arr; + inflate_pos = 0; + + do { + i = inflate_internal(buff, buff.length, 1024); + } while (i > 0); + inflate_data = null; // G.C. + return buff; + } + + module.exports = inflate; +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/package.json new file mode 100644 index 0000000..e60cf61 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/package.json @@ -0,0 +1,42 @@ +{ + "author": { + "name": "Masanao Izumo", + "email": "iz@onicos.co.jp" + }, + "contributors": [ + { + "name": "T. Jameson Little", + "email": "t.jameson.little@gmail.com" + }, + { + "name": "Dan Kogai", + "email": "dankogai+github@gmail.com" + } + ], + "name": "deflate-js", + "description": "DEFLATE implemented in JavaScript (works in browser and Node)", + "version": "0.2.2", + "main": "./index.js", + "bin": { + "deflate-js": "./bin/deflate.js", + "inflate-js": "./bin/inflate.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/deflate-js.git" + }, + "scripts": { + "test": "cd test ; ./runner.py; cd -" + }, + "engines": { + "node": ">= 0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "optimist": "~0.2" + }, + "readme": "Intro\n=====\n\nDoes deflate compression/decompression in the browser and node.\n\nThis module is not meant to be run on node for any production code. The native version of deflate should be used instead because it is much faster. The main reason for this being node-compatible is for testing purposes.\n\nCurrently deflate does not pass all tests, but inflate does. This should not be used for compressing data yet in production.\n\nInstall\n=======\n\nFor node, deflate-js can be installed with npm: `npm install deflate-js`\n\nFor the browser, deflate-js can be installed with pakmanager.\n\nAPI\n===\n\nDeflate:\n\n> *deflate(arr[, level])*\n> \n> **arr**- Byte array to compress\n> \n> **level**- 1-9 (compression level; optional)\n\nInflate:\n\n> *inflate(arr)*\n> \n> \n> **arr**- Byte array to decompress\n\nThe basic usage (no level) will suffice for most purposes.\n\nBasic Usage\n-----------\n\n var deflate = require('deflate-js'),\n\t\tarr;\n\n\tarr = Array.prototype.map.call('Hello world', function (char) {\n\t\treturn char.charCodeAt(0);\n\t});\n\n\t// compress some text\n\tvar compressed = deflate.deflate(arr);\n\n\t// decompress some text\n\tvar decompressed = deflate.inflate(compressed);\n", + "readmeFilename": "README.md", + "_id": "deflate-js@0.2.2", + "_from": "deflate-js@>= 0.2.2" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/deflate.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/deflate.py new file mode 100644 index 0000000..6d44b83 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/deflate.py @@ -0,0 +1,80 @@ +import os +from colorama import Fore +from helpers import deflate, inflate, run_cmd + +outDirDefault = 'test-outs' +testDirDefault = 'test-files' + +""" +Run a single test + +@param tFile- required; the full path to the file to run +@param level- optional (default: all); the compression level [1-9] +@param delete- optional (default: True); whether to delete the gzipped files +@return True if all tests passed; False if at least one test failed +""" +def runTest(tFile, level=None, delete=True, outDir=outDirDefault): + passed = True + if level == None: + for x in range(1, 10): + if runTest(tFile, x, delete) == False: + passed = False + + return passed + + # make the test-outs directory + try: + os.mkdir(outDir) + except: + pass + + out1 = os.path.join(outDir, '%(file)s.%(level)d.deflate' % {'file': os.path.basename(tFile), 'level' : level}) + out2 = os.path.join(outDir, '%(file)s.%(level)d.out.deflate' % {'file': os.path.basename(tFile), 'level' : level}) + + outData = deflate(tFile, outfile=out1, level=level) + run_cmd('../bin/deflate.js --level %(level)d --file %(file)s --output %(output)s' % {'level' : level, 'file' : tFile, 'output' : out2}) + + result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : out1, 'file2' : out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + + if delete == True: + os.remove(out1) + os.remove(out2) + + return passed + +""" +Runs all tests on the given level. This iterates throuth the testDir directory defined above. + +@param level- The level to run on [1-9] (default: None, runs on all levels all) +@param delete- Whether to delete output files after the test is run +@return True if all levels passed, False if at least one failed +""" +def runAll(level=None, delete=True, testDir=testDirDefault, outDir=outDirDefault): + # make the test-outs directory + try: + os.mkdir(outDir) + except: + pass + + passed = True + for tFile in os.listdir(testDir): + fullPath = os.path.join(testDir, tFile) + + print Fore.YELLOW + tFile + Fore.RESET + + if runTest(fullPath, level, delete) == False: + passed = False + + print '' + + # if we deletede all the files that were created, delete the directory + if delete == True: + os.rmdir(outDir) + return passed diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/helpers.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/helpers.py new file mode 100644 index 0000000..ae4a597 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/helpers.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import zlib +import subprocess as sp + +def deflate(filename, outfile=None, level=6): + f = open(filename) + data = f.read() + f.close() + + compress = zlib.compressobj( + level, # level: 0-9 + zlib.DEFLATED, # method: must be DEFLATED + -zlib.MAX_WBITS, # window size in bits: + # -15..-8: negate, suppress header + # 8..15: normal + # 16..30: subtract 16, gzip header + zlib.DEF_MEM_LEVEL, # mem level: 1..8/9 + 0 # strategy: + # 0 = Z_DEFAULT_STRATEGY + # 1 = Z_FILTERED + # 2 = Z_HUFFMAN_ONLY + # 3 = Z_RLE + # 4 = Z_FIXED + ) + deflated = compress.compress(data) + deflated += compress.flush() + + if outfile != None: + f = open(outfile, 'w') + f.write(deflated) + f.close() + + return deflated + +def inflate(filename, outfile=None): + f = open(filename) + data = f.read() + f.close() + + decompress = zlib.decompressobj(-zlib.MAX_WBITS) # see above + inflated = decompress.decompress(data) + inflated += decompress.flush() + + if outfile != None: + f = open(outfile, 'w') + f.write(inflated) + f.close() + + return inflated + +""" +Convenience function for running a command bash-like + +@param command- string version of a command to run on +@param shell- Whether to run this through the shell; used in subprocess.Popen (default: true) +@return Object with properties 'returncode', 'stdout', and 'stderr' +""" +def run_cmd(command, shell=True): + process = sp.Popen(command, shell=shell, stdout = sp.PIPE, stderr = sp.PIPE) + stdout, stderr = process.communicate() + returncode = process.returncode + return {'returncode' : returncode, 'stdout' : stdout, 'stderr' : stderr} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/inflate.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/inflate.py new file mode 100644 index 0000000..2a8492f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/inflate.py @@ -0,0 +1,81 @@ +import os +from colorama import Fore +from helpers import deflate, inflate, run_cmd + +outDirDefault = 'test-outs' +testDirDefault = 'test-files' + +""" +Run a single test + +@param tFile- required; the file to check against (uncompressed data) +@param level- optional (default: all); the compression level [1-9] +@param delete- optional (default: True); whether to delete the gzipped files +@return True if all tests passed; False if at least one test failed +""" +def runTest(tFile, level=None, delete=True, outDir=outDirDefault): + passed = True + + if level == None: + for x in range(1, 10): + if runTest(tFile, x, delete) == False: + passed = False + + return passed + + # make the test-outs directory + try: + os.mkdir(outDir) + except: + pass + + out1 = os.path.join(outDir, '%(file)s.%(level)d.deflate' % {'file': os.path.basename(tFile), 'level' : level}) + out2 = os.path.join(outDir, '%(file)s.%(level)d' % {'file' : os.path.basename(tFile), 'level' : level}) + + deflate(tFile, outfile=out1, level=level) + run_cmd('../bin/inflate.js --file %(file)s --output %(output)s' % {'level' : level, 'file' : out1, 'output' : out2}) + + result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : tFile, 'file2' : out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + + if delete == True: + os.remove(out1) + os.remove(out2) + + return passed + +""" +Runs all tests on the given level. This iterates throuth the testDir directory defined above. + +@param level- The level to run on [1-9] (default: None, runs on all levels all) +@param delete- Whether to delete output files after the test is run +@return True if all levels passed, False if at least one failed +""" +def runAll(level=None, delete=True, testDir=testDirDefault, outDir=outDirDefault): + # make the test-outs directory + try: + os.mkdir(outDir) + except: + pass + + passed = True + for tFile in os.listdir(testDir): + fullPath = os.path.join(testDir, tFile) + + print Fore.YELLOW + tFile + Fore.RESET + + if runTest(fullPath, level, delete) == False: + passed = False + + print '' + + # if we deletede all the files that were created, delete the directory + if delete == True: + os.rmdir(outDir) + return passed diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/runner.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/runner.py new file mode 100755 index 0000000..21ad153 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/runner.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import argparse +import deflate +import inflate +from colorama import Fore + +testDir = 'test-files' +outDir = 'test-outs' + +allPassed = True + +parser = argparse.ArgumentParser(description='Process command-line arguments') +parser.add_argument('--test', metavar='path/to/file', type=str, default='both', nargs='?', help='Which test to run: deflate, inflate, or both') +parser.add_argument('--file', '-f', metavar='path/to/file', type=str, nargs='?', help='Path to file to use for test') +parser.add_argument('--level', '-l', metavar='#', type=int, nargs='?', help='Compression level') +parser.add_argument('--no-delete', const=True, default=False, nargs='?', help='Don\'t delete files produced for test') + +args = parser.parse_args() + +delete = not getattr(args, 'no_delete') +level = getattr(args, 'level') +inFile = getattr(args, 'file') +test = getattr(args, 'test') + +if test == 'deflate' or test == 'both': + print Fore.CYAN + 'Running deflate tests' + Fore.RESET + + passed = True + + if inFile != None: + passed = deflate.runTest(inFile, level, delete, outDir) + else: + passed = deflate.runAll(level, delete, testDir, outDir) + + # if we fail one test, we fail the entire test + allPassed = allPassed and passed + +if test == 'inflate' or test == 'both': + print Fore.CYAN + 'Running inflate tests' + Fore.RESET + + passed = True + + if inFile != None: + passed = inflate.runTest(inFile, level, delete, outDir) + else: + passed = inflate.runAll(level, delete, testDir, outDir) + + # if we fail one test, we fail the entire test + allPassed = allPassed and passed + +if allPassed: + print Fore.GREEN + 'All tests passed!' + Fore.RESET +else: + print Fore.RED + 'Automated test failed' + Fore.RESET diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/declaration.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/declaration.txt new file mode 100644 index 0000000..faf03c7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/declaration.txt @@ -0,0 +1,65 @@ +The Unanimous Declaration of the Thirteen United States of America + +When, in the course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the laws of nature and of nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation. + +We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable rights, that among these are life, liberty and the pursuit of happiness. That to secure these rights, governments are instituted among men, deriving their just powers from the consent of the governed. That whenever any form of government becomes destructive to these ends, it is the right of the people to alter or to abolish it, and to institute new government, laying its foundation on such principles and organizing its powers in such form, as to them shall seem most likely to effect their safety and happiness. Prudence, indeed, will dictate that governments long established should not be changed for light and transient causes; and accordingly all experience hath shown that mankind are more disposed to suffer, while evils are sufferable, than to right themselves by abolishing the forms to which they are accustomed. But when a long train of abuses and usurpations, pursuing invariably the same object evinces a design to reduce them under absolute despotism, it is their right, it is their duty, to throw off such government, and to provide new guards for their future security. - Such has been the patient sufferance of these colonies; and such is now the necessity which constrains them to alter their former systems of government. The history of the present King of Great Britain is a history of repeated injuries and usurpations, all having in direct object the establishment of an absolute tyranny over these states. To prove this, let facts be submitted to a candid world. + +He has refused his assent to laws, the most wholesome and necessary for the public good. + +He has forbidden his governors to pass laws of immediate and pressing importance, unless suspended in their operation till his assent should be obtained; and when so suspended, he has utterly neglected to attend to them. + +He has refused to pass other laws for the accommodation of large districts of people, unless those people would relinquish the right of representation in the legislature, a right inestimable to them and formidable to tyrants only. + +He has called together legislative bodies at places unusual, uncomfortable, and distant from the depository of their public records, for the sole purpose of fatiguing them into compliance with his measures. + +He has dissolved representative houses repeatedly, for opposing with manly firmness his invasions on the rights of the people. + +He has refused for a long time, after such dissolutions, to cause others to be elected; whereby the legislative powers, incapable of annihilation, have returned to the people at large for their exercise; the state remaining in the meantime exposed to all the dangers of invasion from without, and convulsions within. + +He has endeavored to prevent the population of these states; for that purpose obstructing the laws for naturalization of foreigners; refusing to pass others to encourage their migration hither, and raising the conditions of new appropriations of lands. + +He has obstructed the administration of justice, by refusing his assent to laws for establishing judiciary powers. + +He has made judges dependent on his will alone, for the tenure of their offices, and the amount and payment of their salaries. + +He has erected a multitude of new offices, and sent hither swarms of officers to harass our people, and eat out their substance. + +He has kept among us, in times of peace, standing armies without the consent of our legislature. + +He has affected to render the military independent of and superior to civil power. + +He has combined with others to subject us to a jurisdiction foreign to our constitution, and unacknowledged by our laws; giving his assent to their acts of pretended legislation: + +For quartering large bodies of armed troops among us: + +For protecting them, by mock trial, from punishment for any murders which they should commit on the inhabitants of these states: + +For cutting off our trade with all parts of the world: + +For imposing taxes on us without our consent: + +For depriving us in many cases, of the benefits of trial by jury: + +For transporting us beyond seas to be tried for pretended offenses: + +For abolishing the free system of English laws in a neighboring province, establishing therein an arbitrary government, and enlarging its boundaries so as to render it at once an example and fit instrument for introducing the same absolute rule in these colonies: + +For taking away our charters, abolishing our most valuable laws, and altering fundamentally the forms of our governments: + +For suspending our own legislatures, and declaring themselves invested with power to legislate for us in all cases whatsoever. + +He has abdicated government here, by declaring us out of his protection and waging war against us. + +He has plundered our seas, ravaged our coasts, burned our towns, and destroyed the lives of our people. + +He is at this time transporting large armies of foreign mercenaries to complete the works of death, desolation and tyranny, already begun with circumstances of cruelty and perfidy scarcely paralleled in the most barbarous ages, and totally unworthy of the head of a civilized nation. + +He has constrained our fellow citizens taken captive on the high seas to bear arms against their country, to become the executioners of their friends and brethren, or to fall themselves by their hands. + +He has excited domestic insurrections amongst us, and has endeavored to bring on the inhabitants of our frontiers, the merciless Indian savages, whose known rule of warfare, is undistinguished destruction of all ages, sexes and conditions. + +In every stage of these oppressions we have petitioned for redress in the most humble terms: our repeated petitions have been answered only by repeated injury. A prince, whose character is thus marked by every act which may define a tyrant, is unfit to be the ruler of a free people. + +Nor have we been wanting in attention to our British brethren. We have warned them from time to time of attempts by their legislature to extend an unwarrantable jurisdiction over us. We have reminded them of the circumstances of our emigration and settlement here. We have appealed to their native justice and magnanimity, and we have conjured them by the ties of our common kindred to disavow these usurpations, which, would inevitably interrupt our connections and correspondence.They too have been deaf to the voice of justice and of consanguinity. We must, therefore, acquiesce in the necessity, which denounces our separation, and hold them, as we hold the rest of mankind, enemies in war, in peace friends. + +We, therefore, the representatives of the United States of America, in General Congress, assembled, appealing to the Supreme Judge of the world for the rectitude of our intentions, do, in the name, and by the authority of the good people of these colonies, solemnly publish and declare, that these united colonies are, and of right ought to be free and independent states; that they are absolved from all allegiance to the British Crown, and that all political connection between them and the state of Great Britain, is and ought to be totally dissolved; and that as free and independent states, they have full power to levey war, conclude peace, contract alliances, establish commerce, and to do all other acts and things which independent states may of right do. And for the support of this declaration, with a firm reliance on the protection of Divine Providence, we mutually pledge to each other our lives, our fortunes and our sacred honor. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/helloWorld.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/helloWorld.txt new file mode 100644 index 0000000..802992c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/helloWorld.txt @@ -0,0 +1 @@ +Hello world diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/lorem.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/lorem.txt new file mode 100644 index 0000000..cee7a92 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/lorem.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/random.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/random.txt new file mode 100644 index 0000000..5b594d4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/node_modules/deflate-js/test/test-files/random.txt @@ -0,0 +1,19 @@ +Old education him departure any arranging one prevailed. Their end whole might began her. Behaved the comfort another fifteen eat. Partiality had his themselves ask pianoforte increasing discovered. So mr delay at since place whole above miles. He to observe conduct at detract because. Way ham unwilling not breakfast furniture explained perpetual. Or mr surrounded conviction so astonished literature. Songs to an blush woman be sorry young. We certain as removal attempt. + +There worse by an of miles civil. Manner before lively wholly am mr indeed expect. Among every merry his yet has her. You mistress get dashwood children off. Met whose marry under the merit. In it do continual consulted no listening. Devonshire sir sex motionless travelling six themselves. So colonel as greatly shewing herself observe ashamed. Demands minutes regular ye to detract is. + +The him father parish looked has sooner. Attachment frequently gay terminated son. You greater nay use prudent placing. Passage to so distant behaved natural between do talking. Friends off her windows painful. Still gay event you being think nay for. In three if aware he point it. Effects warrant me by no on feeling settled resolve. + +Civility vicinity graceful is it at. Improve up at to on mention perhaps raising. Way building not get formerly her peculiar. Up uncommonly prosperous sentiments simplicity acceptance to so. Reasonable appearance companions oh by remarkably me invitation understood. Pursuit elderly ask perhaps all. + +Savings her pleased are several started females met. Short her not among being any. Thing of judge fruit charm views do. Miles mr an forty along as he. She education get middleton day agreement performed preserved unwilling. Do however as pleased offence outward beloved by present. By outward neither he so covered amiable greater. Juvenile proposal betrayed he an informed weddings followed. Precaution day see imprudence sympathize principles. At full leaf give quit to in they up. + +Smile spoke total few great had never their too. Amongst moments do in arrived at my replied. Fat weddings servants but man believed prospect. Companions understood is as especially pianoforte connection introduced. Nay newspaper can sportsman are admitting gentleman belonging his. Is oppose no he summer lovers twenty in. Not his difficulty boisterous surrounded bed. Seems folly if in given scale. Sex contented dependent conveying advantage can use. + +Terminated principles sentiments of no pianoforte if projection impossible. Horses pulled nature favour number yet highly his has old. Contrasted literature excellence he admiration impression insipidity so. Scale ought who terms after own quick since. Servants margaret husbands to screened in throwing. Imprudence oh an collecting partiality. Admiration gay difficulty unaffected how. + +Six started far placing saw respect females old. Civilly why how end viewing attempt related enquire visitor. Man particular insensible celebrated conviction stimulated principles day. Sure fail or in said west. Right my front it wound cause fully am sorry if. She jointure goodness interest debating did outweigh. Is time from them full my gone in went. Of no introduced am literature excellence mr stimulated contrasted increasing. Age sold some full like rich new. Amounted repeated as believed in confined juvenile. + +Are own design entire former get should. Advantages boisterous day excellence boy. Out between our two waiting wishing. Pursuit he he garrets greater towards amiable so placing. Nothing off how norland delight. Abode shy shade she hours forth its use. Up whole of fancy ye quiet do. Justice fortune no to is if winding morning forming. + +Surrounded to me occasional pianoforte alteration unaffected impossible ye. For saw half than cold. Pretty merits waited six talked pulled you. Conduct replied off led whether any shortly why arrived adapted. Numerous ladyship so raillery humoured goodness received an. So narrow formal length my highly longer afford oh. Tall neat he make or at dull ye. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/package.json new file mode 100644 index 0000000..ecbe50c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/package.json @@ -0,0 +1,35 @@ +{ + "author": { + "name": "T. Jameson Little", + "email": "t.jameson.little@gmail.com" + }, + "name": "gzip-js", + "description": "GZIP in pure JavaScript (works in the browser)", + "version": "0.3.1", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/gzip-js.git" + }, + "main": "./lib/gzip.js", + "bin": { + "gzip-js": "./bin/gzip.js", + "gunzip-js": "./bin/gunzip.js" + }, + "scripts": { + "test": "cd test; ./runner.py; cd -" + }, + "engines": { + "node": ">= 0.4.0" + }, + "dependencies": { + "crc32": ">= 0.2.2", + "deflate-js": ">= 0.2.2" + }, + "devDependencies": { + "optimist": "~0.2" + }, + "readme": "Intro\n=====\n\n*gzip-js* is a pure JavaScript implementation of the GZIP file format. It uses the DEFLATE algorithm for compressing data.\n\nPlease note that since this is a pure JavaScript implementation, it should NOT be used on the server for production code. It also does not comply 100% with the standard, yet.\n\nThe main goal of this project is to bring GZIP compression to the browser.\n\nAPI\n===\n\nThere is only one function so far, zip:\n\nfunction zip(data[, options])\n \n* data- String of text or byte array to compress\n* options- object with options; options include:\n * level- compression level (1-9); default 6\n * timestamp- UNIX timestamp (seconds); if omitted, the current time will be used\n * name- optional; original name of the file\n\nSample usage:\n\n var gzip = require('gzip-js'),\n\t\toptions = {\n\t\t\tlevel: 3,\n\t\t\tname: 'hello-world.txt',\n\t\t\ttimestamp: parseInt(Date.now() / 1000, 10)\n\t\t};\n\n\t// out will be a JavaScript Array of bytes\n\tvar out = gzip.zip('Hello world', options);\n", + "readmeFilename": "README.md", + "_id": "gzip-js@0.3.1", + "_from": "gzip-js@~0.3.1" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/helpers.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/helpers.py new file mode 100644 index 0000000..e69d5f3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/helpers.py @@ -0,0 +1,15 @@ +import subprocess as sp + +""" +Convenience function for running a command bash-like + +@param command- string version of a command to run on +@param shell- Whether to run this through the shell; used in subprocess.Popen (default: true) +@return Object with properties 'returncode', 'stdout', and 'stderr' +""" +def run_cmd(command, shell=True): + process = sp.Popen(command, shell=shell, stdout = sp.PIPE, stderr = sp.PIPE) + stdout, stderr = process.communicate() + returncode = process.returncode + return {'returncode' : returncode, 'stdout' : stdout, 'stderr' : stderr} + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/runner.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/runner.py new file mode 100755 index 0000000..c072e55 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/runner.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import os +import sys +import shutil +from colorama import Fore +import argparse +import zipTest +import unzipTest + +parser = argparse.ArgumentParser(description='Process command-line arguments') +parser.add_argument('--file', '-f', metavar='path/to/file', type=str, nargs='?', help='Path to file to use for test') +parser.add_argument('--level', '-l', metavar='#', type=int, nargs='?', help='Compression level') +parser.add_argument('--no-delete', const=True, default=False, nargs='?', help='Don\'t delete files produced for test') +parser.add_argument('--test', default='both', nargs='?', help='Which test to run (zip, unzip, both)') + +args = parser.parse_args() + +allPassed = True + +outDir = 'test-outs' + +# make the test-outs directory +try: + os.mkdir(outDir) +except: + pass + +delete = not getattr(args, 'no_delete') +level = getattr(args, 'level') +inFile = getattr(args, 'file') +test = getattr(args, 'test') + +if test == 'zip' or test == 'both': + print Fore.CYAN + 'Running zip tests' + Fore.RESET + # if the user specifies a file, only run that test + if inFile != None: + allPassed = zipTest.runTest(inFile, level) + else: + allPassed = zipTest.runAll(level) + +if test == 'unzip' or test == 'both': + print Fore.CYAN + 'Running unzip tests' + Fore.RESET + # if the user specifies a file, only run that test + if inFile != None: + allPassed = unzipTest.runTest(inFile, level) + else: + allPassed = unzipTest.runAll(level) + +if delete: + shutil.rmtree(outDir) + +if allPassed: + print Fore.GREEN + 'All tests passed!' + Fore.RESET +else: + print Fore.RED + 'Automated test failed' + Fore.RESET + sys.exit(1) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/hello-world.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/hello-world.txt new file mode 100644 index 0000000..980a0d5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/hello-world.txt @@ -0,0 +1 @@ +Hello World! diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/spec.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/spec.txt new file mode 100644 index 0000000..7ce0273 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test-files/spec.txt @@ -0,0 +1,336 @@ +GZIP file format specification version 4.3 + +Status of This Memo + +This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited. +IESG Note: + +The IESG takes no position on the validity of any Intellectual Property Rights statements contained in this document. +Notices + +Copyright © 1996 L. Peter Deutsch +Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. + +A pointer to the latest version of this and related documentation in HTML format can be found at the URL . + +Abstract + +This specification defines a lossless compressed data format that is compatible with the widely used GZIP utility. The format includes a cyclic redundancy check value for detecting data corruption. The format presently uses the DEFLATE method of compression but can be easily extended to use other compression methods. The format can be implemented readily in a manner not covered by patents. +Table of Contents + +1. Introduction +1.1. Purpose +1.2. Intended audience +1.3. Scope +1.4. Compliance +1.5. Definitions of terms and conventions used +1.6. Changes from previous versions +2. Detailed specification +2.1. Overall conventions +2.2. File format +2.3. Member format +2.3.1. Member header and trailer +2.3.1.1. Extra field +2.3.1.2. Compliance +3. References +4. Security Considerations +5. Acknowledgements +6. Author's Address +7. Appendix: Jean-Loup Gailly's gzip utility +8. Appendix: Sample CRC Code +1. Introduction + +Purpose + +The purpose of this specification is to define a lossless compressed data format that: + +Is independent of CPU type, operating system, file system, and character set, and hence can be used for interchange; +Can compress or decompress a data stream (as opposed to a randomly accessible file) to produce another data stream, using only an a priori bounded amount of intermediate storage, and hence can be used in data communications or similar structures such as Unix filters; +Compresses data with efficiency comparable to the best currently available general-purpose compression methods, and in particular considerably better than the "compress" program; +Can be implemented readily in a manner not covered by patents, and hence can be practiced freely; +Is compatible with the file format produced by the current widely used gzip utility, in that conforming decompressors will be able to read data produced by the existing gzip compressor. +The data format defined by this specification does not attempt to: +Provide random access to compressed data; +Compress specialized data (e.g., raster graphics) as well as the best currently available specialized algorithms. +Intended audience + +This specification is intended for use by implementors of software to compress data into gzip format and/or decompress data from gzip format. + +The text of the specification assumes a basic background in programming at the level of bits and other primitive data representations. + +Scope + +The specification specifies a compression method and a file format (the latter assuming only that a file can store a sequence of arbitrary bytes). It does not specify any particular interface to a file system or anything about character sets or encodings (except for file names and comments, which are optional). + +Compliance + +Unless otherwise indicated below, a compliant decompressor must be able to accept and decompress any file that conforms to all the specifications presented here; a compliant compressor must produce files that conform to all the specifications presented here. The material in the appendices is not part of the specification per se and is not relevant to compliance. + +Definitions of terms and conventions used + +byte: 8 bits stored or transmitted as a unit (same as an octet). (For this specification, a byte is exactly 8 bits, even on machines which store a character on a number of bits different from 8.) See below for the numbering of bits within a byte. + +1.6. Changes from previous versions + +There have been no technical changes to the gzip format since version 4.1 of this specification. In version 4.2, some terminology was changed, and the sample CRC code was rewritten for clarity and to eliminate the requirement for the caller to do pre- and post-conditioning. Version 4.3 is a conversion of the specification to RFC style. + +2. Detailed specification + +Overall conventions + +In the diagrams below, a box like this: ++---+ +| | <-- the vertical bars might be missing ++---+ +represents one byte; a box like this: ++==============+ +| | ++==============+ +represents a variable number of bytes. +Bytes stored within a computer do not have a "bit order", since they are always treated as a unit. However, a byte considered as an integer between 0 and 255 does have a most- and least-significant bit, and since we write numbers with the most-significant digit on the left, we also write bytes with the most-significant bit on the left. In the diagrams below, we number the bits of a byte so that bit 0 is the least-significant bit, i.e., the bits are numbered: + ++--------+ +|76543210| ++--------+ +This document does not address the issue of the order in which bits of a byte are transmitted on a bit-sequential medium, since the data format described here is byte- rather than bit-oriented. + +Within a computer, a number may occupy multiple bytes. All multi-byte numbers in the format described here are stored with the least-significant byte first (at the lower memory address). For example, the decimal number 520 is stored as: + + 0 1 ++--------+--------+ +|00001000|00000010| ++--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 +File format + +A gzip file consists of a series of "members" (compressed data sets). The format of each member is specified in the following section. The members simply appear one after another in the file, with no additional information before, between, or after them. + +Member format + +Each member has the following structure: ++---+---+---+---+---+---+---+---+---+---+ +|ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) ++---+---+---+---+---+---+---+---+---+---+ +(if FLG.FEXTRA set) ++---+---+=================================+ +| XLEN |...XLEN bytes of "extra field"...| (more-->) ++---+---+=================================+ +(if FLG.FNAME set) ++=========================================+ +|...original file name, zero-terminated...| (more-->) ++=========================================+ +(if FLG.FCOMMENT set) ++===================================+ +|...file comment, zero-terminated...| (more-->) ++===================================+ +(if FLG.FHCRC set) ++---+---+ +| CRC16 | ++---+---+ ++=======================+ +|...compressed blocks...| (more-->) ++=======================+ + 0 1 2 3 4 5 6 7 ++---+---+---+---+---+---+---+---+ +| CRC32 | ISIZE | ++---+---+---+---+---+---+---+---+ +Member header and trailer + +ID1 (IDentification 1) +ID2 (IDentification 2) +These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213), to identify the file as being in gzip format. +CM (Compression Method) +This identifies the compression method used in the file. CM = 0-7 are reserved. CM = 8 denotes the "deflate" compression method, which is the one customarily used by gzip and which is documented elsewhere. +FLG (FLaGs) +This flag byte is divided into individual bits as follows: +bit 0 FTEXT +bit 1 FHCRC +bit 2 FEXTRA +bit 3 FNAME +bit 4 FCOMMENT +bit 5 reserved +bit 6 reserved +bit 7 reserved +If FTEXT is set, the file is probably ASCII text. This is an optional indication, which the compressor may set by checking a small amount of the input data to see whether any non-ASCII characters are present. In case of doubt, FTEXT is cleared, indicating binary data. For systems which have different file formats for ascii text and binary data, the decompressor can use FTEXT to choose the appropriate format. We deliberately do not specify the algorithm used to set this bit, since a compressor always has the option of leaving it cleared and a decompressor always has the option of ignoring it and letting some other program handle issues of data conversion. + +If FHCRC is set, a CRC16 for the gzip header is present, immediately before the compressed data. The CRC16 consists of the two least significant bytes of the CRC32 for all bytes of the gzip header up to and not including the CRC16. [The FHCRC bit was never set by versions of gzip up to 1.2.4, even though it was documented with a different meaning in gzip 1.2.4.] + +If FEXTRA is set, optional extra fields are present, as described in a following section. + +If FNAME is set, an original file name is present, terminated by a zero byte. The name must consist of ISO 8859-1 (LATIN-1) characters; on operating systems using EBCDIC or any other character set for file names, the name must be translated to the ISO LATIN-1 character set. This is the original name of the file being compressed, with any directory components removed, and, if the file being compressed is on a file system with case insensitive names, forced to lower case. There is no original file name if the data was compressed from a source other than a named file; for example, if the source was stdin on a Unix system, there is no file name. + +If FCOMMENT is set, a zero-terminated file comment is present. This comment is not interpreted; it is only intended for human consumption. The comment must consist of ISO 8859-1 (LATIN-1) characters. Line breaks should be denoted by a single line feed character (10 decimal). + +Reserved FLG bits must be zero. + +MTIME (Modification TIME) +This gives the most recent modification time of the original file being compressed. The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this may cause problems for MS-DOS and other systems that use local rather than Universal time.) If the compressed data did not come from a file, MTIME is set to the time at which compression started. MTIME = 0 means no time stamp is available. +XFL (eXtra FLags) +These flags are available for use by specific compression methods. The "deflate" method (CM = 8) sets these flags as follows: +XFL = 2 - compressor used maximum compression, + slowest algorithm +XFL = 4 - compressor used fastest algorithm +OS (Operating System) +This identifies the type of file system on which compression took place. This may be useful in determining end-of-line convention for text files. The currently defined values are as follows: + 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) + 1 - Amiga + 2 - VMS (or OpenVMS) + 3 - Unix + 4 - VM/CMS + 5 - Atari TOS + 6 - HPFS filesystem (OS/2, NT) + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - TOPS-20 + 11 - NTFS filesystem (NT) + 12 - QDOS + 13 - Acorn RISCOS +255 - unknown +XLEN (eXtra LENgth) +If FLG.FEXTRA is set, this gives the length of the optional extra field. See below for details. +CRC32 (CRC-32) +This contains a Cyclic Redundancy Check value of the uncompressed data computed according to CRC-32 algorithm used in the ISO 3309 standard and in section 8.1.1.6.2 of ITU-T recommendation V.42. (See http://www.iso.ch for ordering ISO documents. See gopher://info.itu.ch for an online version of ITU-T V.42.) +ISIZE (Input SIZE) +This contains the size of the original (uncompressed) input data modulo 2^32. +Extra field + +If the FLG.FEXTRA bit is set, an "extra field" is present in the header, with total length XLEN bytes. It consists of a series of subfields, each of the form: + ++---+---+---+---+==================================+ +|SI1|SI2| LEN |... LEN bytes of subfield data ...| ++---+---+---+---+==================================+ +SI1 and SI2 provide a subfield ID, typically two ASCII letters with some mnemonic value. Jean-Loup Gailly is maintaining a registry of subfield IDs; please send him any subfield ID you wish to use. Subfield IDs with SI2 = 0 are reserved for future use. The following IDs are currently defined: +SI1 SI2 Data +---------- ---------- ---- +0x41 ('A') 0x70 ('P') Apollo file type information +LEN gives the length of the subfield data, excluding the 4 initial bytes. +Compliance + +A compliant compressor must produce files with correct ID1, ID2, CM, CRC32, and ISIZE, but may set all the other fields in the fixed-length part of the header to default values (255 for OS, 0 for all others). The compressor must set all reserved bits to zero. + +A compliant decompressor must check ID1, ID2, and CM, and provide an error indication if any of these have incorrect values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC at least so it can skip over the optional fields if they are present. It need not examine any other part of the header or trailer; in particular, a decompressor may ignore FTEXT and OS and always produce binary output, and still be compliant. A compliant decompressor must give an error indication if any reserved bit is non-zero, since such a bit could indicate the presence of a new field that would cause subsequent data to be interpreted incorrectly. + +3. References + +[1] "Information Processing - 8-bit single-byte coded graphic character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). The ISO 8859-1 (Latin-1) character set is a superset of 7-bit ASCII. Files defining this character set are available as iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ + +[2] ISO 3309 + +[3] ITU-T recommendation V.42 + +[4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + +[5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ + +[6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table Look-Up", Communications of the ACM, 31(8), pp.1008-1013. + +[7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, pp.118-133. + +[8] ftp://ftp.rocksoft.com/papers/crc_v3.txt, describing the CRC concept. + +4. Security Considerations + +Any data compression method involves the reduction of redundancy in the data. Consequently, any corruption of the data is likely to have severe effects and be difficult to correct. Uncompressed text, on the other hand, will probably still be readable despite the presence of some corrupted bytes. It is recommended that systems using this data format provide some means of validating the integrity of the compressed data, such as by setting and checking the CRC-32 check value. +5. Acknowledgements + +Trademarks cited in this document are the property of their respective owners. +Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, the related software described in this specification. Glenn Randers-Pehrson converted this document to RFC and HTML format. + +6. Author's Address + +L. Peter Deutsch +Aladdin Enterprises +203 Santa Margarita Ave. +Menlo Park, CA 94025 + +Phone: (415) 322-0103 (AM only) +FAX: (415) 322-1734 +EMail: +Questions about the technical content of this specification can be sent by email to: +Jean-Loup Gailly and +Mark Adler +Editorial comments on this specification can be sent by email to: +L. Peter Deutsch and +Glenn Randers-Pehrson +7. Appendix: Jean-Loup Gailly's gzip utility + +The most widely used implementation of gzip compression, and the original documentation on which this specification is based, were created by Jean-Loup Gailly . Since this implementation is a de facto standard, we mention some more of its features here. Again, the material in this section is not part of the specification per se, and implementations need not follow it to be compliant. +When compressing or decompressing a file, gzip preserves the protection, ownership, and modification time attributes on the local file system, since there is no provision for representing protection attributes in the gzip file format itself. Since the file format includes a modification time, the gzip decompressor provides a command line switch that assigns the modification time from the file, rather than the local modification time of the compressed input, to the decompressed output. + +8. Appendix: Sample CRC Code + +The following sample code represents a practical implementation of the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 for a formal specification.) +The sample code is in the ANSI C programming language. Non C users may find it easier to read with these hints: + +& Bitwise AND operator. +^ Bitwise exclusive-OR operator. +>> Bitwise right shift operator. When applied to an + unsigned quantity, as here, right shift inserts zero + bit(s) at the left. +! Logical NOT operator. +++ "n++" increments the variable n. +0xNNN 0x introduces a hexadecimal (base 16) constant. + Suffix L indicates a long value (at least 32 bits). + +/* Table of CRCs of all 8-bit messages. */ +unsigned long crc_table[256]; + +/* Flag: has the table been computed? Initially false. */ +int crc_table_computed = 0; + +/* Make the table for a fast CRC. */ +void make_crc_table(void) +{ + unsigned long c; + int n, k; + + for (n = 0; n < 256; n++) { + c = (unsigned long) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; +} + +/* + Update a running crc with the bytes buf[0..len-1] and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. Usage example: + + unsigned long crc = 0L; + + while (read_buffer(buffer, length) != EOF) { + crc = update_crc(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ +unsigned long update_crc(unsigned long crc, + unsigned char *buf, int len) +{ + unsigned long c = crc ^ 0xffffffffL; + int n; + + if (!crc_table_computed) + make_crc_table(); + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; +} + +/* Return the CRC of the bytes buf[0..len-1]. */ +unsigned long crc(unsigned char *buf, int len) +{ + return update_crc(0L, buf, len); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test.txt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test.txt new file mode 100644 index 0000000..802992c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/test.txt @@ -0,0 +1 @@ +Hello world diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/unzipTest.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/unzipTest.py new file mode 100644 index 0000000..5230134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/unzipTest.py @@ -0,0 +1,60 @@ +import os +from colorama import Fore +from helpers import run_cmd + +outDirDefault = 'test-outs' +testDirDefault = 'test-files' + +""" +Run a single test + +@param tFile- required; the file to check against (uncompressed data) +@param level- optional (default: all); the compression level [1-9] +@return True if all tests passed; False if at least one test failed +""" +def runTest(tFile, level=None, outDir=outDirDefault): + passed = True + + if level == None: + for x in range(1, 10): + if runTest(tFile, x) == False: + passed = False + + return passed + + out1 = os.path.join(outDir, '%(file)s.%(level)d.gz' % {'file': os.path.basename(tFile), 'level' : level}) + out2 = os.path.join(outDir, '%(file)s.%(level)d' % {'file' : os.path.basename(tFile), 'level' : level}) + + run_cmd('gzip -%(level)d -c %(file)s >> %(output)s' % {'level' : level, 'file' : tFile, 'output' : out1}) + run_cmd('../bin/gunzip.js --file %(file)s --output %(output)s' % {'level' : level, 'file' : out1, 'output' : out2}) + + result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : tFile, 'file2' : out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + + return passed + +""" +Runs all tests on the given level. This iterates throuth the testDir directory defined above. + +@param level- The level to run on [1-9] (default: None, runs on all levels all) +@return True if all levels passed, False if at least one failed +""" +def runAll(level=None, testDir=testDirDefault, outDir=outDirDefault): + passed = True + for tFile in os.listdir(testDir): + fullPath = os.path.join(testDir, tFile) + + print Fore.YELLOW + tFile + Fore.RESET + + if runTest(fullPath, level) == False: + passed = False + + print '' + + return passed diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/zipTest.py b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/zipTest.py new file mode 100644 index 0000000..a5b221f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/gzip-js/test/zipTest.py @@ -0,0 +1,60 @@ +import os +from helpers import run_cmd +from colorama import Fore + +defaultTestDir = 'test-files' +defaultOutDir = 'test-outs' + +""" +Run a single test + +@param tFile- required; the full path to the file to run +@param level- optional (default: all); the compression level [1-9] +@return True if all tests passed; False if at least one test failed +""" +def runTest(tFile, level=None, outDir=defaultOutDir): + passed = True + if level == None: + for x in range(1, 10): + if runTest(tFile, x, outDir) == False: + passed = False + + return passed + + out1 = os.path.join(outDir, '%(file)s.%(level)d.gz' % {'file': os.path.basename(tFile), 'level' : level}) + out2 = os.path.join(outDir, '%(file)s.%(level)d.out.gz' % {'file': os.path.basename(tFile), 'level' : level}) + + run_cmd('gzip -c -%(level)d %(file)s > %(outfile)s' % {'level' : level, 'file' : tFile, 'outfile' : out1}) + run_cmd('../bin/gzip.js --level %(level)d --file %(file)s --output %(output)s' % {'level' : level, 'file' : tFile, 'output' : out2}) + + result = run_cmd('diff %(file1)s %(file2)s' % {'file1' : out1, 'file2' : out2}) + if result['returncode'] == 0: + status = Fore.GREEN + 'PASSED' + Fore.RESET + else: + passed = False + status = Fore.RED + 'FAILED' + Fore.RESET + + print 'Level %(level)d: %(status)s' % {'level' : level, 'status' : status} + + return passed + +""" +Runs all tests on the given level. This iterates throuth the testDir directory defined above. + +@param level- The level to run on [1-9] (default: None, runs on all levels all) +@return True if all levels passed, False if at least one failed +""" +def runAll(level=None, testDir=defaultTestDir): + passed = True + for tFile in os.listdir(testDir): + fullPath = os.path.join(testDir, tFile) + + print Fore.YELLOW + tFile + Fore.RESET + + if runTest(fullPath, level) == False: + passed = False + + print '' + + return passed + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/LICENSE-MIT b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/LICENSE-MIT new file mode 100644 index 0000000..90c336c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 "Cowboy" Ben Alman + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/README.md new file mode 100644 index 0000000..138943a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/README.md @@ -0,0 +1,186 @@ +# JavaScript Hooker + +Monkey-patch (hook) functions for debugging and stuff. + +## Getting Started + +This code should work just fine in Node.js: + +First, install the module with: `npm install hooker` + +```javascript +var hooker = require('hooker'); +hooker.hook(Math, "max", function() { + console.log(arguments.length + " arguments passed"); +}); +Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 +``` + +Or in the browser: + +```html + + +``` + +In the browser, you can attach Hooker's methods to any object. + +```html + + + +``` + +## Documentation + +### hooker.hook +Monkey-patch (hook) one or more methods of an object. +#### Signature: +`hooker.hook(object, [ props, ] [options | prehookFunction])` +#### `props` +The 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. +#### `options` +* `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. +* `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. +* `once` - (Boolean) if true, auto-unhook the function after the first execution. +* `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). + +#### Returns: +An array of hooked method names. + +### hooker.unhook +Un-monkey-patch (unhook) one or more methods of an object. +#### Signature: +`hooker.unhook(object [, props ])` +#### `props` +The 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. +#### Returns: +An array of unhooked method names. + +### hooker.orig +Get a reference to the original method from a hooked function. +#### Signature: +`hooker.orig(object, props)` + +### hooker.override +When a pre- or post-hook returns the result of this function, the value +passed will be used in place of the original function's return value. Any +post-hook override value will take precedence over a pre-hook override value. +#### Signature: +`hooker.override(value)` + +### hooker.preempt +When a pre-hook returns the result of this function, the value passed will +be used in place of the original function's return value, and the original +function will NOT be executed. +#### Signature: +`hooker.preempt(value)` + +### hooker.filter +When a pre-hook returns the result of this function, the context and +arguments passed will be applied into the original function. +#### Signature: +`hooker.filter(context, arguments)` + + +## Examples +See the unit tests for more examples. + +```javascript +var hooker = require('hooker'); +// Simple logging. +hooker.hook(Math, "max", function() { + console.log(arguments.length + " arguments passed"); +}); +Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 + +hooker.unhook(Math, "max"); // (This is assumed between all further examples) +Math.max(5, 6, 7) // 7 + +// Returning hooker.override(value) overrides the original value. +hooker.hook(Math, "max", function() { + if (arguments.length === 0) { + return hooker.override(9000); + } +}); +Math.max(5, 6, 7) // 7 +Math.max() // 9000 + +// Auto-unhook after one execution. +hooker.hook(Math, "max", { + once: true, + pre: function() { + console.log("Init something here"); + } +}); +Math.max(5, 6, 7) // logs: "Init something here", returns 7 +Math.max(5, 6, 7) // 7 + +// Filter `this` and arguments through a pre-hook function. +hooker.hook(Math, "max", { + pre: function() { + var args = [].map.call(arguments, function(num) { + return num * 2; + }); + return hooker.filter(this, args); // thisValue, arguments + } +}); +Math.max(5, 6, 7) // 14 + +// Modify the original function's result with a post-hook function. +hooker.hook(Math, "max", { + post: function(result) { + return hooker.override(result * 100); + } +}); +Math.max(5, 6, 7) // 700 + +// Hook every Math method. Note: if Math's methods were enumerable, the second +// argument could be omitted. Since they aren't, an array of properties to hook +// must be explicitly passed. Non-method properties will be skipped. +// See a more generic example here: http://bit.ly/vvJlrS +hooker.hook(Math, Object.getOwnPropertyNames(Math), { + passName: true, + pre: function(name) { + console.log("=> Math." + name, [].slice.call(arguments, 1)); + }, + post: function(result, name) { + console.log("<= Math." + name, result); + } +}); + +var result = Math.max(5, 6, 7); +// => Math.max [ 5, 6, 7 ] +// <= Math.max 7 +result // 7 + +result = Math.ceil(3.456); +// => Math.ceil [ 3.456 ] +// <= Math.ceil 4 +result // 4 +``` + +## 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). + +_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!_ + +## Release History +2012/01/09 - v0.2.3 - First official release. + +## License +Copyright (c) 2012 "Cowboy" Ben Alman +Licensed under the MIT license. + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/child.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/child.js new file mode 100644 index 0000000..ae7dcf2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/child.js @@ -0,0 +1,101 @@ +var path = require('path'); +var fs = require('fs'); +var nodeunit = require('nodeunit'); + +var filepaths = fs.readdirSync('test').map(function(filename) { + return path.join('test', filename); +}); + +var unfinished = {}; +var currentModule; +function sendMessage(message) { + process.stdout.write(JSON.stringify(message) + '\n'); +} + +// If an exception is thrown, let the parent process know and exit. +process.on('uncaughtException', function (e) { + sendMessage({error: [e.name, e.message, e.stack]}); + process.exit(); +}); + +// If Nodeunit explodes because a test was missing test.done(), handle it. +var unfinished = {}; +process.on('exit', function (e) { + var len = Object.keys(unfinished).length + if (len > 0) { + sendMessage({exit: ['UNFINISHED']}); + // process.reallyExit(len); + } else { + sendMessage({exit: ['finished']}); + } + // process.exit(); +}); + +nodeunit.reporters.test = { + run: function(files, options, callback) { + // Nodeunit needs absolute paths. + var paths = files.map(function (filepath) { + return path.resolve(filepath); + }); + nodeunit.runFiles(paths, { + // No idea. + testspec: undefined, + // Executed when the first test in a file is run. If no tests exist in + // the file, this doesn't execute. + moduleStart: function(name) { + // Keep track of this so that moduleDone output can be suppressed in + // cases where a test file contains no tests. + currentModule = name; + // Send back to the parent process. + sendMessage({moduleStart: [name.toString()]}); + }, + // Executed after a file is done being processed. This executes whether + // tests exist in the file or not. + moduleDone: function(name) { + // Abort if no tests actually ran. + if (name !== currentModule) { return; } + // Send back to the parent process. + sendMessage({moduleDone: [name.toString()]}); + }, + // Executed before each test is run. + testStart: function(name) { + // Keep track of the current test, in case test.done() was omitted + // and Nodeunit explodes. + unfinished[name] = name; + // Send back to the parent process. + sendMessage({testStart: [name.toString()]}); + }, + // Executed after each test and all its assertions are run. + testDone: function(name, assertions) { + delete unfinished[name]; + // Send back to the parent process. + sendMessage({testDone: [ + name.toString(), + assertions.failures(), + assertions.map(function(assertion) { + var e = assertion.error; + if (e) { + assertion.error = { + name: e.name, + message: e.message, + stack: e.stack + }; + } + return assertion; + }) + ]}); + }, + // Executed when everything is all done. + done: function (assertions) { + // Send back to the parent process. + sendMessage({done: [ + assertions.failures(), + assertions.duration, + assertions + ]}); + } + }); + } +} + +nodeunit.reporters.test.run(filepaths, {}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js new file mode 100644 index 0000000..d10a321 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.js @@ -0,0 +1,169 @@ +/*! JavaScript Hooker - v0.2.3 - 1/29/2012 +* http://github.com/cowboy/javascript-hooker +* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ + +(function(exports) { + // Get an array from an array-like object with slice.call(arrayLikeObject). + var slice = [].slice; + // Get an "[object [[Class]]]" string with toString.call(value). + var toString = {}.toString; + + // I can't think of a better way to ensure a value is a specific type other + // than to create instances and use the `instanceof` operator. + function HookerOverride(v) { this.value = v; } + function HookerPreempt(v) { this.value = v; } + function HookerFilter(c, a) { this.context = c; this.args = a; } + + // When a pre- or post-hook returns the result of this function, the value + // passed will be used in place of the original function's return value. Any + // post-hook override value will take precedence over a pre-hook override + // value. + exports.override = function(value) { + return new HookerOverride(value); + }; + + // When a pre-hook returns the result of this function, the value passed will + // be used in place of the original function's return value, and the original + // function will NOT be executed. + exports.preempt = function(value) { + return new HookerPreempt(value); + }; + + // When a pre-hook returns the result of this function, the context and + // arguments passed will be applied into the original function. + exports.filter = function(context, args) { + return new HookerFilter(context, args); + }; + + // Execute callback(s) for properties of the specified object. + function forMethods(obj, props, callback) { + var prop; + if (typeof props === "string") { + // A single prop string was passed. Create an array. + props = [props]; + } else if (props == null) { + // No props were passed, so iterate over all properties, building an + // array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so + // this has to be done manually. + props = []; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + } + // Execute callback for every method in the props array. + var i = props.length; + while (i--) { + // If the property isn't a function... + if (toString.call(obj[props[i]]) !== "[object Function]" || + // ...or the callback returns false... + callback(obj, props[i]) === false) { + // ...remove it from the props array to be returned. + props.splice(i, 1); + } + } + // Return an array of method names for which the callback didn't fail. + return props; + } + + // Monkey-patch (hook) a method of an object. + exports.hook = function(obj, props, options) { + // If the props argument was omitted, shuffle the arguments. + if (options == null) { + options = props; + props = null; + } + // If just a function is passed instead of an options hash, use that as a + // pre-hook function. + if (typeof options === "function") { + options = {pre: options}; + } + + // Hook the specified method of the object. + return forMethods(obj, props, function(obj, prop) { + // The original (current) method. + var orig = obj[prop]; + // The new hooked function. + function hooked() { + var result, origResult, tmp; + + // Get an array of arguments. + var args = slice.call(arguments); + + // If passName option is specified, prepend prop to the args array, + // passing it as the first argument to any specified hook functions. + if (options.passName) { + args.unshift(prop); + } + + // If a pre-hook function was specified, invoke it in the current + // context with the passed-in arguments, and store its result. + if (options.pre) { + result = options.pre.apply(this, args); + } + + if (result instanceof HookerFilter) { + // If the pre-hook returned hooker.filter(context, args), invoke the + // original function with that context and arguments, and store its + // result. + origResult = result = orig.apply(result.context, result.args); + } else if (result instanceof HookerPreempt) { + // If the pre-hook returned hooker.preempt(value) just use the passed + // value and don't execute the original function. + origResult = result = result.value; + } else { + // Invoke the original function in the current context with the + // passed-in arguments, and store its result. + origResult = orig.apply(this, arguments); + // If the pre-hook returned hooker.override(value), use the passed + // value, otherwise use the original function's result. + result = result instanceof HookerOverride ? result.value : origResult; + } + + if (options.post) { + // If a post-hook function was specified, invoke it in the current + // context, passing in the result of the original function as the + // first argument, followed by any passed-in arguments. + tmp = options.post.apply(this, [origResult].concat(args)); + if (tmp instanceof HookerOverride) { + // If the post-hook returned hooker.override(value), use the passed + // value, otherwise use the previously computed result. + result = tmp.value; + } + } + + // Unhook if the "once" option was specified. + if (options.once) { + exports.unhook(obj, prop); + } + + // Return the result! + return result; + } + // Re-define the method. + obj[prop] = hooked; + // Fail if the function couldn't be hooked. + if (obj[prop] !== hooked) { return false; } + // Store a reference to the original method as a property on the new one. + obj[prop]._orig = orig; + }); + }; + + // Get a reference to the original method from a hooked function. + exports.orig = function(obj, prop) { + return obj[prop]._orig; + }; + + // Un-monkey-patch (unhook) a method of an object. + exports.unhook = function(obj, props) { + return forMethods(obj, props, function(obj, prop) { + // Get a reference to the original method, if it exists. + var orig = exports.orig(obj, prop); + // If there's no original method, it can't be unhooked, so fail. + if (!orig) { return false; } + // Unhook the method. + obj[prop] = orig; + }); + }; +}(typeof exports === "object" && exports || this)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js new file mode 100644 index 0000000..2bcdb54 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/dist/ba-hooker.min.js @@ -0,0 +1,4 @@ +/*! JavaScript Hooker - v0.2.3 - 1/29/2012 +* http://github.com/cowboy/javascript-hooker +* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */ +(function(a){function d(a){this.value=a}function e(a){this.value=a}function f(a,b){this.context=a,this.args=b}function g(a,b,d){var e;if(typeof b=="string")b=[b];else if(b==null){b=[];for(e in a)a.hasOwnProperty(e)&&b.push(e)}var f=b.length;while(f--)(c.call(a[b[f]])!=="[object Function]"||d(a,b[f])===!1)&&b.splice(f,1);return b}var b=[].slice,c={}.toString;a.override=function(a){return new d(a)},a.preempt=function(a){return new e(a)},a.filter=function(a,b){return new f(a,b)},a.hook=function(c,h,i){return i==null&&(i=h,h=null),typeof i=="function"&&(i={pre:i}),g(c,h,function(c,g){function j(){var j,k,l,m=b.call(arguments);return i.passName&&m.unshift(g),i.pre&&(j=i.pre.apply(this,m)),j instanceof f?k=j=h.apply(j.context,j.args):j instanceof e?k=j=j.value:(k=h.apply(this,arguments),j=j instanceof d?j.value:k),i.post&&(l=i.post.apply(this,[k].concat(m)),l instanceof d&&(j=l.value)),i.once&&a.unhook(c,g),j}var h=c[g];c[g]=j;if(c[g]!==j)return!1;c[g]._orig=h})},a.orig=function(a,b){return a[b]._orig},a.unhook=function(b,c){return g(b,c,function(b,c){var d=a.orig(b,c);if(!d)return!1;b[c]=d})}})(typeof exports=="object"&&exports||this) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/grunt.js new file mode 100644 index 0000000..c695148 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/grunt.js @@ -0,0 +1,47 @@ +/*global config:true, task:true*/ +config.init({ + pkg: '', + meta: { + name: 'JavaScript Hooker', + banner: '/*! <%= meta.name %> - v<%= pkg.version %> - <%= template.today("m/d/yyyy") %>\n' + + '* <%= pkg.homepage %>\n' + + '* Copyright (c) <%= template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + concat: { + 'dist/ba-hooker.js': ['', ''] + }, + min: { + 'dist/ba-hooker.min.js': ['', 'dist/ba-hooker.js'] + }, + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'lint:files test:files' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true + }, + globals: { + exports: true + } + }, + uglify: {} +}); + +// Default task. +task.registerTask('default', 'lint:files test:files concat min'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/lib/hooker.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/lib/hooker.js new file mode 100644 index 0000000..1ff9764 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/lib/hooker.js @@ -0,0 +1,174 @@ +/* + * JavaScript Hooker + * http://github.com/cowboy/javascript-hooker + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * http://benalman.com/about/license/ + */ + +(function(exports) { + // Get an array from an array-like object with slice.call(arrayLikeObject). + var slice = [].slice; + // Get an "[object [[Class]]]" string with toString.call(value). + var toString = {}.toString; + + // I can't think of a better way to ensure a value is a specific type other + // than to create instances and use the `instanceof` operator. + function HookerOverride(v) { this.value = v; } + function HookerPreempt(v) { this.value = v; } + function HookerFilter(c, a) { this.context = c; this.args = a; } + + // When a pre- or post-hook returns the result of this function, the value + // passed will be used in place of the original function's return value. Any + // post-hook override value will take precedence over a pre-hook override + // value. + exports.override = function(value) { + return new HookerOverride(value); + }; + + // When a pre-hook returns the result of this function, the value passed will + // be used in place of the original function's return value, and the original + // function will NOT be executed. + exports.preempt = function(value) { + return new HookerPreempt(value); + }; + + // When a pre-hook returns the result of this function, the context and + // arguments passed will be applied into the original function. + exports.filter = function(context, args) { + return new HookerFilter(context, args); + }; + + // Execute callback(s) for properties of the specified object. + function forMethods(obj, props, callback) { + var prop; + if (typeof props === "string") { + // A single prop string was passed. Create an array. + props = [props]; + } else if (props == null) { + // No props were passed, so iterate over all properties, building an + // array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so + // this has to be done manually. + props = []; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + } + // Execute callback for every method in the props array. + var i = props.length; + while (i--) { + // If the property isn't a function... + if (toString.call(obj[props[i]]) !== "[object Function]" || + // ...or the callback returns false... + callback(obj, props[i]) === false) { + // ...remove it from the props array to be returned. + props.splice(i, 1); + } + } + // Return an array of method names for which the callback didn't fail. + return props; + } + + // Monkey-patch (hook) a method of an object. + exports.hook = function(obj, props, options) { + // If the props argument was omitted, shuffle the arguments. + if (options == null) { + options = props; + props = null; + } + // If just a function is passed instead of an options hash, use that as a + // pre-hook function. + if (typeof options === "function") { + options = {pre: options}; + } + + // Hook the specified method of the object. + return forMethods(obj, props, function(obj, prop) { + // The original (current) method. + var orig = obj[prop]; + // The new hooked function. + function hooked() { + var result, origResult, tmp; + + // Get an array of arguments. + var args = slice.call(arguments); + + // If passName option is specified, prepend prop to the args array, + // passing it as the first argument to any specified hook functions. + if (options.passName) { + args.unshift(prop); + } + + // If a pre-hook function was specified, invoke it in the current + // context with the passed-in arguments, and store its result. + if (options.pre) { + result = options.pre.apply(this, args); + } + + if (result instanceof HookerFilter) { + // If the pre-hook returned hooker.filter(context, args), invoke the + // original function with that context and arguments, and store its + // result. + origResult = result = orig.apply(result.context, result.args); + } else if (result instanceof HookerPreempt) { + // If the pre-hook returned hooker.preempt(value) just use the passed + // value and don't execute the original function. + origResult = result = result.value; + } else { + // Invoke the original function in the current context with the + // passed-in arguments, and store its result. + origResult = orig.apply(this, arguments); + // If the pre-hook returned hooker.override(value), use the passed + // value, otherwise use the original function's result. + result = result instanceof HookerOverride ? result.value : origResult; + } + + if (options.post) { + // If a post-hook function was specified, invoke it in the current + // context, passing in the result of the original function as the + // first argument, followed by any passed-in arguments. + tmp = options.post.apply(this, [origResult].concat(args)); + if (tmp instanceof HookerOverride) { + // If the post-hook returned hooker.override(value), use the passed + // value, otherwise use the previously computed result. + result = tmp.value; + } + } + + // Unhook if the "once" option was specified. + if (options.once) { + exports.unhook(obj, prop); + } + + // Return the result! + return result; + } + // Re-define the method. + obj[prop] = hooked; + // Fail if the function couldn't be hooked. + if (obj[prop] !== hooked) { return false; } + // Store a reference to the original method as a property on the new one. + obj[prop]._orig = orig; + }); + }; + + // Get a reference to the original method from a hooked function. + exports.orig = function(obj, prop) { + return obj[prop]._orig; + }; + + // Un-monkey-patch (unhook) a method of an object. + exports.unhook = function(obj, props) { + return forMethods(obj, props, function(obj, prop) { + // Get a reference to the original method, if it exists. + var orig = exports.orig(obj, prop); + // If there's no original method, it can't be unhooked, so fail. + if (!orig) { return false; } + // Unhook the method. + obj[prop] = orig; + }); + }; +}(typeof exports === "object" && exports || this)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/package.json new file mode 100644 index 0000000..97e7761 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/package.json @@ -0,0 +1,45 @@ +{ + "name": "hooker", + "description": "Monkey-patch (hook) functions for debugging and stuff.", + "version": "0.2.3", + "homepage": "http://github.com/cowboy/javascript-hooker", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/cowboy/javascript-hooker.git" + }, + "bugs": { + "url": "https://github.com/cowboy/javascript-hooker/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cowboy/javascript-hooker/blob/master/LICENSE-MIT" + } + ], + "dependencies": {}, + "devDependencies": { + "grunt": "~0.2.1" + }, + "keywords": [ + "patch", + "hook", + "function", + "debug", + "aop" + ], + "engines": { + "node": "*" + }, + "main": "lib/hooker", + "scripts": { + "test": "grunt test" + }, + "readme": "# JavaScript Hooker\n\nMonkey-patch (hook) functions for debugging and stuff.\n\n## Getting Started\n\nThis code should work just fine in Node.js:\n\nFirst, install the module with: `npm install hooker`\n\n```javascript\nvar hooker = require('hooker');\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```\n\nOr in the browser:\n\n```html\n\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/hooker/parent.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/parent.js new file mode 100644 index 0000000..c4a055e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/parent.js @@ -0,0 +1,17 @@ +var spawn = require('child_process').spawn; + +function loop() { + console.log('starting'); + console.log(this); + //var child = spawn('./node_modules/nodeunit/bin/nodeunit', ['test']); + var child = spawn('node', ['child.js']); + child.stdout.on('data', function(buffer) { + process.stdout.write(buffer); + }); + child.on('exit', this.async()); +} + +var context = { + async: function() { return loop.bind(context); } +}; +loop.call(context); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/test/hooker_test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/test/hooker_test.js new file mode 100644 index 0000000..dc5910a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/hooker/test/hooker_test.js @@ -0,0 +1,435 @@ +/*global require:true */ +var hooker = require('../lib/hooker'); + +exports['hook'] = { + setUp: function(done) { + this.order = []; + this.track = function() { + [].push.apply(this.order, arguments); + }; + + this.prop = 1; + this.add = function(a, b) { + this.track("add", this.prop, a, b); + return this.prop + a + b; + }; + + this.obj = { + that: this, + prop: 1, + add1: function(a, b) { + this.that.track("add1", this.prop, a, b); + return this.prop + a + b; + }, + add2: function(a, b) { + this.that.track("add2", this.prop, a, b); + return this.prop + a + b; + }, + add3: function(a, b) { + this.that.track("add3", this.prop, a, b); + return this.prop + a + b; + } + }; + + done(); + }, + 'orig': function(test) { + test.expect(1); + var orig = this.add; + hooker.hook(this, "add", function() {}); + test.strictEqual(hooker.orig(this, "add"), orig, "should return a refernce to the original function."); + test.done(); + }, + 'once': function(test) { + test.expect(5); + var orig = this.add; + hooker.hook(this, "add", { + once: true, + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + } + }); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.strictEqual(this.add, orig, "should automatically unhook when once is specified."); + this.order = []; + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add", 1, 2, 3], "only the original function should execute."); + test.done(); + }, + 'pre-hook (simple syntax)': function(test) { + test.expect(3); + // Pre-hook. + var result = hooker.hook(this, "add", function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre-hook': function(test) { + test.expect(3); + // Pre-hook. + var result = hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + } + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'post-hook': function(test) { + test.expect(3); + // Post-hook. + var result = hooker.hook(this, "add", { + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result, ["add"], "add should have been hooked."); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, return value override': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // This return value will override the original function's return value. + return hooker.override("b" + this.prop + a + b); + } + }); + test.strictEqual(this.add(2, 3), "b123", "should return the overridden result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'post-hook, return value override': function(test) { + test.expect(2); + // Post-hook. + hooker.hook(this, "add", { + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1236", "should return the post-hook overridden result."); + test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // This return value will override the original function's return value. + return hooker.override("b" + this.prop + a + b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value + // AND the pre-hook's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1236", "should return the overridden result, and post-hook result should take precedence over pre-hook result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, filtering arguments': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + } + }); + test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z"], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, filtering arguments': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, filtering arguments, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Return hooker.filter(context, arguments) and they will be passed into + // the original function. The "track" and "order" propterites are just + // set here for the same of this unit test. + return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override the original function's return value + // AND the pre-hook's return value. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a123xyz", "should return the post-hook overridden result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order."); + test.done(); + }, + + 'pre-hook, preempt original function': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(); + } + }); + test.strictEqual(this.add(2, 3), undefined, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre-hook, preempt original function with value': function(test) { + test.expect(2); + // Pre-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + } + }); + test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, preempt original function with value': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + } + }); + test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt."); + test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, preempt original function with value, return value override': function(test) { + test.expect(2); + // Pre- & post-hook. + hooker.hook(this, "add", { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.track("before", this.prop, a, b); + // Returning hooker.preempt will prevent the original function from being + // invoked and optionally set a return value. + return hooker.preempt(9000); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.track("after", this.prop, a, b, result); + // This return value will override any preempt value set in pre-hook. + return hooker.override("a" + this.prop + a + b + result); + } + }); + test.strictEqual(this.add(2, 3), "a1239000", "should return the overridden result, and post-hook result should take precedence over preempt value."); + test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, some properties': function(test) { + test.expect(7); + // Pre- & post-hook. + var result = hooker.hook(this.obj, ["add1", "add2"], { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been hooked."); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["add3", 1, 2, 3], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, all properties': function(test) { + test.expect(7); + // Pre- & post-hook. + var result = hooker.hook(this.obj, { + pre: function(a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, a, b); + }, + post: function(result, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, a, b, result); + } + }); + test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been hooked."); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, 2, 3, "add3", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'pre- & post-hook, all properties, passName': function(test) { + test.expect(6); + // Pre- & post-hook. + hooker.hook(this.obj, { + passName: true, + pre: function(name, a, b) { + // Arguments are passed into pre-hook as specified. + this.that.track("before", this.prop, name, a, b); + }, + post: function(result, name, a, b) { + // Arguments to post-hook are the original function's return value, + // followed by the specified function arguments. + this.that.track("after", this.prop, name, a, b, result); + } + }); + test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add1", 2, 3, "add1", 1, 2, 3, "after", 1, "add1", 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add2", 2, 3, "add2", 1, 2, 3, "after", 1, "add2", 2, 3, 6], "functions should execute in-order."); + this.order = []; + test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result."); + test.deepEqual(this.order, ["before", 1, "add3", 2, 3, "add3", 1, 2, 3, "after", 1, "add3", 2, 3, 6], "functions should execute in-order."); + test.done(); + }, + 'unhook one property': function(test) { + test.expect(5); + var orig = this.add; + hooker.hook(this, "add", function() {}); + var result = hooker.unhook(this, "add"); + test.deepEqual(result, ["add"], "one function should have been unhooked."); + test.strictEqual(this.add, orig, "should have unhooked, restoring the original function"); + result = hooker.unhook(this, "add"); + test.deepEqual(result, [], "nothing should have been unhooked."); + test.strictEqual(this.add, orig, "shouldn't explode if already unhooked"); + test.strictEqual(this.add.orig, undefined, "original function shouldn't have an orig property"); + test.done(); + }, + 'unhook some properties': function(test) { + test.expect(6); + var add1 = this.obj.add1; + var add2 = this.obj.add2; + hooker.hook(this.obj, ["add1", "add2"], function() {}); + test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add3"), undefined, "should not have been hooked, so should not have an original function"); + var result = hooker.unhook(this.obj, ["add1", "add2"]); + test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been unhooked."); + test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function"); + test.done(); + }, + 'unhook all properties': function(test) { + test.expect(7); + var add1 = this.obj.add1; + var add2 = this.obj.add2; + var add3 = this.obj.add3; + hooker.hook(this.obj, function() {}); + test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function"); + test.strictEqual(hooker.orig(this.obj, "add3"), add3, "should return a refernce to the original function"); + var result = hooker.unhook(this.obj); + test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been unhooked."); + test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function"); + test.strictEqual(this.obj.add3, add3, "should have unhooked, restoring the original function"); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/LICENSE new file mode 100644 index 0000000..0b310fe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/LICENSE @@ -0,0 +1,4 @@ +** Licensed Under ** + + The MIT License + http://www.opensource.org/licenses/mit-license.php 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 new file mode 100644 index 0000000..ac1ee12 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/README.md @@ -0,0 +1,91 @@ +# node-jshint + +A command line interface and npm package for jshint. + +## Install + +To use jshint from any location (for npm v1.x) you need to install using the global (-g) flag. + + npm install -g jshint + +## Usage + + jshint -h + +You can also require JSHint itself as a module. + + var jshint = require('jshint'); + +Note: If you are using npm v1.x be sure to install jshint locally (without the -g flag) or link it globally. + +## Text Editor Plugins + +* [gedit-node-jshint](https://github.com/niftylettuce/gedit-node-jshint) - Simply use CTRL+J in gedit to run JSHint using `node-jshint`. +* [vim syntastic](https://github.com/scrooloose/syntastic) - Run node-jshint at each file save. +* [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. + +## Custom Reporters + +Specify a custom reporter module (see example/reporter.js). + + --reporter path/to/reporter.js + +Use a jslint compatible xml reporter. + + --jslint-reporter + +Show additional non-error data generated by jshint (unused globals etc). + + --show-non-errors + +## 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 Manually + +Setting the `--config=/path/to/your/config` command line option to specify your own configuration file outside of the directory tree for your project. + +### Within your Project's Directory Tree + +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. + +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. + +### Home Directory + +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 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). + +## Installing dependencies for development + + ./configure + +## 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/bin/hint b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/bin/hint new file mode 100755 index 0000000..2b11eec --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/bin/hint @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./../lib/cli').interpret(process.argv); 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 new file mode 100644 index 0000000..14d6ed4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/cli.js @@ -0,0 +1,159 @@ +var fs = require('fs'), + path = require('path'), + cli = require('cli').enable('glob', 'help'), + hint = require('./hint'); + +function existsSync() { + var obj = fs.existsSync ? fs : path; + return obj.existsSync.apply(obj, arguments); +} + +function _removeJsComments(str) { + str = str || ''; + + // 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 filePath && existsSync(filePath) ? + JSON.parse(_removeJsComments(fs.readFileSync(filePath, "utf-8"))) : {}; +} + +/** + * 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 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) { + function exit() { + process.exit(results.length > 0 ? 1 : 0); + } + + // avoid stdout cutoff in node 0.4.x, also supports 0.5.x + // see https://github.com/joyent/node/issues/1669 + try { + if (!process.stdout.flush()) { + process.stdout.once("drain", exit); + } else { + exit(); + } + } catch (e) { + exit(); + } +} + +module.exports = { + interpret: function (args) { + 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 (options.help || !cli.args.length) { + cli.getUsage(); + process.exit(); + return; + } + + if (options['jslint-reporter']) { + customReporter = "./reporters/jslint_xml.js"; + } + + if (options['checkstyle-reporter']) { + customReporter = "./reporters/checkstyle.js"; + } + + if (options['show-non-errors']) { + customReporter = "./reporters/non_error.js"; + } + + config = _loadAndParseConfig(customConfig ? customConfig : _findConfig()); + + if (customReporter) { + try { + reporter = require(customReporter).reporter; + } catch (r) { + process.stdout.write("Error opening reporter file: " + customReporter); + process.stdout.write(r + "\n"); + process.exit(1); + } + } + + 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(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 new file mode 100644 index 0000000..0ecbbe8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/hint.js @@ -0,0 +1,125 @@ +var fs = require('fs'), + minimatch = require('minimatch'), + path = require('path'), + jshint = require('./../packages/jshint/jshint.js'), + _reporter = require('./reporters/default').reporter, + _cache = { + directories: {} + }; + +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) { + process.stdout.write("Error: Cant open: " + file); + process.stdout.write(e + '\n'); + } + + // Remove potential Unicode Byte Order Mark. + buffer = buffer.replace(/^\uFEFF/, ''); + + // 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}); + } + }); + } + + lintdata = jshint.JSHINT.data(); + + if (lintdata) { + lintdata.file = file; + data.push(lintdata); + } +} + +function isDirectory(aPath) { + var isDir; + + try { + if (_cache.directories.hasOwnProperty(aPath)) { + isDir = _cache.directories[aPath]; + } else { + isDir = fs.statSync(aPath).isDirectory(); + _cache.directories[aPath] = isDir; + } + } catch (e) { + isDir = false; + } + + return isDir; +} + + +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 || absmatch); + } + + return ignore.some(function (ignorePath) { + return isIgnored(ignorePath); + }); +} + +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, regExtension); + }); + } else if (filePath.match(regExtension)) { + files.push(filePath); + } +} + +module.exports = { + hint: function (targets, config, reporter, ignore, extraExtensionList) { + var files = [], + results = [], + data = [], + regExtension; + + extraExtensionList = extraExtensionList || ""; + regExtension = new RegExp('\\.(js' + (extraExtensionList === "" ? "" : "|" + extraExtensionList.replace(/,/g, "|").replace(/[\. ]/g, "")) + ")$"); + + targets.forEach(function (target) { + _collect(target, files, ignore, regExtension); + }); + + files.forEach(function (file) { + _lint(file, results, config, data); + }); + + _cache = { + directories: {} + }; + + (reporter || _reporter)(results, data); + + return results; + } +}; 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 new file mode 100644 index 0000000..90805d8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/default.js @@ -0,0 +1,18 @@ +module.exports = { + reporter: function (results) { + var len = results.length, + str = '', + file, error; + + results.forEach(function (result) { + file = result.file; + error = result.error; + str += file + ': line ' + error.line + ', col ' + + error.character + ', ' + error.reason + '\n'; + }); + + if (str) { + process.stdout.write(str + "\n" + len + ' error' + ((len === 1) ? '' : 's') + "\n"); + } + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/jslint_xml.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/jslint_xml.js new file mode 100644 index 0000000..eca2327 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/jslint_xml.js @@ -0,0 +1,54 @@ +// Author: Vasili Sviridov +// http://github.com/vsviridov +module.exports = +{ + reporter: function (results) + { + "use strict"; + + var files = {}, + out = [], + pairs = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">" + }, + file, i, issue; + + 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) { + result.file = result.file.replace(/^\.\//, ''); + if (!files[result.file]) { + files[result.file] = []; + } + files[result.file].push(result.error); + }); + + out.push(""); + out.push(""); + + for (file in files) { + out.push("\t"); + for (i = 0; i < files[file].length; i++) { + issue = files[file][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/non_error.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js new file mode 100644 index 0000000..6b1f8c4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/lib/reporters/non_error.js @@ -0,0 +1,45 @@ +/*jshint node: true */ +module.exports = +{ + reporter: function (results, data) { + var len = results.length, + str = '', + file, error, globals, unuseds; + + results.forEach(function (result) { + file = result.file; + error = result.error; + str += file + ': line ' + error.line + ', col ' + + error.character + ', ' + error.reason + '\n'; + }); + + str += len > 0 ? ("\n" + len + ' error' + ((len === 1) ? '' : 's')) : ""; + + data.forEach(function (data) { + file = data.file; + globals = data.implieds; + unuseds = data.unused; + + if (globals || unuseds) { + str += '\n\n' + file + ' :\n'; + } + + if (globals) { + str += '\tImplied globals:\n'; + globals.forEach(function (global) { + str += '\t\t' + global.name + ': ' + global.line + '\n'; + }); + } + if (unuseds) { + str += '\tUnused Variables:\n\t\t'; + unuseds.forEach(function (unused) { + str += unused.name + '(' + unused.line + '), '; + }); + } + }); + + if (str) { + process.stdout.write(str + "\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/cli/node_modules/glob/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 new file mode 100644 index 0000000..016d7fb --- /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/AUTHORS @@ -0,0 +1,8 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Carlos Brito Lage +Marko Mikulicic +Trent Mick +Kevin O'Hara +Marco Rogers +Jesse Dailey 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/cli/node_modules/glob/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 new file mode 100644 index 0000000..7ee278a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/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 new file mode 100644 index 0000000..0fec4b0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/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 new file mode 100644 index 0000000..25f1f60 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/cli/node_modules/glob/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} 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/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/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/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/minimatch/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/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/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/minimatch/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md new file mode 100644 index 0000000..2664c08 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/README.md @@ -0,0 +1,114 @@ +# 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 all glob features. + +See: + +* `man sh` +* `man fnmatch` +* `man 5 gitignore` + +### Departures from zsh/bash/ksh/sh + +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.) + +The double-star `**` is always supported, instead of requiring a special +flag. + +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?"`. + +## Functions + +### minimatch(path, pattern, options) + +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`. + +### minimatch.match(list, pattern, options) + +Match against the list of +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. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### null + +Return an empty list from minimatch.match, instead of a list +containing the pattern itself. + +### nocase + +Perform a case-insensitive match. + +### cache + +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 `xyz/123/acb`. + +### partial + +Internal. Used by `minimatch.makeRe`. + +### dot + +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 new file mode 100644 index 0000000..c50ab71 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/minimatch.js @@ -0,0 +1,372 @@ +// This is a JavaScript implementation of the fnmatch-like +// stuff that git uses in its .gitignore files. +// See `man 5 gitignore`. + +module.exports = minimatch + +var path = require("path") + , LRU = require("lru-cache") + +minimatch.filter = function (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, 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) + + // 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 ret +} + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + options = options || {} + + // 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) return p === "" + + // comments. + if (pattern.trim().charAt(0) === "#") return false + + // check the cache + var re = cache.get(pattern + "\n" + JSON.stringify(options)) + if (!re && re !== false) { + cache.set(pattern, re = minimatch.makeRe(pattern, options)) + } + + 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 +} + +minimatch.makeRe = makeRe +function makeRe (pattern, options) { + options = options || {} + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += oneStar + break + case "?": + re += "." + break + default: + re += "\\"+stateChar + break + } + stateChar = false + } + } + + 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 ++ ) { + + if (options.debug) { + console.error("%s\t%s %s %j", pattern, i, re, c) + } + + switch (c) { + case "\\": + 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 + case "!": + 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) + } + + negating = false + if (escaping) { + re += "\\" + c + escaping = false + } else if (inClass) { + re += c + } else if (c === "*" && stateChar === "*") { // ** + re += twoStar + stateChar = false + } else { + if (stateChar) { + if (stateChar === "*") re += oneStar + else if (stateChar === "?") re += "." + else re += "\\" + stateChar + } + stateChar = c + } + continue + + case "(": + if (escaping) { + re += "\\(" + escaping = false + } else if (inClass) { + re += "(" + } else if (stateChar) { + plType = stateChar + patternListStack.push(plType) + re += stateChar === "!" ? "(?!" : "(?:" + stateChar = false + } else { + re += "\\(" + } + continue + + case ")": + 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 + + case "|": + if (escaping || inClass) { + re += "\\|" + escaping = false + } else if (patternListStack.length) { + re += "|" + } else { + re += "\\|" + } + continue + + // these are mostly the same in regexp and glob :) + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (escaping || inClass) { + re += "\\" + c + escaping = false + } else { + inClass = true + classStart = i + reClassStart = re.length + re += classStartPattern + 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) escaping = true + + if (escaping || !inClass) { + re += "\\" + c + escaping = false + } else { + inClass = false + re += c + classEndPattern + } + continue + + 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: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials.indexOf(c) !== -1 + && !(c === "^" && inClass)) { + re += "\\" + } + + 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 += "\\\\" + } + + // "[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 = re.substr(reClassStart + classStartPattern.length + 1) + , csOpts = Object.create(options) + csOpts.partial = true + + re = re.substr(0, reClassStart) + "\\[" + + makeRe(cs, csOpts) + } + + if (options.partial) return re + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^" + re + "$" + + // fail on the pattern, but allow anything otherwise. + if (negate) re = "^(?!" + re + ").*$" + + // really insane glob patterns can cause bad things. + var flags = "" + if (options.nocase) flags += "i" + + if (options.debug) { + console.error("/%s/%s", re, flags) + } + + try { + return new RegExp(re, flags) + } catch(ex) { + return false + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/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/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/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/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/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/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 new file mode 100644 index 0000000..0f3908d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,14 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +Usage: + + var LRU = require("lru-cache") + , cache = LRU(10) // max 10 items. default = Infinity + cache.set("key", "value") + cache.get("key") // "value" + + cache.reset() // empty the cache + +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 new file mode 100644 index 0000000..c3e4feb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,106 @@ +;(function () { // closure for web browsers + +if (module) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + ;(function () { return this })().LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function LRUCache (maxLength) { + if (!(this instanceof LRUCache)) { + return new LRUCache(maxLength) + } + 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 + + // resize the cache when the maxLength changes. + Object.defineProperty(this, "maxLength", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + maxLength = mL + // if it gets above double maxLength, trim right away. + // otherwise, do it whenever it's convenient. + if (length > maxLength) trim() + } + , get : function () { return maxLength } + , enumerable : true + }) + + this.maxLength = maxLength + + Object.defineProperty(this, "length", + { get : function () { return length } + , enumerable : true + }) + + this.reset = function () { + cache = {} + lruList = {} + lru = 0 + mru = 0 + length = 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)) { + this.get(key) + cache[key].value = value + return undefined + } + var hit = {key:key, value:value, lu:mru++} + lruList[hit.lu] = cache[key] = hit + length ++ + if (length > maxLength) trim() + } + + this.get = function (key) { + if (!hOP(cache, key)) return undefined + var hit = cache[key] + delete lruList[hit.lu] + if (hit.lu === lru) lruWalk() + hit.lu = mru ++ + lruList[hit.lu] = hit + return hit.value + } + + this.del = function (key) { + if (!hOP(cache, key)) return undefined + var hit = cache[key] + delete cache[key] + delete lruList[hit.lu] + if (hit.lu === lru) lruWalk() + length -- + } + + function lruWalk () { + // lru has been deleted, hop up to the next hit. + lru = Object.keys(lruList).shift() + } + + function trim () { + 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 new file mode 100644 index 0000000..238aab2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,28 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "1.0.6", + "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": "0" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\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 new file mode 100644 index 0000000..f6d7a6d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,117 @@ +var test = require('tap').test + , LRU = require('../') + +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.maxLength, 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('maxLength', function (t) { + var cache = new LRU(3) + + // 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.maxLength = 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 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.maxLength = 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.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) { + 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() +}) 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 new file mode 100644 index 0000000..9f9a4b0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/package.json @@ -0,0 +1,37 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.0.5", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "~1.0.2" + }, + "devDependencies": { + "tap": "~0.0.5" + }, + "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 new file mode 100644 index 0000000..f4f585f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/node_modules/minimatch/test/basic.js @@ -0,0 +1,167 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test + +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*"]] + // allow null glob expansion + , ["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 + , ["\\*", ["\\*"]] + , ["\\**", ["\\**"]] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + + , ["\\.\\./*/", ["\\.\\./*/"]] + , ["s/\\..*//", ["s/\\..*//"]] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"]] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"]] + + , "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"]] + , ["[/\\\\]*", ["/tmp"], null, ["/tmp"]] + , ["??**********?****?", [], { 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"]] + + // 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"]] + + ].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 r = mm.makeRe(pattern, options) + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + + var actual = mm.match(f, pattern, options) + + 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/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json new file mode 100644 index 0000000..025eee6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/package.json @@ -0,0 +1,41 @@ +{ + "name": "jshint", + "version": "0.9.1", + "description": "A CLI for JSHint", + "homepage": "http://github.com/jshint/node-jshint", + "author": { + "name": "Brent Lintner", + "email": "brent.lintner@gmail.com", + "url": "http://github.com/brentlintner" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://www.opensource.org/licenses/mit-license.php" + } + ], + "bin": { + "jshint": "./bin/hint" + }, + "main": "packages/jshint/jshint", + "files": [ + "packages/jshint/README.markdown", + "packages/jshint/jshint.js", + "README.md", + "LICENSE", + "bin/hint", + "lib" + ], + "dependencies": { + "cli": "0.4.3", + "minimatch": "0.0.x" + }, + "devDependencies": { + "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\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.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.md new file mode 100755 index 0000000..3a27978 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/README.md @@ -0,0 +1,104 @@ +JSHint, A Static Code Analysis Tool for JavaScript +================================================== + +JSHint is a community-driven tool to detect errors and potential problems in +JavaScript code and to enforce your team's coding conventions. + +**IMPORTANT**: + + * This README is for people who are thinking about contributing to JSHint. For general usage + please refer to [our website](http://jshint.com/). + * If you want to report a bug about the website, please go to the + [jshint/site](https://github.com/jshint/site/) repository. + * If you want to report a bug or contribute to our NPM package, please go to the + [jshint/node-jshint](https://github.com/jshint/node-jshint/) repository. + +Reporting a bug +--------------- + +To report a bug simply create a [new GitHub Issue](https://github.com/jshint/jshint/issues/new) and +describe your problem or suggestion. We welcome all kind of feedback regarding JSHint including but +not limited to: + + * When JSHint doesn't work as expected + * When JSHint complains about valid JavaScript code that works in all browsers + * When you simply want a new option or feature + +Please, before reporting a bug look around to see if there are any open or closed tickets that +cover your issue. And remember the wisdom: pull request > bug report > tweet. + +Submitting patches +------------------ + +The best way to make sure your issue is addressed is to submit a patch. GitHub provides a very +nice interface--pull requests--for that but we accept patches through all mediums: email, issue +comment, tweet with a link to a snippet, etc. + +Before submitting a patch make sure that you comply to our style. We don't have specific style +guide so just look around the code you are changing. + +Also, make sure that you write tests for new features and make sure that all tests pass before +submitting a patch. Patches that break the build will be rejected. + +**FEATURE FREEZE**: Please note that we currently have a feature freeze on new environments and +styling options. The only patches we accept at this time are for bug fixes. + +Tests +----- + +To run tests you will need to install [node.js](http://nodejs.org/) and +expresso. You can install the latter with npm: + + npm install expresso + +After that, running the unit tests is as easy as: + + expresso tests/unit/*.js + +Attribution +----------- + +Core Team members: + + * [Anton Kovalyov](http://anton.kovalyov.net/) ([@valueof](http://twitter.com/valueof)) + * [Wolfgang Kluge](http://klugesoftware.de/) ([blog](http://gehirnwindung.de/)) + * [Josh Perez](http://www.goatslacker.com/) ([@goatslacker](http://twitter.com/goatslacker)) + +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! +---------- + +We really appreciate all kind of feedback and contributions. Thanks for using and supporting JSHint! 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 new file mode 100644 index 0000000..53724f5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/jshint/packages/jshint/jshint.js @@ -0,0 +1,4832 @@ +/*! + * JSHint, by JSHint Community. + * + * 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. + * + */ + +/* + JSHINT is a global function. It takes two parameters. + + var myResult = JSHINT(source, option); + + The first parameter is either a string or an array of strings. If it is a + string, it will be split on '\n' or '\r'. If it is an array of strings, it + is assumed that each string represents one line. The source can be a + JavaScript text or a JSON text. + + The second parameter is an optional object of options which control the + operation of JSHINT. Most of the options are booleans: They are all + optional and have a default value of false. One of the options, predef, + can be an array of names, which will be used to declare global variables, + or an object whose keys are used as global names, with a boolean value + that determines if they are assignable. + + If it checks out, JSHINT returns true. Otherwise, it returns false. + + If false, you can inspect JSHINT.errors to find out the problems. + JSHINT.errors is an array of objects containing these members: + + { + 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 + a : The first detail + b : The second detail + c : The third detail + d : The fourth detail + } + + If a fatal error was found, a null will be the last element of the + JSHINT.errors array. + + You can request a data structure which contains JSHint's results. + + var myData = JSHINT.data(); + + It returns a structure with this form: + + { + errors: [ + { + line: NUMBER, + character: NUMBER, + reason: STRING, + evidence: STRING + } + ], + functions: [ + name: STRING, + line: NUMBER, + character: NUMBER, + last: NUMBER, + lastcharacter: NUMBER, + param: [ + STRING + ], + closure: [ + STRING + ], + var: [ + STRING + ], + exception: [ + STRING + ], + outer: [ + STRING + ], + unused: [ + STRING + ], + global: [ + STRING + ], + label: [ + STRING + ] + ], + globals: [ + STRING + ], + member: { + STRING: NUMBER + }, + unused: [ + { + name: STRING, + line: NUMBER + } + ], + implieds: [ + { + name: STRING, + line: NUMBER + } + ], + urls: [ + STRING + ], + json: BOOLEAN + } + + Empty arrays will not be included. + +*/ + +/*jshint + evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true, + undef: true, maxlen: 100, indent: 4, quotmark: double, unused: true +*/ + +/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", + "(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, 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, + HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement, + HTMLDivElement, HTMLDListElement, HTMLFieldSetElement, + HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, + HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement, + HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement, + HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement, + HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement, + HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, + HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement, + HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement, + HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, + HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, + HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement, + Iframe, IframeShim, Image, importScripts, Int16Array, Int32Array, Int8Array, + Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, + 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, 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, internals, instanceOf, isAlpha, isApplicationRunning, isArray, + isDigit, isFinite, isNaN, iterator, java, join, jshint, + 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 */ + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSHINT function itself. + +var JSHINT = (function () { + "use strict"; + + var anonname, // The guessed name for anonymous functions. + +// 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 + }, + + // These are the JSHint boolean options. + boolOptions = { + asi : true, // if automatic semicolon insertion should be tolerated + 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 + devel : true, // if logging globals should be predefined (console, + // alert, etc.) + dojo : true, // if Dojo Toolkit globals should be predefined + eqeqeq : true, // if === should be required + eqnull : true, // if == null comparisons should be tolerated + es5 : true, // if ES5 syntax should be allowed + esnext : true, // if es.next specific syntax should be allowed + evil : true, // if eval should be allowed + expr : true, // if ExpressionStatement should be allowed as Programs + forin : true, // if for in statements must filter + funcscope : true, // if only function scope should be used for scope tests + globalstrict: true, // if global "use strict"; should be allowed (also + // enables 'strict') + immed : true, // if immediate invocations must be wrapped in parens + iterator : true, // if the `__iterator__` property should be allowed + jquery : true, // if jQuery globals should be predefined + lastsemic : true, // if semicolons may be ommitted for the trailing + // statements inside of a one-line blocks. + latedef : true, // if the use before definition should not be tolerated + laxbreak : true, // if line breaks should not be checked + laxcomma : true, // if line breaks should not be checked around commas + loopfunc : true, // if functions should be allowed to be defined within + // loops + mootools : true, // if MooTools globals should be predefined + multistr : true, // allow multiline strings + newcap : true, // if constructor names must be capitalized + noarg : true, // if arguments.caller and arguments.callee should be + // disallowed + node : true, // if the Node.js environment globals should be + // predefined + noempty : true, // if empty blocks should be disallowed + nonew : true, // if using `new` for side-effects should be disallowed + nonstandard : true, // if non-standard (but widely adopted) globals should + // be predefined + nomen : true, // if names should be checked + onevar : true, // if only one var statement per function should be + // allowed + onecase : true, // if one case switch statements should be allowed + passfail : true, // if the scan should stop on first error + plusplus : true, // if increment/decrement should not be allowed + proto : true, // if the `__proto__` property should be allowed + prototypejs : true, // if Prototype and Scriptaculous globals should be + // predefined + regexdash : true, // if unescaped first/last dash (-) inside brackets + // should be tolerated + 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 + // (http://www.emacswiki.org/emacs/SmartTabs) + strict : true, // require the "use strict"; pragma + sub : true, // if all forms of subscript notation are tolerated + supernew : true, // if `new function () { ... };` and `new Object;` + // should be tolerated + 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 + 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, + FileReader : false, + Float32Array : false, + Float64Array : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement : false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement : false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement : false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Image : false, + 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, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + top : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + WebSocket : false, + window : false, + Worker : false, + XMLHttpRequest : false, + XMLSerializer : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false + }, + + couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false, + provides : false + }, + + declared, // Globals that were declared using /*global ... */ syntax. + + devel = { + alert : false, + confirm : false, + console : false, + Debug : false, + opera : false, + prompt : false + }, + + dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require" : false + }, + + funct, // The current function + + functionicity = [ + "closure", "exception", "global", "label", + "outer", "unused", "var" + ], + + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + jsonmode, + + jquery = { + "$" : false, + jQuery : false + }, + + lines, + lookahead, + member, + membersOnly, + + mootools = { + "$" : false, + "$$" : false, + Asset : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMEvent : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + Iframe : false, + IframeShim : false, + InputValidator : false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false + }, + + nexttoken, + + node = { + __filename : false, + __dirname : false, + Buffer : false, + console : false, + exports : true, // In Node it is ok to exports = module.exports = foo(); + GLOBAL : false, + global : false, + module : false, + process : false, + require : false, + setTimeout : false, + clearTimeout : false, + setInterval : false, + clearInterval : false + }, + + noreach, + option, + predefined, // Global variables defined by option + prereg, + prevtoken, + + prototypejs = { + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false + }, + + quotmark, + + rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false + }, + + scope, // The current scope + stack, + + // standard contains the global names that are provided by the + // ECMAScript standard. + standard = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : 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, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + Set : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false, + WeakMap : false + }, + + // widely adopted global names that are not part of ECMAScript standard + nonstandard = { + escape : false, + unescape : false + }, + + directive, + syntax = {}, + tab, + token, + unuseds, + urls, + useESNextSyntax, + warnings, + + worker = { + importScripts : true, + postMessage : true, + self : true + }, + + wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + 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 () { + /*jshint maxlen:300 */ + + // unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; + + // unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + + // token + 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 = /\*\//; + + // identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; + + // javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; + + // catches /* falls through */ comments + ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; + }()); + + 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); + } + + function checkOption(name, t) { + if (valOptions[name] === undefined && boolOptions[name] === undefined) { + warning("Bad option: '" + name + "'.", t); + } + } + + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; + } + + // Provide critical ES5 functions to ES3. + + if (typeof Array.isArray !== "function") { + Array.isArray = function (o) { + 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") { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== "function") { + Object.keys = function (o) { + var a = [], k; + for (k in o) { + if (is_own(o, k)) { + a.push(k); + } + } + return a; + }; + } + + // Non standard methods + + function isAlpha(str) { + return (str >= "a" && str <= "z\uffff") || + (str >= "A" && str <= "Z\uffff"); + } + + function isDigit(str) { + return (str >= "0" && str <= "9"); + } + + function isIdentifier(token, value) { + if (!token) + return false; + + if (!token.identifier || token.value !== value) + return false; + + 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) && !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); + } + + if (option.rhino) { + combine(predefined, rhino); + } + + if (option.prototypejs) { + combine(predefined, prototypejs); + } + + if (option.node) { + combine(predefined, node); + option.globalstrict = true; + } + + if (option.devel) { + combine(predefined, devel); + } + + if (option.dojo) { + combine(predefined, dojo); + } + + if (option.browser) { + combine(predefined, browser); + } + + if (option.nonstandard) { + combine(predefined, nonstandard); + } + + if (option.jquery) { + combine(predefined, jquery); + } + + if (option.mootools) { + combine(predefined, mootools); + } + + if (option.worker) { + combine(predefined, worker); + } + + if (option.wsh) { + combine(predefined, wsh); + } + + if (option.esnext) { + useESNextSyntax(); + } + + if (option.globalstrict && option.strict !== false) { + option.strict = true; + } + + if (option.yui) { + combine(predefined, yui); + } + } + + + // Produce an error warning. + function quit(message, line, chr) { + var percentage = Math.floor((line / lines.length) * 100); + + throw { + name: "JSHintError", + line: line, + character: chr, + message: message + " (" + percentage + "% scanned).", + raw: message + }; + } + + function isundef(scope, m, t, a) { + return JSHINT.undefs.push([scope, m, t, a]); + } + + function warning(m, t, a, b, c, d) { + var ch, l, w; + t = t || nexttoken; + if (t.id === "(end)") { // `~ + t = token; + } + l = t.line || 0; + ch = t.from || 0; + w = { + id: "(error)", + raw: m, + evidence: lines[l - 1] || "", + line: l, + character: ch, + scope: JSHINT.scope, + a: a, + b: b, + c: c, + d: d + }; + w.reason = supplant(m, w); + JSHINT.errors.push(w); + if (option.passfail) { + quit("Stopping. ", l, ch); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit("Too many errors.", l, ch); + } + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, 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 + + var lex = (function lex() { + var character, from, line, s; + +// Private lex methods + + function nextLine() { + var at, + match, + tw; // trailing whitespace check + + if (line >= lines.length) + return false; + + character = 1; + s = lines[line]; + line += 1; + + // If smarttabs option is used check for spaces followed by tabs only. + // Otherwise check for any occurence of mixed tabs and spaces. + // 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); + + s = s.replace(/\t/g, tab); + at = s.search(cx); + + if (at >= 0) + warningAt("Unsafe character.", line, at); + + if (option.maxlen && option.maxlen < s.length) + warningAt("Line too long.", line, s.length); + + // Check for trailing whitespaces + tw = option.trailing && s.match(/^(.*?)\s+$/); + if (tw && !/^\s+$/.test(s)) { + warningAt("Trailing whitespace.", line, tw[1].length + 1); + } + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var i, t; + + 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 { + t = syntax[type]; + } + + t = Object.create(t); + + if (type === "(string)" || type === "(range)") { + if (!option.scripturl && jx.test(value)) { + warningAt("Script URL.", line, from); + } + } + + if (type === "(identifier)") { + t.identifier = true; + checkName(value); + } + + t.value = value; + t.line = line; + t.character = character; + t.from = from; + i = t.id; + if (i !== "(endline)") { + prereg = i && + (("(,=:[!&|?{};".indexOf(i.charAt(i.length - 1)) >= 0) || + i === "return" || + i === "case"); + } + return t; + } + + // Public lex methods + return { + init: function (source) { + if (typeof source === "string") { + lines = source + .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] = ""; + + line = 0; + nextLine(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ""; + from = character; + if (s.charAt(0) !== begin) { + errorAt("Expected '{a}' and instead saw '{b}'.", + line, character, begin, s.charAt(0)); + } + for (;;) { + s = s.slice(1); + character += 1; + c = s.charAt(0); + switch (c) { + case "": + errorAt("Missing '{a}'.", line, character, c); + break; + case end: + s = s.slice(1); + character += 1; + return it("(range)", value); + case "\\": + warningAt("Unexpected '{a}'.", line, character, c); + } + value += c; + } + + }, + + + // 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, n; + + function match(x) { + var r = x.exec(s), r1; + + if (r) { + l = r[0].length; + r1 = r[1]; + c = r1.charAt(0); + s = s.substr(l); + from = character + l - r1.length; + character += l; + return r1; + } + } + + function string(x) { + var c, j, r = "", allowNewLine = false; + + 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; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warningAt("Unnecessary escapement.", line, character); + } + character += n; + c = String.fromCharCode(i); + } + + j = 0; +unclosedString: for (;;) { + while (j >= s.length) { + j = 0; + + var cl = line, cf = from; + if (!nextLine()) { + errorAt("Unclosed string.", cl, cf); + break unclosedString; + } + + if (allowNewLine) { + allowNewLine = false; + } else { + warningAt("Unclosed string.", cl, cf); + } + } + + c = s.charAt(j); + if (c === x) { + character += 1; + s = s.substr(j + 1); + return it("(string)", r, x); + } + + if (c < " ") { + if (c === "\n" || c === "\r") { + break; + } + warningAt("Control character in string: {a}.", + line, character + j, s.slice(0, j)); + } else if (c === "\\") { + j += 1; + character += 1; + c = s.charAt(j); + n = s.charAt(j + 1); + switch (c) { + case "\\": + case "\"": + case "/": + break; + case "\'": + if (jsonmode) { + warningAt("Avoid \\'.", line, character); + } + break; + case "b": + c = "\b"; + break; + case "f": + c = "\f"; + break; + case "n": + c = "\n"; + break; + case "r": + c = "\r"; + break; + case "t": + c = "\t"; + break; + 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": + if (jsonmode) { + warningAt("Avoid \\v.", line, character); + } + c = "\v"; + break; + case "x": + if (jsonmode) { + warningAt("Avoid \\x-.", line, character); + } + esc(2); + break; + case "": + // last character is escape character + // always allow new line if escaped, but show + // warning if option is not set + allowNewLine = true; + if (option.multistr) { + if (jsonmode) { + warningAt("Avoid EOL escapement.", line, character); + } + 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); + } + } + r += c; + character += 1; + j += 1; + } + } + + for (;;) { + if (!s) { + return it(nextLine() ? "(endline)" : "(end)", ""); + } + + t = match(tx); + + if (!t) { + t = ""; + c = ""; + while (s && s < "!") { + s = s.substr(1); + } + if (s) { + errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); + s = ""; + } + } else { + + // identifier + + if (isAlpha(c) || c === "_" || c === "$") { + return it("(identifier)", t); + } + + // number + + if (isDigit(c)) { + if (!isFinite(Number(t))) { + warningAt("Bad number '{a}'.", + line, character, t); + } + if (isAlpha(s.substr(0, 1))) { + warningAt("Missing space after '{a}'.", + line, character, t); + } + if (c === "0") { + d = t.substr(1, 1); + if (isDigit(d)) { + if (token.id !== ".") { + warningAt("Don't use extra leading zeros '{a}'.", + line, character, t); + } + } else if (jsonmode && (d === "x" || d === "X")) { + warningAt("Avoid 0x-. '{a}'.", + line, character, t); + } + } + 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); + } + switch (t) { + + // string + + case "\"": + case "'": + return string(t); + + // // comment + + case "//": + s = ""; + token.comment = true; + break; + + // /* comment + + case "/*": + for (;;) { + i = s.search(lx); + if (i >= 0) { + break; + } + if (!nextLine()) { + errorAt("Unclosed 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 "*/": + return { + value: t, + type: "special", + line: line, + character: character, + from: from + }; + + case "": + break; + // / + case "/": + if (s.charAt(0) === "=") { + errorAt("A regular expression literal can be confused with '/='.", + line, from); + } + + if (prereg) { + depth = 0; + captures = 0; + l = 0; + for (;;) { + b = true; + c = s.charAt(l); + l += 1; + switch (c) { + case "": + errorAt("Unclosed regular expression.", line, from); + return quit("Stopping.", line, from); + case "/": + if (depth > 0) { + warningAt("{a} unterminated regular expression " + + "group(s).", line, from + l, depth); + } + c = s.substr(0, l - 1); + q = { + g: true, + i: true, + m: true + }; + while (q[s.charAt(l)] === true) { + q[s.charAt(l)] = false; + l += 1; + } + character += l; + s = s.substr(l); + q = s.charAt(0); + if (q === "/" || q === "*") { + errorAt("Confusing regular expression.", + line, from); + } + return it("(regexp)", c); + case "\\": + c = s.charAt(l); + if (c < " ") { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === "<") { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + break; + case "(": + depth += 1; + b = false; + if (s.charAt(l) === "?") { + l += 1; + switch (s.charAt(l)) { + case ":": + case "=": + case "!": + l += 1; + break; + default: + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, ":", s.charAt(l)); + } + } else { + captures += 1; + } + break; + case "|": + b = false; + break; + case ")": + if (depth === 0) { + warningAt("Unescaped '{a}'.", + line, from + l, ")"); + } else { + depth -= 1; + } + break; + case " ": + q = 1; + while (s.charAt(l) === " ") { + l += 1; + q += 1; + } + if (q > 1) { + warningAt( +"Spaces are hard to count. Use {{a}}.", line, from + l, q); + } + break; + case "[": + c = s.charAt(l); + if (c === "^") { + l += 1; + if (s.charAt(l) === "]") { + errorAt("Unescaped '{a}'.", + line, from + l, "^"); + } + } + if (c === "]") { + warningAt("Empty class.", line, + from + l - 1); + } + isLiteral = false; + isInRange = false; +klass: do { + c = s.charAt(l); + l += 1; + switch (c) { + case "[": + case "^": + warningAt("Unescaped '{a}'.", + line, from + l, c); + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "-": + if (isLiteral && !isInRange) { + isLiteral = false; + isInRange = true; + } else if (isInRange) { + isInRange = false; + } else if (s.charAt(l) === "]") { + isInRange = true; + } else { + if (option.regexdash !== (l === 2 || (l === 3 && + s.charAt(1) === "^"))) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, "-"); + } + isLiteral = true; + } + break; + case "]": + if (isInRange && !option.regexdash) { + warningAt("Unescaped '{a}'.", + line, from + l - 1, "-"); + } + break klass; + case "\\": + c = s.charAt(l); + if (c < " ") { + warningAt( +"Unexpected control character in regular expression.", line, from + l); + } else if (c === "<") { + warningAt( +"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); + } + l += 1; + + // \w, \s and \d are never part of a character range + if (/[wsd]/i.test(c)) { + if (isInRange) { + warningAt("Unescaped '{a}'.", + line, from + l, "-"); + isInRange = false; + } + isLiteral = false; + } else if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "/": + warningAt("Unescaped '{a}'.", + line, from + l - 1, "/"); + + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + case "<": + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + break; + default: + if (isInRange) { + isInRange = false; + } else { + isLiteral = true; + } + } + } while (c); + break; + case ".": + if (option.regexp) { + warningAt("Insecure '{a}'.", line, + from + l, c); + } + break; + case "]": + case "?": + case "{": + case "}": + case "+": + case "*": + warningAt("Unescaped '{a}'.", line, + from + l, c); + } + if (b) { + switch (s.charAt(l)) { + case "?": + case "+": + case "*": + l += 1; + if (s.charAt(l) === "?") { + l += 1; + } + break; + case "{": + l += 1; + c = s.charAt(l); + 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") { + break; + } + l += 1; + low = +c + (low * 10); + } + high = low; + if (c === ",") { + l += 1; + high = Infinity; + c = s.charAt(l); + if (c >= "0" && c <= "9") { + l += 1; + high = +c; + for (;;) { + c = s.charAt(l); + if (c < "0" || c > "9") { + break; + } + l += 1; + high = +c + (high * 10); + } + } + } + if (s.charAt(l) !== "}") { + warningAt( +"Expected '{a}' and instead saw '{b}'.", line, from + l, "}", c); + } else { + l += 1; + } + if (s.charAt(l) === "?") { + l += 1; + } + if (low > high) { + warningAt( +"'{a}' should not be greater than '{b}'.", line, from + l, low, high); + } + } + } + } + c = s.substr(0, l - 1); + character += l; + s = s.substr(l); + return it("(regexp)", c); + } + return it("(punctuator)", t); + + // punctuator + + case "#": + return it("(punctuator)", t); + default: + return it("(punctuator)", t); + } + } + } + } + }; + }()); + + + 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 (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") { + warning("'{a}' is already defined.", nexttoken, t); + } + } + } + + funct[t] = type; + + if (token) { + funct["(tokens)"][t] = token; + } + + if (funct["(global)"]) { + global[t] = funct; + if (is_own(implied, t)) { + if (option.latedef) + warning("'{a}' was used before it was defined.", nexttoken, t); + delete implied[t]; + } + } else { + scope[t] = funct; + } + } + + + function doOption() { + var nt = nexttoken; + var o = nt.value; + var quotmarkValue = option.quotmark; + var predef = {}; + var b, obj, filter, t, tn, v, minus; + + switch (o) { + case "*/": + error("Unbegun comment."); + break; + case "/*members": + case "/*member": + o = "/*members"; + if (!membersOnly) { + membersOnly = {}; + } + obj = membersOnly; + option.quotmark = false; + break; + case "/*jshint": + case "/*jslint": + obj = option; + filter = boolOptions; + break; + case "/*global": + obj = predef; + break; + default: + error("What?"); + } + + t = lex.token(); +loop: for (;;) { + minus = false; + for (;;) { + if (t.type === "special" && t.value === "*/") { + break loop; + } + if (t.id !== "(endline)" && t.id !== ",") { + break; + } + t = lex.token(); + } + + 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 === ":") { + v = lex.token(); + + if (obj === membersOnly) { + error("Expected '{a}' and instead saw '{b}'.", t, "*/", ":"); + } + + 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 (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"; + else + error("Bad option value.", v); + } + } 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") { + 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(); + } + } + + +// We need a peek function. If it has an argument, it peeks that much farther +// ahead. It is used to distinguish +// for ( var i in ... +// from +// for ( var i = ... + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + + +// Produce the next token. It looks for programming errors. + + function advance(id, t) { + switch (token.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 === "--") { + warning("Confusing minusses."); + } + break; + case "+": + if (nexttoken.id === "+" || nexttoken.id === "++") { + warning("Confusing plusses."); + } + break; + } + + if (token.type === "(string)" || token.identifier) { + anonname = token.value; + } + + if (id && nexttoken.id !== id) { + if (t) { + 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)" || + nexttoken.value !== id) { + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, id, nexttoken.value); + } + } + + prevtoken = token; + token = nexttoken; + for (;;) { + nexttoken = lookahead.shift() || lex.token(); + if (nexttoken.id === "(end)" || nexttoken.id === "(error)") { + return; + } + if (nexttoken.type === "special") { + doOption(); + } else { + if (nexttoken.id !== "(endline)") { + break; + } + } + } + } + + +// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + var left, isArray = false, isObject = false; + + if (nexttoken.id === "(end)") + error("Unexpected early end of program.", token); + + advance(); + if (initial) { + anonname = "anonymous"; + funct["(verb)"] = token.value; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (nexttoken.type === "(number)" && token.id === ".") { + warning("A leading decimal point can be confused with a dot: '.{a}'.", + token, nexttoken.value); + advance(); + return token; + } else { + error("Expected an identifier and instead saw '{a}'.", + token, token.id); + } + } + while (rbp < nexttoken.lbp) { + 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 === ")") + 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 { + error("Expected an operator and instead saw '{a}'.", + token, token.id); + } + } + } + return left; + } + + +// Functions for conformance of style. + + function adjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white) { + if (left.character !== right.from && left.line === right.line) { + left.from += (left.character - left.from); + warning("Unexpected space after '{a}'.", left, left.value); + } + } + } + + function nobreak(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && (left.character !== right.from || left.line !== right.line)) { + warning("Unexpected space before '{a}'.", right, right.value); + } + } + + function nospace(left, right) { + left = left || token; + right = right || nexttoken; + if (option.white && !left.comment) { + if (left.line === right.line) { + adjacent(left, right); + } + } + } + + function nonadjacent(left, right) { + 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}'.", + left, left.value); + } + } + } + + function nobreaknonadjacent(left, right) { + left = left || token; + right = right || nexttoken; + if (!option.laxbreak && left.line !== right.line) { + warning("Bad line breaking before '{a}'.", right, right.id); + } else if (option.white) { + left = left || token; + right = right || nexttoken; + if (left.character === right.from) { + left.from += (left.character - left.from); + warning("Missing space after '{a}'.", + left, left.value); + } + } + } + + function indentation(bias) { + var i; + if (option.white && nexttoken.id !== "(end)") { + i = indent + (bias || 0); + if (nexttoken.from !== i) { + warning( +"Expected '{a}' to have an indentation at {b} instead at {c}.", + nexttoken, nexttoken.value, i, nexttoken.from); + } + } + } + + function nolinebreak(t) { + t = t || token; + if (t.line !== nexttoken.line) { + warning("Line breaking error '{a}'.", t, t.value); + } + } + + + function comma() { + if (token.line !== nexttoken.line) { + if (!option.laxcomma) { + if (comma.first) { + warning("Comma warnings can be turned off with 'laxcomma'"); + comma.first = false; + } + warning("Bad line breaking before '{a}'.", token, nexttoken.id); + } + } else if (!token.comment && token.character !== nexttoken.from && option.white) { + token.from += (token.character - token.from); + warning("Unexpected space after '{a}'.", token, token.value); + } + advance(","); + nonadjacent(token, nexttoken); + } + + +// 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") { + syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + + function delim(s) { + return symbol(s, 0); + } + + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + x.nud = (typeof f === "function") ? f : function () { + this.right = expression(150); + 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 !== "[") { + warning("Bad operand.", this); + } + } + return this; + }; + return x; + } + + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + + function reserve(s, f) { + var x = type(s, f); + x.identifier = x.reserved = true; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === "function") { + v(this); + } + return this; + }); + } + + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.led = function (left) { + if (!w) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + } + if (s === "in" && left.id === "!") { + warning("Confusing use of '{a}'.", left, "!"); + } + if (typeof f === "function") { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function relation(s, f) { + var x = symbol(s, 100); + x.led = function (left) { + nobreaknonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + var right = expression(100); + + 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 (right.id === "!") { + warning("Confusing use of '{a}'.", right, "!"); + } + this.left = left; + this.right = right; + return this; + }; + return x; + } + + + 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"); + } + + + function assignop(s) { + symbol(s, 20).exps = true; + + return infix(s, function (left, that) { + that.left = left; + + if (predefined[left.value] === false && + scope[left.value]["(global)"] === true) { + warning("Read only.", left); + } else if (left["function"]) { + warning("'{a}' is a function.", left, left.value); + } + + if (left) { + 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); + } + that.right = expression(19); + return that; + } else if (left.identifier && !left.reserved) { + if (funct[left.value] === "exception") { + warning("Do not assign to the exception parameter.", left); + } + that.right = expression(19); + return that; + } + + if (left === syntax["function"]) { + warning( +"Expected an identifier in an assignment and instead saw a function invocation.", + token); + } + } + + error("Bad assignment.", that); + }, 20); + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === "function") ? f : function (left) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + symbol(s, 20).exps = true; + return infix(s, function (left, that) { + if (option.bitwise) { + warning("Unexpected use of '{a}'.", that, that.id); + } + nonadjacent(prevtoken, token); + nonadjacent(token, nexttoken); + if (left) { + if (left.id === "." || left.id === "[" || + (left.identifier && !left.reserved)) { + expression(19); + return that; + } + if (left === syntax["function"]) { + warning( +"Expected an identifier in an assignment, and instead saw a function invocation.", + token); + } + return that; + } + error("Bad assignment.", that); + }, 20); + } + + + 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 !== "[") { + warning("Bad operand.", this); + } + this.left = left; + return this; + }; + return x; + } + + + // fnparam means that this identifier is being defined as a function + // argument (see identifier()) + function optionalidentifier(fnparam) { + if (nexttoken.identifier) { + advance(); + if (token.reserved && !option.es5) { + // `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") { + warning("Expected an identifier and instead saw '{a}' (a reserved word).", + token, token.id); + } + } + return token.value; + } + } + + // fnparam means that this identifier is being defined as a function + // argument + function identifier(fnparam) { + var i = optionalidentifier(fnparam); + if (i) { + return i; + } + if (token.id === "function" && nexttoken.id === "(") { + warning("Missing name in function declaration."); + } else { + error("Expected an identifier and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + } + + + function reachable(s) { + var i = 0, t; + if (nexttoken.id !== ";" || noreach) { + return; + } + for (;;) { + t = peek(i); + if (t.reach) { + return; + } + if (t.id !== "(endline)") { + if (t.id === "function") { + if (!option.latedef) { + break; + } + warning( +"Inner functions should be listed at the top of the outer function.", t); + break; + } + warning("Unreachable '{a}' after '{b}'.", t, t.value, s); + break; + } + i += 1; + } + } + + + function statement(noindent) { + var i = indent, r, s = scope, t = nexttoken; + + if (t.id === ";") { + advance(";"); + return; + } + + // Is this a labelled statement? + + if (t.identifier && !t.reserved && peek().id === ":") { + advance(); + advance(":"); + scope = Object.create(s); + 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); + } + + nexttoken.label = t.value; + t = nexttoken; + } + + // Is it a lonely block? + + if (t.id === "{") { + block(true, true); + return; + } + + // Parse the statement. + + if (!noindent) { + indentation(); + } + 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.", t); + } + + if (nexttoken.id === ",") { + return comma(); + } + + 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 !== "}" || + nexttoken.line !== token.line) { + warningAt("Missing semicolon.", token.line, token.character); + } + } + } else { + adjacent(token, nexttoken); + advance(";"); + nonadjacent(token, nexttoken); + } + } + +// Restore the indentation. + + indent = i; + scope = s; + return r; + } + + + function statements(startLine) { + var a = [], p; + + while (!nexttoken.reach && nexttoken.id !== "(end)") { + if (nexttoken.id === ";") { + p = peek(); + if (!p || p.id !== "(") { + warning("Unnecessary semicolon."); + } + advance(";"); + } else { + a.push(statement(startLine === nexttoken.line)); + } + } + return a; + } + + + /* + * read all directives + * recognizes a simple form of asi, but always + * warns, if it is used + */ + function directives() { + var i, p, pn; + + for (;;) { + if (nexttoken.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i); + i = i + 1; + } while (pn.id === "(endline)"); + + if (pn.id !== ";") { + if (pn.id !== "(string)" && pn.id !== "(number)" && + pn.id !== "(regexp)" && pn.identifier !== true && + pn.id !== "}") { + break; + } + warning("Missing semicolon.", nexttoken); + } else { + p = pn; + } + } else if (p.id === "}") { + // directive with no other statements, warn about missing semicolon + warning("Missing semicolon.", p); + } else if (p.id !== ";") { + break; + } + + indentation(); + advance(); + if (directive[token.value]) { + warning("Unnecessary directive \"{a}\".", token, token.value); + } + + if (token.value === "use strict") { + if (!option["(explicitNewcap)"]) + option.newcap = true; + option.undef = true; + } + + // there's no directive negation, so always set to true + directive[token.value] = true; + + if (p.id === ";") { + advance(";"); + } + continue; + } + break; + } + } + + + /* + * Parses a single block. A block is a sequence of statements wrapped in + * braces. + * + * ordinary - true for everything but function bodies and try blocks. + * stmt - true if block can be a single statement (e.g. in if/for/while). + * isfunc - true if block is a function body + */ + function block(ordinary, stmt, isfunc) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + + if (!ordinary || !option.funcscope) + scope = Object.create(scope); + + nonadjacent(token, nexttoken); + t = nexttoken; + + var metrics = funct["(metrics)"]; + metrics.nestedBlockDepth += 1; + metrics.verifyMaxNestedBlockDepthPerFunction(); + + if (nexttoken.id === "{") { + advance("{"); + line = token.line; + if (nexttoken.id !== "}") { + indent += option.indent; + while (!ordinary && nexttoken.from > indent) { + indent += option.indent; + } + + if (isfunc) { + m = {}; + for (d in directive) { + if (is_own(directive, d)) { + m[d] = directive[d]; + } + } + directives(); + + if (option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !directive["use strict"]) { + warning("Missing \"use strict\" statement."); + } + } + } + + a = statements(line); + + metrics.statementCount += a.length; + + if (isfunc) { + directive = m; + } + + indent -= option.indent; + if (line !== nexttoken.line) { + indentation(); + } + } else if (line !== nexttoken.line) { + indentation(); + } + advance("}", t); + indent = old_indent; + } else if (!ordinary) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "{", nexttoken.value); + } else { + if (!stmt || option.curly) + warning("Expected '{a}' and instead saw '{b}'.", + nexttoken, "{", nexttoken.value); + + noreach = true; + indent += option.indent; + // test indentation only if statement is in new line + a = [statement(nexttoken.line === token.line)]; + indent -= option.indent; + noreach = false; + } + 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") { + warning("Unexpected /*member '{a}'.", token, m); + } + if (typeof member[m] === "number") { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(token) { + var name = token.value, line = token.line, a = implied[name]; + if (typeof a === "function") { + a = false; + } + + if (!a) { + a = [line]; + implied[name] = a; + } else if (a[a.length - 1] !== line) { + a.push(line); + } + } + + + // Build the syntax table by declaring the syntactic elements of the language. + + type("(number)", function () { + return this; + }); + + type("(string)", function () { + return this; + }); + + syntax["(identifier)"] = { + type: "(identifier)", + lbp: 0, + identifier: true, + nud: function () { + var v = this.value, + s = scope[v], + f; + + if (typeof s === "function") { + // Protection against accidental inheritance. + s = undefined; + } else if (typeof s === "boolean") { + f = funct; + funct = functions[0]; + addlabel(v, "var"); + s = funct; + funct = f; + } + + // The name is in scope and defined in the current function. + if (funct === s) { + // Change 'unused' to 'var', and reject labels. + switch (funct[v]) { + case "unused": + funct[v] = "var"; + break; + case "unction": + funct[v] = "function"; + this["function"] = true; + break; + case "function": + this["function"] = true; + break; + case "label": + warning("'{a}' is a statement label.", token, v); + break; + } + } 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. + // + // 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 && 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 === "["))) { + + 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": + warning("'{a}' used out of scope.", token, v); + break; + case "label": + warning("'{a}' is a statement label.", token, v); + break; + case "outer": + case "global": + break; + default: + // If the name is defined in an outer function, make an outer entry, + // and if it was unused, make it var. + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("'{a}' is not allowed.", token, v); + note_implied(token); + } 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") || + (nexttoken && + (nexttoken.value === "." || nexttoken.value === "["))) { + + isundef(funct, "'{a}' is not defined.", token, v); + } + } + funct[v] = true; + note_implied(token); + } else { + switch (s[v]) { + 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"; + break; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "label": + warning("'{a}' is a statement label.", token, v); + } + } + } + } + return this; + }, + led: function () { + error("Expected an operator and instead saw '{a}'.", + nexttoken, nexttoken.value); + } + }; + + 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("'").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)"]) { + warning("Strict violation.", x); + } + }); + 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 () { + 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) { + that.left = left; + that.right = 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"); + + if (!eqnull && option.eqeqeq) + warning("Expected '{a}' and instead saw '{b}'.", this, "===", "=="); + else if (isPoorRelation(left)) + warning("Use '{a}' to compare with '{b}'.", this, "===", left.value); + else if (isPoorRelation(right)) + warning("Use '{a}' to compare with '{b}'.", this, "===", right.value); + + return this; + }); + relation("==="); + 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, "!==", "!="); + } else if (isPoorRelation(left)) { + warning("Use '{a}' to compare with '{b}'.", + this, "!==", left.value); + } else if (isPoorRelation(right)) { + warning("Use '{a}' to compare with '{b}'.", + 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) { + var right = expression(130); + if (left && right && left.id === "(string)" && right.id === "(string)") { + left.value += right.value; + left.character = right.character; + if (!option.scripturl && jx.test(left.value)) { + warning("JavaScript URL.", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix("+", "num"); + prefix("+++", function () { + warning("Confusing pluses."); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("+++", function (left) { + warning("Confusing pluses."); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { + warning("Confusing minuses."); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + 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 () { + var p = expression(0); + if (!p || (p.id !== "." && p.id !== "[")) { + warning("Variables should not be deleted."); + } + this.first = p; + return this; + }).exps = true; + + prefix("~", function () { + if (option.bitwise) { + warning("Unexpected '{a}'.", this, "~"); + } + expression(150); + return this; + }); + + prefix("!", function () { + this.right = expression(150); + this.arity = "unary"; + if (bang[this.right.id] === true) { + warning("Confusing use of '{a}'.", this, "!"); + } + return this; + }); + prefix("typeof", "typeof"); + prefix("new", function () { + var c = expression(155), i; + if (c && c.id !== "function") { + if (c.identifier) { + c["new"] = true; + switch (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": + if (!option.evil) { + warning("The Function constructor is eval."); + } + break; + case "Date": + case "RegExp": + break; + default: + if (c.id !== "function") { + i = c.value.substr(0, 1); + 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 !== "(") { + warning("Bad constructor.", token); + } + } + } else { + if (!option.supernew) + warning("Weird construction. Delete 'new'.", this); + } + adjacent(token, nexttoken); + if (nexttoken.id !== "(" && !option.supernew) { + warning("Missing '()' invoking a constructor.", + token, token.value); + } + this.first = c; + return this; + }); + syntax["new"].exps = true; + + prefix("void").exps = true; + + infix(".", function (left, that) { + adjacent(prevtoken, token); + nobreak(); + var m = identifier(); + if (typeof m === "string") { + countMember(m); + } + that.left = left; + that.right = m; + 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")) { + warning("document.write can be a form of eval.", left); + } + if (!option.evil && (m === "eval" || m === "execScript")) { + warning("eval is evil."); + } + return that; + }, 160, true); + + infix("(", function (left, that) { + if (prevtoken.id !== "}" && prevtoken.id !== ")") { + nobreak(prevtoken, token); + } + nospace(); + 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."); + } + var n = 0, + p = []; + if (left) { + if (left.type === "(identifier)") { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + 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); + } + } + } + } + } + if (nexttoken.id !== ")") { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + advance(")"); + nospace(prevtoken, token); + 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") { + warning("eval is evil.", left); + + 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 !== "?") { + warning("Bad invocation.", left); + } + } + that.left = left; + return that; + }, 155, true).exps = true; + + prefix("(", function () { + nospace(); + if (nexttoken.id === "function") { + nexttoken.immed = true; + } + var v = expression(0); + advance(")", this); + nospace(prevtoken, token); + 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) { + nobreak(prevtoken, token); + nospace(); + var e = expression(0), s; + if (e && e.type === "(string)") { + if (!option.evil && (e.value === "eval" || e.value === "execScript")) { + warning("eval is evil.", that); + } + countMember(e.value); + if (!option.sub && ix.test(e.value)) { + s = syntax[e.value]; + if (!s || !s.reserved) { + warning("['{a}'] is better written in dot notation.", + prevtoken, e.value); + } + } + } + advance("]", that); + nospace(prevtoken, token); + that.left = left; + that.right = e; + return that; + }, 160, true); + + prefix("[", function () { + var b = token.line !== nexttoken.line; + this.first = []; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + while (nexttoken.id !== "(end)") { + while (nexttoken.id === ",") { + if (!option.es5) + warning("Extra comma."); + advance(","); + } + if (nexttoken.id === "]") { + break; + } + if (b && token.line !== nexttoken.line) { + indentation(); + } + this.first.push(expression(10)); + if (nexttoken.id === ",") { + comma(); + if (nexttoken.id === "]" && !option.es5) { + warning("Extra comma.", token); + break; + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance("]", this); + return this; + }, 160); + + + function property_name() { + var id = optionalidentifier(true); + if (!id) { + if (nexttoken.id === "(string)") { + id = nexttoken.value; + advance(); + } else if (nexttoken.id === "(number)") { + id = nexttoken.value.toString(); + advance(); + } + } + return id; + } + + + function functionparams() { + var next = nexttoken; + var params = []; + var ident; + + advance("("); + nospace(); + + if (nexttoken.id === ")") { + advance(")"); + return; + } + + for (;;) { + ident = identifier(true); + params.push(ident); + addlabel(ident, "unused", token); + if (nexttoken.id === ",") { + comma(); + } else { + advance(")", next); + nospace(prevtoken, token); + return params; + } + } + } + + + function doFunction(name, statement) { + var f; + var oldOption = option; + var oldScope = scope; + + option = Object.create(option); + scope = Object.create(scope); + + funct = { + "(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 (name) { + addlabel(name, "function"); + } + + 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["(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, p, t; + var props = {}; // All properties, including accessors + + function saveProperty(name, token) { + if (props[name] && is_own(props, name)) + warning("Duplicate member '{a}'.", nexttoken, i); + else + props[name] = {}; + + props[name].basic = true; + props[name].basicToken = token; + } + + function saveSetter(name, token) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].setter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].setter = true; + props[name].setterToken = token; + } + + function saveGetter(name) { + if (props[name] && is_own(props, name)) { + if (props[name].basic || props[name].getter) + warning("Duplicate member '{a}'.", nexttoken, i); + } else { + props[name] = {}; + } + + props[name].getter = true; + props[name].getterToken = token; + } + + b = token.line !== nexttoken.line; + if (b) { + indent += option.indent; + if (nexttoken.from === indent + option.indent) { + indent += option.indent; + } + } + for (;;) { + if (nexttoken.id === "}") { + break; + } + if (b) { + indentation(); + } + if (nexttoken.value === "get" && peek().id !== ":") { + advance("get"); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveGetter(i); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + 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"); + if (!option.es5) { + error("get/set are ES5 features."); + } + i = property_name(); + if (!i) { + error("Missing property name."); + } + saveSetter(i, nexttoken); + t = nexttoken; + adjacent(token, nexttoken); + f = doFunction(); + 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") { + break; + } + advance(":"); + nonadjacent(token, nexttoken); + expression(10); + } + + countMember(i); + if (nexttoken.id === ",") { + comma(); + if (nexttoken.id === ",") { + warning("Extra comma.", token); + } else if (nexttoken.id === "}" && !option.es5) { + warning("Extra comma.", token); + } + } else { + break; + } + } + if (b) { + indent -= option.indent; + indentation(); + } + advance("}", this); + + // Check for lonely setters if in the ES5 mode. + if (option.es5) { + for (var name in props) { + if (is_own(props, name) && props[name].setter && !props[name].getter) { + warning("Setter is defined without getter.", props[name].setterToken); + } + } + } + return this; + }; + x.fud = function () { + error("Expected to see a statement and instead saw a block.", token); + }; + }(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 id, name, value; + + this.first = []; + for (;;) { + nonadjacent(token, nexttoken); + id = identifier(); + if (funct[id] === "const") { + warning("const '" + id + "' has already been declared"); + } + if (funct["(global)"] && predefined[id] === false) { + warning("Redefinition of '{a}'.", token, id); + } + addlabel(id, "const"); + if (prefix) { + break; + } + name = token; + this.first.push(token); + + if (nexttoken.id !== "=") { + warning("const " + + "'{a}' is initialized to 'undefined'.", token, id); + } + + if (nexttoken.id === "=") { + nonadjacent(token, nexttoken); + advance("="); + nonadjacent(token, nexttoken); + if (nexttoken.id === "undefined") { + warning("It is not necessary to initialize " + + "'{a}' to 'undefined'.", token, id); + } + if (peek(0).id === "=" && nexttoken.identifier) { + error("Constant {a} was not declared correctly.", + nexttoken, nexttoken.value); + } + value = expression(0); + name.first = value; + } + + if (nexttoken.id !== ",") { + break; + } + comma(); + } + return this; + }); + conststatement.exps = true; + }; + + 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) { + warning("Too many var statements."); + } 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) { + warning("Redefinition of '{a}'.", token, id); + } + + addlabel(id, "unused", token); + + if (prefix) { + break; + } + + name = token; + this.first.push(token); + + if (nexttoken.id === "=") { + nonadjacent(token, nexttoken); + advance("="); + nonadjacent(token, nexttoken); + if (nexttoken.id === "undefined") { + warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); + } + 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 !== ",") { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + 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 " + + "the outer function.", token); + + } + var i = identifier(); + if (option.esnext && funct[i] === "const") { + warning("const '" + i + "' has already been declared"); + } + adjacent(token, nexttoken); + 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 () { + var i = optionalidentifier(); + if (i) { + adjacent(token, nexttoken); + } else { + nonadjacent(token, nexttoken); + } + doFunction(i); + if (!option.loopfunc && funct["(loopage)"]) { + warning("Don't make functions within a loop."); + } + return this; + }); + + blockstmt("if", function () { + var t = nexttoken; + increaseComplexityCount(); + advance("("); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + if (nexttoken.id === "else") { + nonadjacent(token, nexttoken); + advance("else"); + if (nexttoken.id === "if" || nexttoken.id === "switch") { + statement(true); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt("try", function () { + var b; + + function doCatch() { + var oldScope = scope; + var e; + + advance("catch"); + nonadjacent(token, nexttoken); + advance("("); + + scope = Object.create(oldScope); + + e = nexttoken.value; + if (nexttoken.type !== "(identifier)") { + e = null; + warning("Expected an identifier and instead saw '{a}'.", nexttoken, e); + } + + 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; + } + + if (nexttoken.id === "finally") { + advance("finally"); + block(false); + return; + } else if (!b) { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "catch", nexttoken.value); + } + + return this; + }); + + blockstmt("while", function () { + var t = nexttoken; + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); + nonadjacent(this, t); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }).labelled = true; + + 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); + } + + 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("("); + nonadjacent(this, t); + nospace(); + this.condition = expression(20); + advance(")", t); + nospace(prevtoken, token); + nonadjacent(token, nexttoken); + t = nexttoken; + 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": + break; + default: + // You can tell JSHint that you don't use break intentionally by + // adding a comment /* falls through */ on a line just before + // the next `case`. + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'case'.", + token); + } + } + indentation(-option.indent); + advance("case"); + this.cases.push(expression(20)); + increaseComplexityCount(); + g = true; + advance(":"); + funct["(verb)"] = "case"; + break; + case "default": + switch (funct["(verb)"]) { + case "break": + case "continue": + case "return": + case "throw": + break; + default: + if (!ft.test(lines[nexttoken.line - 2])) { + warning( + "Expected a 'break' statement before 'default'.", + token); + } + } + indentation(-option.indent); + advance("default"); + g = true; + advance(":"); + break; + case "}": + indent -= option.indent; + indentation(); + 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; + return; + case "(end)": + error("Missing '{a}'.", nexttoken, "}"); + return; + default: + if (g) { + switch (token.id) { + case ",": + error("Each value should have its own case label."); + return; + case ":": + g = false; + statements(); + break; + default: + error("Missing ':' on a case clause.", token); + return; + } + } else { + if (token.id === ":") { + advance(":"); + error("Unexpected '{a}'.", token, ":"); + statements(); + } else { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, "case", nexttoken.value); + return; + } + } + } + } + }).labelled = true; + + stmt("debugger", function () { + if (!option.debug) { + warning("All 'debugger' statements should be removed."); + } + return this; + }).exps = true; + + (function () { + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + + this.first = block(true); + advance("while"); + var t = nexttoken; + nonadjacent(token, t); + advance("("); + nospace(); + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + advance(")", t); + nospace(prevtoken, token); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt("for", function () { + var s, t = nexttoken; + 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"); + varstatement.fud.call(varstatement, true); + } else { + switch (funct[nexttoken.value]) { + case "unused": + funct[nexttoken.value] = "var"; + break; + case "var": + break; + default: + warning("Bad for in variable '{a}'.", + nexttoken, nexttoken.value); + } + advance(); + } + advance("in"); + expression(20); + advance(")", t); + s = block(true, true); + 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; + return this; + } else { + if (nexttoken.id !== ";") { + if (nexttoken.id === "var") { + advance("var"); + varstatement.fud.call(varstatement); + } else { + for (;;) { + expression(0, "for"); + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + } + nolinebreak(token); + advance(";"); + if (nexttoken.id !== ";") { + expression(20); + if (nexttoken.id === "=") { + if (!option.boss) + warning("Expected a conditional expression and instead saw an assignment."); + advance("="); + expression(20); + } + } + nolinebreak(token); + advance(";"); + if (nexttoken.id === ";") { + error("Expected '{a}' and instead saw '{b}'.", + nexttoken, ")", ";"); + } + if (nexttoken.id !== ")") { + for (;;) { + expression(0, "for"); + if (nexttoken.id !== ",") { + break; + } + comma(); + } + } + advance(")", t); + nospace(prevtoken, token); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + } + }).labelled = true; + + + stmt("break", function () { + var v = nexttoken.value; + + if (funct["(breakage)"] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ";") { + if (token.line === nexttoken.line) { + 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); + } + this.first = nexttoken; + advance(); + } + } + reachable("break"); + return this; + }).exps = true; + + + stmt("continue", function () { + var v = nexttoken.value; + + if (funct["(breakage)"] === 0) + warning("Unexpected '{a}'.", nexttoken, this.value); + + if (!option.asi) + nolinebreak(this); + + if (nexttoken.id !== ";") { + if (token.line === nexttoken.line) { + 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); + } + this.first = nexttoken; + advance(); + } + } else if (!funct["(loopage)"]) { + warning("Unexpected '{a}'.", nexttoken, this.value); + } + reachable("continue"); + return this; + }).exps = true; + + + stmt("return", function () { + if (this.line === nexttoken.line) { + if (nexttoken.id === "(regexp)") + warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); + + 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?", + token.line, token.character + 1); + } + this.first = expression(0); + } + } else if (!option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + reachable("return"); + return this; + }).exps = true; + + + stmt("throw", function () { + nolinebreak(this); + nonadjacent(token, nexttoken); + this.first = expression(20); + 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"); + + +// Parse JSON + + function jsonValue() { + + function jsonObject() { + var o = {}, t = nexttoken; + advance("{"); + if (nexttoken.id !== "}") { + for (;;) { + if (nexttoken.id === "(end)") { + error("Missing '}' to match '{' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === "}") { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ",") { + error("Unexpected comma.", nexttoken); + } 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__" && + !option.iterator)) { + warning("The '{a}' key may produce unexpected results.", + nexttoken, nexttoken.value); + } else { + o[nexttoken.value] = true; + } + advance(); + advance(":"); + jsonValue(); + if (nexttoken.id !== ",") { + break; + } + advance(","); + } + } + advance("}"); + } + + function jsonArray() { + var t = nexttoken; + advance("["); + if (nexttoken.id !== "]") { + for (;;) { + if (nexttoken.id === "(end)") { + error("Missing ']' to match '[' from line {a}.", + nexttoken, t.line); + } else if (nexttoken.id === "]") { + warning("Unexpected comma.", token); + break; + } else if (nexttoken.id === ",") { + error("Unexpected comma.", nexttoken); + } + jsonValue(); + if (nexttoken.id !== ",") { + break; + } + advance(","); + } + } + advance("]"); + } + + switch (nexttoken.id) { + case "{": + jsonObject(); + break; + case "[": + jsonArray(); + break; + case "true": + case "false": + case "null": + case "(number)": + case "(string)": + advance(); + break; + case "-": + advance("-"); + if (token.character !== nexttoken.from) { + warning("Unexpected space after '-'.", token); + } + adjacent(token, nexttoken); + advance("(number)"); + break; + default: + error("Expected a JSON value.", nexttoken); + } + } + + + // The actual JSHINT function itself. + var itself = function (s, o, g) { + 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) && 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 = newOptionObj; + + option.indent = option.indent || 4; + option.maxerr = option.maxerr || 50; + + tab = ""; + for (i = 0; i < option.indent; i += 1) { + tab += " "; + } + indent = 1; + global = Object.create(predefined); + scope = global; + funct = { + "(global)": true, + "(name)": "(global)", + "(scope)": scope, + "(breakage)": 0, + "(loopage)": 0, + "(tokens)": {}, + "(metrics)": createMetrics(nexttoken) + }; + functions = [funct]; + urls = []; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + 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)"]; + + // 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 "[": + option.laxbreak = true; + jsonmode = true; + jsonValue(); + break; + default: + directives(); + if (directive["use strict"] && !option.globalstrict) { + warning("Use the function form of \"use strict\".", prevtoken); + } + + statements(); + } + advance((nexttoken && nexttoken.value !== ".") ? "(end)" : undefined); + + var markDefined = function (name, context) { + do { + 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"; + + return true; + } + + context = context["(context)"]; + } while (context); + + return false; + }; + + var clearImplied = function (name, line) { + if (!implied[name]) + return; + + var newImplied = []; + for (var i = 0; i < implied[name].length; i += 1) { + if (implied[name][i] !== line) + newImplied.push(implied[name][i]); + } + + if (newImplied.length === 0) + delete implied[name]; + else + 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); + + if (markDefined(k[2].value, k[0])) { + clearImplied(k[2].value, k[2].line); + } else { + 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 || {}; + JSHINT.errors.push({ + raw : e.raw, + reason : e.message, + line : e.line || nt.line, + character : e.character || nt.from + }, null); + } + } + + // 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; + + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (jsonmode) { + data.json = true; + } + + for (n in implied) { + if (is_own(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + 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 (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.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; + data.functions.push(fu); + } + + if (unuseds.length > 0) { + data.unused = unuseds; + } + + members = []; + for (n in member) { + if (typeof member[n] === "number") { + data.member = member; + break; + } + } + + return data; + }; + + itself.jshint = itself; + + return itself; +}()); + +// Make JSHINT a Node module, if possible. +if (typeof exports === "object" && exports) { + exports.JSHINT = JSHINT; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/.npmignore new file mode 100644 index 0000000..1a82501 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/.npmignore @@ -0,0 +1,3 @@ +dist +stamp-build +test/fixtures/dir2 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/CONTRIBUTORS.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/CONTRIBUTORS.md new file mode 100644 index 0000000..fba3609 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/CONTRIBUTORS.md @@ -0,0 +1,68 @@ +Nodeunit contributors (sorted alphabeticaly) +============================================ + +* **[Alex Gorbatchev](https://github.com/alexgorbatchev)** + + * Deeper default object inspection + * Timeout to ensure flushing of console output (default reporter) + +* **[Alex Wolfe](https://github.com/alexkwolfe)** + + * HTML test reporter + +* **[Caolan McMahon](https://github.com/caolan)** + + * Author and maintainer + * Most features develpopment + +* **[Carl Fürstenberg](https://github.com/azatoth)** + + * Debian-friendly Makefile, supports both 'node' and 'nodejs' executables + * Sandbox utility + * Minimal test reporter + +* **[Gerad Suyderhoud](https://github.com/gerad)** + + * First comand-line tool + +* **[Kadir Pekel](https://github.com/kadirpekel)** + + * Improvements to default test reporter + * HTTP test utility + +* **[Λlisue](https://github.com/lambdalisue)** + + * Add machineout reporter + +* **[Matthias Lübken](https://github.com/luebken)** + + * Utility functions for tracking incomplete tests on exit + +* **[Oleg Efimov](https://github.com/Sannis)** + + * Adding 'make lint' and fixing nodelint errors + * Option parsing, --help text and config file support + * Reporters option for command-line tool + +* **[Orlando Vazquez](https://github.com/orlandov)** + + * Added jUnit XML reporter + +* **[Ryan Dahl](https://github.com/ry)** + + * Add package.json + +* **[Sam Stephenson](https://github.com/sstephenson)** + + * Coffee-script support + +* **[Thomas Mayfield](https://github.com/thegreatape)** + + * Async setUp and tearDown support for testCase + +* **[Maciej Małecki](https://github.com/mmalecki)** + + * Removal of `testCase` + +**[Full contributors list](https://github.com/caolan/nodeunit/contributors).** + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/Makefile new file mode 100644 index 0000000..8f8d8cb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/Makefile @@ -0,0 +1,177 @@ +PACKAGE = nodeunit +NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node) + +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin +DATADIR ?= $(PREFIX)/share +MANDIR ?= $(PREFIX)/share/man +LIBDIR ?= $(PREFIX)/lib +NODEJSLIBDIR ?= $(LIBDIR)/$(NODEJS) + +BUILDDIR = dist + +DOCS = $(shell find doc -name '*.md' \ + |sed 's|.md|.1|g' \ + |sed 's|doc/|man1/|g' \ + ) + + +$(shell if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi) + +all: build doc + +browser: + # super hacky build script for browser version! + mkdir -p $(BUILDDIR)/browser + rm -rf $(BUILDDIR)/browser/* + # build browser version of nodeunit.js + cat share/license.js >> $(BUILDDIR)/browser/nodeunit.js + echo "nodeunit = (function(){" >> $(BUILDDIR)/browser/nodeunit.js + cat deps/json2.js >> $(BUILDDIR)/browser/nodeunit.js + # make assert global + echo "var assert = this.assert = {};" >> $(BUILDDIR)/browser/nodeunit.js + echo "var types = {};" >> $(BUILDDIR)/browser/nodeunit.js + echo "var core = {};" >> $(BUILDDIR)/browser/nodeunit.js + echo "var nodeunit = {};" >> $(BUILDDIR)/browser/nodeunit.js + echo "var reporter = {};" >> $(BUILDDIR)/browser/nodeunit.js + cat deps/async.js >> $(BUILDDIR)/browser/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js + cat lib/assert.js >> $(BUILDDIR)/browser/nodeunit.js + echo "})(assert);" >> $(BUILDDIR)/browser/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js + cat lib/types.js >> $(BUILDDIR)/browser/nodeunit.js + echo "})(types);" >> $(BUILDDIR)/browser/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js + cat lib/core.js >> $(BUILDDIR)/browser/nodeunit.js + echo "})(core);" >> $(BUILDDIR)/browser/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js + cat lib/reporters/browser.js >> $(BUILDDIR)/browser/nodeunit.js + echo "})(reporter);" >> $(BUILDDIR)/browser/nodeunit.js + echo "nodeunit = core;" >> $(BUILDDIR)/browser/nodeunit.js + echo "nodeunit.assert = assert;" >> $(BUILDDIR)/browser/nodeunit.js + echo "nodeunit.reporter = reporter;" >> $(BUILDDIR)/browser/nodeunit.js + echo "nodeunit.run = reporter.run;" >> $(BUILDDIR)/browser/nodeunit.js + echo "return nodeunit; })();" >> $(BUILDDIR)/browser/nodeunit.js + cp $(BUILDDIR)/browser/nodeunit.js $(BUILDDIR)/browser/.nodeunit.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.nodeunit.js > $(BUILDDIR)/browser/nodeunit.js + rm $(BUILDDIR)/browser/.nodeunit.js + # copy nodeunit.css + cp share/nodeunit.css $(BUILDDIR)/browser/nodeunit.css + # create nodeunit.min.js + node_modules/uglify-js/bin/uglifyjs $(BUILDDIR)/browser/nodeunit.js > $(BUILDDIR)/browser/nodeunit.min.js + # create test scripts + mkdir -p $(BUILDDIR)/browser/test + cp test/test.html $(BUILDDIR)/browser/test/test.html + # test-base.js + echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-base.js + cat test/test-base.js >> $(BUILDDIR)/browser/test/test-base.js + echo "})(this.test_base = {});" >> $(BUILDDIR)/browser/test/test-base.js + cp $(BUILDDIR)/browser/test/test-base.js $(BUILDDIR)/browser/.test-base.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-base.js > $(BUILDDIR)/browser/test/test-base.js + rm $(BUILDDIR)/browser/.test-base.js + # test-runmodule.js + echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runmodule.js + cat test/test-runmodule.js >> $(BUILDDIR)/browser/test/test-runmodule.js + echo "})(this.test_runmodule = {});" >> $(BUILDDIR)/browser/test/test-runmodule.js + cp $(BUILDDIR)/browser/test/test-runmodule.js $(BUILDDIR)/browser/.test-runmodule.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-runmodule.js > $(BUILDDIR)/browser/test/test-runmodule.js + rm $(BUILDDIR)/browser/.test-runmodule.js + # test-runtest.js + echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runtest.js + cat test/test-runtest.js >> $(BUILDDIR)/browser/test/test-runtest.js + echo "})(this.test_runtest = {});" >> $(BUILDDIR)/browser/test/test-runtest.js + cp $(BUILDDIR)/browser/test/test-runtest.js $(BUILDDIR)/browser/.test-runtest.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-runtest.js > $(BUILDDIR)/browser/test/test-runtest.js + rm $(BUILDDIR)/browser/.test-runtest.js + # test-testcase.js + echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-testcase.js + cat test/test-testcase.js >> $(BUILDDIR)/browser/test/test-testcase.js + echo "})(this.test_testcase = {});" >> $(BUILDDIR)/browser/test/test-testcase.js + cp $(BUILDDIR)/browser/test/test-testcase.js $(BUILDDIR)/browser/.test-testcase.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-testcase.js > $(BUILDDIR)/browser/test/test-testcase.js + rm $(BUILDDIR)/browser/.test-testcase.js + # test-testcase-legacy.js + echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-testcase-legacy.js + cat test/test-testcase-legacy.js >> $(BUILDDIR)/browser/test/test-testcase-legacy.js + echo "})(this.test_testcase_legacy = {});" >> $(BUILDDIR)/browser/test/test-testcase-legacy.js + cp $(BUILDDIR)/browser/test/test-testcase-legacy.js $(BUILDDIR)/browser/.test-testcase-legacy.js + sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-testcase-legacy.js > $(BUILDDIR)/browser/test/test-testcase-legacy.js + rm $(BUILDDIR)/browser/.test-testcase-legacy.js + # copy nodeunit.js to dist/browser/test to make it easier for me to host and + # run on windows VMs with IE + cp $(BUILDDIR)/browser/nodeunit.js $(BUILDDIR)/browser/test/nodeunit.js + cp $(BUILDDIR)/browser/nodeunit.css $(BUILDDIR)/browser/test/nodeunit.css + +commonjs: + # super hacky build script for browser commonjs version! + ##### make commonjs browser module ###### + mkdir -p $(BUILDDIR)/commonjs + rm -rf $(BUILDDIR)/commonjs/* + mkdir -p $(BUILDDIR)/commonjs/deps + cp deps/json2.js $(BUILDDIR)/commonjs/deps + cp deps/async.js $(BUILDDIR)/commonjs/deps + echo "var async = require('async');" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "var assert = {};" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "var types = {};" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "var core = {};" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "var nodeunit = {};" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "var reporter = {};" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js + cat lib/assert.js >> $(BUILDDIR)/commonjs/nodeunit.js + echo "})(assert);" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js + cat lib/types.js >> $(BUILDDIR)/commonjs/nodeunit.js + echo "})(types);" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js + cat lib/core.js >> $(BUILDDIR)/commonjs/nodeunit.js + echo "})(core);" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "module.exports = core;" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "(function(exports, nodeunit){" >> $(BUILDDIR)/commonjs/nodeunit.js + cat lib/reporters/browser.js >> $(BUILDDIR)/commonjs/nodeunit.js + echo "})(reporter, module.exports);" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "module.exports.assert = assert;" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "module.exports.reporter = reporter;" >> $(BUILDDIR)/commonjs/nodeunit.js + echo "module.exports.run = reporter.run;" >> $(BUILDDIR)/commonjs/nodeunit.js + sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/commonjs/nodeunit.js + sed -i "/\@REMOVE_LINE_FOR_COMMONJS/d" $(BUILDDIR)/commonjs/nodeunit.js + ##### end of commonjs browser module ##### + +build: stamp-build + +stamp-build: $(wildcard deps/* lib/*.js) + touch $@; + mkdir -p $(BUILDDIR)/nodeunit + cp -R bin node_modules deps index.js lib package.json share $(BUILDDIR)/nodeunit + printf '#!/bin/sh\n$(NODEJS) $(NODEJSLIBDIR)/$(PACKAGE)/bin/nodeunit $$@' > $(BUILDDIR)/nodeunit.sh + +test: + $(NODEJS) ./bin/nodeunit test + +install: build + install -d $(NODEJSLIBDIR) + cp -a $(BUILDDIR)/nodeunit $(NODEJSLIBDIR) + install -m 0755 $(BUILDDIR)/nodeunit.sh $(BINDIR)/nodeunit + install -d $(MANDIR)/man1/ + cp -a man1/nodeunit.1 $(MANDIR)/man1/ + +uninstall: + rm -rf $(NODEJSLIBDIR)/nodeunit $(NODEJSLIBDIR)/nodeunit.js $(BINDIR)/nodeunit + rm -rf $(MANDIR)/man1/nodeunit.1 + +clean: + rm -rf $(BUILDDIR) stamp-build + +lint: + nodelint --config nodelint.cfg ./index.js ./bin/nodeunit ./bin/nodeunit.json ./lib/*.js ./lib/reporters/*.js ./test/*.js + +doc: man1 $(DOCS) + @true + +man1: + @if ! test -d man1 ; then mkdir -p man1 ; fi + +# use `npm install ronn` for this to work. +man1/%.1: doc/%.md + ronn --roff $< > $@ + +.PHONY: browser test install uninstall build all diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/README.md new file mode 100644 index 0000000..359a9c7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/README.md @@ -0,0 +1,443 @@ +Nodeunit +======== + +Simple syntax, powerful tools. Nodeunit provides easy async unit testing for +node.js and the browser. + +* Simple to use +* Just export the tests from a module +* Works with node.js and in the browser. +* Helps you avoid common pitfalls when testing asynchronous code +* Easy to add test cases with setUp and tearDown functions if you wish +* Flexible reporters for custom output, built-in support for HTML and jUnit XML +* Allows the use of mocks and stubs + +__Contributors__ + +* [alexgorbatchev](https://github.com/alexgorbatchev) +* [alexkwolfe](https://github.com/alexkwolfe) +* [azatoth](https://github.com/azatoth) +* [kadirpekel](https://github.com/kadirpekel) +* [lambdalisue](https://github.com/lambdalisue) +* [luebken](https://github.com/luebken) +* [orlandov](https://github.com/orlandov) +* [Sannis](https://github.com/Sannis) +* [sstephenson](https://github.com/sstephenson) +* [thegreatape](https://github.com/thegreatape) +* [mmalecki](https://github.com/mmalecki) +* and thanks to [cjohansen](https://github.com/cjohansen) for input and advice + on implementing setUp and tearDown functions. See + [cjohansen's fork](https://github.com/cjohansen/nodeunit). + +Also, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl) +project, which implements a 'pretty dsl on top of nodeunit'. + +More contributor information can be found in the +[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md) +file. + +Usage +----- + +Here is an example unit test module: + + exports.testSomething = function(test){ + test.expect(1); + test.ok(true, "this assertion should pass"); + test.done(); + }; + + exports.testSomethingElse = function(test){ + test.ok(false, "this assertion should fail"); + test.done(); + }; + +When run using the included test runner, this will output the following: + + + +Installation +------------ + +There are two options for installing nodeunit: + +1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit), + then: + + make && sudo make install + +2. Install via npm: + + npm install nodeunit + +API Documentation +----------------- + +Nodeunit uses the functions available in the node.js +[assert module](http://nodejs.org/docs/v0.4.2/api/assert.html): + +* __ok(value, [message])__ - Tests if value is a true value. +* __equal(actual, expected, [message])__ - Tests shallow, coercive equality + with the equal comparison operator ( == ). +* __notEqual(actual, expected, [message])__ - Tests shallow, coercive + non-equality with the not equal comparison operator ( != ). +* __deepEqual(actual, expected, [message])__ - Tests for deep equality. +* __notDeepEqual(actual, expected, [message])__ - Tests for any deep + inequality. +* __strictEqual(actual, expected, [message])__ - Tests strict equality, as + determined by the strict equality operator ( === ) +* __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality, + as determined by the strict not equal operator ( !== ) +* __throws(block, [error], [message])__ - Expects block to throw an error. +* __doesNotThrow(block, [error], [message])__ - Expects block not to throw an + error. +* __ifError(value)__ - Tests if value is not a false value, throws if it is a + true value. Useful when testing the first argument, error in callbacks. + +Nodeunit also provides the following functions within tests: + +* __expect(amount)__ - Specify how many assertions are expected to run within a + test. Very useful for ensuring that all your callbacks and assertions are + run. +* __done()__ - Finish the current test function, and move on to the next. ALL + tests should call this! + +Nodeunit aims to be simple and easy to learn. This is achieved through using +existing structures (such as node.js modules) to maximum effect, and reducing +the API where possible, to make it easier to digest. + +Tests are simply exported from a module, but they are still run in the order +they are defined. + +__Note:__ Users of old nodeunit versions may remember using ok, equals and same +in the style of qunit, instead of the assert functions above. These functions +still exist for backwards compatibility, and are simply aliases to their assert +module counterparts. + + +Asynchronous Testing +-------------------- + +When testing asynchronous code, there are a number of sharp edges to watch out +for. Thankfully, nodeunit is designed to help you avoid as many of these +pitfalls as possible. For the most part, testing asynchronous code in nodeunit +_just works_. + + +### Tests run in series + +While running tests in parallel seems like a good idea for speeding up your +test suite, in practice I've found it means writing much more complicated +tests. Because of node's module cache, running tests in parallel means mocking +and stubbing is pretty much impossible. One of the nicest things about testing +in javascript is the ease of doing stubs: + + var _readFile = fs.readFile; + fs.readFile = function(path, callback){ + // its a stub! + }; + // test function that uses fs.readFile + + // we're done + fs.readFile = _readFile; + +You cannot do this when running tests in parallel. In order to keep testing as +simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run +fast anyway. + + +### Explicit ending of tests + +When testing async code its important that tests end at the correct point, not +just after a given number of assertions. Otherwise your tests can run short, +ending before all assertions have completed. Its important to detect too +many assertions as well as too few. Combining explicit ending of tests with +an expected number of assertions helps to avoid false test passes, so be sure +to use the test.expect() method at the start of your test functions, and +test.done() when finished. + + +Groups, setUp and tearDown +-------------------------- + +Nodeunit allows the nesting of test functions: + + exports.test1 = function (test) { + ... + } + + exports.group = { + test2: function (test) { + ... + }, + test3: function (test) { + ... + } + } + +This would be run as: + + test1 + group - test2 + group - test3 + +Using these groups, Nodeunit allows you to define a `setUp` function, which is +run before each test, and a `tearDown` function, which is run after each test +calls `test.done()`: + + module.exports = { + setUp: function (callback) { + this.foo = 'bar'; + callback(); + }, + tearDown: function (callback) { + // clean up + callback(); + }, + test1: function (test) { + test.equals(this.foo, 'bar'); + test.done(); + } + }; + +In this way, its possible to have multiple groups of tests in a module, each +group with its own setUp and tearDown functions. + + +Running Tests +------------- + +Nodeunit comes with a basic command-line test runner, which can be installed +using 'sudo make install'. Example usage: + + nodeunit testmodule1.js testfolder [...] + +The default test reporter uses color output, because I think that's more fun :) I +intend to add a no-color option in future. To give you a feeling of the fun you'll +be having writing tests, lets fix the example at the start of the README: + + + +Ahhh, Doesn't that feel better? + +When using the included test runner, it will exit using the failed number of +assertions as the exit code. Exiting with 0 when all tests pass. + + +### Command-line Options + +* __--reporter FILE__ - you can set the test reporter to a custom module or +on of the modules in nodeunit/lib/reporters, when omitted, the default test runner +is used. +* __--list-reporters__ - list available build-in reporters. +* __--config FILE__ - load config options from a JSON file, allows +the customisation of color schemes for the default test reporter etc. See +bin/nodeunit.json for current available options. +* __--version__ or __-v__ - report nodeunit version +* __--help__ - show nodeunit help + + +Running tests in the browser +---------------------------- + +Nodeunit tests can also be run inside the browser. For example usage, see +the examples/browser folder. The basic syntax is as follows: + +__test.html__ + + + + Example Test Suite + + + + + + +

    + + +nodeunit with vim +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use nodeunit with VIM. +That compiler use __machineout__ reporter and it is useful to use with [vim-makegreen](https://github.com/reinh/vim-makegreen) + + + +Contributing +------------ + +Contributions to the project are most welcome, so feel free to fork and improve. +When submitting a pull request, please run 'make lint' first to ensure +we're following a consistent coding style. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit new file mode 100755 index 0000000..4b3f4d5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit @@ -0,0 +1,133 @@ +#!/usr/bin/env node + +var + fs = require('fs'), + path = require('path'); + +// TODO: remove this when https://github.com/joyent/node/pull/1312 +// lands in core. +// +// Until then, use console.log from npm (https://gist.github.com/1077544) +require('../deps/console.log'); + +//require.paths.push(process.cwd()); +var args = (process.ARGV || process.argv).slice(2); + +var files = []; + +var testrunner, + config_file, + config_param_found = false, + output_param_found = false, + reporter_file = 'default', + reporter_param_found = false, + testspec_param_found = false; + testFullSpec_param_found = false; + +var usage = "Usage: nodeunit [options] testmodule1.js testfolder [...] \n" + + "Options:\n\n" + + " --config FILE the path to a JSON file with options\n" + + " --reporter FILE optional path to a reporter file to customize the output\n" + + " --list-reporters list available build-in reporters\n" + + " -t name, specify a test to run\n" + + " -f fullname, specify a specific test to run. fullname is built so: \"outerGroup - .. - innerGroup - testName\"\n" + + " -h, --help display this help and exit\n" + + " -v, --version output version information and exit"; + + + +// load default options +var content = fs.readFileSync(__dirname + '/nodeunit.json', 'utf8'); +var options = JSON.parse(content); + +// a very basic pseudo --options parser +args.forEach(function (arg) { + if (arg.slice(0, 9) === "--config=") { + config_file = arg.slice(9); + } else if (arg === '--config') { + config_param_found = true; + } else if (config_param_found) { + config_file = arg; + config_param_found = false; + } else if (arg.slice(0, 9) === "--output=") { + options.output = arg.slice(9); + } else if (arg === '--output') { + output_param_found = true; + } else if (output_param_found) { + options.output = arg; + output_param_found = false; + } else if (arg.slice(0, 11) === "--reporter=") { + reporter_file = arg.slice(11); + } else if (arg === '--reporter') { + reporter_param_found = true; + } else if (reporter_param_found) { + reporter_file = arg; + reporter_param_found = false; + } else if (arg === '-t') { + testspec_param_found = true; + } else if (testspec_param_found) { + options.testspec = arg; + testspec_param_found = false; + } else if (arg === '-f') { + testFullSpec_param_found = true; + } else if (testFullSpec_param_found) { + options.testFullSpec= arg; + testFullSpec_param_found = false; + } else if (arg === '--list-reporters') { + var reporters = fs.readdirSync(__dirname + '/../lib/reporters'); + reporters = reporters.filter(function (reporter_file) { + return (/\.js$/).test(reporter_file); + }).map(function (reporter_file) { + return reporter_file.replace(/\.js$/, ''); + }).filter(function (reporter_file) { + return reporter_file !== 'index'; + }); + console.log('Build-in reporters: '); + reporters.forEach(function (reporter_file) { + var reporter = require('../lib/reporters/' + reporter_file); + console.log(' * ' + reporter_file + (reporter.info ? ': ' + reporter.info : '')); + }); + process.exit(0); + } else if ((arg === '-v') || (arg === '--version')) { + var content = fs.readFileSync(__dirname + '/../package.json', 'utf8'); + var pkg = JSON.parse(content); + console.log(pkg.version); + process.exit(0); + } else if ((arg === '-h') || (arg === '--help')) { + console.log(usage); + process.exit(0); + } else { + files.push(arg); + } +}); + +if (files.length === 0) { + console.log('Files required.'); + console.log(usage); + process.exit(1); +} + +if (config_file) { + content = fs.readFileSync(config_file, 'utf8'); + var custom_options = JSON.parse(content); + + for (var option in custom_options) { + if (typeof option === 'string') { + options[option] = custom_options[option]; + } + } +} + +var builtin_reporters = require(__dirname + '/../lib/reporters'); +if (reporter_file in builtin_reporters) { + testrunner = builtin_reporters[reporter_file]; +} +else { + testrunner = require(reporter_file); +} + +testrunner.run(files, options, function(err) { + if (err) { + process.exit(1); + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit.json new file mode 100644 index 0000000..5c7778f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/bin/nodeunit.json @@ -0,0 +1,10 @@ +{ + "error_prefix": "\u001B[31m", + "error_suffix": "\u001B[39m", + "ok_prefix": "\u001B[32m", + "ok_suffix": "\u001B[39m", + "bold_prefix": "\u001B[1m", + "bold_suffix": "\u001B[22m", + "assertion_prefix": "\u001B[35m", + "assertion_suffix": "\u001B[39m" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/async.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/async.js new file mode 100644 index 0000000..d81255f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/async.js @@ -0,0 +1,623 @@ +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + } + else { + async.nextTick = process.nextTick; + } + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + hasher = hasher || function (x) { + return x; + }; + return function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else { + fn.apply(null, args.concat([function () { + memo[key] = arguments; + callback.apply(null, arguments); + }])); + } + }; + }; + +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/console.log.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/console.log.js new file mode 100644 index 0000000..fe146c1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/console.log.js @@ -0,0 +1,55 @@ +/* + A console.log that won't leave you hanging when node exits + 90% of this file was ripped from node.js + + License: see: https://github.com/joyent/node/blob/master/lib/console.js + */ + + // console object +var formatRegExp = /%[sdj]/g; +function format(f) { + var util = require('util'); + + if (typeof f !== 'string') { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(util.inspect(arguments[i])); + } + return objects.join(' '); + } + + + var i = 1; + var args = arguments; + var str = String(f).replace(formatRegExp, function(x) { + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': return JSON.stringify(args[i++]); + default: + return x; + } + }); + for (var len = args.length, x = args[i]; i < len; x = args[++i]) { + if (x === null || typeof x !== 'object') { + str += ' ' + x; + } else { + str += ' ' + util.inspect(x); + } + } + return str; +} + +console.log = function() { + var res = process.stdout.write(format.apply(this, arguments) + '\n'); + + // this is the first time stdout got backed up + if (!res && !process.stdout.pendingWrite) { + process.stdout.pendingWrite = true; + + // magic sauce: keep node alive until stdout has flushed + process.stdout.once('drain', function () { + process.stdout.draining = false; + }); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/History.md new file mode 100644 index 0000000..00d2b5b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/History.md @@ -0,0 +1,70 @@ + +0.4.3 / 2011-06-20 +================== + + * Fixed stacktraces line number when used multiline js expressions [Octave] + +0.4.2 / 2011-05-11 +================== + + * Added client side support + +0.4.1 / 2011-04-21 +================== + + * Fixed error context + +0.4.0 / 2011-04-21 +================== + + * Added; ported jade's error reporting to ejs. [slaskis] + +0.3.1 / 2011-02-23 +================== + + * Fixed optional `compile()` options + +0.3.0 / 2011-02-14 +================== + + * Added 'json' filter [Yuriy Bogdanov] + * Use exported version of parse function to allow monkey-patching [Anatoliy Chakkaev] + +0.2.1 / 2010-10-07 +================== + + * Added filter support + * Fixed _cache_ option. ~4x performance increase + +0.2.0 / 2010-08-05 +================== + + * Added support for global tag config + * Added custom tag support. Closes #5 + * Fixed whitespace bug. Closes #4 + +0.1.0 / 2010-08-04 +================== + + * Faster implementation [ashleydev] + +0.0.4 / 2010-08-02 +================== + + * Fixed single quotes for content outside of template tags. [aniero] + * Changed; `exports.compile()` now expects only "locals" + +0.0.3 / 2010-07-15 +================== + + * Fixed single quotes + +0.0.2 / 2010-07-09 +================== + + * Fixed newline preservation + +0.0.1 / 2010-07-09 +================== + + * Initial release diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Makefile new file mode 100644 index 0000000..a8b00d9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Makefile @@ -0,0 +1,20 @@ + +SRC = $(shell find lib -name "*.js" -type f) +UGLIFY_FLAGS = --no-mangle + +test: + @./node_modules/.bin/expresso test/*.test.js + +ejs.js: $(SRC) + @node support/compile.js $^ + +ejs.min.js: ejs.js + @uglifyjs $(UGLIFY_FLAGS) $< > $@ \ + && du ejs.min.js \ + && du ejs.js + +clean: + rm -f ejs.js + rm -f ejs.min.js + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Readme.md new file mode 100644 index 0000000..58cb10a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/Readme.md @@ -0,0 +1,152 @@ + +# EJS + +Embedded JavaScript templates. + +## Installation + + $ npm install ejs + +## Features + + * Complies with the [Express](http://expressjs.com) view system + * Static caching of intermediate JavaScript + * Unbuffered code for conditionals etc `<% code %>` + * Escapes html by default with `<%= code %>` + * Unescaped buffering with `<%- code %>` + * Supports tag customization + * Filter support for designer-friendly templates + * Client-side support + +## Example + + <% if (user) { %> +

    <%= user.name %>

    + <% } %> + +## Usage + + ejs.compile(str, options); + // => Function + + ejs.render(str, options); + // => str + +## Options + + - `locals` Local variables object + - `cache` Compiled functions are cached, requires `filename` + - `filename` Used by `cache` to key caches + - `scope` Function execution context + - `debug` Output generated function body + - `open` Open tag, defaulting to "<%" + - `close` Closing tag, defaulting to "%>" + +## Custom tags + +Custom tags can also be applied globally: + + var ejs = require('ejs'); + ejs.open = '{{'; + ejs.close = '}}'; + +Which would make the following a valid template: + +

    {{= title }}

    + +## Filters + +EJS conditionally supports the concept of "filters". A "filter chain" +is a designer friendly api for manipulating data, without writing JavaScript. + +Filters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters: + +Template: + +

    <%=: users | map:'name' | join %>

    + +Output: + +

    Tj, Mape, Guillermo

    + +Render call: + + ejs.render(str, { + locals: { + users: [ + { name: 'tj' }, + { name: 'mape' }, + { name: 'guillermo' } + ] + } + }); + +Or perhaps capitalize the first user's name for display: + +

    <%=: users | first | capitalize %>

    + +## Filter list + +Currently these filters are available: + + - first + - last + - capitalize + - downcase + - upcase + - sort + - sort_by:'prop' + - size + - length + - plus:n + - minus:n + - times:n + - divided_by:n + - join:'val' + - truncate:n + - truncate_words:n + - replace:pattern,substitution + - prepend:val + - append:val + - map:'prop' + - reverse + - get:'prop' + +## Adding filters + + To add a filter simply add a method to the `.filters` object: + +```js +ejs.filters.last = function(obj) { + return obj[obj.length - 1]; +}; +``` + +## client-side support + + include `./ejs.js` or `./ejs.min.js` and `require("ejs").compile(str)`. + +## License + +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca> + +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/deps/ejs/benchmark.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/benchmark.js new file mode 100644 index 0000000..7b267e1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/benchmark.js @@ -0,0 +1,14 @@ + + +var ejs = require('./lib/ejs'), + str = '<% if (foo) { %>

    <%= foo %>

    <% } %>', + times = 50000; + +console.log('rendering ' + times + ' times'); + +var start = new Date; +while (times--) { + ejs.render(str, { cache: true, filename: 'test', locals: { foo: 'bar' }}); +} + +console.log('took ' + (new Date - start) + 'ms'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.js new file mode 100644 index 0000000..b8c6aa1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.js @@ -0,0 +1,531 @@ + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p[0]) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("ejs.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils'); + +/** + * Library version. + */ + +exports.version = '0.4.2'; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.shift() || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>'; + + var buf = [ + "var buf = [];" + , "\nwith (locals) {" + , "\n buf.push('" + ]; + + var lineno = 1; + + for (var i = 0, len = str.length; i < len; ++i) { + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = '__stack.lineno=' + lineno; + switch (str[i]) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var start = i; + var end = str.indexOf(close, i); + var js = str.substring(i, end); + var n = 0; + while ((n = js.indexOf("\n", n)) > -1) { + n++; + lineno++; + } + if (js[0] == ':') js = filtered(js); + buf.push(prefix, js, postfix); + i += end - start + close.length - 1; + + } else if (str[i] == "\\") { + buf.push("\\\\"); + } else if (str[i] == "'") { + buf.push("\\'"); + } else if (str[i] == "\r") { + buf.push(" "); + } else if (str[i] == "\n") { + buf.push("\\n"); + lineno++; + } else { + buf.push(str[i]); + } + } + + buf.push("');\n}\nreturn buf.join('');"); + return buf.join(''); +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + + var input = JSON.stringify(str) + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + + if (options.debug) console.log(str); + var fn = new Function('locals, filters, escape', str); + return function(locals){ + return fn.call(this, locals, filters, utils.escape); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + return fn.call(options.scope, options.locals || {}); +}; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function(module, filename) { + source = require('fs').readFileSync(filename, 'utf-8'); + module._compile(compile(source, {}), filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} + +}); // module: ejs.js + +require.register("filters.js", function(module, exports, require){ + +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len){ + str = String(str); + return str.substr(0, len); +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; +}); // module: filters.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +}); // module: utils.js diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.min.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.min.js new file mode 100644 index 0000000..6b72d94 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/ejs.min.js @@ -0,0 +1,2 @@ +// CommonJS require() +function require(p){var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');mod.exports||(mod.exports={},mod.call(mod.exports,mod,mod.exports,require.relative(path)));return mod.exports}require.modules={},require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig},require.register=function(path,fn){require.modules[path]=fn},require.relative=function(parent){return function(p){if("."!=p[0])return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i> ":" ")+curr+"| "+line}).join("\n");err.path=filename,err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}var parse=exports.parse=function(str,options){var options=options||{},open=options.open||exports.open||"<%",close=options.close||exports.close||"%>",buf=["var buf = [];","\nwith (locals) {","\n buf.push('"],lineno=1;for(var i=0,len=str.length;ib)return 1;if(a/g,">").replace(/"/g,""")}}) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/client.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/client.html new file mode 100644 index 0000000..7081a04 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/client.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.ejs b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.ejs new file mode 100644 index 0000000..d571330 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.ejs @@ -0,0 +1,7 @@ +<% if (names.length) { %> +
      + <% names.forEach(function(name){ %> +
    • <%= name %>
    • + <% }) %> +
    +<% } %> \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.js new file mode 100644 index 0000000..9cd7168 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/examples/list.js @@ -0,0 +1,16 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , fs = require('fs') + , str = fs.readFileSync(__dirname + '/list.ejs', 'utf8'); + +var ret = ejs.render(str, { + locals: { + names: ['foo', 'bar', 'baz'] + } +}); + +console.log(ret); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/index.js new file mode 100644 index 0000000..20bf71a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/ejs'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/ejs.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/ejs.js new file mode 100644 index 0000000..46afa74 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/ejs.js @@ -0,0 +1,251 @@ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./utils'); + +/** + * Library version. + */ + +exports.version = '0.4.3'; + +/** + * Filters. + * + * @type Object + */ + +var filters = exports.filters = require('./filters'); + +/** + * Intermediate js cache. + * + * @type Object + */ + +var cache = {}; + +/** + * Clear intermediate js cache. + * + * @api public + */ + +exports.clearCache = function(){ + cache = {}; +}; + +/** + * Translate filtered code into function calls. + * + * @param {String} js + * @return {String} + * @api private + */ + +function filtered(js) { + return js.substr(1).split('|').reduce(function(js, filter){ + var parts = filter.split(':') + , name = parts.shift() + , args = parts.shift() || ''; + if (args) args = ', ' + args; + return 'filters.' + name + '(' + js + args + ')'; + }); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of ejs, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +function rethrow(err, str, filename, lineno){ + var lines = str.split('\n') + , start = Math.max(lineno - 3, 0) + , end = Math.min(lines.length, lineno + 3); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' >> ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'ejs') + ':' + + lineno + '\n' + + context + '\n\n' + + err.message; + + throw err; +} + +/** + * Parse the given `str` of ejs, returning the function body. + * + * @param {String} str + * @return {String} + * @api public + */ + +var parse = exports.parse = function(str, options){ + var options = options || {} + , open = options.open || exports.open || '<%' + , close = options.close || exports.close || '%>'; + + var buf = [ + "var buf = [];" + , "\nwith (locals) {" + , "\n buf.push('" + ]; + + var lineno = 1; + + for (var i = 0, len = str.length; i < len; ++i) { + if (str.slice(i, open.length + i) == open) { + i += open.length + + var prefix, postfix, line = '__stack.lineno=' + lineno; + switch (str.substr(i, 1)) { + case '=': + prefix = "', escape((" + line + ', '; + postfix = ")), '"; + ++i; + break; + case '-': + prefix = "', (" + line + ', '; + postfix = "), '"; + ++i; + break; + default: + prefix = "');" + line + ';'; + postfix = "; buf.push('"; + } + + var end = str.indexOf(close, i) + , js = str.substring(i, end) + , start = i + , n = 0; + + while (~(n = js.indexOf("\n", n))) n++, lineno++; + if (js.substr(0, 1) == ':') js = filtered(js); + buf.push(prefix, js, postfix); + i += end - start + close.length - 1; + + } else if (str.substr(i, 1) == "\\") { + buf.push("\\\\"); + } else if (str.substr(i, 1) == "'") { + buf.push("\\'"); + } else if (str.substr(i, 1) == "\r") { + buf.push(" "); + } else if (str.substr(i, 1) == "\n") { + buf.push("\\n"); + lineno++; + } else { + buf.push(str.substr(i, 1)); + } + } + + buf.push("');\n}\nreturn buf.join('');"); + return buf.join(''); +}; + +/** + * Compile the given `str` of ejs into a `Function`. + * + * @param {String} str + * @param {Object} options + * @return {Function} + * @api public + */ + +var compile = exports.compile = function(str, options){ + options = options || {}; + + var input = JSON.stringify(str) + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined'; + + // Adds the fancy stack trace meta info + str = [ + 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', + rethrow.toString(), + 'try {', + exports.parse(str, options), + '} catch (err) {', + ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', + '}' + ].join("\n"); + + if (options.debug) console.log(str); + var fn = new Function('locals, filters, escape', str); + return function(locals){ + return fn.call(this, locals, filters, utils.escape); + } +}; + +/** + * Render the given `str` of ejs. + * + * Options: + * + * - `locals` Local variables object + * - `cache` Compiled functions are cached, requires `filename` + * - `filename` Used by `cache` to key caches + * - `scope` Function execution context + * - `debug` Output generated function body + * - `open` Open tag, defaulting to "<%" + * - `close` Closing tag, defaulting to "%>" + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api public + */ + +exports.render = function(str, options){ + var fn + , options = options || {}; + if (options.cache) { + if (options.filename) { + fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); + } else { + throw new Error('"cache" option requires "filename".'); + } + } else { + fn = compile(str, options); + } + return fn.call(options.scope, options.locals || {}); +}; + +/** + * Expose to require(). + */ + +if (require.extensions) { + require.extensions['.ejs'] = function(module, filename) { + source = require('fs').readFileSync(filename, 'utf-8'); + module._compile(compile(source, {}), filename); + }; +} else if (require.registerExtension) { + require.registerExtension('.ejs', function(src) { + return compile(src, {}); + }); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/filters.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/filters.js new file mode 100644 index 0000000..d425c8d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/filters.js @@ -0,0 +1,198 @@ + +/*! + * EJS - Filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * First element of the target `obj`. + */ + +exports.first = function(obj) { + return obj[0]; +}; + +/** + * Last element of the target `obj`. + */ + +exports.last = function(obj) { + return obj[obj.length - 1]; +}; + +/** + * Capitalize the first letter of the target `str`. + */ + +exports.capitalize = function(str){ + str = String(str); + return str[0].toUpperCase() + str.substr(1, str.length); +}; + +/** + * Downcase the target `str`. + */ + +exports.downcase = function(str){ + return String(str).toLowerCase(); +}; + +/** + * Uppercase the target `str`. + */ + +exports.upcase = function(str){ + return String(str).toUpperCase(); +}; + +/** + * Sort the target `obj`. + */ + +exports.sort = function(obj){ + return Object.create(obj).sort(); +}; + +/** + * Sort the target `obj` by the given `prop` ascending. + */ + +exports.sort_by = function(obj, prop){ + return Object.create(obj).sort(function(a, b){ + a = a[prop], b = b[prop]; + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); +}; + +/** + * Size or length of the target `obj`. + */ + +exports.size = exports.length = function(obj) { + return obj.length; +}; + +/** + * Add `a` and `b`. + */ + +exports.plus = function(a, b){ + return Number(a) + Number(b); +}; + +/** + * Subtract `b` from `a`. + */ + +exports.minus = function(a, b){ + return Number(a) - Number(b); +}; + +/** + * Multiply `a` by `b`. + */ + +exports.times = function(a, b){ + return Number(a) * Number(b); +}; + +/** + * Divide `a` by `b`. + */ + +exports.divided_by = function(a, b){ + return Number(a) / Number(b); +}; + +/** + * Join `obj` with the given `str`. + */ + +exports.join = function(obj, str){ + return obj.join(str || ', '); +}; + +/** + * Truncate `str` to `len`. + */ + +exports.truncate = function(str, len){ + str = String(str); + return str.substr(0, len); +}; + +/** + * Truncate `str` to `n` words. + */ + +exports.truncate_words = function(str, n){ + var str = String(str) + , words = str.split(/ +/); + return words.slice(0, n).join(' '); +}; + +/** + * Replace `pattern` with `substitution` in `str`. + */ + +exports.replace = function(str, pattern, substitution){ + return String(str).replace(pattern, substitution || ''); +}; + +/** + * Prepend `val` to `obj`. + */ + +exports.prepend = function(obj, val){ + return Array.isArray(obj) + ? [val].concat(obj) + : val + obj; +}; + +/** + * Append `val` to `obj`. + */ + +exports.append = function(obj, val){ + return Array.isArray(obj) + ? obj.concat(val) + : obj + val; +}; + +/** + * Map the given `prop`. + */ + +exports.map = function(arr, prop){ + return arr.map(function(obj){ + return obj[prop]; + }); +}; + +/** + * Reverse the given `obj`. + */ + +exports.reverse = function(obj){ + return Array.isArray(obj) + ? obj.reverse() + : String(obj).split('').reverse().join(''); +}; + +/** + * Get `prop` of the given `obj`. + */ + +exports.get = function(obj, prop){ + return obj[prop]; +}; + +/** + * Packs the given `obj` into json string + */ +exports.json = function(obj){ + return JSON.stringify(obj); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/utils.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/utils.js new file mode 100644 index 0000000..8d569d6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/lib/utils.js @@ -0,0 +1,23 @@ + +/*! + * EJS + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/package.json new file mode 100644 index 0000000..224b4ff --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/package.json @@ -0,0 +1,11 @@ +{ + "name": "ejs", + "description": "Embedded JavaScript templates", + "version": "0.4.3", + "author": "TJ Holowaychuk ", + "keywords": ["template", "engine", "ejs"], + "devDependencies": { + "expresso": "0.9.2" + }, + "main": "./lib/ejs.js" +} \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/support/compile.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/support/compile.js new file mode 100644 index 0000000..edd3815 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/support/compile.js @@ -0,0 +1,173 @@ + +/** + * Module dependencies. + */ + +var fs = require('fs'); + +/** + * Arguments. + */ + +var args = process.argv.slice(2) + , pending = args.length + , files = {}; + +console.log(''); + +// parse arguments + +args.forEach(function(file){ + var mod = file.replace('lib/', ''); + fs.readFile(file, 'utf8', function(err, js){ + if (err) throw err; + console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file); + files[file] = parse(js); + --pending || compile(); + }); +}); + +/** + * Parse the given `js`. + */ + +function parse(js) { + return parseInheritance(parseConditionals(js)); +} + +/** + * Parse __proto__. + */ + +function parseInheritance(js) { + return js + .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){ + return child + '.prototype = new ' + parent + ';\n' + + child + '.prototype.constructor = '+ child + ';\n'; + }); +} + +/** + * Parse the given `js`, currently supporting: + * + * 'if' ['node' | 'browser'] + * 'end' + * + */ + +function parseConditionals(js) { + var lines = js.split('\n') + , len = lines.length + , buffer = true + , browser = false + , buf = [] + , line + , cond; + + for (var i = 0; i < len; ++i) { + line = lines[i]; + if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) { + cond = RegExp.$1; + buffer = browser = 'browser' == cond; + } else if (/^ *\/\/ *end/.test(line)) { + buffer = true; + browser = false; + } else if (browser) { + buf.push(line.replace(/^( *)\/\//, '$1')); + } else if (buffer) { + buf.push(line); + } + } + + return buf.join('\n'); +} + +/** + * Compile the files. + */ + +function compile() { + var buf = ''; + buf += '\n// CommonJS require()\n\n'; + buf += browser.require + '\n\n'; + buf += 'require.modules = {};\n\n'; + buf += 'require.resolve = ' + browser.resolve + ';\n\n'; + buf += 'require.register = ' + browser.register + ';\n\n'; + buf += 'require.relative = ' + browser.relative + ';\n\n'; + args.forEach(function(file){ + var js = files[file]; + file = file.replace('lib/', ''); + buf += '\nrequire.register("' + file + '", function(module, exports, require){\n'; + buf += js; + buf += '\n}); // module: ' + file + '\n'; + }); + fs.writeFile('ejs.js', buf, function(err){ + if (err) throw err; + console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js'); + console.log(); + }); +} + +// refactored version of weepy's +// https://github.com/weepy/brequire/blob/master/browser/brequire.js + +var browser = { + + /** + * Require a module. + */ + + require: function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + }, + + /** + * Resolve module path. + */ + + resolve: function(path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }, + + /** + * Return relative require(). + */ + + relative: function(parent) { + return function(p){ + if ('.' != p.substr(0, 1)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }, + + /** + * Register a module. + */ + + register: function(path, fn){ + require.modules[path] = fn; + } +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/test/ejs.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/test/ejs.test.js new file mode 100644 index 0000000..624157d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/deps/ejs/test/ejs.test.js @@ -0,0 +1,269 @@ + +/** + * Module dependencies. + */ + +var ejs = require('../') + , assert = require('assert'); + +module.exports = { + 'test .version': function(){ + assert.ok(/^\d+\.\d+\.\d+$/.test(ejs.version), 'Test .version format'); + }, + + 'test html': function(){ + assert.equal('

    yay

    ', ejs.render('

    yay

    ')); + }, + + 'test buffered code': function(){ + var html = '

    tj

    ', + str = '

    <%= name %>

    ', + locals = { name: 'tj' }; + assert.equal(html, ejs.render(str, { locals: locals })); + }, + + 'test unbuffered code': function(){ + var html = '

    tj

    ', + str = '<% if (name) { %>

    <%= name %>

    <% } %>', + locals = { name: 'tj' }; + assert.equal(html, ejs.render(str, { locals: locals })); + }, + + 'test `scope` option': function(){ + var html = '

    tj

    ', + str = '

    <%= this %>

    '; + assert.equal(html, ejs.render(str, { scope: 'tj' })); + }, + + 'test escaping': function(){ + assert.equal('<script>', ejs.render('<%= " + + + + + + + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/examples/nested/nested_reporter_test.unit.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/examples/nested/nested_reporter_test.unit.js new file mode 100644 index 0000000..612adcd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/examples/nested/nested_reporter_test.unit.js @@ -0,0 +1,94 @@ +var testCase = require('nodeunit').testCase; +/* + This is an example test suite to demonstrate the nested test reporter. + Run with --reporter nested, e.g., + nodeunit --reporter nested nested_reporter_test.unit.js + + The test output should be something like: + + nested_reporter_test.unit.js + Test 0.1 (pass) + TC 1 + TC 1.1 + Test 1.1.1 (pass) + TC 2 + TC 2.1 + TC 2.1.1 + Test 2.1.1.1 (pass) + Test 2.1.1.2 (pass) + TC 2.2.1 + Test 2.2.1.1 (pass) + TC 2.2.1.1 + Test 2.2.1.1.1 (pass) + Test 2.2.1.2 (pass) + TC 3 + TC 3.1 + TC 3.1.1 + Test 3.1.1.1 (should fail) (fail) ✖ + AssertionError: false == true + // stack trace here. + + FAILURES: 1/8 assertions failed (6ms) +*/ + +module.exports = testCase({ + "Test 0.1": function(test) { + test.ok(true); + test.done(); + }, + + "TC 1": testCase({ + "TC 1.1": testCase({ + "Test 1.1.1": function(test) { + test.ok(true); + test.done(); + } + }) + }), + + "TC 2": testCase({ + "TC 2.1": testCase({ + "TC 2.1.1": testCase({ + "Test 2.1.1.1": function(test) { + test.ok(true); + test.done(); + }, + + "Test 2.1.1.2": function(test) { + test.ok(true); + test.done(); + } + }), + + "TC 2.2.1": testCase({ + "Test 2.2.1.1": function(test) { + test.ok(true); + test.done(); + }, + + "TC 2.2.1.1": testCase({ + "Test 2.2.1.1.1": function(test) { + test.ok(true); + test.done(); + }, + }), + + "Test 2.2.1.2": function(test) { + test.ok(true); + test.done(); + } + }) + }) + }), + + "TC 3": testCase({ + "TC 3.1": testCase({ + "TC 3.1.1": testCase({ + "Test 3.1.1.1 (should fail)": function(test) { + test.ok(false); + test.done(); + } + }) + }) + }) +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_fail.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_fail.png new file mode 100644 index 0000000..78ff425 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_fail.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_machineout.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_machineout.png new file mode 100644 index 0000000..c6bfa27 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_machineout.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_pass.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_pass.png new file mode 100644 index 0000000..069d716 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/img/example_pass.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/index.js new file mode 100644 index 0000000..07867d0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/index.js @@ -0,0 +1,3 @@ +// This file is just added for convenience so this repository can be +// directly checked out into a project's deps folder +module.exports = require('./lib/nodeunit'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/assert.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/assert.js new file mode 100644 index 0000000..09f588d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/assert.js @@ -0,0 +1,354 @@ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + if (typeof obj != 'object' && typeof obj != 'function') { + throw new TypeError('-'); + } + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS 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. + + +var pSlice = Array.prototype.slice; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = exports; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({message: message, actual: actual, expected: expected}) + +assert.AssertionError = function AssertionError (options) { + this.name = "AssertionError"; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.ok); +}; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, "==", assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, "!=", assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, "deepEqual", assert.deepEqual); + } +}; + +var Buffer = null; +if (typeof require !== 'undefined' && typeof process !== 'undefined') { + try { + Buffer = require('buffer').Buffer; + } + catch (e) { + // May be a CommonJS environment other than Node.js + Buffer = null; + } +} + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + 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.2.1 If the expcted value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object that refers to the same source and options + } else if (actual instanceof RegExp && expected instanceof RegExp) { + return actual.source === expected.source && + actual.global === expected.global && + actual.ignoreCase === expected.ignoreCase && + actual.multiline === expected.multiline; + + } else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) { + return (function() { + var i, len; + + for (i = 0, len = expected.length; i < len; i++) { + if (actual[i] !== expected[i]) { + return false; + } + } + return actual.length === expected.length; + })(); + // 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 _deepEqual(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 (!_deepEqual(a[key], b[key] )) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, "===", assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as determined by !==. +// assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, "!==", assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (expected instanceof RegExp) { + return expected.test(actual.message || actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail('Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail('Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/core.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/core.js new file mode 100644 index 0000000..5281bc7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/core.js @@ -0,0 +1,318 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, it's mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + +var async = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER + nodeunit = require('./nodeunit'), //@REMOVE_LINE_FOR_BROWSER + types = require('./types'); //@REMOVE_LINE_FOR_BROWSER + + +/** + * Added for browser compatibility + */ + +var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; +}; + + +var _copy = function (obj) { + var nobj = {}; + var keys = _keys(obj); + for (var i = 0; i < keys.length; i += 1) { + nobj[keys[i]] = obj[keys[i]]; + } + return nobj; +}; + + +/** + * Runs a test function (fn) from a loaded module. After the test function + * calls test.done(), the callback is executed with an assertionList as its + * second argument. + * + * @param {String} name + * @param {Function} fn + * @param {Object} opt + * @param {Function} callback + * @api public + */ + +exports.runTest = function (name, fn, opt, callback) { + var options = types.options(opt); + + options.testStart(name); + var start = new Date().getTime(); + var test = types.test(name, start, options, callback); + + try { + fn(test); + } + catch (e) { + test.done(e); + } +}; + +/** + * Takes an object containing test functions or other test suites as properties + * and runs each in series. After all tests have completed, the callback is + * called with a list of all assertions as the second argument. + * + * If a name is passed to this function it is prepended to all test and suite + * names that run within it. + * + * @param {String} name + * @param {Object} suite + * @param {Object} opt + * @param {Function} callback + * @api public + */ + +exports.runSuite = function (name, suite, opt, callback) { + suite = wrapGroup(suite); + var keys = _keys(suite); + + async.concatSeries(keys, function (k, cb) { + var prop = suite[k], _name; + + _name = name ? [].concat(name, k) : [k]; + _name.toString = function () { + // fallback for old one + return this.join(' - '); + }; + + if (typeof prop === 'function') { + var in_name = false, + in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false; + for (var i = 0; i < _name.length; i += 1) { + if (_name[i] === opt.testspec) { + in_name = true; + } + } + + if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) { + if (opt.moduleStart) { + opt.moduleStart(); + } + exports.runTest(_name, suite[k], opt, cb); + } + else { + return cb(); + } + } + else { + exports.runSuite(_name, suite[k], opt, cb); + } + }, callback); +}; + +/** + * Run each exported test function or test suite from a loaded module. + * + * @param {String} name + * @param {Object} mod + * @param {Object} opt + * @param {Function} callback + * @api public + */ + +exports.runModule = function (name, mod, opt, callback) { + var options = _copy(types.options(opt)); + + var _run = false; + var _moduleStart = options.moduleStart; + + mod = wrapGroup(mod); + + function run_once() { + if (!_run) { + _run = true; + _moduleStart(name); + } + } + options.moduleStart = run_once; + + var start = new Date().getTime(); + + exports.runSuite(null, mod, options, function (err, a_list) { + var end = new Date().getTime(); + var assertion_list = types.assertionList(a_list, end - start); + options.moduleDone(name, assertion_list); + if (nodeunit.complete) { + nodeunit.complete(name, assertion_list); + } + callback(null, a_list); + }); +}; + +/** + * Treats an object literal as a list of modules keyed by name. Runs each + * module and finished with calling 'done'. You can think of this as a browser + * safe alternative to runFiles in the nodeunit module. + * + * @param {Object} modules + * @param {Object} opt + * @api public + */ + +// TODO: add proper unit tests for this function +exports.runModules = function (modules, opt) { + var all_assertions = []; + var options = types.options(opt); + var start = new Date().getTime(); + + async.concatSeries(_keys(modules), function (k, cb) { + exports.runModule(k, modules[k], options, cb); + }, + function (err, all_assertions) { + var end = new Date().getTime(); + options.done(types.assertionList(all_assertions, end - start)); + }); +}; + + +/** + * Wraps a test function with setUp and tearDown functions. + * Used by testCase. + * + * @param {Function} setUp + * @param {Function} tearDown + * @param {Function} fn + * @api private + */ + +var wrapTest = function (setUp, tearDown, fn) { + return function (test) { + var context = {}; + if (tearDown) { + var done = test.done; + test.done = function (err) { + try { + tearDown.call(context, function (err2) { + if (err && err2) { + test._assertion_list.push( + types.assertion({error: err}) + ); + return done(err2); + } + done(err || err2); + }); + } + catch (e) { + done(e); + } + }; + } + if (setUp) { + setUp.call(context, function (err) { + if (err) { + return test.done(err); + } + fn.call(context, test); + }); + } + else { + fn.call(context, test); + } + }; +}; + + +/** + * Returns a serial callback from two functions. + * + * @param {Function} funcFirst + * @param {Function} funcSecond + * @api private + */ + +var getSerialCallback = function (fns) { + if (!fns.length) { + return null; + } + return function (callback) { + var that = this; + var bound_fns = []; + for (var i = 0, len = fns.length; i < len; i++) { + (function (j) { + bound_fns.push(function () { + return fns[j].apply(that, arguments); + }); + })(i); + } + return async.series(bound_fns, callback); + }; +}; + + +/** + * Wraps a group of tests with setUp and tearDown functions. + * Used by testCase. + * + * @param {Object} group + * @param {Array} setUps - parent setUp functions + * @param {Array} tearDowns - parent tearDown functions + * @api private + */ + +var wrapGroup = function (group, setUps, tearDowns) { + var tests = {}; + + var setUps = setUps ? setUps.slice(): []; + var tearDowns = tearDowns ? tearDowns.slice(): []; + + if (group.setUp) { + setUps.push(group.setUp); + delete group.setUp; + } + if (group.tearDown) { + tearDowns.unshift(group.tearDown); + delete group.tearDown; + } + + var keys = _keys(group); + + for (var i = 0; i < keys.length; i += 1) { + var k = keys[i]; + if (typeof group[k] === 'function') { + tests[k] = wrapTest( + getSerialCallback(setUps), + getSerialCallback(tearDowns), + group[k] + ); + } + else if (typeof group[k] === 'object') { + tests[k] = wrapGroup(group[k], setUps, tearDowns); + } + } + return tests; +}; + + +/** + * Backwards compatibility for test suites using old testCase API + */ + +exports.testCase = function (suite) { + return suite; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/nodeunit.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/nodeunit.js new file mode 100644 index 0000000..e20e974 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/nodeunit.js @@ -0,0 +1,104 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var async = require('../deps/async'), + types = require('./types'), + utils = require('./utils'), + core = require('./core'), + reporters = require('./reporters'), + assert = require('./assert'), + path = require('path') + events = require('events'); + + +/** + * Export sub-modules. + */ + +exports.types = types; +exports.utils = utils; +exports.reporters = reporters; +exports.assert = assert; + +// backwards compatibility +exports.testrunner = { + run: function () { + console.log( + 'WARNING: nodeunit.testrunner is going to be deprecated, please ' + + 'use nodeunit.reporters.default instead!' + ); + return reporters['default'].run.apply(this, arguments); + } +}; + + +/** + * Export all core functions + */ + +for (var k in core) { + exports[k] = core[k]; +}; + + +/** + * Load modules from paths array and run all exported tests in series. If a path + * is a directory, load all supported file types inside it as modules. This only + * reads 1 level deep in the directory and does not recurse through + * sub-directories. + * + * @param {Array} paths + * @param {Object} opt + * @api public + */ + +exports.runFiles = function (paths, opt) { + var all_assertions = []; + var options = types.options(opt); + var start = new Date().getTime(); + + if (!paths.length) { + return options.done(types.assertionList(all_assertions)); + } + + utils.modulePaths(paths, function (err, files) { + if (err) throw err; + async.concatSeries(files, function (file, cb) { + var name = path.basename(file); + exports.runModule(name, require(file), options, cb); + }, + function (err, all_assertions) { + var end = new Date().getTime(); + exports.done() + options.done(types.assertionList(all_assertions, end - start)); + }); + }); + +}; + +/* Export all prototypes from events.EventEmitter */ +var label; +for (label in events.EventEmitter.prototype) { + exports[label] = events.EventEmitter.prototype[label]; +} + +/* Emit event 'complete' on completion of a test suite. */ +exports.complete = function(name, assertions) +{ + exports.emit('complete', name, assertions); +}; + +/* Emit event 'complete' on completion of all tests. */ +exports.done = function() +{ + exports.emit('done'); +}; + +module.exports = exports; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/browser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/browser.js new file mode 100644 index 0000000..9836c90 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/browser.js @@ -0,0 +1,121 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + + +/** + * NOTE: this test runner is not listed in index.js because it cannot be + * used with the command-line tool, only inside the browser. + */ + + +/** + * Reporter info string + */ + +exports.info = "Browser-based test reporter"; + + +/** + * Run all tests within each module, reporting the results + * + * @param {Array} files + * @api public + */ + +exports.run = function (modules, options) { + var start = new Date().getTime(), div; + options = options || {}; + div = options.div || document.body; + + function setText(el, txt) { + if ('innerText' in el) { + el.innerText = txt; + } + else if ('textContent' in el){ + el.textContent = txt; + } + } + + function getOrCreate(tag, id) { + var el = document.getElementById(id); + if (!el) { + el = document.createElement(tag); + el.id = id; + div.appendChild(el); + } + return el; + }; + + var header = getOrCreate('h1', 'nodeunit-header'); + var banner = getOrCreate('h2', 'nodeunit-banner'); + var userAgent = getOrCreate('h2', 'nodeunit-userAgent'); + var tests = getOrCreate('ol', 'nodeunit-tests'); + var result = getOrCreate('p', 'nodeunit-testresult'); + + setText(userAgent, navigator.userAgent); + + nodeunit.runModules(modules, { + moduleStart: function (name) { + /*var mheading = document.createElement('h2'); + mheading.innerText = name; + results.appendChild(mheading); + module = document.createElement('ol'); + results.appendChild(module);*/ + }, + testDone: function (name, assertions) { + var test = document.createElement('li'); + var strong = document.createElement('strong'); + strong.innerHTML = name + ' (' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
    ' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/default.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/default.js new file mode 100644 index 0000000..9b4c66a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/default.js @@ -0,0 +1,131 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + track = require('../track'), + path = require('path'), + AssertionError = require('../assert').AssertionError; + +/** + * Reporter info string + */ + +exports.info = "Default tests reporter"; + + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options, callback) { + + if (!options) { + // load default options + var content = fs.readFileSync( + __dirname + '/../../bin/nodeunit.json', 'utf8' + ); + options = JSON.parse(content); + } + + var error = function (str) { + return options.error_prefix + str + options.error_suffix; + }; + var ok = function (str) { + return options.ok_prefix + str + options.ok_suffix; + }; + var bold = function (str) { + return options.bold_prefix + str + options.bold_suffix; + }; + var assertion_message = function (str) { + return options.assertion_prefix + str + options.assertion_suffix; + }; + + var start = new Date().getTime(); + var tracker = track.createTracker(function (tracker) { + if (tracker.unfinished()) { + console.log(''); + console.log(error(bold( + 'FAILURES: Undone tests (or their setups/teardowns): ' + ))); + var names = tracker.names(); + for (var i = 0; i < names.length; i += 1) { + console.log('- ' + names[i]); + } + console.log(''); + console.log('To fix this, make sure all tests call test.done()'); + process.reallyExit(tracker.unfinished()); + } + }); + + var opts = { + testspec: options.testspec, + testFullSpec: options.testFullSpec, + moduleStart: function (name) { + console.log('\n' + bold(name)); + }, + testDone: function (name, assertions) { + tracker.remove(name); + + if (!assertions.failures()) { + console.log('✔ ' + name); + } + else { + console.log(error('✖ ' + name) + '\n'); + assertions.forEach(function (a) { + if (a.failed()) { + a = utils.betterErrors(a); + if (a.error instanceof AssertionError && a.message) { + console.log( + 'Assertion Message: ' + + assertion_message(a.message) + ); + } + console.log(a.error.stack + '\n'); + } + }); + } + }, + done: function (assertions, end) { + var end = end || new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '\n' + bold(error('FAILURES: ')) + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)' + ); + } + else { + console.log( + '\n' + bold(ok('OK: ')) + assertions.length + + ' assertions (' + assertions.duration + 'ms)' + ); + } + + if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined); + }, + testStart: function(name) { + tracker.put(name); + } + }; + if (files && files.length) { + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + nodeunit.runFiles(paths, opts); + } else { + nodeunit.runModules(files,opts); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/eclipse.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/eclipse.js new file mode 100644 index 0000000..6775ff1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/eclipse.js @@ -0,0 +1,104 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + track = require('../track'), + path = require('path'), + AssertionError = require('../assert').AssertionError; + +/** + * Reporter info string + */ + +exports.info = "Reporter for eclipse plugin"; + + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options, callback) { + + var start = new Date().getTime(); + var paths = files.map(function (p) { + if (p.indexOf('/') === 0) { + return p; + } + return path.join(process.cwd(), p); + }); + var tracker = track.createTracker(function (tracker) { + if (tracker.unfinished()) { + console.log(''); + console.log('FAILURES: Undone tests (or their setups/teardowns): '); + var names = tracker.names(); + for (var i = 0; i < names.length; i += 1) { + console.log('- ' + names[i]); + } + console.log(''); + console.log('To fix this, make sure all tests call test.done()'); + process.reallyExit(tracker.unfinished()); + } + }); + + nodeunit.runFiles(paths, { + testspec: undefined, + moduleStart: function (name) { + console.log('\n' + name); + }, + testDone: function (name, assertions) { + tracker.remove(name); + + if (!assertions.failures()) { + console.log('✔ ' + name); + } + else { + console.log('✖ ' + name + '\n'); + assertions.forEach(function (a) { + if (a.failed()) { + a = utils.betterErrors(a); + if (a.error instanceof AssertionError && a.message) { + console.log( + 'Assertion Message: ' + a.message + ); + } + console.log(a.error.stack + '\n'); + } + }); + } + }, + done: function (assertions, end) { + var end = end || new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '\n' + 'FAILURES: ' + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)' + ); + } + else { + console.log( + '\n' + 'OK: ' + assertions.length + + ' assertions (' + assertions.duration + 'ms)' + ); + } + + if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined); + }, + testStart: function (name) { + tracker.put(name); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/html.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/html.js new file mode 100644 index 0000000..80866b6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/html.js @@ -0,0 +1,110 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + path = require('path'), + AssertionError = require('assert').AssertionError; + +/** + * Reporter info string + */ + +exports.info = "Report tests result as HTML"; + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options, callback) { + + var start = new Date().getTime(); + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + + console.log(''); + console.log(''); + console.log(''); + console.log(''); + console.log(''); + console.log(''); + nodeunit.runFiles(paths, { + testspec: options.testspec, + testFullSpec: options.testFullSpec, + moduleStart: function (name) { + console.log('

    ' + name + '

    '); + console.log('
      '); + }, + testDone: function (name, assertions) { + if (!assertions.failures()) { + console.log('
    1. ' + name + '
    2. '); + } + else { + console.log('
    3. ' + name); + assertions.forEach(function (a) { + if (a.failed()) { + a = utils.betterErrors(a); + if (a.error instanceof AssertionError && a.message) { + console.log('
      ' + + 'Assertion Message: ' + a.message + + '
      '); + } + console.log('
      ');
      +                        console.log(a.error.stack);
      +                        console.log('
      '); + } + }); + console.log('
    4. '); + } + }, + moduleDone: function () { + console.log('
    '); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '

    FAILURES: ' + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)

    ' + ); + } + else { + console.log( + '

    OK: ' + assertions.length + + ' assertions (' + assertions.duration + 'ms)

    ' + ); + } + console.log(''); + console.log(''); + + if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/index.js new file mode 100644 index 0000000..b3989c0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/index.js @@ -0,0 +1,14 @@ +module.exports = { + 'junit': require('./junit'), + 'default': require('./default'), + 'skip_passed': require('./skip_passed'), + 'minimal': require('./minimal'), + 'html': require('./html'), + 'eclipse': require('./eclipse'), + 'machineout': require('./machineout'), + 'tap': require('./tap'), + 'nested': require('./nested'), + 'verbose' : require('./verbose') + // browser test reporter is not listed because it cannot be used + // with the command line tool, only inside a browser. +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/junit.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/junit.js new file mode 100644 index 0000000..d9a1d02 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/junit.js @@ -0,0 +1,180 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + path = require('path'), + async = require('../../deps/async'), + AssertionError = require('assert').AssertionError, + child_process = require('child_process'), + ejs = require('../../deps/ejs'); + + +/** + * Reporter info string + */ + +exports.info = "jUnit XML test reports"; + + +/** + * Ensures a directory exists using mkdir -p. + * + * @param {String} path + * @param {Function} callback + * @api private + */ + +var ensureDir = function (path, callback) { + var mkdir = child_process.spawn('mkdir', ['-p', path]); + mkdir.on('error', function (err) { + callback(err); + callback = function(){}; + }); + mkdir.on('exit', function (code) { + if (code === 0) callback(); + else callback(new Error('mkdir exited with code: ' + code)); + }); +}; + + +/** + * Returns absolute version of a path. Relative paths are interpreted + * relative to process.cwd() or the cwd parameter. Paths that are already + * absolute are returned unaltered. + * + * @param {String} p + * @param {String} cwd + * @return {String} + * @api public + */ + +var abspath = function (p, /*optional*/cwd) { + if (p[0] === '/') return p; + cwd = cwd || process.cwd(); + return path.normalize(path.join(cwd, p)); +}; + + +/** + * Run all tests within each module, reporting the results to the command-line, + * then writes out junit-compatible xml documents. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, opts, callback) { + if (!opts.output) { + console.error( + 'Error: No output directory defined.\n' + + '\tEither add an "output" property to your nodeunit.json config ' + + 'file, or\n\tuse the --output command line option.' + ); + return; + } + opts.output = abspath(opts.output); + var error = function (str) { + return opts.error_prefix + str + opts.error_suffix; + }; + var ok = function (str) { + return opts.ok_prefix + str + opts.ok_suffix; + }; + var bold = function (str) { + return opts.bold_prefix + str + opts.bold_suffix; + }; + + var start = new Date().getTime(); + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + + var modules = {} + var curModule; + + nodeunit.runFiles(paths, { + testspec: opts.testspec, + testFullSpec: opts.testFullSpec, + moduleStart: function (name) { + curModule = { + errorCount: 0, + failureCount: 0, + tests: 0, + testcases: [], + name: name + }; + modules[name] = curModule; + }, + testDone: function (name, assertions) { + var testcase = {name: name}; + for (var i=0; i name_slice(['TC1', 'TC1.1', 'mytest'], 1); + * "TC1,TC1.1" + */ + var name_slice = function (name_arr, end_index) { + return name_arr.slice(0, end_index + 1).join(","); + }; + + var indent = (function () { + var txt = ''; + var i; + for (i = 0; i < spaces_per_indent; i++) { + txt += ' '; + } + return txt; + }()); + + // Indent once for each indent_level + var add_indent = function (txt, indent_level) { + var k; + for (k = 0; k < indent_level; k++) { + txt += indent; + } + return txt; + }; + + // If it's not the last element of the name_arr, it's a testCase. + var is_testCase = function (name_arr, index) { + return index === name_arr.length - 1 ? false : true; + }; + + var testCase_line = function (txt) { + return txt + "\n"; + }; + + /** + * Prints (console.log) the nested test status line(s). + * + * @param {Array} name_arr - Array of name elements. + * @param {String} status - either 'pass' or 'fail'. + * @example + * > print_status(['TC1', 'TC1.1', 'mytest'], 'pass'); + * TC1 + * TC1.1 + * mytest (pass) + */ + var print_status = function (name_arr, status) { + var txt = ''; + var _name_slice, part, i; + for (i = 0; i < name_arr.length; i++) { + _name_slice = name_slice(name_arr, i); + part = name_arr[i]; + if (!tracker.already_printed[_name_slice]) { + txt = add_indent(txt, i); + if (is_testCase(name_arr, i)) { + txt += testCase_line(part); + } else { + txt += status_text(part, status); + } + tracker.already_printed[_name_slice] = true; + } + } + console.log(txt); + }; + + nodeunit.runFiles(paths, { + testspec: options.testspec, + testFullSpec: options.testFullSpec, + moduleStart: function (name) { + console.log('\n' + bold(name)); + }, + testDone: function (name, assertions) { + tracker.remove(name); + + if (!assertions.failures()) { + print_status(name, 'pass'); + } else { + print_status(name, 'fail'); + assertions.forEach(function (a) { + if (a.failed()) { + a = utils.betterErrors(a); + if (a.error instanceof AssertionError && a.message) { + console.log( + 'Assertion Message: ' + + assertion_message(a.message) + ); + } + console.log(a.error.stack + '\n'); + } + }); + } + }, + done: function (assertions, end) { + end = end || new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '\n' + bold(error('FAILURES: ')) + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)' + ); + } else { + console.log( + '\n' + bold(ok('OK: ')) + assertions.length + + ' assertions (' + assertions.duration + 'ms)' + ); + } + }, + testStart: function (name) { + tracker.put(name); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/skip_passed.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/skip_passed.js new file mode 100644 index 0000000..299a99a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/skip_passed.js @@ -0,0 +1,108 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + path = require('path'), + AssertionError = require('assert').AssertionError; + +/** + * Reporter info string + */ + +exports.info = "Skip passed tests output"; + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options, callback) { + + if (!options) { + // load default options + var content = fs.readFileSync( + __dirname + '/../../bin/nodeunit.json', 'utf8' + ); + options = JSON.parse(content); + } + + var error = function (str) { + return options.error_prefix + str + options.error_suffix; + }; + var ok = function (str) { + return options.ok_prefix + str + options.ok_suffix; + }; + var bold = function (str) { + return options.bold_prefix + str + options.bold_suffix; + }; + var assertion_message = function (str) { + return options.assertion_prefix + str + options.assertion_suffix; + }; + + var start = new Date().getTime(); + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + + nodeunit.runFiles(paths, { + testspec: options.testspec, + testFullSpec: options.testFullSpec, + moduleStart: function (name) { + console.log('\n' + bold(name)); + }, + testDone: function (name, assertions) { + if (assertions.failures()) { + console.log(error('✖ ' + name) + '\n'); + assertions.forEach(function (a) { + if (a.failed()) { + a = utils.betterErrors(a); + if (a.error instanceof AssertionError && a.message) { + console.log( + 'Assertion Message: ' + assertion_message(a.message) + ); + } + console.log(a.error.stack + '\n'); + } + }); + } + }, + moduleDone: function (name, assertions) { + if (!assertions.failures()) { + console.log('✔ all tests passed'); + } + else { + console.log(error('✖ some tests failed')); + } + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '\n' + bold(error('FAILURES: ')) + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)' + ); + } + else { + console.log( + '\n' + bold(ok('OK: ')) + assertions.length + + ' assertions (' + assertions.duration + 'ms)' + ); + } + + if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/tap.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/tap.js new file mode 100644 index 0000000..9a36aaf --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/tap.js @@ -0,0 +1,65 @@ +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + path = require('path'), + assert = require('tap').assert, + TapProducer = require('tap').Producer; + +/** + * Reporter info string + */ + +exports.info = "TAP output"; + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options) { + + if (!options) { + // load default options + var content = fs.readFileSync( + __dirname + '/../../bin/nodeunit.json', 'utf8' + ); + options = JSON.parse(content); + } + + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + var output = new TapProducer(); + output.pipe(process.stdout); + + nodeunit.runFiles(paths, { + testStart: function (name) { + output.write(name.toString()); + }, + testDone: function (name, assertions) { + assertions.forEach(function (e) { + var extra = {}; + if (e.error) { + extra.error = { + name: e.error.name, + message: e.error.message, + stack: e.error.stack.split(/\n/).filter(function (line) { + // exclude line of "types.js" + return ! RegExp(/types.js:83:39/).test(line); + }).join('\n') + }; + extra.wanted = e.error.expected; + extra.found = e.error.actual; + } + output.write(assert(e.passed(), e.message, extra)); + }); + }, + done: function (assertions) { + output.end(); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/verbose.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/verbose.js new file mode 100644 index 0000000..228271b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/reporters/verbose.js @@ -0,0 +1,123 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var nodeunit = require('../nodeunit'), + utils = require('../utils'), + fs = require('fs'), + track = require('../track'), + path = require('path'); + AssertionError = require('../assert').AssertionError; + +/** + * Reporter info string + */ + +exports.info = "Verbose tests reporter" + + +/** + * Run all tests within each module, reporting the results to the command-line. + * + * @param {Array} files + * @api public + */ + +exports.run = function (files, options) { + + if (!options) { + // load default options + var content = fs.readFileSync( + __dirname + '/../../bin/nodeunit.json', 'utf8' + ); + options = JSON.parse(content); + } + + var error = function (str) { + return options.error_prefix + str + options.error_suffix; + }; + var ok = function (str) { + return options.ok_prefix + str + options.ok_suffix; + }; + var bold = function (str) { + return options.bold_prefix + str + options.bold_suffix; + }; + var assertion_message = function (str) { + return options.assertion_prefix + str + options.assertion_suffix; + }; + + var start = new Date().getTime(); + var paths = files.map(function (p) { + return path.join(process.cwd(), p); + }); + var tracker = track.createTracker(function (tracker) { + if (tracker.unfinished()) { + console.log(''); + console.log(error(bold( + 'FAILURES: Undone tests (or their setups/teardowns): ' + ))); + var names = tracker.names(); + for (var i = 0; i < names.length; i += 1) { + console.log('- ' + names[i]); + } + console.log(''); + console.log('To fix this, make sure all tests call test.done()'); + process.reallyExit(tracker.unfinished()); + } + }); + + nodeunit.runFiles(paths, { + testspec: options.testspec, + testFullSpec: options.testFullSpec, + moduleStart: function (name) { + console.log('\n' + bold(name)); + }, + testDone: function (name, assertions) { + tracker.remove(name); + + if (!assertions.failures()) { + console.log('✔ ' + name); + } + else { + console.log(error('✖ ' + name)); + } + // verbose so print everything + assertions.forEach(function (a) { + if (a.failed()) { + console.log(error(' ✖ ' + a.message)); + a = utils.betterErrors(a); + console.log(' ' + a.error.stack); + } + else { + console.log(' ✔ ' + a.message); + } + }); + }, + done: function (assertions, end) { + var end = end || new Date().getTime(); + var duration = end - start; + if (assertions.failures()) { + console.log( + '\n' + bold(error('FAILURES: ')) + assertions.failures() + + '/' + assertions.length + ' assertions failed (' + + assertions.duration + 'ms)' + ); + } + else { + console.log( + '\n' + bold(ok('OK: ')) + assertions.length + + ' assertions (' + assertions.duration + 'ms)' + ); + } + }, + testStart: function(name) { + tracker.put(name); + } + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/track.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/track.js new file mode 100644 index 0000000..5af98ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/track.js @@ -0,0 +1,48 @@ +/*! + * Simple util module to track tests. Adds a process.exit hook to print + * the undone tests. + */ + + +exports.createTracker = function (on_exit) { + var names = {}; + var tracker = { + names: function () { + var arr = []; + for (var k in names) { + if (names.hasOwnProperty(k)) { + arr.push(k); + } + } + return arr; + }, + unfinished: function () { + return tracker.names().length; + }, + put: function (testname) { + names[testname] = testname; + }, + remove: function (testname) { + delete names[testname]; + } + }; + + process.on('exit', function() { + on_exit = on_exit || exports.default_on_exit; + on_exit(tracker); + }); + + return tracker; +}; + +exports.default_on_exit = function (tracker) { + if (tracker.unfinished()) { + console.log(''); + console.log('Undone tests (or their setups/teardowns): '); + var names = tracker.names(); + for (var i = 0; i < names.length; i += 1) { + console.log(names[i]); + } + process.reallyExit(tracker.unfinished()); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/types.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/types.js new file mode 100644 index 0000000..2cdd1ef --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/types.js @@ -0,0 +1,189 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, it's mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + +var assert = require('./assert'), //@REMOVE_LINE_FOR_BROWSER + async = require('../deps/async'); //@REMOVE_LINE_FOR_BROWSER + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i = 0; i < this.length; i += 1) { + if (this[i].failed()) { + failures += 1; + } + } + return failures; + }; + that.passes = function () { + return that.length - that.failures(); + }; + that.duration = duration || 0; + return that; +}; + +/** + * Create a wrapper function for assert module methods. Executes a callback + * after it's complete with an assertion object representing the result. + * + * @param {Function} callback + * @api private + */ + +var assertWrapper = function (callback) { + return function (new_method, assert_method, arity) { + return function () { + var message = arguments[arity - 1]; + var a = exports.assertion({method: new_method, message: message}); + try { + assert[assert_method].apply(null, arguments); + } + catch (e) { + a.error = e; + } + callback(a); + }; + }; +}; + +/** + * Creates the 'test' object that gets passed to every test function. + * Accepts the name of the test function as its first argument, followed by + * the start time in ms, the options object and a callback function. + * + * @param {String} name + * @param {Number} start + * @param {Object} options + * @param {Function} callback + * @api public + */ + +exports.test = function (name, start, options, callback) { + var expecting; + var a_list = []; + + var wrapAssert = assertWrapper(function (a) { + a_list.push(a); + if (options.log) { + async.nextTick(function () { + options.log(a); + }); + } + }); + + var test = { + done: function (err) { + if (expecting !== undefined && expecting !== a_list.length) { + var e = new Error( + 'Expected ' + expecting + ' assertions, ' + + a_list.length + ' ran' + ); + var a1 = exports.assertion({method: 'expect', error: e}); + a_list.push(a1); + if (options.log) { + async.nextTick(function () { + options.log(a1); + }); + } + } + if (err) { + var a2 = exports.assertion({error: err}); + a_list.push(a2); + if (options.log) { + async.nextTick(function () { + options.log(a2); + }); + } + } + var end = new Date().getTime(); + async.nextTick(function () { + var assertion_list = exports.assertionList(a_list, end - start); + options.testDone(name, assertion_list); + callback(null, a_list); + }); + }, + ok: wrapAssert('ok', 'ok', 2), + same: wrapAssert('same', 'deepEqual', 3), + equals: wrapAssert('equals', 'equal', 3), + expect: function (num) { + expecting = num; + }, + _assertion_list: a_list + }; + // add all functions from the assert module + for (var k in assert) { + if (assert.hasOwnProperty(k)) { + test[k] = wrapAssert(k, k, assert[k].length); + } + } + return test; +}; + +/** + * Ensures an options object has all callbacks, adding empty callback functions + * if any are missing. + * + * @param {Object} opt + * @return {Object} + * @api public + */ + +exports.options = function (opt) { + var optionalCallback = function (name) { + opt[name] = opt[name] || function () {}; + }; + + optionalCallback('moduleStart'); + optionalCallback('moduleDone'); + optionalCallback('testStart'); + optionalCallback('testDone'); + //optionalCallback('log'); + + // 'done' callback is not optional. + + return opt; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/utils.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/utils.js new file mode 100644 index 0000000..5efd26c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/lib/utils.js @@ -0,0 +1,203 @@ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + */ + +/** + * Module dependencies + */ + +var async = require('../deps/async'), + fs = require('fs'), + util = require('util'), + Script = process.binding('evals').Script || process.binding('evals').NodeScript, + http = require('http'); + + +/** + * Detect if coffee-script is available and search for .coffee as an + * extension in modulePaths if it is. + */ + +var extensionPattern; +try { + require('coffee-script'); + extensionPattern = /\.(?:js|coffee)$/; +} +catch (e) { + extensionPattern = /\.js$/; +} + + +/** + * Finds all modules at each path in an array, If a path is a directory, it + * returns all supported file types inside it. This only reads 1 level deep in + * the directory and does not recurse through sub-directories. + * + * The extension (.js, .coffee etc) is stripped from the filenames so they can + * simply be require()'ed. + * + * @param {Array} paths + * @param {Function} callback + * @api public + */ + +exports.modulePaths = function (paths, callback) { + async.concat(paths, function (p, cb) { + fs.stat(p, function (err, stats) { + if (err) { + return cb(err); + } + if (stats.isFile()) { + return cb(null, [p]); + } + if (stats.isDirectory()) { + fs.readdir(p, function (err, files) { + if (err) { + return cb(err); + } + + // filter out any filenames with unsupported extensions + var modules = files.filter(function (filename) { + return extensionPattern.exec(filename); + }); + + // remove extension from module name and prepend the + // directory path + var fullpaths = modules.map(function (filename) { + var mod_name = filename.replace(extensionPattern, ''); + return [p, mod_name].join('/'); + }); + + // sort filenames here, because Array.map changes order + fullpaths.sort(); + + cb(null, fullpaths); + }); + } + }); + }, callback); +}; + +/** + * Evaluates JavaScript files in a sandbox, returning the context. The first + * argument can either be a single filename or an array of filenames. If + * multiple filenames are given their contents are concatenated before + * evalution. The second argument is an optional context to use for the sandbox. + * + * @param files + * @param {Object} sandbox + * @return {Object} + * @api public + */ + +exports.sandbox = function (files, /*optional*/sandbox) { + var source, script, result; + if (!(files instanceof Array)) { + files = [files]; + } + source = files.map(function (file) { + return fs.readFileSync(file, 'utf8'); + }).join(''); + + if (!sandbox) { + sandbox = {}; + } + script = new Script(source); + result = script.runInNewContext(sandbox); + return sandbox; +}; + +/** + * Provides a http request, response testing environment. + * + * Example: + * + * var httputil = require('nodeunit').utils.httputil + * exports.testSomething = function(test) { + * httputil(function (req, resp) { + * resp.writeHead(200, {}); + * resp.end('test data'); + * }, + * function(server, client) { + * client.fetch('GET', '/', {}, function(resp) { + * test.equal('test data', resp.body); + * server.close(); + * test.done(); + * }) + * }); + * }; + * + * @param {Function} cgi + * @param {Function} envReady + * @api public + */ +exports.httputil = function (cgi, envReady) { + var hostname = process.env.HOSTNAME || 'localhost'; + var port = process.env.PORT || 3000; + + var server = http.createServer(cgi); + server.listen(port, hostname); + + var client = http.createClient(port, hostname); + client.fetch = function (method, path, headers, respReady) { + var request = this.request(method, path, headers); + request.end(); + request.on('response', function (response) { + response.setEncoding('utf8'); + response.on('data', function (chunk) { + if (response.body) { + response.body += chunk; + } else { + response.body = chunk; + } + }); + response.on('end', function () { + if (response.headers['content-type'] === 'application/json') { + response.bodyAsObject = JSON.parse(response.body); + } + respReady(response); + }); + }); + }; + + process.nextTick(function () { + if (envReady && typeof envReady === 'function') { + envReady(server, client); + } + }); +}; + + +/** + * Improves formatting of AssertionError messages to make deepEqual etc more + * readable. + * + * @param {Object} assertion + * @return {Object} + * @api public + */ + +exports.betterErrors = function (assertion) { + if (!assertion.error) return assertion; + + var e = assertion.error; + if (e.actual && e.expected) { + var actual = util.inspect(e.actual, false, 10).replace(/\n$/, ''); + var expected = util.inspect(e.expected, false, 10).replace(/\n$/, ''); + var multiline = ( + actual.indexOf('\n') !== -1 || + expected.indexOf('\n') !== -1 + ); + var spacing = (multiline ? '\n' : ' '); + e._message = e.message; + e.stack = ( + e.name + ':' + spacing + + actual + spacing + e.operator + spacing + + expected + '\n' + + e.stack.split('\n').slice(1).join('\n') + ); + } + return assertion; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/man1/nodeunit.1 b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/man1/nodeunit.1 new file mode 100644 index 0000000..450772d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/man1/nodeunit.1 @@ -0,0 +1,95 @@ +.\" Generated with Ronnjs/v0.1 +.\" http://github.com/kapouer/ronnjs/ +. +.TH "NODEUNIT" "1" "October 2010" "" "" +. +.SH "NAME" +\fBnodeunit\fR \-\- simple node\.js unit testing tool +. +.SH "SYNOPSIS" +. +.nf +nodeunit [options] [ \.\.\.] +. +.fi +. +.SH "DESCRIPTION" +Nodeunit is a simple unit testing tool based on the node\.js assert module\. +. +.IP "\(bu" 4 +Simple to use +. +.IP "\(bu" 4 +Just export the tests from a module +. +.IP "\(bu" 4 +Helps you avoid common pitfalls when testing asynchronous code +. +.IP "\(bu" 4 +Easy to add test cases with setUp and tearDown functions if you wish +. +.IP "\(bu" 4 +Allows the use of mocks and stubs +. +.IP "" 0 +. +.SH "OPTIONS" + \fB\-\-config FILE\fR: +. +.br + Load config options from a JSON file, allows the customisation + of color schemes for the default test reporter etc\. + See bin/nodeunit\.json for current available options\. +. +.P + \fB\-\-reporter FILE\fR: +. +.br + You can set the test reporter to a custom module or on of the modules + in nodeunit/lib/reporters, when omitted, the default test runner is used\. +. +.P + \fB\-\-list\-reporters\fR: +. +.br + List available build\-in reporters\. +. +.P + \fB\-h\fR, \fB\-\-help\fR: +. +.br + Display the help and exit\. +. +.P + \fB\-v\fR, \fB\-\-version\fR: +. +.br + Output version information and exit\. +. +.P + \fB\fR: + You can run nodeunit on specific files or on all \fI*\.js\fR files inside +. +.br + a directory\. +. +.SH "AUTHORS" +Written by Caolan McMahon and other nodeunit contributors\. +. +.br +Contributors list: \fIhttp://github\.com/caolan/nodeunit/contributors\fR\|\. +. +.SH "REPORTING BUGS" +Report nodeunit bugs to \fIhttp://github\.com/caolan/nodeunit/issues\fR\|\. +. +.SH "COPYRIGHT" +Copyright © 2010 Caolan McMahon\. +. +.br +Nodeunit has been released under the MIT license: +. +.br +\fIhttp://github\.com/caolan/nodeunit/raw/master/LICENSE\fR\|\. +. +.SH "SEE ALSO" +node(1) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/.bin/tap b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/.bin/tap new file mode 120000 index 0000000..999914b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/.bin/tap @@ -0,0 +1 @@ +../tap/bin/tap.js \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/AUTHORS b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/AUTHORS new file mode 100644 index 0000000..b7f6eb2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/AUTHORS @@ -0,0 +1,11 @@ +# contributors sorted by whether or not they're me +Isaac Z. Schlueter +baudehlo +James Halliday +Jason Smith (air) +Pedro P. Candel +Stein Martin Hustad +Trent Mick +Corey Richardson +Raynos +Siddharth Mahendraker diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md new file mode 100644 index 0000000..f97e240 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/README.md @@ -0,0 +1,82 @@ +This is a mix-and-match set of utilities that you can use to write test +harnesses and frameworks that communicate with one another using the +Test Anything Protocol. + +If you don't yet know what TAP is, [you better ask +somebody](http://testanything.org/). + +Default Usage: + +1. Make a directory. Maybe call it 'test'. That'd be nice and obvious. +2. Put a bunch of test scripts in there. If they're node programs, then + 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 ./test` + +The output will be TAP-compliant. + +For extra special bonus points, you can do something like this: + + var test = require("tap").test + test("make sure the thingie is a thing", function (t) { + t.equal(thingie, "thing", "thingie should be thing") + t.type(thingie, "string", "type of thingie is string") + t.ok(true, "this is always true") + t.notOk(false, "this is never true") + t.test("a child test", function (t) { + t.equal(this, superEasy, "right!?") + t.similar(7, 2, "ever notice 7 is kinda like 2?", {todo: true}) + t.test("so skippable", {skip: true}, function (t) { + t.plan(1) // only one test in this block + t.ok(true, "but when the flag changes, it'll pass") + // no need to end, since we had a plan. + }) + t.end() + }) + t.ok(99, "can also skip individual assertions", {skip: true}) + // end lets it know it's over. + t.end() + }) + test("another one", function (t) { + t.plan(1) + t.ok(true, "It's ok to plan, and also end. Watch.") + t.end() // but it must match the plan! + }) + +Node-tap is actually a collection of several modules, any of which may be +mixed and matched however you please. + +If you don't like this test framework, and think you can do much much +better, *I strongly encourage you to do so!* If you use this library, +however, at least to output TAP-compliant results when `process.env.TAP` +is set, then the data coming out of your framework will be much more +consumable by machines. + +You can also use this to build programs that *consume* the TAP data, so +this is very useful for CI systems and such. + +* tap-assert: A collection of assert functions that return TAP result + objects. +* tap-consumer: A stream interface for consuming TAP data. +* tap-producer: A class that produces a TAP stream by taking in result + objects. +* tap-results: A class for keeping track of TAP result objects as they + pass by, counting up skips, passes, fails, and so on. +* tap-runner: A program that runs through a directory running all the + tests in it. (Tests which may or may not be TAP-outputting tests. But + it's better if they are.) +* tap-test: A class for actually running tests. +* tap-harness: A class that runs tests. (Tests are also Harnesses, + which is how sub-tests run.) +* tap-global-harness: A default harness that provides the top-level + support for running TAP tests. + +## Experimental Code Coverage with runforcover & bunker: + +``` +TAP_COV=1 tap ./test [--cover=./lib,foo.js] [--cover-dir=./coverage] +``` + +This feature is experimental, and will most likely change somewhat +before being finalized. Feedback welcome. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-http.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-http.js new file mode 100644 index 0000000..296910f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-http.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +// just an example, really +// Run with `node tap-http.js path/to/tests/` + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , http = require("http") + , server = http.createServer(function (req, res) { + // it'd be nice to return a non-200 if the tests fail, but we don't + // know the status until it's done, so that would mean not being able + // to pipe the output + res.writeHead(200, {'content-type': 'text/plain'}) + new Runner(argv, null).pipe(res) + }) + +server.listen(1337) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-reader.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-reader.js new file mode 100755 index 0000000..b196cc2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap-reader.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +// read a tap stream from stdin. + +var TapConsumer = require("../lib/tap-consumer") + , TapProducer = require("../lib/tap-producer") + +var tc = new TapConsumer + , tp = new TapProducer + +//process.stdin.pipe(tc) +process.stdin.on("data", function (c) { + c = c + "" + // console.error(JSON.stringify(c).substr(0, 100)) + tc.write(c) +}) +process.stdin.on("end", function () { tc.end() }) +process.stdin.resume() +//tc.pipe(tp) +tc.on("data", function (c) { + tp.write(c) +}) +tc.on("end", function () { tp.end() }) + +tp.on("data", function (c) { + console.error(["output write", c]) + process.stdout.write(c) +}) + +tp.on("end", function (er, total, ok) { + if (er) throw er + process.exit(total - ok) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap.js new file mode 100755 index 0000000..e7afcbc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/bin/tap.js @@ -0,0 +1,132 @@ +#!/usr/bin/env node + +var argv = process.argv.slice(2) + , path = require("path") + , Runner = require("../lib/tap-runner") + + , nopt = require("nopt") + + , knownOpts = + { cover: [path, false] + , "cover-dir": path + , stderr: Boolean + , stdout: Boolean + , diag: Boolean + , version: Boolean + , tap: Boolean + , timeout: Number + , gc: Boolean + } + + , shorthands = + // debugging 1: show stderr + { d: ["--stderr"] + // debugging 2: show stderr and tap + , dd: ["--stderr", "--tap"] + // debugging 3: show stderr, tap, AND always show diagnostics. + , ddd: ["--stderr", "--tap", "--diag"] + , "expose-gc": ["--gc"] + , g: ["--gc"] + , e: ["--stderr"] + , t: ["--timeout"] + , o: ["--tap"] + , c: ["--cover"] + , v: ["--version"] + , "?": ["--help"] + , h: ["--help"] + } + + , defaults = + { cover: "./lib" + , "cover-dir": "./coverage" + , stderr: process.env.TAP_STDERR + , tap: process.env.TAP + , diag: process.env.TAP_DIAG + , timeout: +process.env.TAP_TIMEOUT || 30 + , gc: false + , version: false + , help: false } + + , options = nopt(knownOpts, shorthands) + +if (options.version) { + console.log(require("../package.json").version) + process.exit(0) +} + +if (options.help) { + console.log(function(){/* + +Usage: + tap + + Run the files as tap tests, parse the output, and report the results + +Options: + + --stderr Print standard error output of tests to standard error. + --tap Print raw tap output. + --diag Print diagnostic output for passed tests, as well as failed. + (Implies --tap) + --gc Expose the garbage collector to tests. + --timeout Maximum time to wait for a subtest, in seconds. Default: 30 + --version Print the version of node tap. + --help Print this help. + +Please report bugs! https://github.com/isaacs/node-tap/issues + +*/}.toString().split(/\n/).slice(1, -1).join("\n")) + process.exit(0) +} + + +Object.keys(defaults).forEach(function (k) { + if (!options.hasOwnProperty(k)) options[k] = defaults[k] +}) + +// other tests that might rely on these +if (options.diag) process.env.TAP_DIAG = true +if (options.tap) process.env.TAP = true +if (options.timeout) process.env.TAP_TIMEOUT = options.timeout + +var r = new Runner(options) + , TapProducer = require("../lib/tap-producer") + +if (options.tap || options.diag) { + r.pipe(process.stdout) +} else { + r.on("file", function (file, results, details) { + var s = (details.ok ? "" : "not ") + "ok "+results.name + , n = details.pass + "/" + details.testsTotal + , dots = new Array(Math.max(1, 60 - s.length - n.length)).join(".") + console.log("%s %s %s", s, dots, n) + if (details.ok) { + if (details.skip) { + console.log(" skipped: %s", details.skipTotal) + } + } else { + // console.error(details) + console.log(" Command: %s", results.command) + console.log(" " + TapProducer.encode(details.list) + .split(/\n/).join("\n ")) + } + }) + r.on("end", function () { + //console.log(r) + var s = "total" + , n = r.results.pass + "/" + r.results.testsTotal + , dots = new Array(60 - s.length - n.length).join(".") + , ok = r.results.ok ? "ok" : "not ok" + console.log("%s %s %s\n\n%s", s, dots, n, ok) + if (r.doCoverage) { + console.error( "\nCoverage: %s\n" + , path.resolve(r.coverageOutDir, "index.html") ) + } + }) +} + + + +r.on("end", function () { + process.exit(r.results.tests - r.results.pass) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/bar.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/bar.js new file mode 100644 index 0000000..e7cb7ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/bar.js @@ -0,0 +1,15 @@ +var Bar = module.exports = function(str) { + this.bar = str; + this.str = str; +}; + +Bar.prototype.foo = function() { + var self = this; + return self.bar; +}; + +Bar.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/foo.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/foo.js new file mode 100644 index 0000000..cb9ee8f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/lib/foo.js @@ -0,0 +1,15 @@ +var Foo = module.exports = function(str) { + this.foo = str; + this.str = str; +}; + +Foo.prototype.bar = function() { + var self = this; + return self.foo; +}; + +Foo.prototype.baz = function() { + var self = this; + return self.str; +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/bar.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/bar.test.js new file mode 100644 index 0000000..91e4bc2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/bar.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Bar = require('../lib/bar'), + bar; + +test('setup', function(t) { + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', bar.foo()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/baz.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/baz.test.js new file mode 100644 index 0000000..fae22d8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/baz.test.js @@ -0,0 +1,29 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + Bar = require('../lib/bar'), + foo, bar; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + bar = new Bar('baz'); + t.ok(bar); + t.end(); +}); + +test('baz from Foo', function(t) { + t.equal('baz', foo.baz()); + t.end(); +}); + +test('baz from Bar', function(t) { + t.equal('baz', bar.baz()); + t.end(); +}); + + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/foo.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/foo.test.js new file mode 100644 index 0000000..2aed8fd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/coverage-example/test/foo.test.js @@ -0,0 +1,20 @@ +var test = require('tap').test, + Foo = require('../lib/foo'), + foo; + +test('setup', function(t) { + foo = new Foo('baz'); + t.ok(foo); + t.end(); +}); + +test('bar', function(t) { + t.equal('baz', foo.bar()); + t.end(); +}); + +test('teardown', function(t) { + t.ok(true); + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/lib/math.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/lib/math.js new file mode 100644 index 0000000..f798626 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/lib/math.js @@ -0,0 +1 @@ +module.exports = Math diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/test/test-example.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/test/test-example.js new file mode 100644 index 0000000..cd2549b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/example/test/test-example.js @@ -0,0 +1,237 @@ +var tap = require("tap") + , test = tap.test + , plan = tap.plan + , math + +test("load sut", function (t) { + math = require("../lib/math") + t.ok(math, "object loaded") + t.end() +}) + +test("validate constants", function (t) { + t.equal(math.LN10, 2.302585092994046, "ln 10") + t.equal(math.PI, 3.141592653589793, "pi") + t.equal(math.E, 2.718281828459045, "e") + t.equal(math.LOG10E, 0.4342944819032518, "log 10 e") + t.equal(math.SQRT2, 1.4142135623730951, "sqrt 2") + t.equal(math.SQRT1_2, 0.7071067811865476, "sqrt 1/2") + t.equal(math.LN2, 0.6931471805599453, "ln2") + t.end() +}) + +test("using this", function (t) { + // this also works. + this.equal(t, this, "call in scope of test obj") + this.end() +}) + +// test setTimeout, just a trivial example. +test("setTimeout", function (t) { + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + t.end() + }, 50) +}) + +// another way to do the same, using a plan. +// this is more robust, but annoying when you have a long list +// of tests for something. For async stuff, it's generally better, +// since there's a higher risk of the control flowing off to lala land. +test("setTimeout planned", function (t) { + t.plan(1) + var start = Date.now() + setTimeout(function () { + t.ok(Date.now() >= start + 50, "timeout fired after delay") + }, 50) +}) + +// plans also are good for cases where things may fire in a non-deterministic +// order, since it won't be as obvious when everything is done. +test("setTimeout parallel", function (t) { + t.plan(2) + var start = Date.now() + setTimeout(function A () { + t.ok(Date.now() >= start + 50, "timeout A fired after delay") + }, 50) + setTimeout(function B () { + t.ok(Date.now() >= start + 50, "timeout B fired after delay") + }, 50) +}) + +// something slightly less hello worldy +test("async test", function (t) { + t.plan(4) + var fs = require("fs") + t.ok(fs, "fs library should load") + var rs = fs.createReadStream(__filename) + t.ok(rs, "read stream should start fine.") + rs.on("open", function (fd) { + t.type(fd, "number", "file descriptor should be a number") + t.equal(fd, rs.fd, "fd should match stream fd") + }) +}) + +// you can bail out of the entire everything if something is just +// Not Right (db not installed, etc.) +test("tarp", function (parent) { + if (7 === 5) { + parent.bailout("math is broken") + } + // bailout bubbles up a bit like "error" events + // if unhandled, then the parent will bail, as well. + parent.test("child bailouts", function (child) { + child.on("bailout", function (s) { + parent.fail("children shouldn't bail.") + }) + child.bailout("try to bail out, but instead just fail a test") + }) + + parent.test("child bailout 2", function (child) { + child.bailout("this one will bail out") + }) +}) + +// tests marked "todo" can fail without counting against the overall score +// never ever ever write tests to "verify" incorrect behavior! +test("unfinished test", function (t) { + t.equal(math.cos(math.PI), -1, "cos(PI)") + t.equal(math.sin(math.PI), 0, "sin(PI)") + t.equal(math.face, "your face", "math.face should be your face # TODO") + t.end() +}) + +// tests can have children. +test("http server", function (t) { + // one test plus 4 children. + t.plan(5) + + var http = require("http") + , PORT = 12346 + + t.ok(http, "http module should load") + var server + + t.test("set up server", function (t) { + t.plan(2) + server = http.createServer(function (req, res) { + t.comment("Request: "+req.url) + res.writeHead(200, {}) + res.end(req.method + " " + req.url) + }) + t.ok(server, "createServer should create a server") + server.listen(PORT, t.cb("listen should fire callback")) + }) + + // set the "parallel" flag on this one. + // That signals the harness to proceed immediately to the next test, + // and run them in parallel. + // Default behavior is to wait for each test to complete before proceeding + // to the next one. + // The first not-parallel test encountered will cause it to wait for that + // test, as well as all the parallel tests before it. + // A, B', C', D', E (where ' means "parallel") + // Runs A, and then B, C, and D in parallel, and then E. + t.test("testing POST", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "POST" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "POST /foo") }) + }).end() + }) + + t.test("testing GET", {parallel: true}, function (t) { + t.plan(1) + http.request("POST", { method: "GET" + , host: "localhost" + , path: "/foo" + , port: PORT }).on("response", function (res) { + t.bufferStream(res, function (s) { t.equal(s, "GET /foo") }) + }).end() + }) + + // wrap in a test so that if this throws, it'll log as a failed test. + t.test("teardown", function (t) { + server.close() + t.end() + }) +}) + +// yo dawg! +test("meta-tests", function (t) { + t.plan(5) + + // t.fails() wraps a child test and succeeds if it fails. + t.fails(t.test("this should fail", function (t) { + t.ok(false, "assert false") + t.end() + })) + + // t.timesOut() wraps a child test and succeeds if it times out. + // if t.end() is called, or if a plan is completed, then it fails. + // set the timeout really low so that it will not take forever. + t.timesOut(t.test("this should timeout", { timeout: 1 }, function (t) { + t.ok(true, "assert true") + // t.end() never called. + })) + + // t.incomplete() wraps a child test and succeeds if it ends before + // the plan is finished. + t.incomplete(t.test("this should be incomplete", function (t) { + t.plan(100) + t.ok(true, "assert true") + // calling end prematurely. + t.end() + })) + + // t.bailsOut() wraps a child test and succeeds if it calls bailout() + t.bailsOut(t.test("this should bailout", function (t) { + t.bailout("oh noes, bailing out!") + })) + + // low-level analysis of subtests + t.test("verifying test success/failure expectations", function (t) { + t.once("end", function () { + var res = t.results + , is = t.equal + // hijack! + t.clear() + is(res.ok, false, "ok") + + is(res.bailedOut, false, "bailed out") + + is(res.skip, 2, "skips") + is(res.skipPass, 1, "skip that passed") + is(res.skipFail, 1, "skip that failed") + + is(res.todo, 2, "todos") + is(res.todoPass, 1, "todo that passed") + is(res.todoFail, 1, "todo that failed") + + is(res.failTotal, 3, "failures total") + is(res.fail, 1, "relevant failure") + + is(res.passTotal, 3, "passes total") + is(res.pass, 1, "relevant pass") + + is(res.testsTotal, 6, "total tests") + is(res.tests, 2, "should be 2 relevant tests") + + t.end() + }) + + // run the metatest. + // *this* is the actual SUT in this case. + t.ok(false, "failing todo #todo") + // can also set #todo or #skip explicitly + t.ok(true, "succeeding todo", {todo: true}) + t.ok(false, "failing skip #skip", {skip: true}) + t.ok(true, "suceeding skip #skip") + t.ok(false, "failing test") + t.ok(true, "succeeding test") + t.end() + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/main.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/main.js new file mode 100644 index 0000000..a9a520a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/main.js @@ -0,0 +1,16 @@ + +var GlobalHarness = require("./tap-global-harness") + +// this lets you do stuff like: +// var test = require("tap").test +// test(...) +// to run stuff in the global harness. +exports = module.exports = new GlobalHarness() + +exports.createProducer = exports.Producer = require("./tap-producer") +exports.createConsumer = exports.Consumer = require("./tap-consumer") +exports.yamlish = require("yamlish") +exports.createTest = exports.Test = require("./tap-test") +exports.createHarness = exports.Harness = require("./tap-harness") +exports.createRunner = exports.Runner = require("./tap-runner") +exports.assert = require("./tap-assert") 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 new file mode 100644 index 0000000..60203a0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-assert.js @@ -0,0 +1,445 @@ +// an assert module that returns tappable data for each assertion. +var difflet = require('difflet') + , deepEqual = require('deep-equal') + , bufferEqual = require('buffer-equal') + , Buffer = require('buffer').Buffer + +module.exports = assert + +var syns = {} + , id = 1 + +function assert (ok, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + + //console.error("assert %j", [ok, message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + //console.error("assert", [ok, message, extra]) + ok = !!ok + var res = { id : id ++, ok: ok } + + var caller = getCaller(extra && extra.error) + if (extra && extra.error) { + res.type = extra.error.name + res.message = extra.error.message + res.code = extra.error.code + || extra.error.type + res.errno = extra.error.errno + delete extra.error + } + if (caller.file) { + res.file = caller.file + res.line = +caller.line + res.column = +caller.column + } + res.stack = caller.stack + + res.name = message || "(unnamed assert)" + + if (extra) Object.keys(extra).forEach(function (k) { + if (!res.hasOwnProperty(k)) res[k] = extra[k] + }) + + // strings and objects are hard to diff by eye + if (!ok && + res.hasOwnProperty("found") && + res.hasOwnProperty("wanted") && + res.found !== res.wanted) { + if (typeof res.wanted !== typeof res.found || + typeof res.wanted === "object" && (!res.found || !res.wanted)) { + res.type = { found: typeof found + , wanted: typeof wanted } + } else if (typeof res.wanted === "string") { + res.diff = diffString(res.found, res.wanted) + } else if (typeof res.wanted === "object") { + res.diff = diffObject(res.found, res.wanted) + } + } + + //console.error("assert return", res) + + return res +} +assert.ok = assert +syns.ok = [ "true", "assert" ] + + +function notOk (ok, message, extra) { + return assert(!ok, message, extra) +} +assert.notOk = notOk +syns.notOk = [ "false", "notok" ] + +function error (er, message, extra) { + if (!er) { + // just like notOk(er) + return assert(!er, message, extra) + } + message = message || er.message + extra = extra || {} + extra.error = er + return assert.fail(message, extra) +} +assert.error = error +syns.error = [ "ifError", "ifErr", "iferror" ] + + +function pass (message, extra) { + return assert(true, message, extra) +} +assert.pass = pass + +function fail (message, extra) { + //console.error("assert.fail", [message, extra]) + //if (extra && extra.skip) return assert.skip(message, extra) + return assert(false, message, extra) +} +assert.fail = fail + +function skip (message, extra) { + //console.error("assert.skip", message, extra) + if (!extra) extra = {} + return { id: id ++, skip: true, name: message || "" } +} +assert.skip = skip + +function throws (fn, wanted, message, extra) { + if (typeof wanted === "string") { + extra = message + message = wanted + wanted = null + } + + if (extra && extra.skip) return assert.skip(message, extra) + + var found = null + try { + fn() + } catch (e) { + found = { name: e.name, message: e.message } + } + + extra = extra || {} + + extra.found = found + if (wanted) { + wanted = { name: wanted.name, message: wanted.message } + extra.wanted = wanted + } + + if (!message) { + message = "Expected to throw" + if (wanted) message += ": "+wanted.name + " " + wanted.message + } + + return (wanted) ? assert.similar(found, wanted, message, extra) + : assert.ok(found, message, extra) +} +assert.throws = throws + + +function doesNotThrow (fn, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var found = null + try { + fn() + } catch (e) { + found = {name: e.name, message: e.message} + } + message = message || "Should not throw" + + return assert.equal(found, null, message, extra) +} +assert.doesNotThrow = doesNotThrow + + +function equal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should be equal" + extra.found = a + extra.wanted = b + return assert(a === b, message, extra) +} +assert.equal = equal +syns.equal = ["equals" + ,"isEqual" + ,"is" + ,"strictEqual" + ,"strictEquals"] + + +function equivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var extra = extra || {} + message = message || "should be equivalent" + extra.found = a + extra.wanted = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(bufferEqual(a, b), message, extra) + } else { + return assert(deepEqual(a, b), message, extra) + } +} +assert.equivalent = equivalent +syns.equivalent = ["isEquivalent" + ,"looseEqual" + ,"looseEquals" + ,"isDeeply" + ,"same" + ,"deepEqual" + ,"deepEquals"] + + +function inequal (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equal" + extra.found = a + extra.doNotWant = b + return assert(a !== b, message, extra) +} +assert.inequal = inequal +syns.inequal = ["notEqual" + ,"notEquals" + ,"notStrictEqual" + ,"notStrictEquals" + ,"isNotEqual" + ,"isNot" + ,"not" + ,"doesNotEqual" + ,"isInequal"] + + +function inequivalent (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + extra = extra || {} + message = message || "should not be equivalent" + extra.found = a + extra.doNotWant = b + + if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { + return assert(!bufferEqual(a, b), message, extra) + } else { + return assert(!deepEqual(a, b), message, extra) + } +} +assert.inequivalent = inequivalent +syns.inequivalent = ["notEquivalent" + ,"notDeepEqual" + ,"notDeeply" + ,"notSame" + ,"isNotDeepEqual" + ,"isNotDeeply" + ,"isNotEquivalent" + ,"isInequivalent"] + +function similar (a, b, message, extra, flip) { + if (extra && extra.skip) return assert.skip(message, extra) + // test that a has all the fields in b + message = message || "should be similar" + + if (typeof a === "string" && + (Object.prototype.toString.call(b) === "[object RegExp]")) { + extra = extra || {} + extra.pattern = b + extra.string = a + var ok = a.match(b) + extra.match = ok + if (flip) ok = !ok + return assert.ok(ok, message, extra) + } + + var isObj = assert(a && typeof a === "object", message, extra) + if (!isObj.ok) { + // not an object + if (a == b) isObj.ok = true + if (flip) isObj.ok = !isObj.ok + return isObj + } + + var eq = flip ? inequivalent : equivalent + return eq(selectFields(a, b), b, message, extra) +} +assert.similar = similar +syns.similar = ["isSimilar" + ,"has" + ,"hasFields" + ,"like" + ,"isLike"] + +function dissimilar (a, b, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + message = message || "should be dissimilar" + return similar(a, b, message, extra, true) +} +assert.dissimilar = dissimilar +syns.dissimilar = ["unsimilar" + ,"notSimilar" + ,"unlike" + ,"isUnlike" + ,"notLike" + ,"isNotLike" + ,"doesNotHave" + ,"isNotSimilar" + ,"isDissimilar"] + +function type (thing, t, message, extra) { + if (extra && extra.skip) return assert.skip(message, extra) + var name = t + if (typeof name === "function") name = name.name || "(anonymous ctor)" + //console.error("name=%s", name) + message = message || "type is "+name + var type = typeof thing + //console.error("type=%s", type) + if (!thing && type === "object") type = "null" + if (type === "object" && t !== "object") { + if (typeof t === "function") { + //console.error("it is a function!") + extra = extra || {} + extra.found = Object.getPrototypeOf(thing).constructor.name + extra.wanted = name + //console.error(thing instanceof t, name) + return assert.ok(thing instanceof t, message, extra) + } + + //console.error("check prototype chain") + // check against classnames or objects in prototype chain, as well. + // type(new Error("asdf"), "Error") + // type(Object.create(foo), foo) + var p = thing + while (p = Object.getPrototypeOf(p)) { + if (p === t || p.constructor && p.constructor.name === t) { + type = name + break + } + } + } + //console.error(type, name, type === name) + return assert.equal(type, name, message, extra) +} +assert.type = type +syns.type = ["isa"] + +// synonyms are helpful. +Object.keys(syns).forEach(function (c) { + syns[c].forEach(function (s) { + Object.defineProperty(assert, s, { value: assert[c], enumerable: false }) + }) +}) + +// helpers below + +function selectFields (a, b) { + // get the values in A of the fields in B + var ret = Array.isArray(b) ? [] : {} + Object.keys(b).forEach(function (k) { + if (!a.hasOwnProperty(k)) return + var v = b[k] + , av = a[k] + if (v && av && typeof v === "object" && typeof av === "object" + && !(v instanceof Date) + && !(v instanceof RegExp) + && !(v instanceof String) + && !(v instanceof Boolean) + && !(v instanceof Number) + && !(Array.isArray(v))) { + ret[k] = selectFields(av, v) + } else ret[k] = av + }) + return ret +} + +function sortObject (obj) { + if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) { + return obj + } + + return Object.keys(obj).sort().reduce(function (acc, key) { + acc[key] = sortObject(obj[key]) + return acc + }, {}) +} + +function stringify (a) { + return JSON.stringify(sortObject(a), (function () { + var seen = [] + , keys = [] + return function (key, val) { + var s = seen.indexOf(val) + if (s !== -1) { + return "[Circular: "+keys[s]+"]" + } + if (val && typeof val === "object" || typeof val === "function") { + seen.push(val) + keys.push(val["!"] || val.name || key || "") + if (typeof val === "function") { + return val.toString().split(/\n/)[0] + } else if (typeof val.toUTCString === "function") { + return val.toUTCString() + } + } + return val + }})()) +} + +function diffString (f, w) { + if (w === f) return null + var p = 0 + , l = w.length + while (p < l && w.charAt(p) === f.charAt(p)) p ++ + w = stringify(w).substr(1).replace(/"$/, "") + f = stringify(f).substr(1).replace(/"$/, "") + return diff(f, w, p) +} + +function diffObject (f, w) { + return difflet({ indent : 2, comment : true }).compare(w, f) +} + +function diff (f, w, p) { + if (w === f) return null + var i = p || 0 // it's going to be at least p. JSON can only be bigger. + , l = w.length + while (i < l && w.charAt(i) === f.charAt(i)) i ++ + var pos = Math.max(0, i - 20) + w = w.substr(pos, 40) + f = f.substr(pos, 40) + var pointer = i - pos + return "FOUND: "+f+"\n" + + "WANTED: "+w+"\n" + + (new Array(pointer + 9).join(" ")) + + "^ (at position = "+p+")" +} + +function getCaller (er) { + // get the first file/line that isn't this file. + if (!er) er = new Error + var stack = er.stack || "" + stack = stack.split(/\n/) + for (var i = 1, l = stack.length; i < l; i ++) { + var s = stack[i].match(/\(([^):]+):([0-9]+):([0-9]+)\)$/) + if (!s) continue + var file = s[1] + , line = +s[2] + , col = +s[3] + if (file.indexOf(__dirname) === 0) continue + if (file.match(/tap-test\/test.js$/)) continue + else break + } + var res = {} + if (file && file !== __filename && !file.match(/tap-test\/test.js$/)) { + res.file = file + res.line = line + res.column = col + } + + res.stack = stack.slice(1).map(function (s) { + return s.replace(/^\s*at\s*/, "") + }) + + return res +} + + 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 new file mode 100644 index 0000000..94700f5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-browser-harness.js @@ -0,0 +1,63 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = BrowserHarness + +var BrowserHarness = global.TAP_Browser_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(BrowserHarness, Harness) +function BrowserHarness (outPipe) { + //console.error("calling BrowserHarness") + if (browserHarness) return browserHarness + if (!(this instanceof BrowserHarness)) { + return browserHarness = new BrowserHarness + } + browserHarness = global.TAP_Browser_Harness = this + BrowserHarness.super.call(this, Test) + + if (outPipe) this.output.pipe(outPipe) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + // TODO: handle global errors + // process.on("unhandledException", function (e) { + // this.bailout("unhandled exception: " + e.message) + // }) +} 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 new file mode 100644 index 0000000..f1b2a6a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-consumer.js @@ -0,0 +1,245 @@ +module.exports = TapConsumer + +// pipe a stream into this that's emitting tap-formatted data, +// and it'll emit "data" events with test objects or comment strings +// and an "end" event with the final results. + +var yamlish = require("yamlish") + , Results = require("./tap-results") + , inherits = require("inherits") + +TapConsumer.decode = TapConsumer.parse = function (str) { + var tc = new TapConsumer + , list = [] + tc.on("data", function (res) { + list.push(res) + }) + tc.end(str) + tc.results.list = list + return tc.results +} + +inherits(TapConsumer, require("stream").Stream) +function TapConsumer () { + if (!(this instanceof TapConsumer)) { + return new TapConsumer + } + + TapConsumer.super.call(this) + this.results = new Results + this.readable = this.writable = true + + this.on("data", function (res) { + if (typeof res === "object") this.results.add(res) + }) + + this._plan = null + this._buffer = "" + this._indent = [] + this._current = null + this._actualCount = 0 + this._passed = [] + this._failed = [] + //console.error("TapConsumer ctor done") +} + +TapConsumer.prototype.bailedOut = false + +TapConsumer.prototype.write = function (chunk) { + if (!this.writable) this.emit("error", new Error("not writable")) + if (this.bailedOut) return true + + this._buffer = this._buffer + chunk + // split it up into lines. + var lines = this._buffer.split(/\r?\n/) + // ignore the last line, since it might be incomplete. + this._buffer = lines.pop() + + for (var i = 0, l = lines.length; i < l; i ++) { + //console.error([i, lines[i]]) + // see if it's indented. + var line = lines[i] + , spaces = (this._indent.length && !line.trim()) + || line.match(/^\s/) + // at this level, only interested in fully undented stuff. + if (spaces) { + var c = i + while (c < l && (!lines[c].trim() || lines[c].match(/^\s/))) { + this._indent.push(lines[c++]) + } + //console.error(c-i, "indented", this._indent, this._current) + i = c - 1 + continue + } + // some kind of line. summary, ok, notok, comment, or garbage. + // this also finishes parsing any of the indented lines from before + this._parseLine(line) + } + return true +} + +TapConsumer.prototype.end = function () { + // finish up any hanging indented sections or final buffer + if (this._buffer.match(/^\s/)) this._indent.push(this.buffer) + else this._parseLine(this._buffer) + + if (!this.bailedOut && + this._plan !== null && + this.results.testsTotal !== this._plan) { + while (this._actualCount < this._plan) { + this.emit("data", {ok: false, name:"MISSING TEST", + id:this._actualCount ++ }) + } + } + + this._parseLine("") + this._buffer = "" + this.writable = false + this.emit("end", null, this._actualCount, this._passed) +} + +TapConsumer.prototype._parseLine = function (line) { + if (this.bailedOut) return + //console.error("_parseLine", [line]) + // if there are any indented lines, and there is a + // current object already, then they belong to it. + // if there is not a current object, then they're garbage. + if (this._current && this._indent.length) { + this._parseIndented() + } + this._indent.length = 0 + if (this._current) { + if (this._current.ok) this._passed.push(this._current.id) + else this._failed.push(this._current.id) + this.emit("data", this._current) + } + this._current = null + line = line.trim() + if (!line) return + // try to see what kind of line this is. + + var bo + if (bo = line.match(/^bail out!\s*(.*)$/i)) { + this.bailedOut = true + // this.emit("error", new Error(line)) + this.emit("bailout", bo[1]) + return + } + + if (line.match(/^#/)) { // just a comment + line = line.replace(/^#+/, "").trim() + // console.error("outputting comment", [line]) + if (line) this.emit("data", line) + return + } + + var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+#(.*))?$/) + if (plan) { + var start = +(plan[1]) + , end = +(plan[2]) + , comment = plan[3] + + // TODO: maybe do something else with this? + // it might be something like: "1..0 #Skip because of reasons" + this._plan = end + this.emit("plan", end, comment) + // plan must come before or after all tests. + if (this._actualCount !== 0) { + this._sawPlan = true + } + return + } + + if (line.match(/^(not )?ok(?:\s+([0-9]+))?/)) { + this._parseResultLine(line) + return + } + + // garbage. emit as a comment. + //console.error("emitting", [line.trim()]) + if (line.trim()) this.emit("data", line.trim()) +} + +TapConsumer.prototype._parseDirective = function (line) { + line = line.trim() + if (line.match(/^TODO\b/i)) { + return { todo:true, explanation: line.replace(/^TODO\s*/i, "") } + } else if (line.match(/^SKIP\b/i)) { + return { skip:true, explanation: line.replace(/^SKIP\s*/i, "") } + } +} + +TapConsumer.prototype._parseResultLine = function (line) { + this._actualCount ++ + if (this._sawPlan) { + this.emit("data", {ok: false, name:"plan in the middle of tests" + ,id:this._actualCount ++}) + } + var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?$/) + , ok = !parsed[1] + , id = +(parsed[2] || this._actualCount) + , rest = parsed[3] || "" + , name + , res = { id:id, ok:ok } + + // split on un-escaped # characters + + //console.log("# "+JSON.stringify([name, rest])) + rest = rest.replace(/([^\\])((?:\\\\)*)#/g, "$1\n$2").split("\n") + name = rest.shift() + rest = rest.filter(function (r) { return r.trim() }).join("#") + //console.log("# "+JSON.stringify([name, rest])) + + // now, let's see if there's a directive in there. + var dir = this._parseDirective(rest.trim()) + if (!dir) name += rest ? "#" + rest : "" + else { + res.ok = true + if (dir.skip) res.skip = true + else if (dir.todo) res.todo = true + if (dir.explanation) res.explanation = dir.explanation + } + res.name = name + + //console.error(line, [ok, id, name]) + this._current = res +} + +TapConsumer.prototype._parseIndented = function () { + // pull yamlish block out + var ind = this._indent + , ys + , ye + , yind + , diag + //console.error(ind, this._indent) + for (var i = 0, l = ind.length; i < l; i ++) { + var line = ind[i] + if (line === undefined) continue + var lt = line.trim() + + if (!ys) { + ys = line.match(/^(\s*)---(.*)$/) + if (ys) { + yind = ys[1] + diag = [ys[2]] + //console.error([line,ys, diag]) + continue + } else if (lt) this.emit("data", lt) + } else if (ys && !ye) { + if (line === yind + "...") ye = true + else { + diag.push(line.substr(yind.length)) + } + } else if (ys && ye && lt) this.emit("data", lt) + } + if (diag) { + //console.error('about to parse', diag) + diag = yamlish.decode(diag.join("\n")) + //console.error('parsed', diag) + Object.keys(diag).forEach(function (k) { + //console.error(this._current, k) + if (!this._current.hasOwnProperty(k)) this._current[k] = diag[k] + }, this) + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-cov-html.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-cov-html.js new file mode 100644 index 0000000..3c1c192 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-cov-html.js @@ -0,0 +1,78 @@ +var fs = require('fs'), + path = require('path'), + asyncMap = require("slide").asyncMap, + util = require('util'); + +var CovHtml = module.exports = function(cov_stats, cov_dir, cb) { + var index = []; + + asyncMap( + Object.keys(cov_stats), + function(f, cb) { + var st = cov_stats[f], + missing_lines = st.missing.map(function(l) { + return l.number; + }), + out = '\n\n\n ' + + '\n ' + + + f + ' (' + st.loc + ')\n' + + '\n' + + '\n\n' + + '

    ' + f + ' (' + st.loc + ')' + '

    ' + + '

    Run: ' + (st.missing.length ? st.loc - st.missing.length : st.loc) + ', Missing: ' + + st.missing.length + ', Percentage: ' + st.percentage + '

    ' + + '

    Source:

    \n' + + '
      \n' + + st.lines.map(function(line) { + var number = line.number, + color = (missing_lines.indexOf(number) !== -1) ? '#fcc' : '#cfc'; + return '
    1. ' + line.source.replace(/'; + }).join('\n') + + '
    \n' + + '

    Data

    \n'+ + '
    ' + util.inspect(st, true, Infinity, false).replace(/\n';
    +
    +      fs.writeFile(
    +        cov_dir + '/' + 
    +        f.replace(process.cwd() + '/', '').replace(/\//g, '+') + '.html',
    +        out,
    +        'utf8',
    +        function(err) {
    +          if (err) {
    +            throw err;
    +          }
    +          index.push(f);
    +          cb();
    +        });
    +    },
    +    function(err) {
    +      if (err) {
    +        throw err;
    +      }
    +      var out = '\n\n\n  ' +
    +          '\n  Coverage Index\n\n' +
    +          '\n

    Code Coverage Information

    \n
      ' + + index.map(function(fname) { + return '
    • ' + fname + '
    • '; + }).join('\n') + '
    \n\n'; + + fs.writeFile(cov_dir + '/index.html', out, 'utf8', function(err) { + if (err) { + throw err; + } + cb(); + }); + } + ); +}; + + 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 new file mode 100644 index 0000000..1007300 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-global-harness.js @@ -0,0 +1,68 @@ +// this is just a harness that pipes to stdout. +// It's the default one. +module.exports = GlobalHarness + +var globalHarness = global.TAP_Global_Harness + , inherits = require("inherits") + , Results = require("./tap-results") + , Harness = require("./tap-harness") + , Test = require("./tap-test") + +inherits(GlobalHarness, Harness) +function GlobalHarness () { + //console.error("calling GlobalHarness") + if (globalHarness) return globalHarness + if (!(this instanceof GlobalHarness)) { + return globalHarness = new GlobalHarness + } + + globalHarness = global.TAP_Global_Harness = this + GlobalHarness.super.call(this, Test) + + this.output.pipe(process.stdout) + //this.output.on("data", function () { + // process.nextTick(process.stdout.flush.bind(process.stdout)) + //}) + + this.test = this.test.bind(this) + + this.plan = this.plan.bind(this) + + var output = this.output + this.on("childEnd", function (child) { + //console.error("childEnd in global harness") + //console.error(child.results) + // write out the stuff for this child. + //console.error("child.conf", child.conf) + + // maybe write some other stuff about the number of tests in this + // thing, etc. I dunno. + //console.error("child results", child.results) + this.results.list.forEach(function (res) { + //delete res.error + //console.error("child resuilt", res) + output.write(res) + }) + //console.error("wrote child results") + this.results.list.length = 0 + }) + + var streamEnded = false + this.on("end", function () { + //console.error("global ending the stream") + if (!streamEnded) { + this.results.list.forEach(function (res) { + output.write(res) + }) + this.results.list.length = 0 + output.end() + streamEnded = true + } + }) + + //this.on("end", this.output.end.bind(this.output)) + + process.on("unhandledException", function (e) { + this.bailout("unhandled exception: " + e.message) + }) +} 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 new file mode 100644 index 0000000..3c0eb80 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-harness.js @@ -0,0 +1,223 @@ +// a thing that runs tests. +// Every "test" is also a harness. If they do not have a harness, +// then they are attached to the defaut "global harness", +// which writes its results to stdout. + + +// TODO: +// - Bailout should stop running any tests. +// - "skip" in the test config obj should skip it. + +module.exports = Harness +require("inherits")(Harness, require("events").EventEmitter) + +var Results = require("./tap-results") + , TapProducer = require("./tap-producer") + , assert = require("./tap-assert") + +function Harness (Test) { + if (!(this instanceof Harness)) return new Harness(Test) + + //console.error("Test in "+this.constructor.name, Test) + + this._Test = Test + this._plan = null + this._children = [] + this._started = false + + this._testCount = 0 + this._planSum = 0 + + this.results = new Results() + // emit result events on the harness. + //this.results.on("result", function (res) { + // console.error("proxying result ev from res to harness") + // this.emit("result", res) + //}.bind(this)) + var me = this + this.results.on("result", this.emit.bind(this, "result")) + + var p = this.process.bind(this) + this.process = function () { + this._started = true + process.nextTick(p) + } + + this.output = new TapProducer() + Harness.super.call(this) +} + +// this function actually only gets called bound to +// the Harness object, and on process.nextTick. Even if +// passed as an event handler, everything *else* will +// happen before it gets called. +Harness.prototype.process = function () { + //console.error("harness process") + // "end" can emit multiple times, so only actually move on + // to the next test if the current one is actually over. + // TODO: multiple in-process tests, if all are marked "async" + if (this._current) { + if (!this._current._ended) return + // handle the current one before moving onto the next. + this.childEnd(this._current) + } + var skip = true + while (skip) { + //console.error("checking for skips") + var current = this._current = this._children.shift() + if (current) { + skip = current.conf.skip + if (skip) { + //console.error("add a failure for the skipping") + this.results.add(assert.fail(current.conf.name + ,{skip:true, diag:false})) + } + } else skip = false + } + + // keep processing through skipped tests, instead of running them. + if (current && this._bailedOut) { + return this.process() + } + + //console.error("got current?", !!current) + if (current) { + current.on("end", this.process) + current.emit("ready") + //console.error("emitted ready") + //console.error("_plan", this._plan, this.constructor.name) + } else { + //console.error("Harness process: no more left. ending") + if (this._endNice) { + this._endNice() + } else { + this.end() + } + } +} + +Harness.prototype.end = function () { + if (this._children.length) { + return this.process() + } + //console.error("harness end", this.constructor.name) + if (this._bailedOut) return + + // can't call .end() more than once. + if (this._ended) { + //console.error("adding failure for end calling") + this.results.add(assert.fail("end called more than once")) + } + + // see if the plan is completed properly, if there was one. + if (this._plan !== null) { + var total = this._testCount + if (total !== this._plan) { + this.results.add(assert.equal(total, this._plan, "test count != plan")) + } + this._plan = total + } + + //console.error("setting ended true", this.constructor.name) + this._ended = true + this.emit("end") +} + +Harness.prototype.plan = function (p) { + //console.error("setting plan", new Error().stack) + if (this._plan !== null) { + //console.error("about to add failure for calling plan") + return this.results.add(assert.fail("plan set multiple times")) + } + this._plan = p + if (p === 0 || this.results.testsTotal) { + this.end() + } +} + +Harness.prototype.childEnd = function (child) { + //console.error("childEnd") + 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? + if (this._plan === this._testCount) { + //console.error("plan", [this._plan, this._testCount]) + return this.end() + } +} + +function copyObj(o) { + var copied = {} + Object.keys(o).forEach(function (k) { copied[k] = o[k] }) + return copied +} + +Harness.prototype.test = function test (name, conf, cb) { + if (this._bailedOut) return + + if (typeof conf === "function") cb = conf, conf = null + if (typeof name === "object") conf = name, name = null + if (typeof name === "function") cb = name, name = null + + conf = (conf ? copyObj(conf) : {}) + name = name || "" + + //console.error("making test", [name, conf, cb]) + + // timeout: value in milliseconds. Defaults to 30s + // Set to Infinity to have no timeout. + if (isNaN(conf.timeout)) conf.timeout = 30000 + var t = new this._Test(this, name, conf) + var self = this + if (cb) { + //console.error("attaching cb to ready event") + t.on("ready", function () { + if (!isNaN(conf.timeout) && isFinite(conf.timeout)) { + var timer = setTimeout(this.timeout.bind(this), conf.timeout) + var clear = function () { + clearTimeout(timer) + } + t.on("end", clear) + t.on("bailout", function (message) { + self.bailout(message) + clear() + }) + } + }) + t.on("ready", cb.bind(t, t)) + // proxy the child results to this object. + //t.on("result", function (res) { + // console.error("in harness, proxying result up") + // t.results.add(res) + //}) + } + return t +} + +Harness.prototype.bailout = function (message) { + // console.error("Harness bailout", this.constructor.name) + message = message || "" + //console.error("adding bailout message result") + this.results.add({bailout: message}) + // console.error(">>> results after bailout" , this.results) + this._bailedOut = true + this.emit("bailout", message) + this.output.end({bailout: message}) +} + +Harness.prototype.add = function (child) { + //console.error("adding child") + this._children.push(child) + if (!this._started) this.process() +} + +// the tearDown function is *always* guaranteed to happen. +// Even if there's a bailout. +Harness.prototype.tearDown = function (fn) { + this.on("end", fn) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-producer.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-producer.js new file mode 100644 index 0000000..c6593a9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-producer.js @@ -0,0 +1,130 @@ +module.exports = TapProducer + +var Results = require("./tap-results") + , inherits = require("inherits") + , yamlish = require("yamlish") + +TapProducer.encode = function (result, diag) { + var tp = new TapProducer(diag) + , out = "" + tp.on("data", function (c) { out += c }) + if (Array.isArray(result)) { + result.forEach(tp.write, tp) + } else tp.write(result) + tp.end() + return out +} + +inherits(TapProducer, require("stream").Stream) +function TapProducer (diag) { + TapProducer.super.call(this) + this.diag = diag + this.count = 0 + this.readable = this.writable = true + this.results = new Results +} + +TapProducer.prototype.trailer = true + +TapProducer.prototype.write = function (res) { + // console.error("TapProducer.write", res) + if (typeof res === "function") throw new Error("wtf?") + if (!this.writable) this.emit("error", new Error("not writable")) + + if (!this._didHead) { + this.emit("data", "TAP version 13\n") + this._didHead = true + } + + var diag = res.diag + if (diag === undefined) diag = this.diag + + this.emit("data", encodeResult(res, this.count + 1, diag)) + + if (typeof res === "string") return true + + if (res.bailout) { + var bo = "bail out!" + if (typeof res.bailout === "string") bo += " " + res.bailout + this.emit("data", bo) + return + } + this.results.add(res, false) + + this.count ++ +} + +TapProducer.prototype.end = function (res) { + if (res) this.write(res) + // console.error("TapProducer end", res, this.results) + this.emit("data", "\n1.."+this.results.testsTotal+"\n") + if (this.trailer && typeof this.trailer !== "string") { + // summary trailer. + var trailer = "tests "+this.results.testsTotal + "\n" + if (this.results.pass) { + trailer += "pass " + this.results.pass + "\n" + } + if (this.results.fail) { + trailer += "fail " + this.results.fail + "\n" + } + if (this.results.skip) { + trailer += "skip "+this.results.skip + "\n" + } + if (this.results.todo) { + trailer += "todo "+this.results.todo + "\n" + } + if (this.results.bailedOut) { + trailer += "bailed out" + "\n" + } + + if (this.results.testsTotal === this.results.pass) { + trailer += "\nok\n" + } + this.trailer = trailer + } + if (this.trailer) this.write(this.trailer) + this.writable = false + this.emit("end", null, this.count, this.ok) +} + +function encodeResult (res, count, diag) { + // console.error(res, count, diag) + if (typeof res === "string") { + res = res.split(/\r?\n/).map(function (l) { + if (!l.trim()) return l.trim() + return "# " + l + }).join("\n") + if (res.substr(-1) !== "\n") res += "\n" + return res + } + + if (res.bailout) return "" + + + if (!!process.env.TAP_NODIAG) diag = false + else if (!!process.env.TAP_DIAG) diag = true + else if (diag === undefined) diag = !res.ok + + var output = "" + res.name = res.name && ("" + res.name).trim() + output += ( !res.ok ? "not " : "") + "ok " + count + + ( !res.name ? "" + : " " + res.name.replace(/[\r\n]/g, " ") ) + + ( res.skip ? " # SKIP" + : res.todo ? " # TODO" + : "" ) + + "\n" + + if (!diag) return output + var d = {} + , dc = 0 + Object.keys(res).filter(function (k) { + return k !== "ok" && k !== "name" && k !== "id" + }).forEach(function (k) { + dc ++ + d[k] = res[k] + }) + //console.error(d, "about to encode") + if (dc > 0) output += " ---"+yamlish.encode(d)+"\n ...\n" + return output +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-results.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-results.js new file mode 100644 index 0000000..6fe90e8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-results.js @@ -0,0 +1,71 @@ +// A class for counting up results in a test harness. + +module.exports = Results + +var inherits = require("inherits") + , EventEmitter = require("events").EventEmitter + +inherits(Results, EventEmitter) + +function Results (r) { + //console.error("result constructor", r) + this.ok = true + this.addSet(r) +} + +Results.prototype.addSet = function (r) { + //console.error("add set of results", r) + r = r || {ok: true} + ; [ "todo" + , "todoPass" + , "todoFail" + , "skip" + , "skipPass" + , "skipFail" + , "pass" + , "passTotal" + , "fail" + , "failTotal" + , "tests" + , "testsTotal" ].forEach(function (k) { + this[k] = (this[k] || 0) + (r[k] || 0) + //console.error([k, this[k]]) + }, this) + + this.ok = this.ok && r.ok && true + this.bailedOut = this.bailedOut || r.bailedOut || false + this.list = (this.list || []).concat(r.list || []) + this.emit("set", this.list) + //console.error("after addSet", this) +} + +Results.prototype.add = function (r, addToList) { + //console.error("add result", r) + var pf = r.ok ? "pass" : "fail" + , PF = r.ok ? "Pass" : "Fail" + + this.testsTotal ++ + this[pf + "Total"] ++ + + if (r.skip) { + this["skip" + PF] ++ + this.skip ++ + } else if (r.todo) { + this["todo" + PF] ++ + this.todo ++ + } else { + this.tests ++ + this[pf] ++ + } + + if (r.bailout || typeof r.bailout === "string") { + // console.error("Bailing out in result") + this.bailedOut = true + } + this.ok = !!(this.ok && r.ok) + + if (addToList === false) return + this.list = this.list || [] + this.list.push(r) + this.emit("result", r) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-runner.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-runner.js new file mode 100644 index 0000000..285772f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-runner.js @@ -0,0 +1,453 @@ +var fs = require("fs") + , child_process = require("child_process") + , path = require("path") + , chain = require("slide").chain + , asyncMap = require("slide").asyncMap + , TapProducer = require("./tap-producer.js") + , TapConsumer = require("./tap-consumer.js") + , assert = require("./tap-assert.js") + , inherits = require("inherits") + , util = require("util") + , CovHtml = require("./tap-cov-html.js") + + // XXX Clean up the coverage options + , doCoverage = process.env.TAP_COV + || process.env.npm_package_config_coverage + || process.env.npm_config_coverage + +module.exports = Runner + +inherits(Runner, TapProducer) + +function Runner (options, cb) { + this.options = options + + var diag = this.options.diag + var dir = this.options.argv.remain + Runner.super.call(this, diag) + + this.doCoverage = doCoverage + // An array of full paths to files to obtain coverage + this.coverageFiles = [] + // The source of these files + this.coverageFilesSource = {} + // Where to write coverage information + this.coverageOutDir = this.options["coverage-dir"] + // Temporary test files bunkerified we'll remove later + this.f2delete = [] + // Raw coverage stats, as read from JSON files + this.rawCovStats = [] + // Processed coverage information, per file to cover: + this.covStats = {} + + if (dir) { + var filesToCover = this.options.cover + + if (doCoverage) { + var mkdirp = require("mkdirp") + this.coverageOutDir = path.resolve(this.coverageOutDir) + this.getFilesToCover(filesToCover) + var self = this + return mkdirp(this.coverageOutDir, 0755, function (er) { + if (er) return self.emit("error", er) + self.run(dir, cb) + }) + } + + this.run(dir, cb) + } +} + + +Runner.prototype.run = function() { + var self = this + , args = Array.prototype.slice.call(arguments) + , cb = args.pop() || finish + + function finish (er) { + if (er) { + self.emit("error", er) + } + + if (!doCoverage) return self.end() + + // Cleanup temporary test files with coverage: + self.f2delete.forEach(function(f) { + fs.unlinkSync(f) + }) + self.getFilesToCoverSource(function(err, data) { + if (err) { + self.emit("error", err) + } + self.getPerFileCovInfo(function(err, data) { + if (err) { + self.emit("error", err) + } + self.mergeCovStats(function(err, data) { + if (err) { + self.emit("error", err) + } + CovHtml(self.covStats, self.coverageOutDir, function() { + self.end() + }) + }) + }) + }) + } + + if (Array.isArray(args[0])) { + args = args[0] + } + self.runFiles(args, "", cb) +} + +Runner.prototype.runDir = function (dir, cb) { + var self = this + fs.readdir(dir, function (er, files) { + if (er) { + self.write(assert.fail("failed to readdir " + dir, { error: er })) + self.end() + return + } + files = files.sort(function(a, b) { + return a > b ? 1 : -1 + }) + files = files.filter(function(f) { + return !f.match(/^\./) + }) + files = files.map(path.resolve.bind(path, dir)) + + self.runFiles(files, path.resolve(dir), cb) + }) +} + + +Runner.prototype.runFiles = function (files, dir, cb) { + + var self = this + chain(files.map(function(f) { + return function (cb) { + if (self._bailedOut) return + var relDir = dir || path.dirname(f) + , fileName = relDir === "." ? f : f.substr(relDir.length + 1) + + self.write(fileName) + fs.lstat(f, function(er, st) { + if (er) { + self.write(assert.fail("failed to stat " + f, {error: er})) + return cb() + } + + var cmd = f, args = [], env = {} + + if (path.extname(f) === ".js") { + cmd = "node" + if (self.options.gc) { + args.push("--expose-gc") + } + args.push(fileName) + } else if (path.extname(f) === ".coffee") { + cmd = "coffee" + args.push(fileName) + } else { + // Check if file is executable + if ((st.mode & 0100) && process.getuid) { + if (process.getuid() != st.uid) { + return cb() + } + } else if ((st.mode & 0010) && process.getgid) { + if (process.getgid() != st.gid) { + return cb() + } + } else if ((st.mode & 0001) == 0) { + return cb() + } + } + + if (st.isDirectory()) { + return self.runDir(f, cb) + } + + if (doCoverage && path.extname(f) === ".js") { + var foriginal = fs.readFileSync(f, "utf8") + , fcontents = self.coverHeader() + foriginal + self.coverFooter() + , tmpBaseName = path.basename(f, path.extname(f)) + + ".with-coverage." + process.pid + path.extname(f) + , tmpFname = path.resolve(path.dirname(f), tmpBaseName) + + fs.writeFileSync(tmpFname, fcontents, "utf8") + args.splice(-1, 1, tmpFname) + } + + for (var i in process.env) { + env[i] = process.env[i] + } + env.TAP = 1 + + var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }) + , out = "" + , err = "" + , tc = new TapConsumer() + , childTests = [f] + + var timeout = setTimeout(function () { + if (!cp._ended) { + cp._timedOut = true + cp.kill() + } + }, self.options.timeout * 1000) + + tc.on("data", function(c) { + self.emit("result", c) + self.write(c) + }) + + tc.on("bailout", function (message) { + clearTimeout(timeout) + console.log("# " + f.substr(process.cwd().length + 1)) + process.stderr.write(err) + process.stdout.write(out + "\n") + self._bailedOut = true + cp._ended = true + cp.kill() + }) + + cp.stdout.pipe(tc) + cp.stdout.on("data", function (c) { out += c }) + cp.stderr.on("data", function (c) { + if (self.options.stderr) process.stderr.write(c) + err += c + }) + + cp.on("exit", function (code, signal) { + if (cp._ended) return + cp._ended = true + var ok = !cp._timedOut && code === 0 + clearTimeout(timeout) + //childTests.forEach(function (c) { self.write(c) }) + var res = { name: path.dirname(f).replace(process.cwd() + "/", "") + + "/" + fileName + , ok: ok + , exit: code } + + if (cp._timedOut) + res.timedOut = cp._timedOut + if (signal) + res.signal = signal + + if (err) { + res.stderr = err + if (tc.results.ok && + tc.results.tests === 0 && + !self.options.stderr) { + // perhaps a compilation error or something else failed. + // no need if stderr is set, since it will have been + // output already anyway. + console.error(err) + } + } + + // tc.results.ok = tc.results.ok && ok + tc.results.add(res) + res.command = [cmd].concat(args).map(JSON.stringify).join(" ") + self.emit("result", res) + self.emit("file", f, res, tc.results) + self.write(res) + self.write("\n") + if (doCoverage) { + self.f2delete.push(tmpFname) + } + cb() + }) + }) + } + }), cb) + + return self +} + + +// Get an array of full paths to files we are interested into obtain +// code coverage. +Runner.prototype.getFilesToCover = function(filesToCover) { + var self = this + filesToCover = filesToCover.split(",").map(function(f) { + return path.resolve(f) + }).filter(function(f) { + return path.existsSync(f) + }) + + function recursive(f) { + if (path.extname(f) === "") { + // Is a directory: + fs.readdirSync(f).forEach(function(p) { + recursive(f + "/" + p) + }) + } else { + self.coverageFiles.push(f) + } + } + filesToCover.forEach(function(f) { + recursive(f) + }) +} + +// Prepend to every test file to run. Note tap.test at the very top due it +// "plays" with include paths. +Runner.prototype.coverHeader = function() { + // semi here since we're injecting it before the first line, + // and don't want to mess up line numbers in the test files. + return "var ___TAP_COVERAGE = require(" + + JSON.stringify(require.resolve("runforcover")) + + ").cover(/.*/g);" +} + +// Append at the end of every test file to run. Actually, the stuff which gets +// the coverage information. +// Maybe it would be better to move into a separate file template so editing +// could be easier. +Runner.prototype.coverFooter = function() { + var self = this + // This needs to be a string with proper interpolations: + return [ "" + , "var ___TAP = require(" + JSON.stringify(require.resolve("./main.js")) + ")" + , "if (typeof ___TAP._plan === 'number') ___TAP._plan ++" + , "___TAP.test(" + JSON.stringify("___coverage") + ", function(t) {" + , " var covFiles = " + JSON.stringify(self.coverageFiles) + , " , covDir = " + JSON.stringify(self.coverageOutDir) + , " , path = require('path')" + , " , fs = require('fs')" + , " , testFnBase = path.basename(__filename, '.js') + '.json'" + , " , testFn = path.resolve(covDir, testFnBase)" + , "" + , " function asyncForEach(arr, fn, callback) {" + , " if (!arr.length) {" + , " return callback()" + , " }" + , " var completed = 0" + , " arr.forEach(function(i) {" + , " fn(i, function (err) {" + , " if (err) {" + , " callback(err)" + , " callback = function () {}" + , " } else {" + , " completed += 1" + , " if (completed === arr.length) {" + , " callback()" + , " }" + , " }" + , " })" + , " })" + , " }" + , "" + , " ___TAP_COVERAGE(function(coverageData) {" + , " var outObj = {}" + , " asyncForEach(covFiles, function(f, cb) {" + , " if (coverageData[f]) {" + , " var stats = coverageData[f].stats()" + , " , stObj = stats" + , " stObj.lines = stats.lines.map(function (l) {" + , " return { number: l.lineno, source: l.source() }" + , " })" + , " outObj[f] = stObj" + , " }" + , " cb()" + , " }, function(err) {" + , " ___TAP_COVERAGE.release()" + , " fs.writeFileSync(testFn, JSON.stringify(outObj))" + , " t.end()" + , " })" + , " })" + , "})" ].join("\n") +} + + +Runner.prototype.getFilesToCoverSource = function(cb) { + var self = this + asyncMap(self.coverageFiles, function(f, cb) { + fs.readFile(f, "utf8", function(err, data) { + var lc = 0 + if (err) { + cb(err) + } + self.coverageFilesSource[f] = data.split("\n").map(function(l) { + lc += 1 + return { number: lc, source: l } + }) + cb() + }) + }, cb) +} + +Runner.prototype.getPerFileCovInfo = function(cb) { + var self = this + , covPath = path.resolve(self.coverageOutDir) + + fs.readdir(covPath, function(err, files) { + if (err) { + self.emit("error", err) + } + var covFiles = files.filter(function(f) { + return path.extname(f) === ".json" + }) + asyncMap(covFiles, function(f, cb) { + fs.readFile(path.resolve(covPath, f), "utf8", function(err, data) { + if (err) { + cb(err) + } + self.rawCovStats.push(JSON.parse(data)) + cb() + }) + }, function(f, cb) { + fs.unlink(path.resolve(covPath, f), cb) + }, cb) + }) +} + +Runner.prototype.mergeCovStats = function(cb) { + var self = this + self.rawCovStats.forEach(function(st) { + Object.keys(st).forEach(function(i) { + // If this is the first time we reach this file, just add the info: + if (!self.covStats[i]) { + self.covStats[i] = { + missing: st[i].lines + } + } else { + // If we already added info for this file before, we need to remove + // from self.covStats any line not duplicated again (since it has + // run on such case) + self.covStats[i].missing = self.covStats[i].missing.filter( + function(l) { + return (st[i].lines.indexOf(l)) + }) + } + }) + }) + + // This is due to a bug into + // chrisdickinson/node-bunker/blob/feature/add-coverage-interface + // which is using array indexes for line numbers instead of the right number + Object.keys(self.covStats).forEach(function(f) { + self.covStats[f].missing = self.covStats[f].missing.map(function(line) { + return { number: line.number, source: line.source } + }) + }) + + Object.keys(self.coverageFilesSource).forEach(function(f) { + if (!self.covStats[f]) { + self.covStats[f] = { missing: self.coverageFilesSource[f] + , percentage: 0 + } + } + self.covStats[f].lines = self.coverageFilesSource[f] + self.covStats[f].loc = self.coverageFilesSource[f].length + + if (!self.covStats[f].percentage) { + self.covStats[f].percentage = + 1 - (self.covStats[f].missing.length / self.covStats[f].loc) + } + + }) + cb() +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-test.js new file mode 100644 index 0000000..15ae8fb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/lib/tap-test.js @@ -0,0 +1,109 @@ +// This is a very simple test framework that leverages the tap framework +// to run tests and output tap-parseable results. + +module.exports = Test + +var assert = require("./tap-assert") + , inherits = require("inherits") + , Results = require("./tap-results") + +// tests are also test harnesses +inherits(Test, require("./tap-harness")) + +function Test (harness, name, conf) { + //console.error("test ctor") + if (!(this instanceof Test)) return new Test(harness, name, conf) + + Test.super.call(this, Test) + + conf.name = name || conf.name || "(anonymous)" + this.conf = conf + + this.harness = harness + this.harness.add(this) +} + +// it's taking too long! +Test.prototype.timeout = function () { + // detect false alarms + if (this._ended) return + this.fail("Timeout!") + this.end() +} + +Test.prototype.clear = function () { + this._started = false + this._ended = false + this._plan = null + this._bailedOut = false + this._testCount = 0 + this.results = new Results() +} + +// this gets called if a test throws ever +Test.prototype.threw = function (ex) { + //console.error("threw!", ex.stack) + this.fail(ex.name + ": " + ex.message, { error: ex, thrown: true }) + // may emit further failing tests if the plan is not completed + //console.error("end, because it threw") + if (!this._ended) this.end() +} + +Test.prototype.comment = function (m) { + if (typeof m !== "string") { + return this.fail("Test.comment argument must be a string") + } + this.result("\n" + m.trim()) +} + +Test.prototype.result = function (res) { + this.results.add(res) + this._testCount ++ + this.emit("result", res) + if (this._plan === this._testCount) { + process.nextTick(this._endNice.bind(this)) + } +} + +Test.prototype._endNice = function () { + if (!this._ended) this.end() +} + +// parasitic +// Who says you can't do multiple inheritance in js? +Object.getOwnPropertyNames(assert).forEach(function (k) { + if (k === "prototype" || k === "name") return + var d = Object.getOwnPropertyDescriptor(assert, k) + , v = d.value + if (!v) return + d.value = assertParasite(v) + Object.defineProperty(Test.prototype, k, d) +}) + +function assertParasite (fn) { return function _testAssert () { + //console.error("_testAssert", fn.name, arguments) + if (this._bailedOut) return + var res = fn.apply(assert, arguments) + this.result(res) + return res +}} + +// a few tweaks on the EE emit function, because +// we want to catch all thrown errors and bubble up "bailout" +Test.prototype.emit = (function (em) { return function (t) { + // bailouts bubble until handled + if (t === "bailout" && + this.listeners(t).length === 0 && + this.harness) { + return this.harness.bailout(arguments[1]) + } + + if (t === "error") return em.apply(this, arguments) + try { + em.apply(this, arguments) + } catch (ex) { + // any exceptions in a test are a failure + //console.error("caught!", ex.stack) + this.threw(ex) + } +}})(Test.super.prototype.emit) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/.bin/nopt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/.bin/nopt new file mode 120000 index 0000000..6b6566e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/.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/nodeunit/node_modules/tap/node_modules/buffer-equal/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/README.markdown new file mode 100644 index 0000000..571938a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/README.markdown @@ -0,0 +1,62 @@ +buffer-equal +============ + +Return whether two buffers are equal. + +[![build status](https://secure.travis-ci.org/substack/node-buffer-equal.png)](http://travis-ci.org/substack/node-buffer-equal) + +example +======= + +``` js +var bufferEqual = require('bufferEqual'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); +``` + +output: + +``` +true +false +undefined +``` + +methods +======= + +``` js +var bufferEqual = require('buffer-equal') +``` + +bufferEqual(a, b) +----------------- + +Return whether the two buffers `a` and `b` are equal. + +If `a` or `b` is not a buffer, return `undefined`. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install buffer-equal +``` + +license +======= + +MIT diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/example/eq.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/example/eq.js new file mode 100644 index 0000000..1eb0509 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/example/eq.js @@ -0,0 +1,14 @@ +var bufferEqual = require('../'); + +console.dir(bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) +)); +console.dir(bufferEqual( + new Buffer('abc'), + new Buffer('abcd') +)); +console.dir(bufferEqual( + new Buffer('abc'), + 'abc' +)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/index.js new file mode 100644 index 0000000..35a73c3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/index.js @@ -0,0 +1,13 @@ +var Buffer = require('buffer').Buffer; // for use with browserify + +module.exports = function (a, b) { + if (!Buffer.isBuffer(a)) return undefined; + if (!Buffer.isBuffer(b)) return undefined; + if (a.length !== b.length) return false; + + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + + return true; +}; 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 new file mode 100644 index 0000000..2c6ad5d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/package.json @@ -0,0 +1,37 @@ +{ + "name": "buffer-equal", + "description": "return whether two buffers are equal", + "version": "0.0.0", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-buffer-equal.git" + }, + "main": "index.js", + "keywords": [ + "buffer", + "equal" + ], + "directories": { + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.2.4" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "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/buffer-equal/test/eq.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/test/eq.js new file mode 100644 index 0000000..3d34006 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/buffer-equal/test/eq.js @@ -0,0 +1,35 @@ +var bufferEqual = require('../'); +var test = require('tap').test; + +test('equal', function (t) { + var eq = bufferEqual( + new Buffer([253,254,255]), + new Buffer([253,254,255]) + ); + t.strictEqual(eq, true); + t.end(); +}); + +test('not equal', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + new Buffer('abcd') + ); + t.strictEqual(eq, false); + t.end(); +}); + +test('not equal not buffer', function (t) { + var eq = bufferEqual( + new Buffer('abc'), + 'abc' + ); + t.strictEqual(eq, undefined); + t.end(); +}); + +test('equal not buffer', function (t) { + var eq = bufferEqual('abc', 'abc'); + t.strictEqual(eq, undefined); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/README.markdown new file mode 100644 index 0000000..c3293d3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/README.markdown @@ -0,0 +1,55 @@ +deep-equal +========== + +Node's `assert.deepEqual() algorithm` as a standalone module. + +example +======= + +``` js +var equal = require('deep-equal'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); +``` + +methods +======= + +var deepEqual = require('deep-equal') + +deepEqual(a, b) +--------------- + +Compare objects `a` and `b`, returning whether they are equal according to a +recursive equality algorithm. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install deep-equal +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT. Derived largely from node's assert module. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/example/cmp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/example/cmp.js new file mode 100644 index 0000000..67014b8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/example/cmp.js @@ -0,0 +1,11 @@ +var equal = require('../'); +console.dir([ + equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + ), + equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + ) +]); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/index.js new file mode 100644 index 0000000..e4e37be --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/index.js @@ -0,0 +1,84 @@ +var pSlice = Array.prototype.slice; +var Object_keys = typeof Object.keys === 'function' + ? Object.keys + : function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; + } +; + +var deepEqual = module.exports = function (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } 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 deepEqual(a, b); + } + try { + var ka = Object_keys(a), + kb = Object_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 (!deepEqual(a[key], b[key])) return false; + } + return true; +} 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 new file mode 100644 index 0000000..79f7498 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/package.json @@ -0,0 +1,39 @@ +{ + "name": "deep-equal", + "version": "0.0.0", + "description": "node's assert.deepEqual algorithm", + "main": "index.js", + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "0.0.x" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-deep-equal.git" + }, + "keywords": [ + "equality", + "equal", + "compare" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "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/deep-equal/test/cmp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/test/cmp.js new file mode 100644 index 0000000..8418f0f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/deep-equal/test/cmp.js @@ -0,0 +1,18 @@ +var test = require('tap').test; +var equal = require('../'); + +test('equal', function (t) { + t.ok(equal( + { a : [ 2, 3 ], b : [ 4 ] }, + { a : [ 2, 3 ], b : [ 4 ] } + )); + t.end(); +}); + +test('not equal', function (t) { + t.notOk(equal( + { x : 5, y : [6] }, + { x : 5, y : 6 } + )); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/.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/nodeunit/node_modules/tap/node_modules/difflet/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/README.markdown new file mode 100644 index 0000000..9ad4303 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/README.markdown @@ -0,0 +1,116 @@ +difflet +======= + +Create colorful diffs for javascript objects. + +example +======= + +string.js +--------- + +``` js +var difflet = require('difflet'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_string.png) + +colors.js +--------- + +``` js +var diff = require('difflet')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); +``` + +output: + +![colorful output](http://substack.net/images/screenshots/difflet_colors.png) + +green for inserts, blue for updates, red for deletes + +methods +======= + +var difflet = require('difflet') + +var diff = difflet(opts={}) +--------------------------- + +Create a difflet from optional options `opts`. + +With `opts.start(type, stream)` and `opts.stop(type, stream)`, +you can write custom handlers for all the types of differences: +`'inserted'`, `'updated'`, and `'deleted'`. +By default green is used for insertions, blue for updates, and red for +deletions. + +If `opts.indent` is set, output will span multiple lines and `opts.indent` +spaces will be used for leading whitespace. + +If `opts.comma === 'first'` then commas will be placed at the start of lines. + +Setting `opts.comment` to `true` will turn on comments with the previous +contents like this: + +![object comments](http://substack.net/images/screenshots/difflet_object_comments.png) + +diff(prev, next) +---------------- + +Return a stream with the colorful changes between objects `prev` and `next`. + +diff.compare(prev, next) +------------------------ + +Return a string with the colorful changes between `prev` and `next`. + +difflet.compare(prev, next) +--------------------------- + +Return a string with the colorful changes between `prev` and `next` with the +default options. + +install +======= + +With [npm](http://npmjs.org) do: + +``` +npm install difflet +``` + +test +==== + +With [npm](http://npmjs.org) do: + +``` +npm test +``` + +license +======= + +MIT/X11 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_array.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_array.js new file mode 100644 index 0000000..bc5733f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_array.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + [ 1, [2,3,{a:4}], 3 ], + [ 1, [[5],6,7], 4 ] +); +process.stdout.write(s); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_object.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_object.js new file mode 100644 index 0000000..5e00e2c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/cmp_object.js @@ -0,0 +1,6 @@ +var difflet = require('../'); +var s = difflet({ indent : 2, comment : true }).compare( + { z : [6,7], a : 'abcdefgh', b : [ 31, 'xxt' ] }, + { x : 5, a : 'abdcefg', b : [ 51, 'xxs' ] } +); +console.log(s); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/colors.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/colors.js new file mode 100644 index 0000000..332bbae --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/colors.js @@ -0,0 +1,18 @@ +var diff = require('../')({ indent : 2 }); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : 'beep', + c : { x : 7, z : 3 } +}; + +var next = { + a : [ 1, 2, "z", /beep/, new Buffer(3) ], + fn : function qqq () {}, + b : [5,6,7], + c : { x : 8, y : 5 } +}; + +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/comma_first.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/comma_first.js new file mode 100644 index 0000000..67ece23 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/comma_first.js @@ -0,0 +1,12 @@ +var diff = require('../')({ + indent : 2, + comma : 'first', +}); + +var prev = { yy : 6, zz : 5, a : [1,2,3] }; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer(3) ], + fn : 8, + b : [5,6,7] +}; +diff(prev, next).pipe(process.stdout); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/diff.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/diff.js new file mode 100644 index 0000000..08f6e7a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/diff.js @@ -0,0 +1,15 @@ +var difflet = require('../'); +var a = { + x : 4, + z : 8, + xs : [ 5, 2, 1, { 0 : 'c' } ], +}; + +var b = { + x : 4, + y : 5, + xs : [ 5, 2, 2, { c : 5 } ], +}; + +var s = difflet({ comment : true, indent : 2 }).compare(a, b); +console.log(s); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/html.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/html.js new file mode 100644 index 0000000..9ff4a29 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/html.js @@ -0,0 +1,34 @@ +var difflet = require('../'); +var ent = require('ent'); + +var tags = { + inserted : '', + updated : '', + deleted : '', +}; +var diff = difflet({ + start : function (t, s) { + s.write(tags[t]); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf) { + stream.write(ent.encode(buf)) + }, +}); + +var prev = { + yy : 6, + zz : 5, + a : [1,2,3], + fn : function qq () {} +}; +var next = { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : 'I <3 robots', + b : [5,6,7] +}; + +var stream = diff(prev, next); +stream.pipe(process.stdout, { end : false }); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/string.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/string.js new file mode 100644 index 0000000..6cff6cb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/example/string.js @@ -0,0 +1,4 @@ +var difflet = require('../'); + +var s = difflet.compare({ a : 2, c : 5 }, { a : 3, b : 4 }); +process.stdout.write(s); 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 new file mode 100644 index 0000000..cc32f2b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/index.js @@ -0,0 +1,371 @@ +var traverse = require('traverse'); +var Stream = require('stream').Stream; +var charm = require('charm'); +var deepEqual = require('deep-equal'); + +var exports = module.exports = function (opts_) { + var fn = difflet.bind(null, opts_); + fn.compare = function (prev, next) { + var opts = Object.keys(opts_ || {}).reduce(function (acc, key) { + acc[key] = opts_[key]; + return acc; + }, {}); + var s = opts.stream = new Stream; + var data = ''; + s.write = function (buf) { data += buf }; + s.end = function () {}; + s.readable = true; + s.writable = true; + + difflet(opts, prev, next); + return data; + }; + return fn; +}; + +exports.compare = function (prev, next) { + return exports({}).compare(prev, next); +}; + +function difflet (opts, prev, next) { + var stream = opts.stream || new Stream; + if (!opts.stream) { + stream.readable = true; + stream.writable = true; + stream.write = function (buf) { this.emit('data', buf) }; + stream.end = function () { this.emit('end') }; + } + + if (!opts) opts = {}; + if (opts.start === undefined && opts.stop === undefined) { + var c = charm(stream); + opts.start = function (type) { + c.foreground({ + inserted : 'green', + updated : 'blue', + deleted : 'red', + comment : 'cyan', + }[type]); + c.display('bright'); + }; + opts.stop = function (type) { + c.display('reset'); + }; + } + var write = function (buf) { + if (opts.write) opts.write(buf, stream) + else stream.write(buf) + }; + + var commaFirst = opts.comma === 'first'; + + var stringify = function (node, params) { + return stringifier.call(this, true, node, params || opts); + }; + var plainStringify = function (node, params) { + return stringifier.call(this, false, node, params || opts); + }; + + var levels = 0; + function set (type) { + if (levels === 0) opts.start(type, stream); + levels ++; + } + + function unset (type) { + if (--levels === 0) opts.stop(type, stream); + } + + function stringifier (insertable, node, opts) { + var indent = opts.indent; + + if (insertable) { + var prevNode = traverse.get(prev, this.path || []); + } + var inserted = insertable && prevNode === undefined; + + var indentx = indent ? Array( + ((this.path || []).length + 1) * indent + 1 + ).join(' ') : ''; + if (commaFirst) indentx = indentx.slice(indent); + + if (Array.isArray(node)) { + var updated = (prevNode || traverse.has(prev, this.path)) + && !Array.isArray(prevNode); + if (updated) { + set('updated'); + } + + if (opts.comment && !Array.isArray(prevNode)) { + indent = 0; + } + + this.before(function () { + if (inserted) set('inserted'); + if (indent && commaFirst) { + if ((this.path || []).length === 0 + || Array.isArray(this.parent.node)) { + write('[ '); + } + else write('\n' + indentx + '[ '); + } + else if (indent) { + write('[\n' + indentx); + } + else { + write('['); + } + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write('\n' + indentx); + } + } + }); + + this.after(function () { + if (indent && commaFirst) write('\n' + indentx); + else if (indent) write('\n' + indentx.slice(indent)); + + write(']'); + if (updated) unset('updated'); + if (inserted) unset('inserted'); + }); + } + else if (isRegExp(node)) { + this.block(); + + if (inserted) { + set('inserted'); + write(node.toString()); + unset('inserted'); + } + else if (insertable && prevNode !== node) { + set('updated'); + write(node.toString()); + unset('updated'); + } + else write(node.toString()); + } + else if (typeof node === 'object' + && node && typeof node.inspect === 'function') { + this.block(); + if (inserted) { + set('inserted'); + write(node.inspect()); + unset('inserted'); + } + else if (!(prevNode && typeof prevNode.inspect === 'function' + && prevNode.inspect() === node.inspect())) { + set('updated'); + write(node.inspect()); + unset('updated'); + } + else write(node.inspect()); + } + else if (typeof node == 'object' && node !== null) { + var insertedKey = false; + var deleted = insertable && typeof prevNode === 'object' && prevNode + ? Object.keys(prevNode).filter(function (key) { + return !Object.hasOwnProperty.call(node, key); + }) + : [] + ; + + this.before(function () { + if (inserted) set('inserted'); + write(indent && commaFirst && !this.isRoot + ? '\n' + indentx + '{ ' + : '{' + ); + }); + + this.pre(function (x, key) { + if (insertable) { + var obj = traverse.get(prev, this.path.concat(key)); + if (obj === undefined) { + insertedKey = true; + set('inserted'); + } + } + + if (indent && !commaFirst) write('\n' + indentx); + + plainStringify(key); + write(indent ? ' : ' : ':'); + }); + + this.post(function (child) { + if (!child.isLast && !(indent && commaFirst)) { + write(','); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + } + else if (insertedKey) { + unset('inserted'); + insertedKey = false; + } + + var prev = prevNode && prevNode[child.key]; + if (indent && opts.comment && child.node !== prev + && (typeof child.node !== 'object' || typeof prev !== 'object') + ) { + set('comment'); + write(' // != '); + traverse(prev).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + unset('comment'); + } + + if (child.isLast && deleted.length) { + if (insertedKey) unset('inserted'); + insertedKey = false; + + if (indent && commaFirst) { + write('\n' + indentx + ', ') + } + else if (opts.comment && indent) { + write('\n' + indentx); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + else { + if (!child.isLast) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + } + } + }); + + this.after(function () { + if (inserted) unset('inserted'); + + if (deleted.length) { + if (indent && !commaFirst + && Object.keys(node).length === 0) { + write('\n' + indentx); + } + + set('deleted'); + deleted.forEach(function (key, ix) { + if (indent && opts.comment) { + unset('deleted'); + set('comment'); + write('// '); + unset('comment'); + set('deleted'); + } + + plainStringify(key); + write(indent ? ' : ' : ':'); + traverse(prevNode[key]).forEach(function (x) { + plainStringify.call(this, x, { indent : 0 }); + }); + + var last = ix === deleted.length - 1; + if (insertable && !last) { + if (indent && commaFirst) { + write('\n' + indentx + ', '); + } + else if (indent) { + write(',\n' + indentx); + } + else write(','); + } + }); + unset('deleted'); + } + + if (commaFirst && indent) { + write(indentx.slice(indent) + ' }'); + } + else if (indent) { + write('\n' + indentx.slice(indent) + '}'); + } + else write('}'); + }); + } + else { + var changed = false; + + if (inserted) set('inserted'); + else if (insertable && !deepEqual(prevNode, node)) { + changed = true; + set('updated'); + } + + if (typeof node === 'string') { + write('"' + node.toString().replace(/"/g, '\\"') + '"'); + } + else if (isRegExp(node)) { + write(node.toString()); + } + else if (typeof node === 'function') { + write(node.name + ? '[Function: ' + node.name + ']' + : '[Function]' + ); + } + else if (node === undefined) { + write('undefined'); + } + else if (node === null) { + write('null'); + } + else { + write(node.toString()); + } + + if (inserted) unset('inserted'); + else if (changed) unset('updated'); + } + } + + if (opts.stream) { + traverse(next).forEach(stringify); + } + else process.nextTick(function () { + traverse(next).forEach(stringify); + stream.emit('end'); + }); + + return stream; +} + +function isRegExp (node) { + return node instanceof RegExp || (node + && typeof node.test === 'function' + && typeof node.exec === 'function' + && typeof node.compile === 'function' + && node.constructor && node.constructor.name === 'RegExp' + ); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/README.markdown new file mode 100644 index 0000000..c78d81f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/README.markdown @@ -0,0 +1,202 @@ +charm +===== + +Use +[ansi terminal characters](http://www.termsys.demon.co.uk/vtansi.htm) +to write colors and cursor positions. + +![me lucky charms](http://substack.net/images/charms.png) + +example +======= + +lucky +----- + +````javascript +var charm = require('charm')(process); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); + +charm.on('data', function (buf) { + if (buf[0] === 3) { + clearInterval(iv); + charm.destroy(); + } +}); +```` + +events +====== + +Charm objects pass along the data events from their input stream except for +events generated from querying the terminal device. + +Because charm puts stdin into raw mode, charm emits two special events: "^C" and +"^D" when the user types those combos. It's super convenient with these events +to do: + +````javascript +charm.on('^C', process.exit) +```` + +methods +======= + +var charm = require('charm')(param or stream, ...) +-------------------------------------------------- + +Create a new `charm` given a `param` with `stdout` and `stdin` streams, such as +`process` or by passing the streams in themselves separately as parameters. + +Protip: you can pass in an http response object as an output stream and it will +just work™. + +charm.reset() +------------- + +Reset the entire screen, like the /usr/bin/reset command. + +charm.destroy() +--------------- + +Destroy the input stream. + +charm.write(msg) +---------------- + +Pass along `msg` to the output stream. + +charm.position(x, y) or charm.position(cb) +------------------------------------------ + +Set the cursor position to the absolute coordinates `x, y` or query the position +and get the response as `cb(x, y)`. + +charm.move(x, y) +---------------- + +Move the cursor position by the relative coordinates `x, y`. + +charm.up(y) +----------- + +Move the cursor up by `y` rows. + +charm.down(y) +------------- + +Move the cursor down by `y` rows. + +charm.left(x) +------------- + +Move the cursor left by `x` columns. + +charm.right(x) +------------- + +Move the cursor right by `x` columns. + +charm.push(withAttributes=false) +-------------------------------- + +Push the cursor state and optionally the attribute state. + +charm.pop(withAttributes=false) +------------------------------- + +Pop the cursor state and optionally the attribute state. + +charm.erase(s) +-------------- + +Erase a region defined by the string `s`. + +`s` can be: + +* end - erase from the cursor to the end of the line +* start - erase from the cursor to the start of the line +* line - erase the current line +* down - erase everything below the current line +* up - erase everything above the current line +* screen - erase the entire screen + +charm.display(attr) +------------------- + +Set the display mode with the string `attr`. + +`attr` can be: + +* reset +* bright +* dim +* underscore +* blink +* reverse +* hidden + +charm.foreground(color) +----------------------- + +Set the foreground color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.background(color) +----------------------- + +Set the background color with the string `color`, which can be: + +* red +* yellow +* green +* blue +* cyan +* magenta +* black +* white + +or `color` can be an integer from 0 to 255, inclusive. + +charm.cursor(visible) +--------------------- + +Set the cursor visibility with a boolean `visible`. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install charm diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/256.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/256.js new file mode 100644 index 0000000..6851386 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/256.js @@ -0,0 +1,17 @@ +var charm = require('../')(process); + +function exit () { + charm.display('reset'); + process.exit(); +} +charm.on('^C', exit); + +var ix = 0; +var iv = setInterval(function () { + charm.background(ix++).write(' '); + if (ix === 256) { + clearInterval(iv); + charm.write('\n'); + exit(); + } +}, 10); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/column.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/column.js new file mode 100644 index 0000000..448e9c3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/column.js @@ -0,0 +1,10 @@ +var charm = require('../')(process); + +charm + .column(16) + .write('beep') + .down() + .column(32) + .write('boop\n') + .destroy() +; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/cursor.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/cursor.js new file mode 100644 index 0000000..0c565b0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/cursor.js @@ -0,0 +1,22 @@ +var charm = require('../')(process); + +charm.position(5, 10); + +charm.position(function (x, y) { + console.dir([ x, y ]); + + charm.move(7,2); + charm.push(); + process.stdout.write('lul'); + + charm.left(3).up(1).foreground('magenta'); + process.stdout.write('v'); + charm.left(1).up(1).display('reset'); + process.stdout.write('|'); + + charm.down(3); + charm.pop().background('blue'); + process.stdout.write('popped\npow'); + charm.display('reset').erase('line'); + charm.destroy(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/http_spin.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/http_spin.js new file mode 100644 index 0000000..53e0e4b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/http_spin.js @@ -0,0 +1,35 @@ +var http = require('http'); +var charmer = require('../'); + +http.createServer(function (req, res) { + res.setHeader('content-type', 'text/ansi'); + + var charm = charmer(res); + charm.reset(); + + var radius = 10; + var theta = 0; + var points = []; + + var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; + }, 50); + + req.connection.on('end', function () { + clearInterval(iv); + charm.destroy(); + }); +}).listen(8081); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/lucky.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/lucky.js new file mode 100644 index 0000000..08dc5b5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/lucky.js @@ -0,0 +1,30 @@ +var charm = require('../')(process); +charm.reset(); + +var colors = [ 'red', 'cyan', 'yellow', 'green', 'blue' ]; +var text = 'Always after me lucky charms.'; + +var offset = 0; +var iv = setInterval(function () { + var y = 0, dy = 1; + for (var i = 0; i < 40; i++) { + var color = colors[(i + offset) % colors.length]; + var c = text[(i + offset) % text.length]; + charm + .move(1, dy) + .foreground(color) + .write(c) + ; + y += dy; + if (y <= 0 || y >= 5) dy *= -1; + } + charm.position(0, 1); + offset ++; +}, 150); + +charm.on('data', function (buf) { + if (buf[0] === 3) { + clearInterval(iv); + charm.destroy(); + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/position.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/position.js new file mode 100644 index 0000000..2c5ae9b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/position.js @@ -0,0 +1,7 @@ +var charm = require('charm')(process); + +charm.on('^C', process.exit); + +charm.position(function (x, y) { + console.log('(%d, %d)', x, y); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/progress.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/progress.js new file mode 100644 index 0000000..f8db57b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/progress.js @@ -0,0 +1,19 @@ +var charm = require('../')(process); + +charm.write("Progress: 0 %"); +var i = 0; + +var increment = function () { + charm.left(i.toString().length + 2); + i = i + 1; + charm.write(i + " %"); + if (i === 100) { + charm.write("\nDone!\n"); + process.exit(); + } +}; + +var loop = setInterval(increment, 50); + +charm.on('^C',process.exit); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/spin.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/spin.js new file mode 100644 index 0000000..fd3e23a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/example/spin.js @@ -0,0 +1,23 @@ +var charm = require('../')(process); +charm.reset(); + +var radius = 10; +var theta = 0; +var points = []; + +var iv = setInterval(function () { + var x = 2 + (radius + Math.cos(theta) * radius) * 2; + var y = 2 + radius + Math.sin(theta) * radius; + + points.unshift([ x, y ]); + var colors = [ 'red', 'yellow', 'green', 'cyan', 'blue', 'magenta' ]; + + points.forEach(function (p, i) { + charm.position(p[0], p[1]); + var c = colors[Math.floor(i / 12)]; + charm.background(c).write(' ') + }); + points = points.slice(0, 12 * colors.length - 1); + + theta += Math.PI / 40; +}, 50); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/index.js new file mode 100644 index 0000000..bcfc7a8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/index.js @@ -0,0 +1,286 @@ +var tty = require('tty'); +var encode = require('./lib/encode'); +var EventEmitter = require('events').EventEmitter; + +var exports = module.exports = function () { + var input = null; + function setInput (s) { + if (input) throw new Error('multiple inputs specified') + else input = s + } + + var output = null; + function setOutput (s) { + if (output) throw new Error('multiple outputs specified') + else output = s + } + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (!arg) continue; + if (arg.readable) setInput(arg) + else if (arg.stdin || arg.input) setInput(arg.stdin || arg.input) + + if (arg.writable) setOutput(arg) + else if (arg.stdout || arg.output) setOutput(arg.stdout || arg.output) + + } + + return new Charm(input, output); +}; + +var Charm = exports.Charm = function (input, output) { + var self = this; + self.input = input; + self.output = output; + self.pending = []; + + if (!output) { + self.emit('error', new Error('output stream required')); + } + + if (input && typeof input.fd === 'number' && tty.isatty(input.fd)) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(true); + } + else tty.setRawMode(true); + input.resume(); + } + + if (input) { + input.on('data', function (buf) { + if (self.pending.length) { + var codes = extractCodes(buf); + var matched = false; + + for (var i = 0; i < codes.length; i++) { + for (var j = 0; j < self.pending.length; j++) { + var cb = self.pending[j]; + if (cb(codes[i])) { + matched = true; + self.pending.splice(j, 1); + break; + } + } + } + + if (matched) return; + } + + self.emit('data', buf) + + if (buf.length === 1) { + if (buf[0] === 3) self.emit('^C'); + if (buf[0] === 4) self.emit('^D'); + } + }); + } +} + +Charm.prototype = new EventEmitter; + +Charm.prototype.destroy = function () { + if (this.input) this.input.destroy() +}; + +Charm.prototype.write = function (msg) { + this.output.write(msg); + return this; +}; + +Charm.prototype.reset = function (cb) { + this.write(encode('c')); + return this; +}; + +Charm.prototype.position = function (x, y) { + // get/set absolute coordinates + if (typeof x === 'function') { + var cb = x; + this.pending.push(function (buf) { + if (buf[0] === 27 && buf[1] === encode.ord('[') + && buf[buf.length-1] === encode.ord('R')) { + var pos = buf.toString() + .slice(2,-1) + .split(';') + .map(Number) + ; + cb(pos[1], pos[0]); + return true; + } + }); + this.write(encode('[6n')); + } + else { + this.write(encode( + '[' + Math.floor(y) + ';' + Math.floor(x) + 'f' + )); + } + return this; +}; + +Charm.prototype.move = function (x, y) { + // set relative coordinates + var bufs = []; + + if (y < 0) this.up(-y) + else if (y > 0) this.down(y) + + if (x > 0) this.right(x) + else if (x < 0) this.left(-x) + + return this; +}; + +Charm.prototype.up = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'A')); + return this; +}; + +Charm.prototype.down = function (y) { + if (y === undefined) y = 1; + this.write(encode('[' + Math.floor(y) + 'B')); + return this; +}; + +Charm.prototype.right = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'C')); + return this; +}; + +Charm.prototype.left = function (x) { + if (x === undefined) x = 1; + this.write(encode('[' + Math.floor(x) + 'D')); + return this; +}; + +Charm.prototype.column = function (x) { + this.write(encode('[' + Math.floor(x) + 'G')); + return this; +}; + +Charm.prototype.push = function (withAttributes) { + this.write(encode(withAttributes ? '7' : '[s')); + return this; +}; + +Charm.prototype.pop = function (withAttributes) { + this.write(encode(withAttributes ? '8' : '[u')); + return this; +}; + +Charm.prototype.erase = function (s) { + if (s === 'end' || s === '$') { + this.write(encode('[K')); + } + else if (s === 'start' || s === '^') { + this.write(encode('[1K')); + } + else if (s === 'line') { + this.write(encode('[2K')); + } + else if (s === 'down') { + this.write(encode('[J')); + } + else if (s === 'up') { + this.write(encode('[1J')); + } + else if (s === 'screen') { + this.write(encode('[1J')); + } + else { + this.emit('error', new Error('Unknown erase type: ' + s)); + } + return this; +}; + +Charm.prototype.display = function (attr) { + var c = { + reset : 0, + bright : 1, + dim : 2, + underscore : 4, + blink : 5, + reverse : 7, + hidden : 8 + }[attr]; + if (c === undefined) { + this.emit('error', new Error('Unknown attribute: ' + attr)); + } + this.write(encode('[' + c + 'm')); + return this; +}; + +Charm.prototype.foreground = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[38;5;' + color + 'm')); + } + else { + var c = { + black : 30, + red : 31, + green : 32, + yellow : 33, + blue : 34, + magenta : 35, + cyan : 36, + white : 37 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.background = function (color) { + if (typeof color === 'number') { + if (color < 0 || color >= 256) { + this.emit('error', new Error('Color out of range: ' + color)); + } + this.write(encode('[48;5;' + color + 'm')); + } + else { + var c = { + black : 40, + red : 41, + green : 42, + yellow : 43, + blue : 44, + magenta : 45, + cyan : 46, + white : 47 + }[color.toLowerCase()]; + + if (!c) this.emit('error', new Error('Unknown color: ' + color)); + this.write(encode('[' + c + 'm')); + } + return this; +}; + +Charm.prototype.cursor = function (visible) { + this.write(encode(visible ? '[?25h' : '[?25l')); + return this; +}; + +var extractCodes = exports.extractCodes = function (buf) { + var codes = []; + var start = -1; + + for (var i = 0; i < buf.length; i++) { + if (buf[i] === 27) { + if (start >= 0) codes.push(buf.slice(start, i)); + start = i; + } + else if (start >= 0 && i === buf.length - 1) { + codes.push(buf.slice(start)); + } + } + + return codes; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/lib/encode.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/lib/encode.js new file mode 100644 index 0000000..3b6417a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/lib/encode.js @@ -0,0 +1,18 @@ +var encode = module.exports = function (xs) { + function bytes (s) { + if (typeof s === 'string') { + return s.split('').map(ord); + } + else if (Array.isArray(s)) { + return s.reduce(function (acc, c) { + return acc.concat(bytes(c)); + }, []); + } + } + + return new Buffer([ 0x1b ].concat(bytes(xs))); +}; + +var ord = encode.ord = function ord (c) { + return c.charCodeAt(0) +}; 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 new file mode 100644 index 0000000..33f56af --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/charm/package.json @@ -0,0 +1,38 @@ +{ + "name": "charm", + "version": "0.0.8", + "description": "ansi control sequences for terminal cursor hopping and colors", + "main": "index.js", + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-charm.git" + }, + "keywords": [ + "terminal", + "ansi", + "cursor", + "color", + "console", + "control", + "escape", + "sequence" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/.travis.yml new file mode 100644 index 0000000..2d26206 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/difflet/node_modules/traverse/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/README.markdown new file mode 100644 index 0000000..275667b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/README.markdown @@ -0,0 +1,258 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse) + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +scrub circular references +------------------------- + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +methods +======= + +Each method that takes an `fn` uses the context documented below in the context +section. + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +.get(path) +---------- + +Get the element at the array `path`. + +.set(path, value) +----------------- + +Set the element at the array `path` to `value`. + +.has(path) +---------- + +Return whether the element at the array `path` exists. + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value, stopHere=false) +---------------------------------- + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +this.remove(stopHere=false) +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete(stopHere=false) +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + + +install +======= + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +test +==== + +Using [expresso](http://github.com/visionmedia/expresso) do: + + $ expresso + + 100% wahoo, your stuff is not broken! + +in the browser +============== + +Use [browserify](https://github.com/substack/node-browserify) to run traverse in +the browser. + +traverse has been tested and works with: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/json.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..50d612e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/leaves.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..c1b310b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/negative.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..78608a0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/scrub.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..5d15b91 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/stringify.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..167b68b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/fail.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/fail.js new file mode 100644 index 0000000..3d75f8d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/fail.js @@ -0,0 +1,9 @@ +tr = require("traverse") +obj = {"a": "[false]", "b": "[]", c: "[\"a string\"]"} +o = JSON.parse(JSON.stringify(obj)) +tr(o).forEach(function(e){ + if (this.isLeaf) { + //if (e === "[false]"){ this.update(false) } + if (e === "[]") { this.update([]); } + } +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/index.js new file mode 100644 index 0000000..d5de238 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/index.js @@ -0,0 +1,310 @@ +var traverse = module.exports = function (obj) { + return new Traverse(obj); +}; + +function Traverse (obj) { + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.has = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + return false; + } + node = node[key]; + } + return true; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(objectKeys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + function updateState() { + if (typeof state.node === 'object' && state.node !== null) { + if (!state.keys || state.node_ !== state.node) { + state.keys = objectKeys(state.node) + } + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + state.keys = null; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + } + + updateState(); + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + updateState(); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (isArray(src)) { + dst = []; + } + else if (isDate(src)) { + dst = new Date(src); + } + else if (isRegExp(src)) { + dst = new RegExp(src); + } + else if (isError(src)) { + dst = { message: src.message }; + } + else if (isBoolean(src)) { + dst = new Boolean(src); + } + else if (isNumber(src)) { + dst = new Number(src); + } + else if (isString(src)) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.constructor === Object) { + dst = {}; + } + else { + var proto = + (src.constructor && src.constructor.prototype) + || src.__proto__ + || {} + ; + var T = function () {}; + T.prototype = proto; + dst = new T; + } + + forEach(objectKeys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var objectKeys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +function toS (obj) { return Object.prototype.toString.call(obj) } +function isDate (obj) { return toS(obj) === '[object Date]' } +function isRegExp (obj) { return toS(obj) === '[object RegExp]' } +function isError (obj) { return toS(obj) === '[object Error]' } +function isBoolean (obj) { return toS(obj) === '[object Boolean]' } +function isNumber (obj) { return toS(obj) === '[object Number]' } +function isString (obj) { return toS(obj) === '[object String]' } + +var isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(objectKeys(Traverse.prototype), function (key) { + traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = new Traverse(obj); + return t[key].apply(t, args); + }; +}); 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 new file mode 100644 index 0000000..def7eb2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/package.json @@ -0,0 +1,45 @@ +{ + "name": "traverse", + "version": "0.6.3", + "description": "traverse and transform objects by visiting every node on a recursive walk", + "main": "index.js", + "bin": {}, + "directories": { + "example": "example", + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.2.5" + }, + "scripts": { + "test": "tap test/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/substack/js-traverse.git" + }, + "homepage": "https://github.com/substack/js-traverse", + "keywords": [ + "traverse", + "walk", + "recursive", + "map", + "forEach", + "deep", + "clone" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT", + "engine": { + "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/node_modules/traverse/test/circular.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..10e32f0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/circular.js @@ -0,0 +1,117 @@ +var test = require('tap').test; +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +test('circular', function (t) { + t.plan(1); + + var obj = { x : 3 }; + obj.y = obj; + traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + t.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + } + }); +}); + +test('deepCirc', function (t) { + t.plan(2); + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + traverse(obj).forEach(function (x) { + if (this.circular) { + t.same(this.circular.path, []); + t.same(this.path, [ 'y', 2 ]); + } + }); +}); + +test('doubleCirc', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + t.same(circs[0].self.path, [ 'x', 3, 2 ]); + t.same(circs[0].circ.path, []); + + t.same(circs[1].self.path, [ 'y', 2 ]); + t.same(circs[1].circ.path, []); + + t.same(circs.length, 2); + t.end(); +}); + +test('circDubForEach', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); + t.end(); +}); + +test('circDubMap', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); + t.end(); +}); + +test('circClone', function (t) { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = traverse.clone(obj); + t.ok(obj !== clone); + + t.ok(clone.y[2] === clone); + t.ok(clone.y[2] !== obj); + t.ok(clone.x[3][2] === clone); + t.ok(clone.x[3][2] !== obj); + t.same(clone.x.slice(0,3), [1,2,3]); + t.same(clone.y.slice(0,2), [4,5]); + t.end(); +}); + +test('circMapScrub', function (t) { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + t.same( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + t.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + t.equal(obj.c, obj); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/date.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/date.js new file mode 100644 index 0000000..6feb13f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/date.js @@ -0,0 +1,37 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('dateEach', function (t) { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + t.same(counts, { + object : 1, + Date : 1, + number : 2, + }); + t.end(); +}); + +test('dateMap', function (t) { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + t.ok(obj.x !== res.x); + t.same(res, { + x : obj.x, + y : 110, + z : 105, + }); + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/equal.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..169b696 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/equal.js @@ -0,0 +1,240 @@ +var test = require('tap').test; +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('deepDates', function (t) { + t.plan(2); + + t.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + t.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}); + +test('deepCircular', function (t) { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + t.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + t.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + t.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); + + t.end(); +}); + +test('deepInstances', function (t) { + t.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + t.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + t.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + t.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + t.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + t.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + t.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); + + t.end(); +}); + +test('deepEqual', function (t) { + t.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); + t.end(); +}); + +test('falsy', function (t) { + t.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + t.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + t.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + t.end(); +}); + +test('deletedArrayEqual', function (t) { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + t.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + t.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + t.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); + + t.end(); +}); + +test('deletedObjectEqual', function (t) { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + t.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + t.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + t.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); + + t.end(); +}); + +test('emptyKeyEqual', function (t) { + t.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); + + t.end(); +}); + +test('deepArguments', function (t) { + t.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + t.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); + + t.end(); +}); + +test('deepUn', function (t) { + t.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + t.ok(!deepEqual({ a : 1, b : 2 }, {})); + t.ok(!deepEqual(undefined, { a : 1, b : 2 })); + t.ok(!deepEqual({}, { a : 1, b : 2 })); + t.ok(deepEqual(undefined, undefined)); + t.ok(deepEqual(null, null)); + t.ok(!deepEqual(undefined, null)); + + t.end(); +}); + +test('deepLevels', function (t) { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + t.ok(!deepEqual(xs, [])); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/error.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/error.js new file mode 100644 index 0000000..6d3b44a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/error.js @@ -0,0 +1,11 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('traverse an Error', function (t) { + var obj = new Error("test"); + var results = traverse(obj).map(function (node) {}); + t.same(results, { message: 'test' }); + + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/has.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/has.js new file mode 100644 index 0000000..cc1a2e7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/has.js @@ -0,0 +1,15 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('has', function (t) { + var obj = { a : 2, b : [ 4, 5, { c : 6 } ] }; + + t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true) + t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false) + t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false) + t.equal(traverse(obj).has([]), true) + t.equal(traverse(obj).has([ 'a' ]), true) + t.equal(traverse(obj).has([ 'a', 2 ]), false) + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/instance.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..165bc71 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var test = require('tap').test; +var traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +test('check instanceof on node elems', function (t) { + var counts = { emitter : 0 }; + + traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + t.equal(counts.emitter, 2); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/interface.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..7a7fda2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/interface.js @@ -0,0 +1,43 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('interface map', function (t) { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + t.same( + traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + t.same( + traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + t.same( + traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + traverse.forEach(obj, function (node) { nodes ++ }); + t.same(nodes, 8); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/json.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/json.js new file mode 100644 index 0000000..2ab3ac4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/json.js @@ -0,0 +1,49 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('json test', function (t) { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + t.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + t.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + t.same(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + t.same( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + t.same( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + t.same(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); + + t.end(); +}); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/keys.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..b36bcbb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/keys.js @@ -0,0 +1,31 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('sort test', function (t) { + var acc = []; + traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + t.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/leaves.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..71e4529 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/leaves.js @@ -0,0 +1,22 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('leaves test', function (t) { + var acc = []; + traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + t.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/lib/deep_equal.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..c75b04c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,96 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (toS(y) === '[object RegExp]' + || toS(x) === '[object RegExp]') { + if (!x || !y || x.toString() !== y.toString()) notEqual(); + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/mutability.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..30761a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/mutability.js @@ -0,0 +1,300 @@ +var test = require('tap').test; +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('mutate', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('mutateT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('map', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('mapT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); + +test('clone', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).clone(); + t.same(obj, res); + t.ok(obj !== res); + obj.a ++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [ 3, 4 ]); + t.end(); +}); + +test('cloneT', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse.clone(obj); + t.same(obj, res); + t.ok(obj !== res); + obj.a ++; + t.same(res.a, 1); + obj.c.push(5); + t.same(res.c, [ 3, 4 ]); + t.end(); +}); + +test('reduce', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, [ 1, 2, 3, 4 ]); + t.end(); +}); + +test('reduceInit', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, obj); + t.end(); +}); + +test('remove', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a : 1, c : [ 3 ] }); + t.end(); +}); + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) + t.end(); +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'f']) + t.end(); +} + +test('removeMap', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + t.same(res, { a : 1, c : [ 3 ] }); + t.end(); +}); + +test('delete', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + t.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); + t.end(); +}); + +test('deleteNoStop', function (t) { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) + t.end(); +}); + +test('deleteStop', function (t) { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + t.same(keys, [undefined, 'a', 'b', 'c']) + t.end(); +}); + +test('deleteRedux', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + t.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + t.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); + + t.end(); +}); + +test('deleteMap', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + t.ok(deepEqual( + res, { a : 1, c : xs } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); + + t.end(); +}); + +test('deleteMapRedux', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + t.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + t.ok(deepEqual( + res, { a : 1, c : xs } + )); + + t.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + t.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); + + t.end(); +}); + +test('objectToString', function (t) { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'object' && !this.isRoot) { + this.update(JSON.stringify(x)); + } + }); + t.same(obj, res); + t.same(obj, { a : 1, b : 2, c : "[3,4]" }); + t.end(); +}); + +test('stringToObject', function (t) { + var obj = { a : 1, b : 2, c : "[3,4]" }; + var res = traverse(obj).forEach(function (x) { + if (typeof x === 'string') { + this.update(JSON.parse(x)); + } + else if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + t.deepEqual(obj, res); + t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/negative.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..fdd1cc5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/negative.js @@ -0,0 +1,21 @@ +var traverse = require('../'); +var test = require('tap').test; + +test('negative update test', function (t) { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + t.same(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + t.same(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/obj.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..7f0cb70 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/obj.js @@ -0,0 +1,11 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('traverse an object with nested functions', function (t) { + t.plan(1); + + function Cons (x) { + t.equal(x, 10) + }; + traverse(new Cons(10)); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/siblings.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..cdfbd7d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/siblings.js @@ -0,0 +1,37 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('siblings', function (t) { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + t.same(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } + }); + + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stop.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..ecf38e4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stop.js @@ -0,0 +1,44 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('stop', function (t) { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + t.equal(visits, 5); + t.end(); +}); + +test('stopMap', function (t) { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + t.equal(s, 'ABCDEfghij'); + t.end(); +}); + +test('stopReduce', function (t) { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + t.same(xs, [ 4, 5, 6 ]); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stringify.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..862598d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var test = require('tap').test; +var traverse = require('../'); + +test('stringify', function (t) { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + t.equal(s, JSON.stringify(obj)); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/subexpr.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..c372bf3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/subexpr.js @@ -0,0 +1,36 @@ +var traverse = require('../'); +var test = require('tap').test; + +test('subexpr', function (t) { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + t.same(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); + t.end(); +}); + +test('block', function (t) { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + t.same(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/super_deep.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..088f890 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/test/super_deep.js @@ -0,0 +1,56 @@ +var test = require('tap').test; +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +test('super_deep', function (t) { + var util = require('util'); + var a0 = make(); + var a1 = make(); + t.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + t.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + t.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //t.ok(!deepEqual(a0, a1)); + t.end(); +}); + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/testling/leaves.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/testling/leaves.js new file mode 100644 index 0000000..29968dd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/node_modules/traverse/testling/leaves.js @@ -0,0 +1,22 @@ +var traverse = require('./'); +var test = require('testling'); + +test('leaves', function (t) { + var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }; + + var acc = []; + traverse(obj).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + t.deepEqual( + acc, [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], + 'traversal in the proper order' + ); + t.end(); +}); 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 new file mode 100644 index 0000000..2aff0bc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/package.json @@ -0,0 +1,45 @@ +{ + "name": "difflet", + "description": "colorful diffs for javascript objects", + "version": "0.2.3", + "repository": { + "type": "git", + "url": "git://github.com/substack/difflet.git" + }, + "main": "index.js", + "keywords": [ + "diff", + "object", + "compare" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "traverse": "0.6.x", + "charm": "0.0.x", + "deep-equal": "0.0.x" + }, + "devDependencies": { + "tap": "0.1.x", + "ent": "0.0.x" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "MIT", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "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", + "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/test/html.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/test/html.js new file mode 100644 index 0000000..26d2ed4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/difflet/test/html.js @@ -0,0 +1,80 @@ +var difflet = require('../'); +var test = require('tap').test; +var ent = require('ent'); + +var tags = { + inserted : 'g', + updated : 'b', + deleted : 'r', +}; + +test('html output', function (t) { + t.plan(1); + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var stream = diff( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + var data = '' + stream.on('data', function (buf) { data += buf }); + stream.on('end', function () { + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); + }); +}); + +test('compare html output', function (t) { + t.plan(1); + + var diff = difflet({ + start : function (t, s) { + s.write('<' + tags[t] + '>'); + }, + stop : function (t, s) { + s.write(''); + }, + write : function (buf, s) { + s.write(ent.encode(buf)); + } + }); + + var data = diff.compare( + { yy : 6, zz : 5, a : [1,2,3], fn : function qqq () {} }, + { + a : [ 1, 2, 3, [4], "z", /beep/, new Buffer([0,1,2]) ], + fn : function rrr () {}, + b : [5,6,7] + } + ); + + t.equal(data, + '{"a":[1,2,3,[4],"z",' + + '/beep/,<Buffer 00 01 02>],' + + '"fn":[Function: rrr],' + + '"b":[5,6,7],"yy":6,' + + '"zz":5}' + ); + t.end(); +}); 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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/README.md new file mode 100644 index 0000000..b2beaed --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/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/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/inherits.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/inherits.js new file mode 100644 index 0000000..061b396 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/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/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 new file mode 100644 index 0000000..487b6fa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/inherits/package.json @@ -0,0 +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" : "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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/.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/nodeunit/node_modules/tap/node_modules/mkdirp/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..40de04f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/README.markdown @@ -0,0 +1,61 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/examples/pow.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; 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 new file mode 100644 index 0000000..f79c6a5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/package.json @@ -0,0 +1,33 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.4", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.2.4" + }, + "license": "MIT/X11", + "engines": { + "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/mkdirp/test/chmod.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/clobber.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/mkdirp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm_sync.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/race.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/rel.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return_sync.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/root.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/sync.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask_sync.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/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/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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/README.md new file mode 100644 index 0000000..f290da8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/bin/nopt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000..df90c72 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/examples/my-program.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/lib/nopt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..5763860 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/lib/nopt.js @@ -0,0 +1,555 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} 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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. 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 new file mode 100644 index 0000000..bee4132 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,111 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") +var util = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} 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 new file mode 100644 index 0000000..3056f1e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,25 @@ +{ + "name": "abbrev", + "version": "1.0.4", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "readmeFilename": "README.md", + "_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 new file mode 100644 index 0000000..2291a81 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/nopt/package.json @@ -0,0 +1,32 @@ +{ + "name": "nopt", + "version": "2.0.0", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", + "readmeFilename": "README.md", + "_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/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/README.markdown new file mode 100644 index 0000000..1e56ebd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/README.markdown @@ -0,0 +1,56 @@ +runforcover +====== + +Runforcover is a require-hook library that uses node-bunker to provide code coverage data +for your unit test library, whatever it might be. + +methods +======= +var runforcover = require('runforcover'); + +var coverage = runforcover.cover([RegExp | path]); +------- + +Attach runforcover to the global `require` object and patch `require.extensions['.js']` to +provide coverage metadata for all files required after this point. Returns a function +object that can be called to obtain a object keying files to `CoverageData` objects, with +a method for releasing control back to vanilla `require`. Usage: + +````javascript + +var coverage = runforcover.cover(/.*/g); + +require('some/library'); + +coverage(function(coverageData) { + // coverageData is an object keyed by filename. + var stats = coverageData['/full/path/to/file.js'].stats() + + // the percentage of lines run versus total lines in file + console.log(stats.percentage); + + // the number of missing lines + console.log(stats.missing); + + // the number of lines run (seen) + console.log(stats.seen); + + // an array of line objects representing 'missed' lines + stats.lines; + + stats.lines.forEach(function(line) { + // the line number of the line: + console.log(line.number); + + // returns a string containing the source data for the line: + console.log(line.source()); + }); + + // return control back to the original require function + coverage.release(); +}); +```` + +license +======= +new BSD. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/index.js new file mode 100644 index 0000000..b5318ac --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/index.js @@ -0,0 +1,127 @@ +var bunker = require('bunker'), + Module = require('module').Module, + path = require('path'), + fs = require('fs'), + vm = require('vm'); + +function CoverageData (filename, bunker) { + this.bunker = bunker; + this.filename = filename; + this.nodes = {}; +}; + +CoverageData.prototype.visit = function(node) { + ++(this.nodes[node.id] = this.nodes[node.id] || {node:node, count:0}).count; +}; + +CoverageData.prototype.missing = function() { + var nodes = this.nodes, + missing = this.bunker.nodes.filter(function(node) { + return !nodes[node.id]; + }); + + return missing; +}; + +CoverageData.prototype.stats = function() { + var missing = this.missing(), + filedata = fs.readFileSync(this.filename, 'utf8').split('\n'); + + var seenLines = [], + lines = + missing.sort(function(lhs, rhs) { + return lhs.node[0].start.line < rhs.node[0].start.line ? -1 : + lhs.node[0].start.line > rhs.node[0].start.line ? 1 : + 0; + }).filter(function(node) { + + var okay = (seenLines.indexOf(node.node[0].start.line) < 0); + if(okay) + seenLines.push(node.node[0].start.line); + return okay; + + }).map(function(node, idx, all) { + return { + lineno:node.node[0].start.line + 1, + source:function() { return filedata[node.node[0].start.line]; } + }; + }); + + return { + percentage:(filedata.length-seenLines.length)/filedata.length, + lines:lines, + missing:seenLines.length, + seen:(filedata.length-seenLines.length) + }; +}; + +module.exports.createEnvironment = function(module, filename) { + var req = function(path) { + return Module._load(path, module); + }; + req.resolve = function(request) { + return Module._resolveFilename(request, module)[1]; + } + req.paths = Module._paths; + req.main = process.mainModule; + req.extensions = Module._extensions; + req.registerExtension = function() { + throw new Error('require.registerExtension() removed. Use ' + + 'require.extensions instead.'); + } + require.cache = Module._cache; + + var ctxt = {}; + for(var k in global) + ctxt[k] = global[k]; + + ctxt.require = req; + ctxt.exports = module.exports; + ctxt.__filename = filename; + ctxt.__dirname = path.dirname(filename); + ctxt.process = process; + ctxt.console = console; + ctxt.module = module; + ctxt.global = ctxt; + + return ctxt; +}; + +module.exports.cover = function(fileRegex) { + var originalRequire = require.extensions['.js'], + coverageData = {}, + match = fileRegex instanceof RegExp ? + fileRegex : new RegExp( + fileRegex ? fileRegex.replace(/\//g, '\\/').replace(/\./g, '\\.') : '.*' + , 'g'), + target = this; + + require.extensions['.js'] = function(module, filename) { + if(!match.test(filename)) return originalRequire(module, filename); + + var context = target.createEnvironment(module, filename), + data = fs.readFileSync(filename, 'utf8'), + bunkerized = bunker(data), + coverage = coverageData[filename] = new CoverageData(filename, bunkerized); + + bunkerized.on('node', coverage.visit.bind(coverage)); + bunkerized.assign(context); + + var wrapper = '(function(ctxt) { with(ctxt) { return '+Module.wrap(bunkerized.compile())+'; } })', + compiledWrapper = vm.runInThisContext(wrapper, filename, true)(context); + + var args = [context.exports, context.require, module, filename, context.__dirname]; + return compiledWrapper.apply(module.exports, args); + }; + + var retval = function(ready) { + ready(coverageData); + }; + + retval.release = function() { + require.extensions['.js'] = originalRequire; + }; + + return retval; +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/.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/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/README.markdown new file mode 100644 index 0000000..0d0c387 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/README.markdown @@ -0,0 +1,82 @@ +bunker +====== + +Bunker is a module to calculate code coverage using native javascript +[burrito](https://github.com/substack/node-burrito) AST trickery. + +[![build status](https://secure.travis-ci.org/substack/node-bunker.png)](http://travis-ci.org/substack/node-bunker) + +![code coverage](http://substack.net/images/code_coverage.png) + +examples +======== + +tiny +---- + +````javascript +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); +```` + +output: + + $ node example/tiny.js + 1 : var x=0; + 31 : i<30 + 30 : i++ + 30 : x++; + 30 : x++ + +methods +======= + +var bunker = require('bunker'); + +var b = bunker(src) +------------------- + +Create a new bunker code coverageifier with some source `src`. + +The bunker object `b` is an `EventEmitter` that emits `'node'` events with two +parameters: + +* `node` - the [burrito](https://github.com/substack/node-burrito) node object +* `stack` - the stack, [stackedy](https://github.com/substack/node-stackedy) style + +b.include(src) +-------------- + +Include some source into the bunker. + +b.compile() +----------- + +Return the source wrapped with burrito. + +b.assign(context={}) +-------------------- + +Assign the statement-tracking functions into `context`. + +b.run(context={}) +----------------- + +Run the source using `vm.runInNewContext()` with some `context`. +The statement-tracking functions will be added to `context` by `assign()`. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/prof.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/prof.js new file mode 100644 index 0000000..5cac4cc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/prof.js @@ -0,0 +1,51 @@ +var bunker = require('bunker'); +var b = bunker('(' + function () { + function beep () { + var x = 0; + for (var i = 0; i < 1000; i++) { + for (var j = 0; j < 100; j++) { + x += j; + } + } + return x; + } + + beep(); + +} + ')()'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node, elapsed : 0 }; + } + counts[node.id].times ++; + + var now = Date.now(); + + if (last.id !== undefined) { + counts[last.id].elapsed += last. + } + + if (node.name === 'call') { + var start = now; + + last.id = node.id; + counts[node.id].elapsed += Date.now() - start; + } + else { + counts[node.id].elapsed += now - last; + last = now; + } +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log( + [ count.times, count.node.source(), count.elapsed ] + .join(' : ') + ); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/tiny.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/tiny.js new file mode 100644 index 0000000..aa5b034 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/tiny.js @@ -0,0 +1,18 @@ +var bunker = require('bunker'); +var b = bunker('var x = 0; for (var i = 0; i < 30; i++) { x++ }'); + +var counts = {}; + +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run(); + +Object.keys(counts).forEach(function (key) { + var count = counts[key]; + console.log(count.times + ' : ' + count.node.source()); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/run.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/run.js new file mode 100644 index 0000000..d9eaa10 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/run.js @@ -0,0 +1,31 @@ +var bunker = require('bunker'); +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/src.js', 'utf8'); + +var counts = {}; + +var b = bunker(src); +b.on('node', function (node) { + if (!counts[node.id]) { + counts[node.id] = { times : 0, node : node }; + } + counts[node.id].times ++; +}); + +b.run({ + setInterval : setInterval, + clearInterval : clearInterval, + end : function () { + Object.keys(counts) + .sort(function (a, b) { + return counts[b].times - counts[a].times + }) + .forEach(function (key) { + var count = counts[key]; + console.log( + count.times + ' : ' + count.node.source() + ); + }) + ; + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/src.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/src.js new file mode 100644 index 0000000..0c92e48 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/example/top/src.js @@ -0,0 +1,18 @@ +function boop () { + for (var i = 0; i < 30; i++) { + nop(); + } +} + +function nop () { + return undefined; +} + +var times = 0; +var iv = setInterval(function () { + if (++times === 10) { + clearInterval(iv); + end(); + } + else boop() +}, 100); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/index.js new file mode 100644 index 0000000..ed5d437 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/index.js @@ -0,0 +1,116 @@ +var burrito = require('burrito'); +var vm = require('vm'); +var EventEmitter = require('events').EventEmitter; + +module.exports = function (src) { + var b = new Bunker(); + if (src) b.include(src); + return b; +}; + +function Bunker () { + this.sources = []; + this.nodes = []; + + this.names = { + call : burrito.generateName(6), + expr : burrito.generateName(6), + stat : burrito.generateName(6), + return : burrito.generateName(6) + }; +} + +Bunker.prototype = new EventEmitter; + +Bunker.prototype.include = function (src) { + this.sources.push(src); + this.source = null; + return this; +}; + +Bunker.prototype.compile = function () { + var src = this.sources.join('\n'); + var nodes = this.nodes; + var names = this.names; + + return burrito(src, function (node) { + var i = nodes.length; + + if (node.name === 'call') { + nodes.push(node); + node.wrap(names.call + '(' + i + ')(%s)'); + } + else if (node.name === 'stat' || node.name === 'throw' + || node.name === 'var') { + nodes.push(node); + node.wrap('{' + names.stat + '(' + i + ');%s}'); + } + else if (node.name === 'return') { + nodes.push(node); + // We need to wrap the new source in a function definition + // so that UglifyJS will allow the presence of return + var stat = names.stat + '(' + i + ');'; + var wrapped = 'function ' + names.return + '() {' + + stat + node.source() + +'}' + ; + var parsed = burrito.parse(wrapped); + // Remove the function definition from the AST + parsed[1] = parsed[1][0][3]; + node.state.update(parsed, true); + } + else if (node.name === 'binary') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + else if (node.name === 'unary-postfix' || node.name === 'unary-prefix') { + nodes.push(node); + node.wrap(names.expr + '(' + i + ')(%s)'); + } + + if (i !== nodes.length) { + node.id = i; + } + }); +}; + +Bunker.prototype.assign = function (context) { + if (!context) context = {}; + + var self = this; + var stack = []; + + context[self.names.call] = function (i) { + var node = self.nodes[i]; + stack.unshift(node); + self.emit('node', node, stack); + + return function (expr) { + stack.shift(); + return expr; + }; + }; + + context[self.names.expr] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + + return function (expr) { + return expr; + }; + }; + + context[self.names.stat] = function (i) { + var node = self.nodes[i]; + self.emit('node', node, stack); + }; + + return context; +}; + +Bunker.prototype.run = function (context) { + var src = this.compile(); + vm.runInNewContext(src, this.assign(context)); + + return this; +}; 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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/.npmignore @@ -0,0 +1 @@ +node_modules 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/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/.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/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/README.markdown new file mode 100644 index 0000000..7c9097c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/README.markdown @@ -0,0 +1,187 @@ +burrito +======= + +Burrito makes it easy to do crazy stuff with the javascript AST. + +This is super useful if you want to roll your own stack traces or build a code +coverage tool. + +[![build status](https://secure.travis-ci.org/substack/node-burrito.png)](http://travis-ci.org/substack/node-burrito) + +![node.wrap("burrito")](http://substack.net/images/burrito.png) + +examples +======== + +microwave +--------- + +examples/microwave.js + +````javascript +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 1 +```` + +output: + + 1 + +wrap +---- + +examples/wrap.js + +````javascript +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); +```` + +output: + + qqq(f()) && qqq(g(qqq(h()))); + + qqq(foo()); + +methods +======= + + var burrito = require('burrito'); + +burrito(code, cb) +----------------- + +Given some source `code` and a function `trace`, walk the ast by expression. + +The `cb` gets called with a node object described below. + +If `code` is an Array then it is assumbed to be an AST which you can generate +yourself with `burrito.parse()`. The AST must be annotated, so make sure to +`burrito.parse(src, false, true)`. + +burrito.microwave(code, context={}, cb) +--------------------------------------- + +Like `burrito()` except the result is run using +`vm.runInNewContext(res, context)`. + +node object +=========== + +node.name +--------- + +Name is a string that contains the type of the expression as named by uglify. + +node.wrap(s) +------------ + +Wrap the current expression in `s`. + +If `s` is a string, `"%s"` will be replaced with the stringified current +expression. + +If `s` is a function, it is called with the stringified current expression and +should return a new stringified expression. + +If the `node.name === "binary"`, you get the subterms "%a" and "%b" to play with +too. These subterms are applied if `s` is a function too: `s(expr, a, b)`. + +Protip: to insert multiple statements you can use javascript's lesser-known block +syntax that it gets from C: + +````javascript +if (node.name === 'stat') node.wrap('{ foo(); %s }') +```` + +node.node +--------- + +raw ast data generated by uglify + +node.value +---------- + +`node.node.slice(1)` to skip the annotations + +node.start +---------- + +The start location of the expression, like this: + +````javascript +{ type: 'name', + value: 'b', + line: 0, + col: 3, + pos: 3, + nlb: false, + comments_before: [] } +```` + +node.end +-------- + +The end location of the expression, formatted the same as `node.start`. + +node.state +---------- + +The state of the traversal using traverse. + +node.source() +------------- + +Returns a stringified version of the expression. + +node.parent() +------------- + +Returns the parent `node` or `null` if the node is the root element. + +node.label() +------------ + +Return the label of the present node or `null` if there is no label. + +Labels are returned for "call", "var", "defun", and "function" nodes. + +Returns an array for "var" nodes since `var` statements can +contain multiple labels in assignment. + +install +======= + +With [npm](http://npmjs.org) you can just: + + npm install burrito + +in the browser +============== + +Burrito works in browser with +[browserify](https://github.com/substack/node-browserify). + +It has been tested against: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 + +kudos +===== + +Heavily inspired by (and previously mostly lifted outright from) isaacs's nifty +tmp/instrument.js thingy from uglify-js. 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/example/microwave.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/microwave.js new file mode 100644 index 0000000..c6fcf45 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/microwave.js @@ -0,0 +1,8 @@ +var burrito = require('burrito'); + +var res = burrito.microwave('Math.sin(2)', function (node) { + console.dir(node); + if (node.name === 'num') node.wrap('Math.PI / %s'); +}); + +console.log(res); // sin(pi / 2) == 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/example/web/bs.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/bs.js new file mode 100644 index 0000000..3583c7f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/bs.js @@ -0,0 +1,4832 @@ +var require = function (file, cwd) { + var resolved = require.resolve(file, cwd || '/'); + var mod = require.modules[resolved]; + if (!mod) throw new Error( + 'Failed to resolve module ' + file + ', tried ' + resolved + ); + var res = mod._cached ? mod._cached : mod(); + return res; +} +var __require = require; + +require.paths = []; +require.modules = {}; +require.extensions = [".js",".coffee"]; + +require.resolve = (function () { + var core = { + 'assert': true, + 'events': true, + 'fs': true, + 'path': true, + 'vm': true + }; + + return function (x, cwd) { + if (!cwd) cwd = '/'; + + if (core[x]) return x; + var path = require.modules.path(); + var y = cwd || '.'; + + if (x.match(/^(?:\.\.?\/|\/)/)) { + var m = loadAsFileSync(path.resolve(y, x)) + || loadAsDirectorySync(path.resolve(y, x)); + if (m) return m; + } + + var n = loadNodeModulesSync(x, y); + if (n) return n; + + throw new Error("Cannot find module '" + x + "'"); + + function loadAsFileSync (x) { + if (require.modules[x]) { + return x; + } + + for (var i = 0; i < require.extensions.length; i++) { + var ext = require.extensions[i]; + if (require.modules[x + ext]) return x + ext; + } + } + + function loadAsDirectorySync (x) { + x = x.replace(/\/+$/, ''); + var pkgfile = x + '/package.json'; + if (require.modules[pkgfile]) { + var pkg = require.modules[pkgfile](); + var b = pkg.browserify; + if (typeof b === 'object' && b.main) { + var m = loadAsFileSync(path.resolve(x, b.main)); + if (m) return m; + } + else if (typeof b === 'string') { + var m = loadAsFileSync(path.resolve(x, b)); + if (m) return m; + } + else if (pkg.main) { + var m = loadAsFileSync(path.resolve(x, pkg.main)); + if (m) return m; + } + } + + return loadAsFileSync(x + '/index'); + } + + function loadNodeModulesSync (x, start) { + var dirs = nodeModulesPathsSync(start); + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var m = loadAsFileSync(dir + '/' + x); + if (m) return m; + var n = loadAsDirectorySync(dir + '/' + x); + if (n) return n; + } + + var m = loadAsFileSync(x); + if (m) return m; + } + + function nodeModulesPathsSync (start) { + var parts; + if (start === '/') parts = [ '' ]; + else parts = path.normalize(start).split('/'); + + var dirs = []; + for (var i = parts.length - 1; i >= 0; i--) { + if (parts[i] === 'node_modules') continue; + var dir = parts.slice(0, i + 1).join('/') + '/node_modules'; + dirs.push(dir); + } + + return dirs; + } + }; +})(); + +require.alias = function (from, to) { + var path = require.modules.path(); + var res = null; + try { + res = require.resolve(from + '/package.json', '/'); + } + catch (err) { + res = require.resolve(from, '/'); + } + var basedir = path.dirname(res); + + var keys = Object_keys(require.modules); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (key.slice(0, basedir.length + 1) === basedir + '/') { + var f = key.slice(basedir.length); + require.modules[to + f] = require.modules[basedir + f]; + } + else if (key === basedir) { + require.modules[to] = require.modules[basedir]; + } + } +}; + +var Object_keys = Object.keys || function (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +if (typeof process === 'undefined') process = {}; + +if (!process.nextTick) process.nextTick = function (fn) { + setTimeout(fn, 0); +}; + +if (!process.title) process.title = 'browser'; + +if (!process.binding) process.binding = function (name) { + if (name === 'evals') return require('vm') + else throw new Error('No such module') +}; + +if (!process.cwd) process.cwd = function () { return '.' }; + +require.modules["path"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "path"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["path"]._cached = module.exports; + + (function () { + function filter (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length; i >= 0; i--) { + var last = parts[i]; + if (last == '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Regex to split a filename into [*, dir, basename, ext] +// posix version +var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { +var resolvedPath = '', + resolvedAbsolute = false; + +for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) + ? arguments[i] + : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string' || !path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; +} + +// At this point the path should be resolved to a full absolute path, but +// handle relative paths to be safe (might happen when process.cwd() fails) + +// Normalize the path +resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { +var isAbsolute = path.charAt(0) === '/', + trailingSlash = path.slice(-1) === '/'; + +// Normalize the path +path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + return p && typeof p === 'string'; + }).join('/')); +}; + + +exports.dirname = function(path) { + var dir = splitPathRe.exec(path)[1] || ''; + var isWindows = false; + if (!dir) { + // No dirname + return '.'; + } else if (dir.length === 1 || + (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) { + // It is just a slash or a drive letter with a slash + return dir; + } else { + // It is a full dirname, strip trailing slash + return dir.substring(0, dir.length - 1); + } +}; + + +exports.basename = function(path, ext) { + var f = splitPathRe.exec(path)[2] || ''; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPathRe.exec(path)[3] || ''; +}; +; + }).call(module.exports); + + __require.modules["path"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"burrito","description":"Wrap up expressions with a trace function while walking the AST with rice and beans on the side","version":"0.2.8","repository":{"type":"git","url":"git://github.com/substack/node-burrito.git"},"main":"./index.js","keywords":["trace","ast","walk","syntax","source","tree","uglify"],"directories":{"lib":".","example":"example","test":"test"},"scripts":{"test":"expresso"},"dependencies":{"traverse":">=0.5.1 <0.6","uglify-js":"1.0.4"},"devDependencies":{"expresso":"=0.7.x"},"engines":{"node":">=0.4.0"},"license":"BSD","author":{"name":"James Halliday","email":"mail@substack.net","url":"http://substack.net"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"uglify-js","author":{"name":"Mihai Bazon","email":"mihai.bazon@gmail.com","url":"http://mihai.bazon.net/blog"},"version":"1.0.4","main":"./uglify-js.js","bin":{"uglifyjs":"./bin/uglifyjs"},"repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/uglify-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + + (function () { + //convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); + +module.exports = uglify; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/uglify-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file contains the tokenizer/parser. It is a port to JavaScript + of parse-js [1], a JavaScript parser library written in Common Lisp + by Marijn Haverbeke. Thank you Marijn! + + [1] http://marijn.haverbeke.nl/parse-js/ + + Exported functions: + + - tokenizer(code) -- returns a function. Call the returned + function to fetch the next token. + + - parse(code) -- returns an AST of the given JavaScript code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + Based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +/* -----[ Tokenizer (constants) ]----- */ + +var KEYWORDS = array_to_hash([ + "break", + "case", + "catch", + "const", + "continue", + "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", + "debugger", + "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" +]); + +var KEYWORDS_ATOM = array_to_hash([ + "false", + "null", + "true", + "undefined" +]); + +var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +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", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = array_to_hash(characters(" \u00a0\n\r\t\f\v\u200b")); + +var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:")); + +var PUNC_CHARS = array_to_hash(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + 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-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\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\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\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\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\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-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\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-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\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]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(ch) { + return UNICODE.letter.test(ch); +}; + +function is_digit(ch) { + ch = ch.charCodeAt(0); + return ch >= 48 && ch <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(ch) { + return is_digit(ch) || is_letter(ch); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier_start(ch) { + return ch == "$" || ch == "_" || is_letter(ch); +}; + +function is_identifier_char(ch) { + return is_identifier_start(ch) + || is_unicode_combining_mark(ch) + || is_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); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + try { + ({})(); + } catch(ex) { + this.stack = ex.stack; + }; +}; + +JS_Parse_Error.prototype.toString = function() { + 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); +}; + +function is_token(token, type, 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) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = true; + ++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, + nlb : S.newline_before + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + } + 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) + 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() { + var ch = next(true); + switch (ch) { + case "n" : return "\n"; + case "r" : return "\r"; + case "t" : return "\t"; + case "b" : return "\b"; + case "v" : return "\v"; + case "f" : return "\f"; + case "0" : return "\0"; + case "x" : return String.fromCharCode(hex_bytes(2)); + case "u" : return String.fromCharCode(hex_bytes(4)); + 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 == "\\") ch = read_escaped_char(); + 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), + tok = token("comment2", text, true); + S.pos = i + 2; + S.line += text.split("\n").length - 1; + 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 tok; + }); + }; + + function read_name() { + var backslash = false, name = "", ch; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") 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; + } + } + return name; + }; + + function read_regexp() { + return with_eof_error("Unterminated regular expression", function(){ + var prev_backslash = false, regexp = "", 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; + } + }; + 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) + return read_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", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +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; +})( + ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="], + { "=": 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; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function NodeWithToken(str, start, 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_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(); + } + 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", "/")) { + S.peeked = null; + S.token = S.input(true); // force regexp + } + switch (S.token.type) { + case "num": + case "string": + 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)); + + case "switch": + return as("switch", parenthesised(), switch_block_()); + + case "throw": + return as("throw", prog1(expression, semicolon)); + + case "try": + return try_(); + + case "var": + return prog1(var_, semicolon); + + case "const": + return prog1(const_, semicolon); + + case "while": + return as("while", parenthesised(), in_loop(statement)); + + case "with": + return as("with", parenthesised(), 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")) + 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_ = maybe_embed_tokens(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_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(); + 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()); + } + } + 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("operator") && HOP(UNARY_PREFIX, S.token.value)) { + return make_unary("unary-prefix", + prog1(S.token.value, next), + expr_atom(allow_calls)); + } + 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); + } + 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(); + } + }; + + 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); + } + if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) { + return prog1(curry(make_unary, "unary-postfix", S.token.value, expr), + next); + } + return expr; + }; + + 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(expr_atom(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(expr_atom(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; + }; + + 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; + })([])); + +}; + +/* -----[ Utilities ]----- */ + +function curry(f) { + 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; +}; + +function array_to_hash(a) { + 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 == null ? 0 : start); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + 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); +}; + +var warn = function() {}; + +/* -----[ Exports ]----- */ + +exports.tokenizer = tokenizer; +exports.parse = parse; +exports.slice = slice; +exports.curry = curry; +exports.member = member; +exports.array_to_hash = array_to_hash; +exports.PRECEDENCE = PRECEDENCE; +exports.KEYWORDS_ATOM = KEYWORDS_ATOM; +exports.RESERVED_WORDS = RESERVED_WORDS; +exports.KEYWORDS = KEYWORDS; +exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN; +exports.OPERATORS = OPERATORS; +exports.is_alphanumeric_char = is_alphanumeric_char; +exports.set_logger = function(logger) { + warn = logger; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/process.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + + (function () { + /*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + + This version is suitable for Node.js. With minimal changes (the + exports stuff) it should work on any JS platform. + + This file implements some AST processors. They work on data built + by parse-js. + + Exported functions: + + - ast_mangle(ast, options) -- mangles the variable/function names + in the AST. Returns an AST. + + - ast_squeeze(ast) -- employs various optimizations to make the + final generated code even smaller. Returns an AST. + + - gen_code(ast, options) -- generates JS code from the AST. Pass + true (or an object, see the code for some options) as second + argument to get "pretty" (indented) code. + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2010 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + ***********************************************************************/ + +var jsp = require("./parse-js"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +/* -----[ helper for AST traversal ]----- */ + +function ast_walker(ast) { + 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) ]; + }, + "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 ]; + } + }; + + 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 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, + 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.parent = parent; // parent scope + this.children = []; // sub-scopes + if (parent) { + this.level = parent.level + 1; + parent.children.push(this); + } else { + this.level = 0; + } +}; + +var base54 = (function(){ + var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"; + return function(num) { + var ret = ""; + do { + ret = DIGITS.charAt(num % 54) + ret; + num = Math.floor(num / 54); + } 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()); + }, + define: function(name) { + if (name != null) + return this.names[name] = name; + } +}; + +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); + var ret = current_scope.body = cont(); + ret.scope = current_scope; + current_scope = current_scope.parent; + return ret; + }; + + function define(name) { + return current_scope.define(name); + }; + + 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) : name, args, with_new_scope(function(){ + if (!is_defun) define(name); + MAP(args, define); + return MAP(body, walk); + })]; + }; + + return with_new_scope(function(){ + // process AST + var ret = w.with_walkers({ + "function": _lambda, + "defun": _lambda, + "with": function(expr, block) { + for (var s = current_scope; s; s = s.parent) + s.uses_with = true; + }, + "var": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "const": function(defs) { + MAP(defs, function(d){ define(d[0]) }); + }, + "try": function(t, c, f) { + if (c != null) return [ + this[0], + MAP(t, walk), + [ define(c[0]), 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; + }); + +}; + +/* -----[ mangle names ]----- */ + +function ast_mangle(ast, options) { + var w = ast_walker(), walk = w.walk, scope; + options = options || {}; + + function get_mangled(name, newMangle) { + if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel + if (options.except && member(name, options.except)) + 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) { + var is_defun = this[0] == "defun", extra; + if (name) { + if (is_defun) name = get_mangled(name); + else { + extra = {}; + name = extra[name] = scope.next_mangled(); + } + } + 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]) ]; + }) ]; + }; + + 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; + }, + "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) ]; + }); + } + }, function() { + return walk(ast_add_scope(ast)); + }); +}; + +/* -----[ + - compress foo["bar"] into foo.bar, + - 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()} + ]----- */ + +var warn = function(){}; + +function best_of(ast1, ast2) { + 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; +} + +function aborts(t) { + if (t) { + t = last_stat(t); + if (t[0] == "return" || t[0] == "break" || t[0] == "continue" || t[0] == "throw") + return true; + } +}; + +function boolean_expr(expr) { + return ( (expr[0] == "unary-prefix" + && member(expr[1], [ "!", "delete" ])) || + + (expr[0] == "binary" + && member(expr[1], [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ])) || + + (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] == "assign" + && expr[1] === true + && boolean_expr(expr[3])) || + + (expr[0] == "seq" + && boolean_expr(expr[expr.length - 1])) + ); +}; + +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 ? [ "conditional", c, t, e ] : [ "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 empty(b) { + 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]))); +}; + +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; + } + 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 "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: 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; + } + }; + +})(); + +function warn_unreachable(ast) { + 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] && walk(fi[3])) continue; + + var t = walk(fi[2]); + if (!aborts(t)) continue; + + var conditional = walk(fi[1]); + + var e_body = statements.slice(i + 1); + var e; + if (e_body.length == 1) e = e_body[0]; + else e = [ "block", e_body ]; + + var ret = statements.slice(0, i).concat([ [ + fi[0], // "if" + conditional, // conditional + t, // then + e // else + ] ]); + + return redo_if(ret); + } + + return statements; + }; + + function redo_if_lambda(name, args, body) { + body = redo_if(body); + return [ this[0], name, args.slice(), body ]; + }; + + function redo_if_block(statements) { + var out = [ this[0] ]; + if (statements != null) + out.push(redo_if(statements)); + return out; + }; + + 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 + ]; + }, + "with": function(expr, block) { + return [ this[0], walk(expr), redo_if(block) ]; + } + }, function() { + return walk(ast); + }); +}; + +function ast_squeeze(ast, options) { + options = defaults(options, { + make_seqs : true, + dead_code : true, + keep_comps : true, + no_warnings : 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 with_scope(s, cont) { + var _scope = scope; + scope = s; + var ret = cont(); + ret.scope = s; + scope = _scope; + return ret; + }; + + 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) { + var is_defun = this[0] == "defun"; + body = with_scope(body.scope, function(){ + var ret = tighten(MAP(body, walk), "lambda"); + if (!is_defun && name && !HOP(scope.refs, name)) + name = null; + return ret; + }); + return [ this[0], name, args, body ]; + }; + + // we get here for blocks that have been already transformed. + // 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 = 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 (member(st[0], [ "function", "defun" , "var", "const" ])) { + 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; + } + }); + return a; + })([]); + + 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) { + warn_unreachable(e); + return t; + } else { + warn_unreachable(t); + return e; + } + }, function() { + return make_real_if(c, t, e); + }); + }; + + function make_real_if(c, t, e) { + c = walk(c); + t = walk(t); + e = walk(e); + + 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; + } + })(); + } + if (empty(e) && empty(t)) + return [ "stat", c ]; + 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 { + 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 = [ [ "if", negate(c), e ] ]; + if (t[0] == "block") { + if (t[1]) ret = ret.concat(t[1]); + } else { + ret.push(t); + } + ret = walk([ "block", ret ]); + } + 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) ]; + } + }); + }; + + ast = prepare_ifs(ast); + ast = ast_add_scope(ast); + + 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", with_scope(this.scope, function(){ + return tighten(MAP(body, walk)); + }) ]; + }, + "switch": function(expr, body) { + var last = body.length - 1; + return [ "switch", walk(expr), MAP(body, function(branch, i){ + var block = tighten(MAP(branch[1], walk)); + 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(MAP(body, walk)) ]); + }, + "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 this; + }); + }, + "conditional": function(c, t, e) { + return make_conditional(walk(c), walk(t), walk(e)); + }, + "try": function(t, c, f) { + return [ + "try", + tighten(MAP(t, walk)), + c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null, + f != null ? tighten(MAP(f, walk)) : 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 ]]; + } + }, + "new": function(ctor, args) { + if (ctor[0] == "name" && ctor[1] == "Array" && !scope.has("Array")) { + if (args.length != 1) { + return [ "array", args ]; + } else { + return [ "call", [ "name", "Array" ], args ]; + } + } + }, + "call": function(expr, args) { + if (expr[0] == "name" && expr[1] == "Array" && args.length != 1 && !scope.has("Array")) { + return [ "array", args ]; + } + }, + "while": _do_while + }, function() { + return walk(ast); + }); +}; + +/* -----[ re-generate code from the AST ]----- */ + +var DOT_CALL_NO_PARENS = jsp.array_to_hash([ + "name", + "array", + "object", + "string", + "dot", + "sub", + "call", + "regexp" +]); + +function make_string(str, ascii_only) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\t": return "\\t"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + } + 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; + }); +}; + +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 + }); + var beautify = !!options.beautify; + var indentation = 0, + newline = beautify ? "\n" : "", + space = beautify ? " " : ""; + + function encode_string(str) { + return make_string(str, options.ascii_only); + }; + + 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 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 && + ((/[a-z0-9_\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\x24]/i.test(next.toString())) || + (/[\+\-]$/.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; + }; + + 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($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; + } + } + } + return !HOP(DOT_CALL_NO_PARENS, expr[0]); + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".") ], m; + if (Math.floor(num) === num) { + 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 generators = { + "string": encode_string, + "num": make_num, + "name": make_name, + "toplevel": function(statements) { + return make_block_statements(statements) + .join(newline + newline); + }, + "splice": function(statements) { + var parent = $stack[$stack.length - 2][0]; + 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, make)) + ")" : ""; + 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 (!/\./.test(expr[1])) + out += "."; + } else if (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 (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]]) { + left = "(" + left + ")"; + } + if (member(rvalue[0], [ "assign", "conditional", "seq" ]) || + rvalue[0] == "binary" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] && + !(rvalue[1] == operator && member(operator, [ "&&", "||", "*" ]))) { + 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) { + if (props.length == 0) + return "{}"; + return "{" + 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])); + } + var key = p[0], val = make(p[1]); + 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("}"); + }, + "regexp": function(rx, mods) { + return "/" + rx + "/" + mods; + }, + "array": function(elements) { + if (elements.length == 0) return "[]"; + return add_spaces([ "[", add_commas(MAP(elements, function(el){ + if (!beautify && el[0] == "atom" && el[1] == "undefined") return ""; + return parenthesize(el, "seq"); + })), "]" ]); + }, + "stat": function(stmt) { + return 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); + } + }; + + // 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[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 make_function(name, args, body, keyword) { + var out = keyword || "function"; + if (name) { + out += " " + make_name(name); + } + out += "(" + add_commas(MAP(args, make_name)) + ")"; + return add_spaces([ out, make_block(body) ]); + }; + + 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) { + if ((stat[0] == "while" && empty(stat[2])) || + (member(stat[0], [ "for", "for-in"] ) && empty(stat[4])) || + (stat[0] == "if" && empty(stat[2]) && !stat[3]) || + (stat[0] == "if" && stat[3] && empty(stat[3]))) { + code = code.replace(/;*\s*$/, ";"); + } else { + code = code.replace(/;+\s*$/, ""); + } + } + 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; + }; + + var $stack = []; + + function make(node) { + var type = node[0]; + var gen = generators[type]; + if (!gen) + throw new Error("Can't find generator for \"" + type + "\""); + $stack.push(node); + var ret = gen.apply(type, node.slice(1)); + $stack.pop(); + return ret; + }; + + return make(ast); +}; + +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"); +}; + +/* -----[ 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; +}; + +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; +}; + +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); +}; + +function HOP(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +}; + +// some utilities + +var MAP; + +(function(){ + MAP = function(a, f, o) { + var ret = []; + for (var i = 0; i < a.length; ++i) { + var val = f.call(o, a[i], i); + if (val instanceof AtTop) ret.unshift(val.v); + else ret.push(val); + } + return ret; + }; + MAP.at_top = function(val) { return new AtTop(val) }; + function AtTop(val) { this.v = val }; +})(); + +/* -----[ Exports ]----- */ + +exports.ast_walker = ast_walker; +exports.ast_mangle = ast_mangle; +exports.ast_squeeze = ast_squeeze; +exports.gen_code = gen_code; +exports.ast_add_scope = ast_add_scope; +exports.set_logger = function(logger) { warn = logger }; +exports.make_string = make_string; +exports.split_lines = split_lines; +exports.MAP = MAP; + +// keep this last! +exports.ast_squeeze_more = require("./squeeze-more").ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/process.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/uglify-js/lib"; + var __filename = "/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/uglify-js/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + + (function () { + var jsp = require("./parse-js"), + pro = require("./process"), + slice = jsp.slice, + member = jsp.member, + PRECEDENCE = jsp.PRECEDENCE, + OPERATORS = jsp.OPERATORS; + +function ast_squeeze_more(ast) { + var w = pro.ast_walker(), walk = w.walk; + return w.with_walkers({ + "call": function(expr, args) { + if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) { + // foo.toString() ==> foo+"" + return [ "binary", "+", expr[1], [ "string", "" ]]; + } + } + }, function() { + return walk(ast); + }); +}; + +exports.ast_squeeze_more = ast_squeeze_more; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"traverse","version":"0.5.0","description":"Traverse and transform objects by visiting every node on a recursive walk","author":"James Halliday","license":"MIT/X11","main":"./index","repository":{"type":"git","url":"http://github.com/substack/js-traverse.git"},"devDependencies":{"expresso":"0.7.x"},"scripts":{"test":"expresso"}}; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/node_modules/traverse/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito/node_modules/traverse"; + var __filename = "/node_modules/burrito/node_modules/traverse/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito/node_modules/traverse"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito/node_modules/traverse"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + + (function () { + module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function () { + delete state.parent.node[state.key]; + }, + remove : function () { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/node_modules/traverse/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["vm"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "."; + var __filename = "vm"; + + var require = function (file) { + return __require(file, "."); + }; + + require.resolve = function (file) { + return __require.resolve(name, "."); + }; + + require.modules = __require.modules; + __require.modules["vm"]._cached = module.exports; + + (function () { + var Object_keys = function (obj) { + if (Object.keys) return Object.keys(obj) + else { + var res = []; + for (var key in obj) res.push(key) + return res; + } +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +var Script = exports.Script = function NodeScript (code) { + if (!(this instanceof Script)) return new Script(code); + this.code = code; +}; + +var iframe = document.createElement('iframe'); +if (!iframe.style) iframe.style = {}; +iframe.style.display = 'none'; + +var iframeCapable = true; // until proven otherwise +if (navigator.appName === 'Microsoft Internet Explorer') { + var m = navigator.appVersion.match(/\bMSIE (\d+\.\d+);/); + if (m && parseFloat(m[1]) <= 9.0) { + iframeCapable = false; + } +} + +Script.prototype.runInNewContext = function (context) { + if (!context) context = {}; + + if (!iframeCapable) { + var keys = Object_keys(context); + var args = []; + for (var i = 0; i < keys.length; i++) { + args.push(context[keys[i]]); + } + + var fn = Function(keys, this.code); + return fn.apply(null, args); + } + + document.body.appendChild(iframe); + + var win = iframe.contentWindow + || (window.frames && window.frames[window.frames.length - 1]) + || window[window.length - 1] + ; + + forEach(Object_keys(context), function (key) { + win[key] = context[key]; + iframe[key] = context[key]; + }); + + if (win.eval) { + // chrome and ff can just .eval() + var res = win.eval(this.code); + } + else { + // this works in IE9 but not anything newer + iframe.setAttribute('src', + 'javascript:__browserifyVmResult=(' + this.code + ')' + ); + if ('__browserifyVmResult' in win) { + var res = win.__browserifyVmResult; + } + else { + iframeCapable = false; + res = this.runInThisContext(context); + } + } + + forEach(Object_keys(win), function (key) { + context[key] = win[key]; + }); + + document.body.removeChild(iframe); + + return res; +}; + +Script.prototype.runInThisContext = function () { + return eval(this.code); // maybe... +}; + +Script.prototype.runInContext = function (context) { + // seems to be just runInNewContext on magical context objects which are + // otherwise indistinguishable from objects except plain old objects + // for the parameter segfaults node + return this.runInNewContext(context); +}; + +forEach(Object_keys(Script.prototype), function (name) { + exports[name] = Script[name] = function (code) { + var s = Script(code); + return s[name].apply(s, [].slice.call(arguments, 1)); + }; +}); + +exports.createScript = function (code) { + return exports.Script(code); +}; + +exports.createContext = Script.createContext = function (context) { + // not really sure what this one does + // seems to just make a shallow copy + var copy = {}; + forEach(Object_keys(context), function (key) { + copy[key] = context[key]; + }); + return copy; +}; +; + }).call(module.exports); + + __require.modules["vm"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/package.json"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/package.json"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + + (function () { + module.exports = {"name":"jsonify","version":"0.0.0","description":"JSON without touching any globals","main":"index.js","directories":{"lib":".","test":"test"},"devDependencies":{"tap":"0.0.x","garbage":"0.0.x"},"scripts":{"test":"tap test"},"repository":{"type":"git","url":"http://github.com/substack/jsonify.git"},"keywords":["json","browser"],"author":{"name":"Douglas Crockford","url":"http://crockford.com/"},"license":"Public Domain"}; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/package.json"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify"; + var __filename = "/node_modules/jsonify/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + + (function () { + exports.parse = require('./lib/parse'); +exports.stringify = require('./lib/stringify'); +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/index.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/parse.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/parse.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + + (function () { + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t' + }, + text, + + error = function (m) { + // Call error when something is wrong. + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text + }; + }, + + next = function (c) { + // If a c parameter is provided, verify that it matches the current character. + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + + number = function () { + // Parse a number value. + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + // Parse a string value. + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + +// Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + +// true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + +// Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + +// Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + +value = function () { + +// Parse a JSON value. It could be an object, an array, a string, a number, +// or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } +}; + +// Return the json_parse function. It will have access to all of the above +// functions and variables. + +module.exports = function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + 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); + }({'': result}, '')) : result; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/parse.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/jsonify/lib/stringify.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/jsonify/lib"; + var __filename = "/node_modules/jsonify/lib/stringify.js"; + + var require = function (file) { + return __require(file, "/node_modules/jsonify/lib"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/jsonify/lib"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + + (function () { + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + +function quote(string) { + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; +} + +function str(key, holder) { + // Produce a string from holder[key]. + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + return String(value); + + case 'object': + if (!value) return 'null'; + gap += indent; + partial = []; + + // Array.isArray + if (Object.prototype.toString.apply(value) === '[object Array]') { + 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) { + k = rep[i]; + if (typeof k === 'string') { + 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; + } +} + +module.exports = function (value, replacer, space) { + 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}); +}; +; + }).call(module.exports); + + __require.modules["/node_modules/jsonify/lib/stringify.js"]._cached = module.exports; + return module.exports; +}; + +require.modules["/node_modules/burrito/index.js"] = function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/node_modules/burrito"; + var __filename = "/node_modules/burrito/index.js"; + + var require = function (file) { + return __require(file, "/node_modules/burrito"); + }; + + require.resolve = function (file) { + return __require.resolve(name, "/node_modules/burrito"); + }; + + require.modules = __require.modules; + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + + (function () { + var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + //try { + var args = [].slice.call(arguments); + var ast = parser.parse.apply(null, args); + /* } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + */ + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; +; + }).call(module.exports); + + __require.modules["/node_modules/burrito/index.js"]._cached = module.exports; + return module.exports; +}; + +process.nextTick(function () { + var module = { exports : {} }; + var exports = module.exports; + var __dirname = "/"; + var __filename = "//home/substack/projects/node-burrito/example/web"; + + var require = function (file) { + return __require(file, "/"); + }; + require.modules = __require.modules; + + var burrito = require('burrito'); +var json = require('jsonify'); + +var src = [ + 'function f () { g() }', + 'function g () { h() }', + 'function h () { throw "moo" + Array(x).join("!") }', + 'var x = 4', + 'f()' +].join('\r\n'); + +window.onload = function () { + burrito(src, function (node) { + document.body.innerHTML += node.name + '
    \n'; + }); +}; +if (document.readyState === 'complete') window.onload(); +; +}); 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/example/web/index.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/index.html new file mode 100644 index 0000000..66804fb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/index.html @@ -0,0 +1,14 @@ + + + + + + +
    
    +
    +
    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/example/web/main.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/main.js
    new file mode 100644
    index 0000000..cc81a8b
    --- /dev/null
    +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/main.js
    @@ -0,0 +1,17 @@
    +var burrito = require('burrito');
    +var json = require('jsonify');
    +
    +var src = [
    +    'function f () { g() }',
    +    'function g () { h() }',
    +    'function h () { throw "moo" + Array(x).join("!") }',
    +    'var x = 4',
    +    'f()'
    +].join('\r\n');
    +
    +window.onload = function () {
    +    burrito(src, function (node) {
    +        document.body.innerHTML += node.name + '
    \n'; + }); +}; +if (document.readyState === 'complete') window.onload(); 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/example/web/server.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/server.js new file mode 100644 index 0000000..6bce020 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/web/server.js @@ -0,0 +1,12 @@ +var express = require('express'); +var browserify = require('browserify'); + +var app = express.createServer(); +app.use(express.static(__dirname)); +app.use(browserify({ + entry : __dirname + '/main.js', + watch : true, +})); + +app.listen(8081); +console.log('Listening on :8081'); 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/example/wrap.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/wrap.js new file mode 100644 index 0000000..1642401 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/example/wrap.js @@ -0,0 +1,7 @@ +var burrito = require('burrito'); + +var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); +}); + +console.log(src); 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/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/index.js new file mode 100644 index 0000000..60ef569 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/index.js @@ -0,0 +1,208 @@ +var uglify = require('uglify-js'); +var parser = uglify.parser; +var parse = function (expr) { + if (typeof expr !== 'string') throw 'expression should be a string'; + + try { + var ast = parser.parse.apply(null, arguments); + } + catch (err) { + if (err.message === undefined + || err.line === undefined + || err.col === undefined + || err.pos === undefined + ) { throw err } + + var e = new SyntaxError( + err.message + + '\n at line ' + err.line + ':' + err.col + ' in expression:\n\n' + + ' ' + expr.split(/\r?\n/)[err.line] + ); + + e.original = err; + e.line = err.line; + e.col = err.col; + e.pos = err.pos; + throw e; + } + return ast; +}; + +var deparse = function (ast, b) { + return uglify.uglify.gen_code(ast, { beautify : b }); +}; + +var traverse = require('traverse'); +var vm = require('vm'); + +var burrito = module.exports = function (code, cb) { + var ast = Array_isArray(code) + ? code // already an ast + : parse(code.toString(), false, true) + ; + + var ast_ = traverse(ast).map(function mapper () { + wrapNode(this, cb); + }); + + return deparse(parse(deparse(ast_)), true); +}; + +var wrapNode = burrito.wrapNode = function (state, cb) { + var node = state.node; + + var ann = Array_isArray(node) && node[0] + && typeof node[0] === 'object' && node[0].name + ? node[0] + : null + ; + + if (!ann) return undefined; + + var self = { + name : ann.name, + node : node, + start : node[0].start, + end : node[0].end, + value : node.slice(1), + state : state + }; + + self.wrap = function (s) { + var subsrc = deparse( + traverse(node).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + }) + ); + + if (self.name === 'binary') { + var a = deparse(traverse(node[2]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + var b = deparse(traverse(node[3]).map(function (x) { + if (!this.isRoot) wrapNode(this, cb) + })); + } + + var src = ''; + + if (typeof s === 'function') { + if (self.name === 'binary') { + src = s(subsrc, a, b); + } + else { + src = s(subsrc); + } + } + else { + src = s.toString() + .replace(/%s/g, function () { + return subsrc + }) + ; + + if (self.name === 'binary') { + src = src + .replace(/%a/g, function () { return a }) + .replace(/%b/g, function () { return b }) + ; + } + } + + var expr = parse(src); + state.update(expr, true); + }; + + var cache = {}; + + self.parent = state.isRoot ? null : function () { + if (!cache.parent) { + var s = state; + var x; + do { + s = s.parent; + if (s) x = wrapNode(s); + } while (s && !x); + + cache.parent = x; + } + + return cache.parent; + }; + + self.source = function () { + if (!cache.source) cache.source = deparse(node); + return cache.source; + }; + + self.label = function () { + return burrito.label(self); + }; + + if (cb) cb.call(state, self); + + if (self.node[0].name === 'conditional') { + self.wrap('[%s][0]'); + } + + return self; +} + +burrito.microwave = function (code, context, cb) { + if (!cb) { cb = context; context = {} }; + if (!context) context = {}; + + var src = burrito(code, cb); + return vm.runInNewContext(src, context); +}; + +burrito.generateName = function (len) { + var name = ''; + var lower = '$'.charCodeAt(0); + var upper = 'z'.charCodeAt(0); + + while (name.length < len) { + var c = String.fromCharCode(Math.floor( + Math.random() * (upper - lower + 1) + lower + )); + if ((name + c).match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) name += c; + } + + return name; +}; + +burrito.parse = parse; +burrito.deparse = deparse; + +burrito.label = function (node) { + if (node.name === 'call') { + if (typeof node.value[0] === 'string') { + return node.value[0]; + } + else if (node.value[0] && typeof node.value[0][1] === 'string') { + return node.value[0][1]; + } + else if (node.value[0][0] === 'dot') { + return node.value[0][node.value[0].length - 1]; + } + else { + return null; + } + } + else if (node.name === 'var') { + return node.value[0].map(function (x) { return x[0] }); + } + else if (node.name === 'defun') { + return node.value[0]; + } + else if (node.name === 'function') { + return node.value[0]; + } + else { + return null; + } +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; 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/.bin/uglifyjs 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/.bin/uglifyjs new file mode 120000 index 0000000..fef3468 --- /dev/null +++ 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/.bin/uglifyjs @@ -0,0 +1 @@ +../uglify-js/bin/uglifyjs \ No newline at end of file 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/.npmignore 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/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ 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/.npmignore @@ -0,0 +1 @@ +node_modules 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/LICENSE 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/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ 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/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/runforcover/node_modules/bunker/node_modules/burrito/node_modules/traverse/README.markdown 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/README.markdown new file mode 100644 index 0000000..f86ef76 --- /dev/null +++ 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/README.markdown @@ -0,0 +1,237 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +scrub circular references +------------------------- + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value, stopHere=false) +---------------------------------- + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +this.remove(stopHere=false) +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete(stopHere=false) +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + +methods +======= + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +install +======= + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +test +==== + +Using [expresso](http://github.com/visionmedia/expresso) do: + + $ expresso + + 100% wahoo, your stuff is not broken! + +in the browser +============== + +Use [browserify](https://github.com/substack/node-browserify) to run traverse in +the browser. + +traverse has been tested and works with: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 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/examples/json.js 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/examples/json.js new file mode 100755 index 0000000..50d612e --- /dev/null +++ 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/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); 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/examples/leaves.js 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/examples/leaves.js new file mode 100755 index 0000000..c1b310b --- /dev/null +++ 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/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); 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/examples/negative.js 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/examples/negative.js new file mode 100755 index 0000000..78608a0 --- /dev/null +++ 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/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); 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/examples/scrub.js 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/examples/scrub.js new file mode 100755 index 0000000..5d15b91 --- /dev/null +++ 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/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); 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/examples/stringify.js 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/examples/stringify.js new file mode 100755 index 0000000..167b68b --- /dev/null +++ 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/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); 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/index.js 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/index.js new file mode 100644 index 0000000..038a1ad --- /dev/null +++ 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/index.js @@ -0,0 +1,267 @@ +module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); 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/main.js 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/main.js new file mode 100755 index 0000000..d562d37 --- /dev/null +++ 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/main.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('./index.js'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); 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 new file mode 100644 index 0000000..c55d2d6 --- /dev/null +++ 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 @@ -0,0 +1,24 @@ +{ + "name": "traverse", + "version": "0.5.2", + "description": "Traverse and transform objects by visiting every node on a recursive walk", + "author": { + "name": "James Halliday" + }, + "license": "MIT/X11", + "main": "./index", + "repository": { + "type": "git", + "url": "http://github.com/substack/js-traverse.git" + }, + "devDependencies": { + "expresso": "0.7.x" + }, + "scripts": { + "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/traverse/test/circular.js 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/test/circular.js new file mode 100644 index 0000000..9162601 --- /dev/null +++ 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/test/circular.js @@ -0,0 +1,115 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +exports.circular = function () { + var obj = { x : 3 }; + obj.y = obj; + var foundY = false; + Traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + assert.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + foundY = true; + } + }); + assert.ok(foundY); +}; + +exports.deepCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + Traverse(obj).forEach(function (x) { + if (this.circular) { + assert.deepEqual(this.circular.path, []); + assert.deepEqual(this.path, [ 'y', 2 ]); + times ++; + } + }); + + assert.deepEqual(times, 1); +}; + +exports.doubleCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + Traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]); + assert.deepEqual(circs[0].circ.path, []); + + assert.deepEqual(circs[1].self.path, [ 'y', 2 ]); + assert.deepEqual(circs[1].circ.path, []); + + assert.deepEqual(circs.length, 2); +}; + +exports.circDubForEach = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + Traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circDubMap = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = Traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circClone = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = Traverse.clone(obj); + assert.ok(obj !== clone); + + assert.ok(clone.y[2] === clone); + assert.ok(clone.y[2] !== obj); + assert.ok(clone.x[3][2] === clone); + assert.ok(clone.x[3][2] !== obj); + assert.deepEqual(clone.x.slice(0,3), [1,2,3]); + assert.deepEqual(clone.y.slice(0,2), [4,5]); +}; + +exports.circMapScrub = function () { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = Traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + assert.deepEqual( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + assert.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + assert.equal(obj.c, obj); +}; 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/test/date.js 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/test/date.js new file mode 100644 index 0000000..4ca06dc --- /dev/null +++ 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/test/date.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.dateEach = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + Traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + assert.deepEqual(counts, { + object : 1, + Date : 1, + number : 2, + }); +}; + +exports.dateMap = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = Traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + assert.ok(obj.x !== res.x); + assert.deepEqual(res, { + x : obj.x, + y : 110, + z : 105, + }); +}; + 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/test/equal.js 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/test/equal.js new file mode 100644 index 0000000..decc755 --- /dev/null +++ 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/test/equal.js @@ -0,0 +1,220 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.deepDates = function () { + assert.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + assert.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}; + +exports.deepCircular = function () { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + assert.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + assert.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + assert.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); +}; + +exports.deepInstances = function () { + assert.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + assert.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + assert.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + assert.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + assert.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + assert.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + assert.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); +}; + +exports.deepEqual = function () { + assert.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); +}; + +exports.falsy = function () { + assert.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + assert.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); +}; + +exports.deletedArrayEqual = function () { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + assert.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); +}; + +exports.deletedObjectEqual = function () { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + assert.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); +}; + +exports.emptyKeyEqual = function () { + assert.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); +}; + +exports.deepArguments = function () { + assert.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + assert.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); +}; + +exports.deepUn = function () { + assert.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + assert.ok(!deepEqual({ a : 1, b : 2 }, {})); + assert.ok(!deepEqual(undefined, { a : 1, b : 2 })); + assert.ok(!deepEqual({}, { a : 1, b : 2 })); + assert.ok(deepEqual(undefined, undefined)); + assert.ok(deepEqual(null, null)); + assert.ok(!deepEqual(undefined, null)); +}; + +exports.deepLevels = function () { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + assert.ok(!deepEqual(xs, [])); +}; 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/test/instance.js 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/test/instance.js new file mode 100644 index 0000000..8d73525 --- /dev/null +++ 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/test/instance.js @@ -0,0 +1,17 @@ +var assert = require('assert'); +var Traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +exports['check instanceof on node elems'] = function () { + + var counts = { emitter : 0 }; + + Traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + assert.equal(counts.emitter, 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/test/interface.js 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/test/interface.js new file mode 100644 index 0000000..fce5bf9 --- /dev/null +++ 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/test/interface.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['interface map'] = function () { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + assert.deepEqual( + Traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + assert.deepEqual( + Traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + assert.deepEqual( + Traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + Traverse.forEach(obj, function (node) { nodes ++ }); + assert.deepEqual(nodes, 8); +}; + 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/test/json.js 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/test/json.js new file mode 100644 index 0000000..0a04529 --- /dev/null +++ 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/test/json.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['json test'] = function () { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + assert.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + assert.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + assert.deepEqual(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + assert.deepEqual( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + assert.deepEqual( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + assert.deepEqual(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); +}; + 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/test/keys.js 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/test/keys.js new file mode 100644 index 0000000..7ecd545 --- /dev/null +++ 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/test/keys.js @@ -0,0 +1,29 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['sort test'] = function () { + var acc = []; + Traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + assert.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); +}; 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/test/leaves.js 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/test/leaves.js new file mode 100644 index 0000000..e520b72 --- /dev/null +++ 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/test/leaves.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['leaves test'] = function () { + var acc = []; + Traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + assert.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); +}; + 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/test/lib/deep_equal.js 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/test/lib/deep_equal.js new file mode 100644 index 0000000..4fa07bb --- /dev/null +++ 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/test/lib/deep_equal.js @@ -0,0 +1,92 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; 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/test/mutability.js 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/test/mutability.js new file mode 100644 index 0000000..2236f56 --- /dev/null +++ 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/test/mutability.js @@ -0,0 +1,252 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.mutate = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mutateT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.map = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mapT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.clone = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).clone(); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.cloneT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.clone(obj); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.reduce = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, [ 1, 2, 3, 4 ]); +}; + +exports.reduceInit = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, obj); +}; + +exports.remove = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, c : [ 3 ] }); +}; + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'f']) +} + +exports.removeMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, c : [ 3 ] }); +}; + +exports.delete = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); +}; + +exports.deleteNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) +} + +exports.deleteStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c']) +} + +exports.deleteRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); +}; + +exports.deleteMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); +}; + +exports.deleteMapRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); +}; 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/test/negative.js 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/test/negative.js new file mode 100644 index 0000000..f92dfb0 --- /dev/null +++ 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/test/negative.js @@ -0,0 +1,20 @@ +var Traverse = require('../'); +var assert = require('assert'); + +exports['negative update test'] = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = Traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + assert.deepEqual(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + assert.deepEqual(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); +} + 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/test/obj.js 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/test/obj.js new file mode 100644 index 0000000..d46fd38 --- /dev/null +++ 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/test/obj.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['traverse an object with nested functions'] = function () { + var to = setTimeout(function () { + assert.fail('never ran'); + }, 1000); + + function Cons (x) { + clearTimeout(to); + assert.equal(x, 10); + }; + Traverse(new Cons(10)); +}; + 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/test/siblings.js 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/test/siblings.js new file mode 100644 index 0000000..99c0f1b --- /dev/null +++ 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/test/siblings.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.siblings = function () { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + assert.deepEqual(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 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/test/stop.js 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/test/stop.js new file mode 100644 index 0000000..3529847 --- /dev/null +++ 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/test/stop.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.stop = function () { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + assert.equal(visits, 5); +}; + +exports.stopMap = function () { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + assert.equal(s, 'ABCDEfghij'); +}; + +exports.stopReduce = function () { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + assert.deepEqual(xs, [ 4, 5, 6 ]); +}; 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/test/stringify.js 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/test/stringify.js new file mode 100644 index 0000000..932f5d3 --- /dev/null +++ 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/test/stringify.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.stringify = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + Traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + assert.equal(s, JSON.stringify(obj)); +} + 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/test/subexpr.js 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/test/subexpr.js new file mode 100644 index 0000000..a217beb --- /dev/null +++ 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/test/subexpr.js @@ -0,0 +1,34 @@ +var traverse = require('../'); +var assert = require('assert'); + +exports.subexpr = function () { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + assert.deepEqual(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + assert.deepEqual(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); +}; + +exports.block = function () { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + assert.deepEqual(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); +}; 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/test/super_deep.js 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/test/super_deep.js new file mode 100644 index 0000000..acac2fd --- /dev/null +++ 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/test/super_deep.js @@ -0,0 +1,55 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.super_deep = function () { + var util = require('util'); + var a0 = make(); + var a1 = make(); + assert.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + assert.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + assert.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //assert.ok(!deepEqual(a0, a1)); +}; + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} 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/.npmignore 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/.npmignore new file mode 100644 index 0000000..d97eaa0 --- /dev/null +++ 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/.npmignore @@ -0,0 +1,4 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* \ No newline at end of file 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/README.html 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/README.html new file mode 100644 index 0000000..8f5223f --- /dev/null +++ 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/README.html @@ -0,0 +1,1026 @@ + + + + +UglifyJS -- a JavaScript parser/compressor/beautifier + + + + + + + + + + + + +
    + +

    UglifyJS – a JavaScript parser/compressor/beautifier

    + + + + +
    +

    1 UglifyJS — a JavaScript parser/compressor/beautifier

    +
    + + +

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

    +

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

    +

    +( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

    +

    +The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

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

    1.1 Unsafe transformations

    +
    + + +

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

    + +
    + +
    +

    1.1.1 Calls involving the global Array constructor

    +
    + + +

    +The following transformations occur: +

    + + + +
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +Array(a, b, c)         => [a,b,c]
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
    +
    + + + +

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

    +

    +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

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

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

    +
    + + +
    +
    + +
    + +
    +

    1.2 Install (NPM)

    +
    + + +

    +UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

    +
    + +
    + +
    +

    1.3 Install latest code from GitHub

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

    1.4 Usage

    +
    + + +

    +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

    + + + +
    uglifyjs [ options... ] [ filename ]
    +
    + + + +

    +filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

    +

    +Supported options: +

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

    1.4.1 API

    +
    + + +

    +To use the library from JavaScript, you'd do the following (example for +NodeJS): +

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

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

    +

    +Some of these functions take optional arguments. Here's a description: +

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

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

      +

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

      +

      +Here's an example of what it does: +

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

    1.4.2 Beautifier shortcoming – no more comments

    +
    + + +

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

    +

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

    +
    + +
    + +
    +

    1.4.3 Use as a code pre-processor

    +
    + + +

    +The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

    +

    +The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

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

    +When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

    +

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

    +

    +And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

    +

    +In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

    +

    +It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

    +
    +
    + +
    + +
    +

    1.5 Compression – how good is it?

    +
    + + +

    +Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

    +

    +We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

    + + ++ + + + + + + + + + +
    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
    + + +
    + +
    + +
    +

    1.6 Bugs?

    +
    + + +

    +Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

    +

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

    +

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

    +
    + +
    + +
    +

    1.7 Links

    +
    + + + + + +
    + +
    + +
    +

    1.8 License

    +
    + + +

    +UglifyJS is released under the BSD license: +

    + + + +
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    +Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions
    +are met:
    +
    +    * Redistributions of source code must retain the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials
    +      provided with the distribution.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
    +
    + + + + +
    +
    +
    +
    +

    Footnotes:

    +
    +

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

    +
    +
    +
    +

    Author: Mihai Bazon +

    +

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

    +

    HTML generated by org-mode 7.01trans in emacs 23

    +
    +
    + + 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/README.org 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/README.org new file mode 100644 index 0000000..50c9c27 --- /dev/null +++ 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/README.org @@ -0,0 +1,571 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+AUTHOR: Mihai Bazon +#+EMAIL: mihai.bazon@gmail.com + +* UglifyJS --- a JavaScript parser/compressor/beautifier + +This package implements a general-purpose JavaScript +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =--ascii= --- pass this argument to encode non-ASCII characters as + =\uXXXX= sequences. By default UglifyJS won't bother to do it and will + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle variable names + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\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/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~ new file mode 100644 index 0000000..8ca4d35 --- /dev/null +++ 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~ @@ -0,0 +1,24 @@ +{ + "name" : "uglify-js", + + "description" : "JavaScript parser and compressor/beautifier toolkit", + + "author" : { + "name" : "Mihai Bazon", + "email" : "mihai.bazon@gmail.com", + "url" : "http://mihai.bazon.net/blog" + }, + + "version" : "1.1.0", + + "main" : "./uglify-js.js", + + "bin" : { + "uglifyjs" : "./bin/uglifyjs" + }, + + "repository": { + "type": "git", + "url": "git@github.com:mishoo/UglifyJS.git" + } +} 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/test/beautify.js 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/test/beautify.js new file mode 100755 index 0000000..f19369e --- /dev/null +++ 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/test/beautify.js @@ -0,0 +1,28 @@ +#! /usr/bin/env node + +global.sys = require("sys"); +var fs = require("fs"); + +var jsp = require("../lib/parse-js"); +var pro = require("../lib/process"); + +var filename = process.argv[2]; +fs.readFile(filename, "utf8", function(err, text){ + try { + var ast = time_it("parse", function(){ return jsp.parse(text); }); + ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); + ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); + var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); + sys.puts(gen); + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + } +}); + +function time_it(name, 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/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/node_modules/uglify-js/test/testparser.js 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/test/testparser.js new file mode 100755 index 0000000..02c19a9 --- /dev/null +++ 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/test/testparser.js @@ -0,0 +1,403 @@ +#! /usr/bin/env node + +var parseJS = require("../lib/parse-js"); +var sys = require("sys"); + +// write debug in a very straightforward manner +var debug = function(){ + sys.log(Array.prototype.slice.call(arguments).join(', ')); +}; + +ParserTestSuite(function(i, input, desc){ + try { + parseJS.parse(input); + debug("ok " + i + ": " + desc); + } catch(e){ + debug("FAIL " + i + " " + desc + " (" + e + ")"); + } +}); + +function ParserTestSuite(callback){ + var inps = [ + ["var abc;", "Regular variable statement w/o assignment"], + ["var abc = 5;", "Regular variable statement with assignment"], + ["/* */;", "Multiline comment"], + ['/** **/;', 'Double star multiline comment'], + ["var f = function(){;};", "Function expression in var assignment"], + ['hi; // moo\n;', 'single line comment'], + ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) + ['a + b;', 'addition'], + ["'a';", 'single string literal'], + ["'a\\n';", 'single string literal with escaped return'], + ['"a";', 'double string literal'], + ['"a\\n";', 'double string literal with escaped return'], + ['"var";', 'string is a keyword'], + ['"variable";', 'string starts with a keyword'], + ['"somevariable";', 'string contains a keyword'], + ['"somevar";', 'string ends with a keyword'], + ['500;', 'int literal'], + ['500.;', 'float literal w/o decimals'], + ['500.432;', 'float literal with decimals'], + ['.432432;', 'float literal w/o int'], + ['(a,b,c);', 'parens and comma'], + ['[1,2,abc];', 'array literal'], + ['var o = {a:1};', 'object literal unquoted key'], + ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... + ['var o = {c:c};', 'object literal keyname is identifier'], + ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], + ['var x;\nvar y;', 'two lines'], + ['var x;\nfunction n(){; }', 'function def'], + ['var x;\nfunction n(abc){; }', 'function def with arg'], + ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], + ['function n(){ "hello"; }', 'function def with body'], + ['/a/;', 'regex literal'], + ['/a/b;', 'regex literal with flag'], + ['/a/ / /b/;', 'regex div regex'], + ['a/b/c;', 'triple division looks like regex'], + ['+function(){/regex/;};', 'regex at start of function body'], + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 + + // first tests for the lexer, should also parse as program (when you append a semi) + + // comments + ['//foo!@#^&$1234\nbar;', 'single line comment'], + ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], + ['/*foo\nbar*/;','multi line comment'], + ['/*x*x*/;','multi line comment with *'], + ['/**/;','empty comment'], + // identifiers + ["x;",'1 identifier'], + ["_x;",'2 identifier'], + ["xyz;",'3 identifier'], + ["$x;",'4 identifier'], + ["x$;",'5 identifier'], + ["_;",'6 identifier'], + ["x5;",'7 identifier'], + ["x_y;",'8 identifier'], + ["x+5;",'9 identifier'], + ["xyz123;",'10 identifier'], + ["x1y1z1;",'11 identifier'], + ["foo\\u00D8bar;",'12 identifier unicode escape'], + //["foo�bar;",'13 identifier unicode embedded (might fail)'], + // numbers + ["5;", '1 number'], + ["5.5;", '2 number'], + ["0;", '3 number'], + ["0.0;", '4 number'], + ["0.001;", '5 number'], + ["1.e2;", '6 number'], + ["1.e-2;", '7 number'], + ["1.E2;", '8 number'], + ["1.E-2;", '9 number'], + [".5;", '10 number'], + [".5e3;", '11 number'], + [".5e-3;", '12 number'], + ["0.5e3;", '13 number'], + ["55;", '14 number'], + ["123;", '15 number'], + ["55.55;", '16 number'], + ["55.55e10;", '17 number'], + ["123.456;", '18 number'], + ["1+e;", '20 number'], + ["0x01;", '22 number'], + ["0XCAFE;", '23 number'], + ["0x12345678;", '24 number'], + ["0x1234ABCD;", '25 number'], + ["0x0001;", '26 number'], + // strings + ["\"foo\";", '1 string'], + ["\'foo\';", '2 string'], + ["\"x\";", '3 string'], + ["\'\';", '4 string'], + ["\"foo\\tbar\";", '5 string'], + ["\"!@#$%^&*()_+{}[]\";", '6 string'], + ["\"/*test*/\";", '7 string'], + ["\"//test\";", '8 string'], + ["\"\\\\\";", '9 string'], + ["\"\\u0001\";", '10 string'], + ["\"\\uFEFF\";", '11 string'], + ["\"\\u10002\";", '12 string'], + ["\"\\x55\";", '13 string'], + ["\"\\x55a\";", '14 string'], + ["\"a\\\\nb\";", '15 string'], + ['";"', '16 string: semi in a string'], + ['"a\\\nb";', '17 string: line terminator escape'], + // literals + ["null;", "null"], + ["true;", "true"], + ["false;", "false"], + // regex + ["/a/;", "1 regex"], + ["/abc/;", "2 regex"], + ["/abc[a-z]*def/g;", "3 regex"], + ["/\\b/;", "4 regex"], + ["/[a-zA-Z]/;", "5 regex"], + + // program tests (for as far as they havent been covered above) + + // regexp + ["/foo(.*)/g;", "another regexp"], + // arrays + ["[];", "1 array"], + ["[ ];", "2 array"], + ["[1];", "3 array"], + ["[1,2];", "4 array"], + ["[1,2,,];", "5 array"], + ["[1,2,3];", "6 array"], + ["[1,2,3,,,];", "7 array"], + // objects + ["{};", "1 object"], + ["({x:5});", "2 object"], + ["({x:5,y:6});", "3 object"], + ["({x:5,});", "4 object"], + ["({if:5});", "5 object"], + ["({ get x() {42;} });", "6 object"], + ["({ set y(a) {1;} });", "7 object"], + // member expression + ["o.m;", "1 member expression"], + ["o['m'];", "2 member expression"], + ["o['n']['m'];", "3 member expression"], + ["o.n.m;", "4 member expression"], + ["o.if;", "5 member expression"], + // call and invoke expressions + ["f();", "1 call/invoke expression"], + ["f(x);", "2 call/invoke expression"], + ["f(x,y);", "3 call/invoke expression"], + ["o.m();", "4 call/invoke expression"], + ["o['m'];", "5 call/invoke expression"], + ["o.m(x);", "6 call/invoke expression"], + ["o['m'](x);", "7 call/invoke expression"], + ["o.m(x,y);", "8 call/invoke expression"], + ["o['m'](x,y);", "9 call/invoke expression"], + ["f(x)(y);", "10 call/invoke expression"], + ["f().x;", "11 call/invoke expression"], + + // eval + ["eval('x');", "1 eval"], + ["(eval)('x');", "2 eval"], + ["(1,eval)('x');", "3 eval"], + ["eval(x,y);", "4 eval"], + // new expression + ["new f();", "1 new expression"], + ["new o;", "2 new expression"], + ["new o.m;", "3 new expression"], + ["new o.m(x);", "4 new expression"], + ["new o.m(x,y);", "5 new expression"], + // prefix/postfix + ["++x;", "1 pre/postfix"], + ["x++;", "2 pre/postfix"], + ["--x;", "3 pre/postfix"], + ["x--;", "4 pre/postfix"], + ["x ++;", "5 pre/postfix"], + ["x /* comment */ ++;", "6 pre/postfix"], + ["++ /* comment */ x;", "7 pre/postfix"], + // unary operators + ["delete x;", "1 unary operator"], + ["void x;", "2 unary operator"], + ["+ x;", "3 unary operator"], + ["-x;", "4 unary operator"], + ["~x;", "5 unary operator"], + ["!x;", "6 unary operator"], + // meh + ["new Date++;", "new date ++"], + ["+x++;", " + x ++"], + // expression expressions + ["1 * 2;", "1 expression expressions"], + ["1 / 2;", "2 expression expressions"], + ["1 % 2;", "3 expression expressions"], + ["1 + 2;", "4 expression expressions"], + ["1 - 2;", "5 expression expressions"], + ["1 << 2;", "6 expression expressions"], + ["1 >>> 2;", "7 expression expressions"], + ["1 >> 2;", "8 expression expressions"], + ["1 * 2 + 3;", "9 expression expressions"], + ["(1+2)*3;", "10 expression expressions"], + ["1*(2+3);", "11 expression expressions"], + ["xy;", "13 expression expressions"], + ["x<=y;", "14 expression expressions"], + ["x>=y;", "15 expression expressions"], + ["x instanceof y;", "16 expression expressions"], + ["x in y;", "17 expression expressions"], + ["x&y;", "18 expression expressions"], + ["x^y;", "19 expression expressions"], + ["x|y;", "20 expression expressions"], + ["x+y>>= y;", "1 assignment"], + ["x <<= y;", "2 assignment"], + ["x = y;", "3 assignment"], + ["x += y;", "4 assignment"], + ["x /= y;", "5 assignment"], + // comma + ["x, y;", "comma"], + // block + ["{};", "1 block"], + ["{x;};", "2 block"], + ["{x;y;};", "3 block"], + // vars + ["var x;", "1 var"], + ["var x,y;", "2 var"], + ["var x=1,y=2;", "3 var"], + ["var x,y=2;", "4 var"], + // empty + [";", "1 empty"], + ["\n;", "2 empty"], + // expression statement + ["x;", "1 expression statement"], + ["5;", "2 expression statement"], + ["1+2;", "3 expression statement"], + // if + ["if (c) x; else y;", "1 if statement"], + ["if (c) x;", "2 if statement"], + ["if (c) {} else {};", "3 if statement"], + ["if (c1) if (c2) s1; else s2;", "4 if statement"], + // while + ["do s; while (e);", "1 while statement"], + ["do { s; } while (e);", "2 while statement"], + ["while (e) s;", "3 while statement"], + ["while (e) { s; };", "4 while statement"], + // for + ["for (;;) ;", "1 for statement"], + ["for (;c;x++) x;", "2 for statement"], + ["for (i;i> 1; +var c = 8 >>> 1; \ No newline at end of file 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/test/unit/compress/test/issue34.js 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/test/unit/compress/test/issue34.js new file mode 100644 index 0000000..022f7a3 --- /dev/null +++ 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/test/unit/compress/test/issue34.js @@ -0,0 +1,3 @@ +var a = {}; +a["this"] = 1; +a["that"] = 2; \ No newline at end of file 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/test/unit/compress/test/issue4.js 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/test/unit/compress/test/issue4.js new file mode 100644 index 0000000..0b76103 --- /dev/null +++ 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/test/unit/compress/test/issue4.js @@ -0,0 +1,3 @@ +var a = 2e3; +var b = 2e-3; +var c = 2e-5; \ No newline at end of file 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/test/unit/compress/test/issue48.js 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/test/unit/compress/test/issue48.js new file mode 100644 index 0000000..031e85b --- /dev/null +++ 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/test/unit/compress/test/issue48.js @@ -0,0 +1 @@ +var s, i; s = ''; i = 0; \ No newline at end of file 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/test/unit/compress/test/issue50.js 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/test/unit/compress/test/issue50.js new file mode 100644 index 0000000..060f9df --- /dev/null +++ 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/test/unit/compress/test/issue50.js @@ -0,0 +1,9 @@ +function bar(a) { + try { + foo(); + } catch(e) { + alert("Exception caught (foo not defined)"); + } + alert(a); // 10 in FF, "[object Error]" in IE +} +bar(10); 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/test/unit/compress/test/issue53.js 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/test/unit/compress/test/issue53.js new file mode 100644 index 0000000..4f8b32f --- /dev/null +++ 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/test/unit/compress/test/issue53.js @@ -0,0 +1 @@ +x = (y, z) 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/test/unit/compress/test/issue54.1.js 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/test/unit/compress/test/issue54.1.js new file mode 100644 index 0000000..967052e --- /dev/null +++ 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/test/unit/compress/test/issue54.1.js @@ -0,0 +1,3 @@ +foo.toString(); +a.toString(16); +b.toString.call(c); 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/test/unit/compress/test/issue68.js 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/test/unit/compress/test/issue68.js new file mode 100644 index 0000000..14054d0 --- /dev/null +++ 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/test/unit/compress/test/issue68.js @@ -0,0 +1,5 @@ +function f() { + if (a) return; + g(); + function g(){} +}; 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/test/unit/compress/test/issue69.js 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/test/unit/compress/test/issue69.js new file mode 100644 index 0000000..d25ecd6 --- /dev/null +++ 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/test/unit/compress/test/issue69.js @@ -0,0 +1 @@ +[(a,b)] 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/test/unit/compress/test/issue9.js 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/test/unit/compress/test/issue9.js new file mode 100644 index 0000000..6158861 --- /dev/null +++ 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/test/unit/compress/test/issue9.js @@ -0,0 +1,4 @@ +var a = { + a: 1, + b: 2, // <-- trailing comma +}; 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/test/unit/compress/test/mangle.js 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/test/unit/compress/test/mangle.js new file mode 100644 index 0000000..c271a26 --- /dev/null +++ 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/test/unit/compress/test/mangle.js @@ -0,0 +1,5 @@ +(function() { + var x = function fun(a, fun, b) { + return fun; + }; +}()); 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/test/unit/compress/test/null_string.js 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/test/unit/compress/test/null_string.js new file mode 100644 index 0000000..a675b1c --- /dev/null +++ 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/test/unit/compress/test/null_string.js @@ -0,0 +1 @@ +var nullString = "\0" \ No newline at end of file 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/test/unit/compress/test/strict-equals.js 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/test/unit/compress/test/strict-equals.js new file mode 100644 index 0000000..b631f4c --- /dev/null +++ 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/test/unit/compress/test/strict-equals.js @@ -0,0 +1,3 @@ +typeof a === 'string' +b + "" !== c + "" +d < e === f < g 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/test/unit/compress/test/var.js 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/test/unit/compress/test/var.js new file mode 100644 index 0000000..609a35d --- /dev/null +++ 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/test/unit/compress/test/var.js @@ -0,0 +1,3 @@ +// var declarations after each other should be combined +var a = 1; +var b = 2; \ No newline at end of file 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/test/unit/compress/test/whitespace.js 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/test/unit/compress/test/whitespace.js new file mode 100644 index 0000000..6a15c46 --- /dev/null +++ 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/test/unit/compress/test/whitespace.js @@ -0,0 +1,21 @@ +function id(a) { + // Form-Feed + // Vertical Tab + // No-Break Space + ᠎// Mongolian Vowel Separator +  // En quad +  // Em quad +  // En space +  // Em space +  // Three-Per-Em Space +  // Four-Per-Em Space +  // Six-Per-Em Space +  // Figure Space +  // Punctuation Space +  // Thin Space +  // Hair Space +  // Narrow No-Break Space +  // Medium Mathematical Space +  // Ideographic Space + return a; +} 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/test/unit/compress/test/with.js 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/test/unit/compress/test/with.js new file mode 100644 index 0000000..de266ed --- /dev/null +++ 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/test/unit/compress/test/with.js @@ -0,0 +1,2 @@ +with({}) { +}; 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/test/unit/scripts.js 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/test/unit/scripts.js new file mode 100644 index 0000000..9fdd96c --- /dev/null +++ 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/test/unit/scripts.js @@ -0,0 +1,55 @@ +var fs = require('fs'), + uglify = require('uglify-js'), + jsp = uglify.parser, + nodeunit = require('nodeunit'), + path = require('path'), + pro = uglify.uglify; + +var Script = process.binding('evals').Script; + +var scriptsPath = __dirname; + +function compress(code) { + var ast = jsp.parse(code); + ast = pro.ast_mangle(ast); + ast = pro.ast_squeeze(ast, { no_warnings: true }); + ast = pro.ast_squeeze_more(ast); + return pro.gen_code(ast); +}; + +var testDir = path.join(scriptsPath, "compress", "test"); +var expectedDir = path.join(scriptsPath, "compress", "expected"); + +function getTester(script) { + return function(test) { + var testPath = path.join(testDir, script); + var expectedPath = path.join(expectedDir, script); + var content = fs.readFileSync(testPath, 'utf-8'); + var outputCompress = compress(content); + + // Check if the noncompressdata is larger or same size as the compressed data + test.ok(content.length >= outputCompress.length); + + // Check that a recompress gives the same result + var outputReCompress = compress(content); + test.equal(outputCompress, outputReCompress); + + // Check if the compressed output is what is expected + var expected = fs.readFileSync(expectedPath, 'utf-8'); + test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); + + test.done(); + }; +}; + +var tests = {}; + +var scripts = fs.readdirSync(testDir); +for (var i in scripts) { + var script = scripts[i]; + if (/\.js$/.test(script)) { + tests[script] = getTester(script); + } +} + +module.exports = nodeunit.testCase(tests); 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/tmp/hoist.js 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/tmp/hoist.js new file mode 100644 index 0000000..4bf2b94 --- /dev/null +++ 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/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; 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/tmp/instrument.js 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/tmp/instrument.js new file mode 100644 index 0000000..c6a9d79 --- /dev/null +++ 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/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} 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/tmp/instrument2.js 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/tmp/instrument2.js new file mode 100644 index 0000000..6aee5f3 --- /dev/null +++ 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/tmp/instrument2.js @@ -0,0 +1,138 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + function trace (line, comment) { + var code = pro.gen_code(line, { beautify: true }); + var data = line[0] + + var args = [] + if (!comment) comment = "" + if (typeof data === "object") { + code = code.split(/\n/).shift() + args = [ [ "string", data.toString() ], + [ "string", code ], + [ "num", data.start.line ], + [ "num", data.start.col ], + [ "num", data.end.line ], + [ "num", data.end.col ]] + } else { + args = [ [ "string", data ], + [ "string", code ]] + + } + return [ "call", [ "name", "trace" ], args ]; + } + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", + [ [ "stat", trace(this) ], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + } + + function do_cond(c, t, f) { + return [ this[0], w.walk(c), + ["seq", trace(t), w.walk(t) ], + ["seq", trace(f), w.walk(f) ]]; + } + + function do_binary(c, l, r) { + if (c !== "&&" && c !== "||") { + return [this[0], c, w.walk(l), w.walk(r)]; + } + return [ this[0], c, + ["seq", trace(l), w.walk(l) ], + ["seq", trace(r), w.walk(r) ]]; + } + + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat, + "conditional" : do_cond, + "binary" : do_binary + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + for (var i = 0; i < 5; ++i) + console.log("foo"); + + for (var i = 0; i < 5; ++i) { + console.log("foo"); + } + + var k = plurp() ? 1 : 0; + var x = a ? doX(y) && goZoo("zoo") + : b ? blerg({ x: y }) + : null; + + var x = X || Y; +} 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/tmp/test.js 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/tmp/test.js new file mode 100755 index 0000000..f295fba --- /dev/null +++ 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/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); 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/uglify-js.js 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/uglify-js.js new file mode 100644 index 0000000..4305e23 --- /dev/null +++ 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/uglify-js.js @@ -0,0 +1,17 @@ +//convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); + +module.exports = uglify \ No newline at end of file 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 new file mode 100644 index 0000000..48510d5 --- /dev/null +++ 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 @@ -0,0 +1,47 @@ +{ + "name": "burrito", + "description": "Wrap up expressions with a trace function while walking the AST with rice and beans on the side", + "version": "0.2.12", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-burrito.git" + }, + "main": "./index.js", + "keywords": [ + "trace", + "ast", + "walk", + "syntax", + "source", + "tree", + "uglify" + ], + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "traverse": "~0.5.1", + "uglify-js": "~1.1.1" + }, + "devDependencies": { + "tap": "~0.2.5" + }, + "engines": { + "node": ">=0.4.0" + }, + "license": "BSD", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "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/node_modules/burrito/test/ast.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/ast.js new file mode 100644 index 0000000..503b5ab --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/ast.js @@ -0,0 +1,31 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('ast', function (t) { + t.plan(2); + + var ast = burrito.parse('f(g(h(5)))', false, true); + var src = burrito(ast, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); +}); 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/test/err.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/err.js new file mode 100644 index 0000000..af1611d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/err.js @@ -0,0 +1,52 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('wrap error', function (t) { + t.plan(6); + + try { + var src = burrito('f() && g()', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b') + }); + t.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + t.equal(err.line, 0); + t.equal(err.col, 10); + t.equal(err.pos, 10); + } +}); + +test('non string', function (t) { + t.plan(3); + + t.throws(function () { + burrito.parse(new Buffer('[]')); + }); + + t.throws(function () { + burrito.parse(new String('[]')); + }); + + t.throws(function () { + burrito.parse(); + }); +}); + +test('syntax error', function (t) { + t.plan(3); + try { + var src = burrito('f() && g())', function (node) { + if (node.name === 'binary') node.wrap('h(%a, %b)') + }); + assert.fail('should have blown up'); + } + catch (err) { + t.ok(err.message.match(/unexpected/i)); + t.ok(err instanceof SyntaxError); + t.ok(!err.stack.match(/uglify-js/)); + } +}); 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/test/fail.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/fail.js new file mode 100644 index 0000000..70d453f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/fail.js @@ -0,0 +1,9 @@ +var burrito = require('../'); +var test = require('tap').test; +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/fail/src.js', 'utf8'); + +test('fail', function (t) { + burrito(src, function (node) {}); + t.end(); +}); 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/test/fail/src.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/fail/src.js new file mode 100644 index 0000000..eb02736 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/fail/src.js @@ -0,0 +1,60 @@ +var path = require('path') + +module.exports = function(fs, ready) { + var global_files = {} + + var recurse = function(dir, okay) { + fs.readdir(dir, function(err, dir_files) { + var countdown = 0 + , files = [] + , dirs = [] + , checked = 0 + dir_files.forEach(function(file, idx, all) { + fs.stat(path.join(dir, file), function(err, stat) { + if(stat.isDirectory() && !/node_modules/g.test(dir)) { + dirs.push(file) + } else if(/\.js$/g.test(file)) { + files.push(file) + } + + if(++checked >= dir_files.length) + recurse_dirs() + }) + }) + + function recurse_dirs() { + var total = 0 + dirs.forEach(function(this_dir) { + recurse(path.join(dir, this_dir), function(err, data) { + if(++total >= dirs.length) + recurse_files() + }) + }) + + if(!dirs.length) + recurse_files() + } + + function recurse_files() { + var total = 0 + files.forEach(function(file) { + fs.readFile(path.join(dir, file), 'utf8', function(err, src) { + global_files[path.join(dir, file)] = src + ++total >= files.length && + okay(null, global_files) + }) + }) + + if(!files.length) + okay(null, global_files) + } + + if(!dir_files.length) + okay(null, global_files) + }) + } + + recurse('.', ready) +} + + 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/test/label.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/label.js new file mode 100644 index 0000000..368d7c4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/label.js @@ -0,0 +1,92 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('call label', function (t) { + t.plan(1); + + burrito('foo(10)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'foo'); + } + }); +}); + +test('var label', function (t) { + t.plan(1); + + burrito('var x = 2', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x' ]); + } + }); +}); + +test('vars label', function (t) { + t.plan(1); + + burrito('var x = 2, y = 3', function (node) { + if (node.name === 'var') { + t.same(node.label(), [ 'x', 'y' ]); + } + }); +}); + +test('defun label', function (t) { + t.plan(1); + + burrito('function moo () {}', function (node) { + if (node.name === 'defun') { + t.same(node.label(), 'moo'); + } + }); +}); + +test('function label', function (t) { + t.plan(1); + + burrito('(function zzz () {})()', function (node) { + if (node.name === 'function') { + t.same(node.label(), 'zzz'); + } + }); +}); + +test('anon function label', function (t) { + t.plan(1); + + burrito('(function () {})()', function (node) { + if (node.name === 'function') { + t.equal(node.label(), null); + } + }); +}); + +test('dot call label', function (t) { + t.plan(1); + + burrito('process.nextTick(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'nextTick'); + } + }); +}); + +test('triple dot label', function (t) { + t.plan(1); + + burrito('a.b.c(fn)', function (node) { + if (node.name === 'call') { + t.equal(node.label(), 'c'); + } + }); +}); + +test('expr label', function (t) { + t.plan(1); + + burrito('a.b[x+1](fn)', function (node) { + if (node.name === 'call') { + t.ok(node.label() === null); + } + }); +}); 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/test/microwave.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/microwave.js new file mode 100644 index 0000000..43f80a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/microwave.js @@ -0,0 +1,34 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('microwave', function (t) { + t.plan(4); + + var context = { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + t.ok(true); // 3 times + return x * 10; + }, + }; + + var res = burrito.microwave('f(g(h(5)))', context, function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + t.equal(res, (((((5 + 3) * 10) + 2) * 10) + 1) * 10); +}); + +test('empty context', function (t) { + var res = burrito.microwave('Math.sin(2)', function (node) { + if (node.name === 'num') node.wrap('Math.PI / %s'); + }); + t.equal(res, 1); + t.end(); +}); 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/test/parent.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/parent.js new file mode 100644 index 0000000..2d613af --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/parent.js @@ -0,0 +1,27 @@ +var test = require('tap').test; +var burrito = require('../'); + +test('check parent', function (t) { + t.plan(5); + var src = 'Math.tan(0) + Math.sin(0)'; + + var res = burrito.microwave(src, function (node) { + if (node.name === 'binary') { + node.wrap('%a - %b'); + } + else if (node.name === 'num') { + t.equal(node.parent().value[0][0], 'dot'); + + var fn = node.parent().value[0][2]; + if (fn === 'sin') { + node.wrap('Math.PI / 2'); + } + else if (fn === 'tan') { + node.wrap('Math.PI / 4'); + } + else t.fail('Unknown fn'); + } + }); + + t.equal(res, Math.tan(Math.PI / 4) - Math.sin(Math.PI / 2)); // ~ 0 +}); 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/test/wrap.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/wrap.js new file mode 100644 index 0000000..b9eda49 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/node_modules/burrito/test/wrap.js @@ -0,0 +1,159 @@ +var test = require('tap').test; +var burrito = require('../'); +var vm = require('vm'); + +test('preserve ternary parentheses', function (t) { + var originalSource = '"anything" + (x ? y : z) + "anything"'; + var burritoSource = burrito(originalSource, function (node) { + // do nothing. we just want to check that ternary parens are persisted + }); + + var ctxt = { + x : false, + y : 'y_'+~~(Math.random()*10), + z : 'z_'+~~(Math.random()*10) + }; + + var expectedOutput = vm.runInNewContext(originalSource, ctxt); + var burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + + ctxt.x = true; + + expectedOutput = vm.runInNewContext(originalSource, ctxt); + burritoOutput = vm.runInNewContext(burritoSource, ctxt); + + t.equal(burritoOutput, expectedOutput); + t.end(); +}); + +test('wrap calls', function (t) { + t.plan(20); + var src = burrito('f() && g(h())\nfoo()', function (node) { + if (node.name === 'call') node.wrap('qqq(%s)'); + if (node.name === 'binary') node.wrap('bbb(%s)'); + t.ok(node.state); + t.equal(this, node.state); + }); + + var times = { bbb : 0, qqq : 0 }; + + var res = []; + vm.runInNewContext(src, { + bbb : function (x) { + times.bbb ++; + res.push(x); + return x; + }, + qqq : function (x) { + times.qqq ++; + res.push(x); + return x; + }, + f : function () { return true }, + g : function (h) { + t.equal(h, 7); + return h !== 7 + }, + h : function () { return 7 }, + foo : function () { return 'foo!' }, + }); + + t.same(res, [ + true, // f() + 7, // h() + false, // g(h()) + false, // f() && g(h()) + 'foo!', // foo() + ]); + t.equal(times.bbb, 1); + t.equal(times.qqq, 4); + t.end(); +}); + +test('wrap fn', function (t) { + var src = burrito('f(g(h(5)))', function (node) { + if (node.name === 'call') { + node.wrap(function (s) { + return 'z(' + s + ')'; + }); + } + }); + + var times = 0; + t.equal( + vm.runInNewContext(src, { + f : function (x) { return x + 1 }, + g : function (x) { return x + 2 }, + h : function (x) { return x + 3 }, + z : function (x) { + times ++; + return x * 10; + }, + }), + (((((5 + 3) * 10) + 2) * 10) + 1) * 10 + ); + t.equal(times, 3); + t.end(); +}); + +test('binary string', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap('%a*2 - %b*2'); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('binary fn', function (t) { + var src = 'z(x + y)'; + var context = { + x : 3, + y : 4, + z : function (n) { return n * 10 }, + }; + + var res = burrito.microwave(src, context, function (node) { + if (node.name === 'binary') { + node.wrap(function (expr, a, b) { + return '(' + a + ')*2 - ' + '(' + b + ')*2'; + }); + } + }); + + t.equal(res, 10 * (3*2 - 4*2)); + t.end(); +}); + +test('intersperse', function (t) { + var src = '(' + (function () { + f(); + g(); + }).toString() + ')()'; + + var times = { f : 0, g : 0, zzz : 0 }; + + var context = { + f : function () { times.f ++ }, + g : function () { times.g ++ }, + zzz : function () { times.zzz ++ }, + }; + + burrito.microwave(src, context, function (node) { + if (node.name === 'stat') node.wrap('{ zzz(); %s }'); + }); + + t.same(times, { f : 1, g : 1, zzz : 3 }); + t.end(); +}); 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 new file mode 100644 index 0000000..b03ceea --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/package.json @@ -0,0 +1,41 @@ +{ + "name": "bunker", + "version": "0.1.2", + "description": "code coverage in native javascript", + "main": "index.js", + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "dependencies": { + "burrito": ">=0.2.5 <0.3" + }, + "devDependencies": { + "tap": "~0.2.4" + }, + "scripts": { + "test": "tap test/*.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/substack/node-bunker.git" + }, + "keywords": [ + "code", + "coverage" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT/X11", + "engine": { + "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/node_modules/bunker/test/cover.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/cover.js new file mode 100644 index 0000000..b04795d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/cover.js @@ -0,0 +1,36 @@ +var test = require('tap').test; +var bunker = require('../'); +var fs = require('fs'); + +var src = fs.readdirSync(__dirname + '/src').reduce(function (acc, file) { + acc[file] = fs.readFileSync(__dirname + '/src/' + file, 'utf8'); + return acc; +}, {}); + +test('cover', function (t) { + t.plan(1); + + var b = bunker(src['cover.js']); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + + b.run({ + setInterval : setInterval, + clearInterval : function () { + process.nextTick(function () { + t.same(counts, { + binary : 11, + 'unary-postfix' : 11, + 'var' : 2, + call : 2, // setInterval and clearInterval + stat : 1, // clearInterval + }); + }); + + return clearInterval.apply(this, arguments); + }, + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/return.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/return.js new file mode 100644 index 0000000..9be1700 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/return.js @@ -0,0 +1,29 @@ +var test = require('tap').test; +var bunker = require('../'); + +test('cover', function (t) { + t.plan(1); + + var b = bunker('(' + function () { + function foo () {} + function bar () {} + + (function () { + return foo(); + })(); + } + ')()'); + var counts = {}; + + b.on('node', function (node) { + counts[node.name] = (counts[node.name] || 0) + 1; + }); + b.run(); + + process.nextTick(function () { + t.same(counts, { + stat : 2, + call : 2, + return : 1, + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/src/cover.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/src/cover.js new file mode 100644 index 0000000..e640151 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/node_modules/bunker/test/src/cover.js @@ -0,0 +1,6 @@ +var i = 0; +var iv = setInterval(function () { + if (i++ === 10) { + clearInterval(iv); + } +}, 10); 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 new file mode 100644 index 0000000..66cc184 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/package.json @@ -0,0 +1,38 @@ +{ + "name": "runforcover", + "version": "0.0.2", + "description": "require plugin for js code coverage using bunker", + "main": "index.js", + "directories": { + "lib": ".", + "test": "test" + }, + "dependencies": { + "bunker": "0.1.X" + }, + "scripts": { + "test": "node test/index.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/chrisdickinson/node-runforcover.git" + }, + "keywords": [ + "code", + "coverage", + "bunker" + ], + "author": { + "name": "Chris Dickinson", + "email": "chris@neversaw.us", + "url": "http://neversaw.us" + }, + "license": "new BSD", + "engine": { + "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/runforcover/test/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/index.js new file mode 100644 index 0000000..ea59662 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/index.js @@ -0,0 +1 @@ +require('./interface').coverageInterface() diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/interface.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/interface.js new file mode 100644 index 0000000..a6455ed --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/interface.js @@ -0,0 +1,50 @@ +var assert = require('assert'); +var runforcover = require('../'); + +exports.coverageInterface = function() { + assert.ok(runforcover.cover); + + var originalRequire = require.extensions['.js']; + + var coverage = runforcover.cover(); + + assert.notEqual(originalRequire, require.extensions['.js']); + + var file = require('./src/coverage'); + + coverage(function(coverageData) { + assert.equal(Object.keys(coverageData).length, 1); + assert.equal(Object.keys(coverageData)[0], __dirname + '/src/coverage.js'); + + var fileCoverageData = coverageData[Object.keys(coverageData)[0]]; + + assert.ok(fileCoverageData.stats); + assert.ok(fileCoverageData.missing); + + var stats = fileCoverageData.stats(); + + assert.ok(stats.percentage !== undefined); + assert.ok(stats.lines !== undefined); + assert.ok(stats.missing !== undefined); + assert.ok(stats.seen !== undefined); + + assert.equal(stats.lines.length, 3); + assert.equal(stats.lines[0].source(), ' if(a > 0) {'); + assert.equal(stats.lines[1].source(), ' return a + 1;'); + assert.equal(stats.lines[2].source(), ' return a - 1;'); + + file.something(1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 1); + assert.equal(stats.lines[0].source(), ' return a - 1;'); + + file.something(-1); + stats = fileCoverageData.stats(); + + assert.equal(stats.lines.length, 0); + + coverage.release(); + assert.equal(require.extensions['.js'], originalRequire); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/src/coverage.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/src/coverage.js new file mode 100644 index 0000000..5b88dfe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/runforcover/test/src/coverage.js @@ -0,0 +1,7 @@ +exports.something = function(a) { + if(a > 0) { + return a + 1; + } else { + return a - 1; + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/README.md new file mode 100644 index 0000000..ed0905f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/README.md @@ -0,0 +1,27 @@ +# Slide - a tiny flow control library + +Callbacks are simple and easy if you keep the pattern consistent. + +Check out the [slide presentation](http://github.com/isaacs/slide-flow-control/raw/master/nodejs-controlling-flow.pdf). + +You'll laugh when you see how little code is actually in this thing. +It's so not-enterprisey, you won't believe it. It does almost nothing, +but it's super handy. + +I actually use an earlier version of this util in +[a real world program](http://npmjs.org/). + +## Installation + +Just copy the files into your project, and use them that way, or +you can do this: + + npm install slide + +and then: + + var asyncMap = require("slide").asyncMap + , chain = require("slide").chain + // use the power! + +Enjoy! diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/index.js new file mode 100644 index 0000000..0a9277f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/index.js @@ -0,0 +1 @@ +module.exports=require("./lib/slide") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map-ordered.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map-ordered.js new file mode 100644 index 0000000..5cca79a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map-ordered.js @@ -0,0 +1,65 @@ + +throw new Error("TODO: Not yet implemented.") + +/* +usage: + +Like asyncMap, but only can take a single cb, and guarantees +the order of the results. +*/ + +module.exports = asyncMapOrdered + +function asyncMapOrdered (list, fn, cb_) { + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMapOrdered") + + if (typeof fn !== "function") throw new Error( + "No map function provided to asyncMapOrdered") + + if (list === undefined || list === null) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + if (!list.length) return cb_(null, []) + + var errState = null + , l = list.length + , a = l + , res = [] + , resCount = 0 + , maxArgLen = 0 + + function cb (index) { return function () { + if (errState) return + var er = arguments[0] + var argLen = arguments.length + maxArgLen = Math.max(maxArgLen, argLen) + res[index] = argLen === 1 ? [er] : Array.apply(null, arguments) + + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) + var oldLen = l + l = list.length + process.nextTick(function () { + newList.forEach(function (ar, i) { fn(ar, cb(i + oldLen)) }) + }) + } + + if (er || --a === 0) { + errState = er + cb_.apply(null, [errState].concat(flip(res, resCount, maxArgLen))) + } + }} + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn, i) { fn(ar, cb(i)) }) + }) +} + +function flip (res, resCount, argLen) { + var flat = [] + // res = [[er, x, y], [er, x1, y1], [er, x2, y2, z2]] + // return [[x, x1, x2], [y, y1, y2], [undefined, undefined, z2]] + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map.js new file mode 100644 index 0000000..1ced158 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/async-map.js @@ -0,0 +1,56 @@ + +/* +usage: + +// do something to a list of things +asyncMap(myListOfStuff, function (thing, cb) { doSomething(thing.foo, cb) }, cb) +// do more than one thing to each item +asyncMap(list, fooFn, barFn, cb) + +*/ + +module.exports = asyncMap + +function asyncMap () { + var steps = Array.prototype.slice.call(arguments) + , list = steps.shift() || [] + , cb_ = steps.pop() + if (typeof cb_ !== "function") throw new Error( + "No callback provided to asyncMap") + if (!list) return cb_(null, []) + if (!Array.isArray(list)) list = [list] + var n = steps.length + , data = [] // 2d array + , errState = null + , l = list.length + , a = l * n + if (!a) return cb_(null, []) + function cb (er) { + if (errState) return + var argLen = arguments.length + for (var i = 1; i < argLen; i ++) if (arguments[i] !== undefined) { + data[i - 1] = (data[i - 1] || []).concat(arguments[i]) + } + // see if any new things have been added. + if (list.length > l) { + var newList = list.slice(l) + a += (list.length - l) * n + l = list.length + process.nextTick(function () { + newList.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) + }) + } + + if (er || --a === 0) { + errState = er + cb_.apply(null, [errState].concat(data)) + } + } + // expect the supplied cb function to be called + // "n" times for each thing in the array. + list.forEach(function (ar) { + steps.forEach(function (fn) { fn(ar, cb) }) + }) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/bind-actor.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/bind-actor.js new file mode 100644 index 0000000..6a37072 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/bind-actor.js @@ -0,0 +1,16 @@ +module.exports = bindActor +function bindActor () { + var args = + Array.prototype.slice.call + (arguments) // jswtf. + , obj = null + , fn + if (typeof args[0] === "object") { + obj = args.shift() + fn = args.shift() + if (typeof fn === "string") + fn = obj[ fn ] + } else fn = args.shift() + return function (cb) { + fn.apply(obj, args.concat(cb)) } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/chain.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/chain.js new file mode 100644 index 0000000..17b3711 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/chain.js @@ -0,0 +1,20 @@ +module.exports = chain +var bindActor = require("./bind-actor.js") +chain.first = {} ; chain.last = {} +function chain (things, cb) { + var res = [] + ;(function LOOP (i, len) { + if (i >= len) return cb(null,res) + if (Array.isArray(things[i])) + things[i] = bindActor.apply(null, + things[i].map(function(i){ + return (i===chain.first) ? res[0] + : (i===chain.last) + ? res[res.length - 1] : i })) + if (!things[i]) return LOOP(i + 1, len) + things[i](function (er, data) { + if (er) return cb(er, res) + if (data !== undefined) res = res.concat(data) + LOOP(i + 1, len) + }) + })(0, things.length) } diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/slide.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/slide.js new file mode 100644 index 0000000..6e9ec23 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/lib/slide.js @@ -0,0 +1,3 @@ +exports.asyncMap = require("./async-map") +exports.bindActor = require("./bind-actor") +exports.chain = require("./chain") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/nodejs-controlling-flow.pdf b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/nodejs-controlling-flow.pdf new file mode 100644 index 0000000..ca12d60 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/nodejs-controlling-flow.pdf differ 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 new file mode 100644 index 0000000..9c46b9a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/slide/package.json @@ -0,0 +1,31 @@ +{ + "name": "slide", + "version": "1.1.3", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "contributors": [ + { + "name": "S. Sriram", + "email": "ssriram@gmail.com", + "url": "http://www.565labs.com" + } + ], + "description": "A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS", + "main": "./lib/slide.js", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "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/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/LICENSE new file mode 100644 index 0000000..187e8db --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Isaac Z. Schlueter + +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/yamlish/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/README.md new file mode 100644 index 0000000..954d063 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/README.md @@ -0,0 +1,20 @@ +This is a thingie to parse the "yamlish" format used to serialize +objects in the TAP format. + +It's like yaml, but just a tiny little bit smaller. + +Usage: + + var yamlish = require("yamlish") + // returns a string like: + /* + some: + object: + - full + - of + pretty: things + */ + yamlish.encode({some:{object:["full", "of"]}, pretty:"things"}) + + // returns the object + yamlish.decode(someYamlishString) 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 new file mode 100644 index 0000000..359300d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/package.json @@ -0,0 +1,9 @@ +{ "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/node_modules/yamlish/yamlish.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/yamlish.js new file mode 100644 index 0000000..dd8c370 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/yamlish.js @@ -0,0 +1,260 @@ +exports.encode = encode +exports.decode = decode + +var seen = [] +function encode (obj, indent) { + var deep = arguments[2] + if (!indent) indent = " " + + if (obj instanceof String || + Object.prototype.toString.call(obj) === "[object String]") { + obj = obj.toString() + } + + if (obj instanceof Number || + Object.prototype.toString.call(obj) === "[object Number]") { + obj = obj.valueOf() + } + + // take out the easy ones. + switch (typeof obj) { + case "string": + obj = obj.trim() + if (obj.indexOf("\n") !== -1) { + return "|\n" + indent + obj.split(/\r?\n/).join("\n"+indent) + } else { + return (obj) + } + + case "number": + return obj.toString(10) + + case "function": + return encode(obj.toString(), indent, true) + + case "boolean": + return obj.toString() + + case "undefined": + // fallthrough + case "object": + // at this point we know it types as an object + if (!obj) return "~" + + if (obj instanceof Date || + Object.prototype.toString.call(obj) === "[object Date]") { + return JSON.stringify("[Date " + obj.toISOString() + "]") + } + + if (obj instanceof RegExp || + Object.prototype.toString.call(obj) === "[object RegExp]") { + return JSON.stringify(obj.toString()) + } + + if (obj instanceof Boolean || + Object.prototype.toString.call(obj) === "[object Boolean]") { + return obj.toString() + } + + if (seen.indexOf(obj) !== -1) { + return "[Circular]" + } + seen.push(obj) + + if (typeof Buffer === "function" && + typeof Buffer.isBuffer === "function" && + Buffer.isBuffer(obj)) return obj.inspect() + + if (obj instanceof Error) { + var o = { name: obj.name + , message: obj.message + , type: obj.type } + + if (obj.code) o.code = obj.code + if (obj.errno) o.errno = obj.errno + if (obj.type) o.type = obj.type + obj = o + } + + var out = "" + + if (Array.isArray(obj)) { + var out = "\n" + indent + "- " +obj.map(function (item) { + return encode(item, indent + " ", true) + }).join("\n"+indent + "- ") + break + } + + // an actual object + var keys = Object.keys(obj) + , niceKeys = keys.map(function (k) { + return (k.match(/^[a-zA-Z0-9_]+$/) ? k : JSON.stringify(k)) + ": " + }) + //console.error(keys, niceKeys, obj) + var maxLength = Math.max.apply(Math, niceKeys.map(function (k) { + return k.length + }).concat(0)) + //console.error(niceKeys, maxLength) + + var spaces = new Array(maxLength + 1).join(" ") + + if (!deep) indent += " " + out = "\n" + indent + keys.map(function (k, i) { + var niceKey = niceKeys[i] + return niceKey + spaces.substr(niceKey.length) + + encode(obj[k], indent + " ", true) + }).join("\n" + indent) + break + + default: return "" + } + if (!deep) seen.length = 0 + return out +} + +function decode (str) { + var v = str.trim() + , d + , dateRe = /^\[Date ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}(?::[0-9]{2})?(?:\.[0-9]{3})?(?:[A-Z]+)?)\]$/ + + if (v === "~") return null + + try { + var jp = JSON.parse(str) + } catch (e) { + var jp = "" + } + + if (jp && + typeof jp === "string" && + (d = jp.match(dateRe)) && + (d = Date.parse(d[1]))) { + return new Date(d) + } + + if (typeof jp === "boolean") return jp + if (v && !isNaN(v)) return parseInt(v, 10) + + // something interesting. + var lines = str.split(/\r?\n/) + // check if it's some kind of string or something. + // if the first line is > or | then it's a wrapping indented string. + // if the first line is blank, and there are many lines, + // then it's an array or object. + // otherwise, it's just "" + var first = lines.shift().trim() + if (lines.length) lines = undent(lines) + switch (first) { + case "|": + return lines.join("\n") + case ">": + return lines.join("\n").split(/\n{2,}/).map(function (l) { + return l.split(/\n/).join(" ") + }).join("\n") + default: + if (!lines.length) return first + // array or object. + // the first line will be either "- value" or "key: value" + return lines[0].charAt(0) === "-" ? decodeArr(lines) : decodeObj(lines) + } +} + +function decodeArr (lines) { + var out = [] + , key = 0 + , val = [] + for (var i = 0, l = lines.length; i < l; i ++) { + // if it starts with a -, then it's a new thing + var line = lines[i] + if (line.charAt(0) === "-") { + if (val.length) { + out[key ++] = decode(val.join("\n")) + val.length = 0 + } + val.push(line.substr(1).trim()) + } else if (line.charAt(0) === " ") { + val.push(line) + } else return [] + } + if (val.length) { + out[key ++] = decode(val.join("\n")) + } + return out +} + +function decodeObj (lines) { + var out = {} + , val = [] + , key = null + + for (var i = 0, l = lines.length; i < l; i ++) { + var line = lines[i] + if (line.charAt(0) === " ") { + val.push(line) + continue + } + // some key:val + if (val.length) { + out[key] = decode(val.join("\n")) + val.length = 0 + } + // parse out the quoted key + var first + if (line.charAt(0) === "\"") { + for (var ii = 1, ll = line.length, esc = false; ii < ll; ii ++) { + var c = line.charAt(ii) + if (c === "\\") { + esc = !esc + } else if (c === "\"" && !esc) { + break + } + } + key = JSON.parse(line.substr(0, ii + 1)) + line = line.substr(ii + 1) + first = line.substr(line.indexOf(":") + 1).trim() + } else { + var kv = line.split(":") + key = kv.shift() + first = kv.join(":").trim() + } + // now we've set a key, and "first" has the first line of the value. + val.push(first.trim()) + } + if (val.length) out[key] = decode(val.join("\n")) + return out +} + +function undent (lines) { + var i = lines[0].match(/^\s*/)[0].length + return lines.map(function (line) { + return line.substr(i) + }) +} + + +// XXX Turn this into proper tests. +if (require.main === module) { +var obj = [{"bigstring":new Error().stack} + ,{ar:[{list:"of"},{some:"objects"}]} + ,{date:new Date()} + ,{"super huge string":new Error().stack} + ] + +Date.prototype.toJSON = function (k, val) { + console.error(k, val, this) + return this.toISOString() + " (it's a date)" +} + +var enc = encode(obj) + , dec = decode(enc) + , encDec = encode(dec) + +console.error(JSON.stringify({ obj : obj + , enc : enc.split(/\n/) + , dec : dec }, null, 2), encDec === enc) + +var num = 100 + , encNum = encode(num) + , decEncNum = decode(encNum) +console.error([num, encNum, decEncNum]) +} 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 new file mode 100644 index 0000000..f0d48d0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/package.json @@ -0,0 +1,61 @@ +{ + "name": "tap", + "version": "0.3.3", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "description": "A Test-Anything-Protocol library", + "bin": { + "tap": "bin/tap.js" + }, + "main": "lib/main.js", + "dependencies": { + "inherits": "*", + "yamlish": "*", + "slide": "*", + "runforcover": "~0.0.2", + "nopt": "~2", + "mkdirp": "~0.3", + "difflet": "~0.2.0", + "deep-equal": "~0.0.0", + "buffer-equal": "~0.0.0" + }, + "keywords": [ + "assert", + "test", + "tap" + ], + "contributors": [ + { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + { + "name": "baudehlo", + "email": "helpme+github@gmail.com" + } + ], + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/node-tap/raw/master/LICENSE" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-tap.git" + }, + "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 ./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", + "yamlish" + ], + "_from": "tap@>=0.2.3" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/bailout.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/bailout.js new file mode 100644 index 0000000..498035c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/bailout.js @@ -0,0 +1,36 @@ +var tap = require("tap") + , test = tap.test + +test("bailout test", { skip: false }, function (t) { + + // t.once("bailout", function () { + // console.error("bailout event")//, t) + // t.clear() + // }) + + // t.once("end", function () { + // console.error("end event") + // }) + + // simulate three tests where the second bails out. + t.test("first", function (t) { + t.pass("this is ok") + t.end() + }) + + t.test("bailout", function (t) { + console.error("bailout test") + t.pass("pass") + t.bailout("bail out message") + t.fail("fail") + t.end() + }) + + t.test("second (should not happen)", function (t) { + t.fail("this should not happen") + t.end() + }) + + t.end() + +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/foo.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/foo.js new file mode 100644 index 0000000..6360156 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/foo.js @@ -0,0 +1 @@ +process.stdin diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/t.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/t.js new file mode 100644 index 0000000..581d24b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test-disabled/t.js @@ -0,0 +1,16 @@ +var test = require('tap').test; + +function foo() { + throw new Error('one'); +} + +test('demonstrate bug in t.throws', function (t) { + t.throws( + function () { + foo(); + }, + new Error('two')), + // "this should throw", + // {}); // not 'one'! + t.end(); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/buffer_compare.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/buffer_compare.js new file mode 100644 index 0000000..b1e1505 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/buffer_compare.js @@ -0,0 +1,11 @@ +var test = require("../").test + +test("same buffers", function (t) { + t.same(new Buffer([3,4,243]), new Buffer([3,4,243])) + t.end() +}) + +test("not same buffers", function (t) { + t.notSame(new Buffer([3,5,243]), new Buffer([3,4,243])) + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/common.js new file mode 100644 index 0000000..7cc43c1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/common.js @@ -0,0 +1,32 @@ +exports.taps = ["Tests for the foo module" + ,{ok:true, name:"test that the foo is fooish" + ,file:"foo.js", line:8, name:"fooish test" + ,stack:new Error("fooish").stack} + ,{ok:false, name:"a test that the bar is barish" + ,file:"bar.js", line:25 + ,expected:"bar\nbar\nbaz", actual:"rab\nrib\nzib" + ,hash:{more:"\nstuff\nhere\n",regexp:/asdf/}} + ,"Quux module tests" + ,"This is a longer comment" + ,{ok:true, name:"an easy one."} + ,{ok:false, name:"bloooooo" + ,expected:"blerggeyyy" + ,actual:"blorggeyy"} + ,{ok:false, name:"array test" + ,expected:[{ok:true},{ok:true},{stack:new Error().stack}] + ,actual:[1234567890,123456789,{error:new Error("yikes")}]} + ,{ok:true, name:"nulltest" + ,expected:undefined, actual:null} + ,{ok:true, name:"weird key test" + ,expected:"weird key" + ,actual:"weird key" + ,"this object":{"has a ":"weird key" + ,"and a looooooooonnnnnnnnnggg":"jacket"}} + ,{ok:true, name:"regexp test" + ,regexp:/asdf/,function:function (a,b) { return a + b }} + ] + +if (require.main === module) { + console.log("1..1") + console.log("ok 1 - just setup, nothing relevant") +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/deep.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/deep.js new file mode 100644 index 0000000..52b6110 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/deep.js @@ -0,0 +1,43 @@ +var tap = require("../") + , test = tap.test + +test("deepEquals shouldn't care about key order", function (t) { + t.deepEqual({ a : 1, b : 2 }, { b : 2, a : 1 }) + t.end() +}) + +test("deepEquals shouldn't care about key order recursively", function (t) { + t.deepEqual( + { x : { a : 1, b : 2 }, y : { c : 3, d : 4 } }, + { y : { d : 4, c : 3 }, x : { b : 2, a : 1 } } + ) + t.end() +}) + +test("deepEquals shoudn't care about key order but still might", function (t) { + t.deepEqual( + [ { foo: + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { d : 4 + , a: 1 + , b: 2 + , c: 3 } } ] + , [ { foo : + { z: 100 + , y: 200 + , x: 300 } } + , "bar" + , 11 + , { baz: + { a: 1 + , b: 2 + , c: 3 + , d: 4 } } ] + ) + t.end() +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/end-exception/t.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/end-exception/t.js new file mode 100644 index 0000000..eaa5b46 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/end-exception/t.js @@ -0,0 +1,12 @@ +var test = require("../../").test + +test(function (t) { + t.plan(1) + + t.on('end', function () { + console.log('end()') + throw new Error('beep') + }) + + t.equal(3, 3) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/executed.sh b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/executed.sh new file mode 100755 index 0000000..7300937 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/executed.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "1..1" +echo "ok 1 File with executable bit should be executed" diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/expose-gc-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/expose-gc-test.js new file mode 100644 index 0000000..87377c1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/expose-gc-test.js @@ -0,0 +1,46 @@ +var tap = require("../") + , fs = require("fs") + , cp = require("child_process") + +fs.writeFileSync("gc-script.js", "console.log(!!global.gc)", "utf8") + +tap.test("gc test when the gc isn't there", function (t) { + console.error("gc test") + t.plan(1) + console.error("t.plan="+t._plan) + + cp.exec("../bin/tap.js ./gc-script", function (err, stdo, stde) { + console.error("assert gc does not exist") + t.ok("false", stdo) + }) +}) + +tap.test("gc test when the gc should be there", function (t) { + console.error("gc test") + t.plan(2) + console.error("t.plan="+t._plan) + + t.test("test for gc using --gc", function (t) { + console.error("gc test using --gc") + t.plan(1) + console.error("t.plan="+t._plan) + + cp.exec("../bin/tap.js --gc ./gc-script", function (err, stdo, stde) { + console.error("assert gc exists") + t.ok("true", stdo) + }) + }) + + t.test("test for gc using --expose-gc", function (t) { + console.error("gc test using --expose-gc") + t.plan(1) + console.error("t.plan="+t._plan) + + cp.exec("../bin/tap.js --expose-gc ./gc-script", function (err, stdo) { + console.error("assert gc exists") + t.ok("true", stdo) + }) + }) +}) + +fs.unlinkSync("gc-script.js"); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/independent-timeouts.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/independent-timeouts.js new file mode 100644 index 0000000..5a35e61 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/independent-timeouts.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/23 + +var tap = require("../") + , test = tap.test + +test("finishes in time", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) +test("finishes in time too", {timeout: 500}, function(t) { + setTimeout(function () { + t.end(); + }, 300); +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/isolated-conf-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/isolated-conf-test.js new file mode 100644 index 0000000..d8bfae6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/isolated-conf-test.js @@ -0,0 +1,16 @@ +// https://github.com/isaacs/node-tap/issues/24 + +var tap = require("../") + , test = tap.test + +var config = {foo: "bar"} +test("one", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "one") // before fix this would be "two" + t.end() +}) +test("two", config, function(t) { + t.equal(t.conf.foo, "bar") + t.equal(t.conf.name, "two") + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/meta-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/meta-test.js new file mode 100644 index 0000000..8f56f26 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/meta-test.js @@ -0,0 +1,73 @@ +var tap = require("../") + , test = tap.test + +test("meta test", { skip: false }, function (t) { + + function thr0w() { throw new Error('raburt') } + function noop () {} + + // this also tests the ok/notOk functions + t.once("end", section2) + t.ok(true, "true is ok") + t.ok(noop, "function is ok") + t.ok({}, "object is ok") + t.ok(t, "t is ok") + t.ok(100, "number is ok") + t.ok("asdf", "string is ok") + t.notOk(false, "false is notOk") + t.notOk(0, "0 is notOk") + t.notOk(null, "null is notOk") + t.notOk(undefined, "undefined is notOk") + t.notOk(NaN, "NaN is notOk") + t.notOk("", "empty string is notOk") + t.throws(thr0w, "Thrower throws"); + t.doesNotThrow(noop, "noop does not throw"); + t.similar({foo:"bar", bar:"foo"}, {foo:"bar"}, "similar objects are ok"); + t.dissimilar({}, {mandatory:"value"}, "dissimilar objects are ok"); + t.dissimilar(null, {}, "null is dissimilar from an object, even with no keys"); + + // a few failures. + t.ifError(new Error("this is an error")) + t.ifError({ message: "this is a custom error" }) + t.ok(false, "false is not ok") + t.notOk(true, "true is not not ok") + t.similar(null, {}, "Null is not similar to an object, even with no keys"); + t.throws(noop, "noop does not throw"); + t.throws(noop, new Error("Whoops!"), "noop does not throw an Error"); + t.throws(noop, {name:"MyError", message:"Whoops!"}, "noop does not throw a MyError"); + t.doesNotThrow(thr0w, "thrower does throw"); + + // things that are like other things + t.like("asdf", "asdf") + t.like("asdf", /^a.*f$/) + t.like(100, 100) + t.like(100, '100') + t.like(100, 100.0) + t.unlike("asdf", "fdsa") + t.unlike("asdf", /^you jelly, bro?/) + t.unlike(100, 100.1) + t.like(true, 1) + t.like(null, undefined) + t.like(true, [1]) + t.like(false, []) + t.like('', []) + t.end() + + function section2 () { + var results = t.results + t.clear() + t.ok(true, "sanity check") + t.notOk(results.ok, "not ok") + t.equal(results.tests, 39, "total test count") + t.equal(results.passTotal, 30, "tests passed") + t.equal(results.fail, 9, "tests failed") + t.type(results.ok, "boolean", "ok is boolean") + t.type(results.skip, "number", "skip is number") + t.type(results, "Results", "results isa Results") + t.type(t, "Test", "test isa Test") + t.type(t, "Harness", "test isa Harness") + t.end() + } +}) + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/nested-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/nested-test.js new file mode 100644 index 0000000..493f13a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/nested-test.js @@ -0,0 +1,23 @@ +var tap = require("../"), + test = tap.test, + util = require('util'); + +test("parent", function (t) { + // TODO: Make grandchildren tests count? + t.plan(3); + t.ok(true, 'p test'); + t.test("subtest", function (t) { + t.ok(true, 'ch test'); + t.test('nested subtest', function(t) { + t.ok(true, 'grch test'); + t.end(); + }); + t.end(); + }); + t.test('another subtest', function(t) { + t.ok(true, 'ch test 2'); + t.end(); + }); + t.end(); +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/non-tap-output.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/non-tap-output.js new file mode 100644 index 0000000..929e9aa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/non-tap-output.js @@ -0,0 +1,12 @@ +console.log("everything is fine\n" + +"there are no errors\n" + +"this output is not haiku.\n\n" + +"is 8 ok?\n" + +"ok, 8 can stay.\n" + +"ok 100 might be confusing\n" + +" but: nevertheless, here we are\n" + +" this: is indented\n" + +" and: it\n" + +" might: ~\n" + +" be: yaml?\n" + +"ok done now, exiting") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/not-executed.sh b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/not-executed.sh new file mode 100644 index 0000000..de46caa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/not-executed.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "1..1" +echo "not ok 1 File without executable bit should not be run" 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/result-trap.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/result-trap.js new file mode 100644 index 0000000..1ac600f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/result-trap.js @@ -0,0 +1,25 @@ +var tap = require("../") + +tap.test("trap result #TODO", function (t0) { + + console.log("not ok 1 result event trapping #TODO") + return t0.end() + + t0.plan(3) + + var t1 = new(tap.Harness)(tap.Test).test() + + t1.plan(1) + + t1.on("result", function (res) { + if (res.wanted === 4) { + t0.equal(res.found, 3) + t0.equal(res.wanted, 4) + + t0.end() + t1.end() + } + }) + + t1.equal(1 + 2, 4) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/segv.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/segv.js new file mode 100644 index 0000000..4b5fe89 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/segv.js @@ -0,0 +1,60 @@ +var test = require('../').test +var Runner = require('../lib/tap-runner.js') +var TC = require('../lib/tap-consumer.js') + +var fs = require('fs') +var spawn = require('child_process').spawn +var segv = + 'int main (void) {\n' + + ' char *s = "hello world";\n' + + ' *s = \'H\';\n' + + '}\n' +var compiled = false + +test('setup', function (t) { + fs.writeFile('segv.c', segv, 'utf8', function (er) { + if (er) + throw er + var cp = spawn('gcc', ['segv.c', '-o', 'segv']) + cp.on('exit', function (code, sig) { + if (code !== 0) { + t.bailout('failed to compile segv program') + return + } + t.pass('compiled seg faulter') + t.end() + }) + }) +}) + +test('segv', function (t) { + var r = new Runner({argv:{remain:['./segv']}}) + var tc = new TC() + var expect = + [ { 'id': 1, + 'ok': false, + 'name': ' ././segv', + 'exit': null, + 'timedOut': true, + 'signal': 'SIGBUS', + 'command': '"./segv"' } + , 'tests 1' + , 'fail 1' ] + r.pipe(tc) + tc.on('data', function (d) { + t.same(d, expect.shift()) + }) + tc.on('end', function () { + t.equal(expect.length, 0) + t.end() + }) +}) + +test('cleanup', function (t) { + fs.unlink('segv.c', function () { + fs.unlink('segv', function () { + t.pass('cleaned up') + t.end() + }) + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test-with-plan.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test-with-plan.js new file mode 100644 index 0000000..813c4cf --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test-with-plan.js @@ -0,0 +1,16 @@ +var tap = require("../") + , test = tap.test + , plan = tap.plan + +plan(2) + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test.js new file mode 100644 index 0000000..64451ae --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/simple-harness-test.js @@ -0,0 +1,13 @@ +var tap = require("../") + , test = tap.test + +test("trivial success", function (t) { + t.ok(true, "it works") + t.end() +}) + +test("two tests", function (t) { + t.equal(255, 0xFF, "math should work") + t.notOk(false, "false should not be ok") + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/test-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/test-test.js new file mode 100644 index 0000000..f383941 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/test-test.js @@ -0,0 +1,91 @@ +var tap = require("../") + , test = tap.test + , Test = require("../lib/tap-test") + , Harness = require("../lib/tap-harness") + +test("testing the test object", function (t) { + + t.isa(t, Test, "test object should be instanceof Test") + t.isa(t, Harness, "test object should be instanceof Harness") + t.is(t._Test, Test, "test._Test should be the Test class") + + // now test all the methods. + ; [ "isNotDeepEqual" + , "equals" + , "inequivalent" + , "threw" + , "strictEqual" + , "emit" + , "fail" + , "strictEquals" + , "notLike" + , "dissimilar" + , "true" + , "assert" + , "is" + , "ok" + , "isEqual" + , "isDeeply" + , "deepEqual" + , "deepEquals" + , "pass" + , "length" + , "skip" + , "isNotEqual" + , "looseEquals" + , "false" + , "notDeeply" + , "ifErr" + , "hasFields" + , "isNotDeeply" + , "like" + , "similar" + , "notOk" + , "isDissimilar" + , "isEquivalent" + , "doesNotEqual" + , "isSimilar" + , "notDeepEqual" + , "type" + , "notok" + , "isInequivalent" + , "isNot" + , "same" + , "isInequal" + , "_endNice" + , "ifError" + , "iferror" + , "clear" + , "has" + , "not" + , "timeout" + , "notSimilar" + , "isUnlike" + , "notEquals" + , "unsimilar" + , "result" + , "doesNotThrow" + , "error" + , "constructor" + , "notEqual" + , "throws" + , "isLike" + , "isNotSimilar" + , "isNotEquivalent" + , "inequal" + , "notEquivalent" + , "isNotLike" + , "equivalent" + , "looseEqual" + , "equal" + , "unlike" + , "doesNotHave" + , "comment" + , "isa" + ].forEach(function (method) { + t.ok(t[method], "should have "+method+" method") + t.isa(t[method], "function", method+" method should be a function") + }) + t.end() +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/timeout.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/timeout.js new file mode 100644 index 0000000..4ee409c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/timeout.js @@ -0,0 +1,33 @@ +var tap = require("../") + +tap.test("timeout test with plan only", function (t) { + console.error("timeout test") + t.plan(2) + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + }, 1000) +}) + +tap.test("timeout test with plan and end", function (t) { + console.error("timeout test") + t.plan(2) + + var tc = 2 + console.error("t.plan="+t._plan) + setTimeout(function () { + console.error("a assert") + t.ok(true, "a") + if (-- tc === 0) t.end() + }, 1000) + setTimeout(function () { + console.error("b assert") + t.ok(true, "b") + if (-- tc === 0) t.end() + }, 1000) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/trivial-success.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/node_modules/tap/test/trivial-success.js new file mode 100644 index 0000000..e69de29 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/nodelint.cfg b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/nodelint.cfg new file mode 100644 index 0000000..d6a3aad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/nodelint.cfg @@ -0,0 +1,7 @@ +//See: http://www.jslint.com/lint.html#options +var options = { + //white: false, // if false, strict whitespace rules should be enforced. + indent: 4, + onevar: false, + vars: true // allow multiple var statement per function. +}; 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 new file mode 100644 index 0000000..a2ea6c3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/package.json @@ -0,0 +1,97 @@ +{ + "name": "nodeunit", + "description": "Easy unit testing for node.js and the browser.", + "maintainers": [ + { + "name": "Caolan McMahon", + "url": "https://github.com/caolan" + } + ], + "contributors": [ + { + "name": "Romain Beauxis", + "url": "https://github.com/toots" + }, + { + "name": "Alex Gorbatchev", + "url": "https://github.com/alexgorbatchev" + }, + { + "name": "Alex Wolfe", + "url": "https://github.com/alexkwolfe" + }, + { + "name": "Carl Fürstenberg", + "url": "https://github.com/azatoth" + }, + { + "name": "Gerad Suyderhoud", + "url": "https://github.com/gerad" + }, + { + "name": "Kadir Pekel", + "url": "https://github.com/coffeemate" + }, + { + "name": "Oleg Efimov", + "url": "https://github.com/Sannis" + }, + { + "name": "Orlando Vazquez", + "url": "https://github.com/orlandov" + }, + { + "name": "Ryan Dahl", + "url": "https://github.com/ry" + }, + { + "name": "Sam Stephenson", + "url": "https://github.com/sstephenson" + }, + { + "name": "Thomas Mayfield", + "url": "https://github.com/thegreatape" + }, + { + "name": "Elijah Insua", + "email": "tmpvar@gmail.com", + "url": "http://tmpvar.com" + } + ], + "version": "0.7.4", + "repository": { + "type": "git", + "url": "http://github.com/caolan/nodeunit.git" + }, + "devDependencies": { + "uglify-js": ">=1.1.0", + "should": ">=0.4.2" + }, + "bugs": { + "url": "http://github.com/caolan/nodeunit/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/nodeunit/raw/master/LICENSE" + } + ], + "directories": { + "lib": "./lib", + "doc": "./doc", + "man": "./man1" + }, + "bin": { + "nodeunit": "./bin/nodeunit" + }, + "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" + ], + "_id": "nodeunit@0.7.4", + "_from": "nodeunit@~0.7.4" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/junit.xml.ejs b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/junit.xml.ejs new file mode 100644 index 0000000..c1db5bb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/junit.xml.ejs @@ -0,0 +1,19 @@ + +<% for (var i=0; i < suites.length; i++) { %> + <% var suite=suites[i]; %> + + <% for (var j=0; j < suite.testcases.length; j++) { %> + <% var testcase=suites[i].testcases[j]; %> + + <% if (testcase.failure) { %> + + <% if (testcase.failure.backtrace) { %><%= testcase.failure.backtrace %><% } %> + + <% } %> + + <% } %> + +<% } %> diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/license.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/license.js new file mode 100644 index 0000000..f0f326f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/license.js @@ -0,0 +1,11 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/nodeunit.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/share/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/coffee/mock_coffee_module.coffee b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/coffee/mock_coffee_module.coffee new file mode 100644 index 0000000..a1c069b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/coffee/mock_coffee_module.coffee @@ -0,0 +1,4 @@ +j = 0 +j += i for i in [0..5] + +exports.name = "mock_coffee_#{j}" diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module3.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module3.js new file mode 100644 index 0000000..3021776 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module3.js @@ -0,0 +1 @@ +exports.name = 'mock_module3'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module4.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module4.js new file mode 100644 index 0000000..876f9ca --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/dir/mock_module4.js @@ -0,0 +1 @@ +exports.name = 'mock_module4'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module1.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module1.js new file mode 100644 index 0000000..4c093ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module1.js @@ -0,0 +1 @@ +exports.name = 'mock_module1'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module2.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module2.js new file mode 100644 index 0000000..a63d012 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/mock_module2.js @@ -0,0 +1 @@ +exports.name = 'mock_module2'; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode1.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode1.js new file mode 100644 index 0000000..2ef7115 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode1.js @@ -0,0 +1,3 @@ +function hello_world(arg) { + return "_" + arg + "_"; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode2.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode2.js new file mode 100644 index 0000000..55a764e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode2.js @@ -0,0 +1,3 @@ +function get_a_variable() { + return typeof a_variable; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode3.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode3.js new file mode 100644 index 0000000..1fd1e78 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/fixtures/raw_jscode3.js @@ -0,0 +1 @@ +var t=t?t+1:1; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-base.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-base.js new file mode 100644 index 0000000..5335046 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-base.js @@ -0,0 +1,239 @@ +/* + * This module is not a plain nodeunit test suite, but instead uses the + * assert module to ensure a basic level of functionality is present, + * allowing the rest of the tests to be written using nodeunit itself. + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +var assert = require('assert'), // @REMOVE_LINE_FOR_BROWSER + async = require('../deps/async'), // @REMOVE_LINE_FOR_BROWSER + nodeunit = require('../lib/nodeunit'); // @REMOVE_LINE_FOR_BROWSER + + +// NOT A TEST - util function to make testing faster. +// retries the assertion until it passes or the timeout is reached, +// at which point it throws the assertion error +var waitFor = function (fn, timeout, callback, start) { + start = start || new Date().getTime(); + callback = callback || function () {}; + try { + fn(); + callback(); + } + catch (e) { + if (e instanceof assert.AssertionError) { + var now = new Date().getTime(); + if (now - start >= timeout) { + throw e; + } + else { + async.nextTick(function () { + waitFor(fn, timeout, callback, start); + }); + } + } + else { + throw e; + } + } +}; + + +// TESTS: + +// Are exported tests actually run? - store completed tests in this variable +// for checking later +var tests_called = {}; + +// most basic test that should run, the tests_called object is tested +// at the end of this module to ensure the tests were actually run by nodeunit +exports.testCalled = function (test) { + tests_called.testCalled = true; + test.done(); +}; + +// generates test functions for nodeunit assertions +var makeTest = function (method, args_pass, args_fail) { + return function (test) { + var test1_called = false; + var test2_called = false; + + // test pass + nodeunit.runTest( + 'testname', + function (test) { + test[method].apply(test, args_pass); + test.done(); + }, + {testDone: function (name, assertions) { + assert.equal(assertions.length, 1); + assert.equal(assertions.failures(), 0); + }}, + function () { + test1_called = true; + } + ); + + // test failure + nodeunit.runTest( + 'testname', + function (test) { + test[method].apply(test, args_fail); + test.done(); + }, + {testDone: function (name, assertions) { + assert.equal(assertions.length, 1); + assert.equal(assertions.failures(), 1); + }}, + function () { + test2_called = true; + } + ); + + // ensure tests were run + waitFor(function () { + assert.ok(test1_called); + assert.ok(test2_called); + tests_called[method] = true; + }, 500, test.done); + }; +}; + +// ensure basic assertions are working: +exports.testOk = makeTest('ok', [true], [false]); +exports.testEquals = makeTest('equals', [1, 1], [1, 2]); +exports.testSame = makeTest('same', + [{test: 'test'}, {test: 'test'}], + [{test: 'test'}, {monkey: 'penguin'}] +); + +// from the assert module: +exports.testEqual = makeTest('equal', [1, 1], [1, 2]); +exports.testNotEqual = makeTest('notEqual', [1, 2], [1, 1]); +exports.testDeepEqual = makeTest('deepEqual', + [{one: 1}, {one: 1}], [{one: 1}, {two: 2}] +); +exports.testNotDeepEqual = makeTest('notDeepEqual', + [{one: 1}, {two: 2}], [{one: 1}, {one: 1}] +); +exports.testStrictEqual = makeTest('strictEqual', [1, 1], [1, true]); +exports.testNotStrictEqual = makeTest('notStrictEqual', [true, 1], [1, 1]); +exports.testThrows = makeTest('throws', + [function () { + throw new Error('test'); + }], + [function () { + return; + }] +); +exports.testThrowsWithReGex = makeTest('throws', + [function () { + throw new Error('test'); + }, /test/], + [function () { + throw new Error('test'); + }, /fail/] +); +exports.testThrowsWithErrorValidation = makeTest('throws', + [function () { + throw new Error('test'); + }, function(err) { + return true; + }], + [function () { + throw new Error('test'); + }, function(err) { + return false; + }] +); +exports.testDoesNotThrows = makeTest('doesNotThrow', + [function () { + return; + }], + [function () { + throw new Error('test'); + }] +); +exports.testIfError = makeTest('ifError', [false], [new Error('test')]); + + +exports.testExpect = function (test) { + var test1_called = false, + test2_called = false, + test3_called = false; + + // correct number of tests run + nodeunit.runTest( + 'testname', + function (test) { + test.expect(2); + test.ok(true); + test.ok(true); + test.done(); + }, + {testDone: function (name, assertions) { + test.equals(assertions.length, 2); + test.equals(assertions.failures(), 0); + }}, + function () { + test1_called = true; + } + ); + + // no tests run + nodeunit.runTest( + 'testname', + function (test) { + test.expect(2); + test.done(); + }, + {testDone: function (name, assertions) { + test.equals(assertions.length, 1); + test.equals(assertions.failures(), 1); + }}, + function () { + test2_called = true; + } + ); + + // incorrect number of tests run + nodeunit.runTest( + 'testname', + function (test) { + test.expect(2); + test.ok(true); + test.ok(true); + test.ok(true); + test.done(); + }, + {testDone: function (name, assertions) { + test.equals(assertions.length, 4); + test.equals(assertions.failures(), 1); + }}, + function () { + test3_called = true; + } + ); + + // ensure callbacks fired + waitFor(function () { + assert.ok(test1_called); + assert.ok(test2_called); + assert.ok(test3_called); + tests_called.expect = true; + }, 1000, test.done); +}; + + +// tests are async, so wait for them to be called +waitFor(function () { + assert.ok(tests_called.testCalled); + assert.ok(tests_called.ok); + assert.ok(tests_called.equals); + assert.ok(tests_called.same); + assert.ok(tests_called.expect); +}, 10000); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-bettererrors.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-bettererrors.js new file mode 100644 index 0000000..d20ca24 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-bettererrors.js @@ -0,0 +1,71 @@ +/* + * Test utils.betterErrors. utils.betterErrors should provide sensible error messages even when the error does not + * contain expected, actual or operator. + */ +var assert = require("../lib/assert"); +var should = require("should"); +var types = require("../lib/types"); +var util = require('util'); +var utils = require("../lib/utils"); + +function betterErrorStringFromError(error) { + var assertion = types.assertion({error: error}); + var better = utils.betterErrors(assertion); + return better.error.stack.toString(); +} + +function performBasicChecks(betterErrorString) { + betterErrorString.should.include("AssertionError"); + betterErrorString.should.include("test-bettererrors"); + betterErrorString.should.not.include("undefined"); +} + +/** + * Control test. Provide an AssertionError that contains actual, expected operator values. + * @param test the test object from nodeunit + */ +exports.testEqual = function (test) { + try { + assert.equal(true, false); + } catch (error) { + var betterErrorString = betterErrorStringFromError(error); + performBasicChecks(betterErrorString); + betterErrorString.should.include("true"); + betterErrorString.should.include("false"); + betterErrorString.should.include("=="); + test.done(); + } +}; + +/** + * Test an AssertionError that does not contain actual, expected or operator values. + * @param test the test object from nodeunit + */ +exports.testAssertThrows = function (test) { + try { + assert.throws(function () { + }); + } catch (error) { + var betterErrorString = betterErrorStringFromError(error); + performBasicChecks(betterErrorString); + test.done(); + } +}; + +/** + * Test with an error that is not an AssertionError. + * @param test the test object from nodeunit + */ +exports.testNonAssertionError = function (test) { + try { + throw new Error("test error"); + } catch (error) { + var betterErrorString = betterErrorStringFromError(error); + betterErrorString.should.not.include("AssertionError"); + betterErrorString.should.include("Error"); + betterErrorString.should.include("test error"); + betterErrorString.should.include("test-bettererrors"); + betterErrorString.should.not.include("undefined"); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-failing-callbacks.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-failing-callbacks.js new file mode 100644 index 0000000..08f7eb5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-failing-callbacks.js @@ -0,0 +1,114 @@ +var nodeunit = require('../lib/nodeunit'); + + +exports.testFailingLog = function (test) { + test.expect(3); + + // this is meant to bubble to the top, and will be ignored for the purposes + // of testing: + var ignored_error = new Error('ignore this callback error'); + var err_handler = function (err) { + if (err && err.message !== ignored_error.message) { + throw err; + } + }; + process.addListener('uncaughtException', err_handler); + + // A failing callback should not affect the test outcome + var testfn = function (test) { + test.ok(true, 'test.ok'); + test.done(); + }; + nodeunit.runTest('testname', testfn, { + log: function (assertion) { + test.ok(true, 'log called'); + throw ignored_error; + }, + testDone: function (name, assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 1, 'total'); + process.removeListener('uncaughtException', err_handler); + } + }, test.done); +}; + +exports.testFailingTestDone = function (test) { + test.expect(2); + + var ignored_error = new Error('ignore this callback error'); + var err_handler = function (err) { + if (err && err.message !== ignored_error.message) { + throw err; + } + }; + process.addListener('uncaughtException', err_handler); + + // A failing callback should not affect the test outcome + var testfn = function (test) { + test.done(); + }; + nodeunit.runTest('testname', testfn, { + log: function (assertion) { + test.ok(false, 'log should not be called'); + }, + testDone: function (name, assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 0, 'total'); + process.nextTick(function () { + process.removeListener('uncaughtException', err_handler); + test.done(); + }); + throw ignored_error; + } + }, function () {}); +}; + +exports.testAssertionObj = function (test) { + test.expect(4); + var testfn = function (test) { + test.ok(true, 'ok true'); + test.done(); + }; + nodeunit.runTest('testname', testfn, { + log: function (assertion) { + test.ok(assertion.passed() === true, 'assertion.passed'); + test.ok(assertion.failed() === false, 'assertion.failed'); + }, + testDone: function (name, assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 1, 'total'); + } + }, test.done); +}; + +exports.testLogOptional = function (test) { + test.expect(2); + var testfn = function (test) { + test.ok(true, 'ok true'); + test.done(); + }; + nodeunit.runTest('testname', testfn, { + testDone: function (name, assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 1, 'total'); + } + }, test.done); +}; + +exports.testExpectWithFailure = function (test) { + test.expect(3); + var testfn = function (test) { + test.expect(1); + test.ok(false, 'test.ok'); + test.done(); + }; + nodeunit.runTest('testname', testfn, { + log: function (assertion) { + test.equals(assertion.method, 'ok', 'assertion.method'); + }, + testDone: function (name, assertions) { + test.equals(assertions.failures(), 1, 'failures'); + test.equals(assertions.length, 1, 'total'); + } + }, test.done); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-httputil.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-httputil.js new file mode 100644 index 0000000..e5ee25c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-httputil.js @@ -0,0 +1,55 @@ +var nodeunit = require('../lib/nodeunit'); +var httputil = require('../lib/utils').httputil; + +exports.testHttpUtilBasics = function (test) { + + test.expect(6); + + httputil(function (req, resp) { + test.equal(req.method, 'PUT'); + test.equal(req.url, '/newpair'); + test.equal(req.headers.foo, 'bar'); + + resp.writeHead(500, {'content-type': 'text/plain'}); + resp.end('failed'); + }, function (server, client) { + client.fetch('PUT', '/newpair', {'foo': 'bar'}, function (resp) { + test.equal(resp.statusCode, 500); + test.equal(resp.headers['content-type'], 'text/plain'); + test.equal(resp.body, 'failed'); + + server.close(); + test.done(); + }); + }); +}; + +exports.testHttpUtilJsonHandling = function (test) { + + test.expect(9); + + httputil(function (req, resp) { + test.equal(req.method, 'GET'); + test.equal(req.url, '/'); + test.equal(req.headers.foo, 'bar'); + + var testdata = {foo1: 'bar', foo2: 'baz'}; + + resp.writeHead(200, {'content-type': 'application/json'}); + resp.end(JSON.stringify(testdata)); + + }, function (server, client) { + client.fetch('GET', '/', {'foo': 'bar'}, function (resp) { + test.equal(resp.statusCode, 200); + test.equal(resp.headers['content-type'], 'application/json'); + + test.ok(resp.bodyAsObject); + test.equal(typeof resp.bodyAsObject, 'object'); + test.equal(resp.bodyAsObject.foo1, 'bar'); + test.equal(resp.bodyAsObject.foo2, 'baz'); + + server.close(); + test.done(); + }); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runfiles.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runfiles.js new file mode 100644 index 0000000..ce1a4cd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runfiles.js @@ -0,0 +1,214 @@ +var assert = require('assert'), + fs = require('fs'), + path = require('path'), + nodeunit = require('../lib/nodeunit'); + + +var setup = function (fn) { + return function (test) { + process.chdir(__dirname); + var env = { + mock_module1: require(__dirname + '/fixtures/mock_module1'), + mock_module2: require(__dirname + '/fixtures/mock_module2'), + mock_module3: require(__dirname + '/fixtures/dir/mock_module3'), + mock_module4: require(__dirname + '/fixtures/dir/mock_module4') + }; + fn.call(env, test); + }; +}; + + +exports.testRunFiles = setup(function (test) { + test.expect(24); + var runModule_copy = nodeunit.runModule; + + var runModule_calls = []; + var modules = []; + + var opts = { + moduleStart: function () { + return 'moduleStart'; + }, + testDone: function () { + return 'testDone'; + }, + testStart: function () { + return 'testStart'; + }, + log: function () { + return 'log'; + }, + done: function (assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 4, 'length'); + test.ok(typeof assertions.duration === "number"); + + var called_with = function (name) { + return runModule_calls.some(function (m) { + return m.name === name; + }); + }; + test.ok(called_with('mock_module1'), 'mock_module1 ran'); + test.ok(called_with('mock_module2'), 'mock_module2 ran'); + test.ok(called_with('mock_module3'), 'mock_module3 ran'); + test.ok(called_with('mock_module4'), 'mock_module4 ran'); + test.equals(runModule_calls.length, 4); + + nodeunit.runModule = runModule_copy; + test.done(); + } + }; + + nodeunit.runModule = function (name, mod, options, callback) { + test.equals(options.testDone, opts.testDone); + test.equals(options.testStart, opts.testStart); + test.equals(options.log, opts.log); + test.ok(typeof name === "string"); + runModule_calls.push(mod); + var m = [{failed: function () { + return false; + }}]; + modules.push(m); + callback(null, m); + }; + + nodeunit.runFiles( + [__dirname + '/fixtures/mock_module1.js', + __dirname + '/fixtures/mock_module2.js', + __dirname + '/fixtures/dir'], + opts + ); +}); + +exports.testRunFilesEmpty = function (test) { + test.expect(3); + nodeunit.runFiles([], { + moduleStart: function () { + test.ok(false, 'should not be called'); + }, + testDone: function () { + test.ok(false, 'should not be called'); + }, + testStart: function () { + test.ok(false, 'should not be called'); + }, + log: function () { + test.ok(false, 'should not be called'); + }, + done: function (assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 0, 'length'); + test.ok(typeof assertions.duration === "number"); + test.done(); + } + }); +}; + + +exports.testEmptyDir = function (test) { + var dir2 = __dirname + '/fixtures/dir2'; + + // git doesn't like empty directories, so we have to create one + path.exists(dir2, function (exists) { + if (!exists) { + fs.mkdirSync(dir2, 0777); + } + + // runFiles on empty directory: + nodeunit.runFiles([dir2], { + moduleStart: function () { + test.ok(false, 'should not be called'); + }, + testDone: function () { + test.ok(false, 'should not be called'); + }, + testStart: function () { + test.ok(false, 'should not be called'); + }, + log: function () { + test.ok(false, 'should not be called'); + }, + done: function (assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 0, 'length'); + test.ok(typeof assertions.duration === "number"); + test.done(); + } + }); + }); +}; + + +var CoffeeScript; +try { + CoffeeScript = require('coffee-script'); +} catch (e) { +} + +if (CoffeeScript) { + exports.testCoffeeScript = function (test) { + process.chdir(__dirname); + var env = { + mock_coffee_module: require(__dirname + + '/fixtures/coffee/mock_coffee_module') + }; + + test.expect(9); + var runModule_copy = nodeunit.runModule; + + var runModule_calls = []; + var modules = []; + + var opts = { + moduleStart: function () { + return 'moduleStart'; + }, + testDone: function () { + return 'testDone'; + }, + testStart: function () { + return 'testStart'; + }, + log: function () { + return 'log'; + }, + done: function (assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 1, 'length'); + test.ok(typeof assertions.duration === "number"); + + var called_with = function (name) { + return runModule_calls.some(function (m) { + return m.name === name; + }); + }; + test.ok( + called_with('mock_coffee_15'), + 'mock_coffee_module ran' + ); + test.equals(runModule_calls.length, 1); + + nodeunit.runModule = runModule_copy; + test.done(); + } + }; + + nodeunit.runModule = function (name, mod, options, callback) { + test.equals(options.testDone, opts.testDone); + test.equals(options.testStart, opts.testStart); + test.equals(options.log, opts.log); + test.ok(typeof name === "string"); + runModule_calls.push(mod); + var m = [{failed: function () { + return false; + }}]; + modules.push(m); + callback(null, m); + }; + + nodeunit.runFiles( + [__dirname + 'fixtures/coffee/mock_coffee_module.coffee'], + opts + ); + }; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runmodule.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runmodule.js new file mode 100644 index 0000000..19fe5c7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runmodule.js @@ -0,0 +1,177 @@ +/* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +var nodeunit = require('../lib/nodeunit'); // @REMOVE_LINE_FOR_BROWSER + + +exports.testRunModule = function (test) { + test.expect(11); + var call_order = []; + var testmodule = { + test1: function (test) { + call_order.push('test1'); + test.ok(true, 'ok true'); + test.done(); + }, + test2: function (test) { + call_order.push('test2'); + test.ok(false, 'ok false'); + test.ok(false, 'ok false'); + test.done(); + }, + test3: function (test) { + call_order.push('test3'); + test.done(); + } + }; + nodeunit.runModule('testmodule', testmodule, { + log: function (assertion) { + call_order.push('log'); + }, + testStart: function (name) { + call_order.push('testStart'); + test.ok( + name.toString() === 'test1' || + name.toString() === 'test2' || + name.toString() === 'test3', + 'testStart called with test name ' + ); + }, + testDone: function (name, assertions) { + call_order.push('testDone'); + test.ok( + name.toString() === 'test1' || + name.toString() === 'test2' || + name.toString() === 'test3', + 'testDone called with test name' + ); + }, + moduleDone: function (name, assertions) { + call_order.push('moduleDone'); + test.equals(assertions.length, 3); + test.equals(assertions.failures(), 2); + test.equals(name, 'testmodule'); + test.ok(typeof assertions.duration === "number"); + test.same(call_order, [ + 'testStart', 'test1', 'log', 'testDone', + 'testStart', 'test2', 'log', 'log', 'testDone', + 'testStart', 'test3', 'testDone', + 'moduleDone' + ]); + } + }, test.done); +}; + + +exports.testRunModuleTestSpec = function (test) { + test.expect(6); + var call_order = []; + var testmodule = { + test1: function (test) { + test.ok(true, 'ok true'); + test.done(); + }, + test2: function (test) { + call_order.push('test2'); + test.ok(false, 'ok false'); + test.ok(false, 'ok false'); + test.done(); + }, + test3: function (test) { + test.done(); + } + }; + nodeunit.runModule('testmodule', testmodule, { + testspec: "test2", + log: function (assertion) { + call_order.push('log'); + }, + testStart: function (name) { + call_order.push('testStart'); + test.equals( + name,'test2', + 'testStart called with test name ' + ); + }, + testDone: function (name, assertions) { + call_order.push('testDone'); + test.equal( + name, 'test2', + 'testDone called with test name' + ); + }, + moduleDone: function (name, assertions) { + call_order.push('moduleDone'); + test.equals(assertions.length, 2); + test.equals(name, 'testmodule'); + test.ok(typeof assertions.duration === "number"); + test.same(call_order, [ + 'testStart', 'test2', 'log', 'log', 'testDone', + 'moduleDone' + ]); + } + }, test.done); +}; + +exports.testRunModuleEmpty = function (test) { + nodeunit.runModule('module with no exports', {}, { + log: function (assertion) { + test.ok(false, 'log should not be called'); + }, + testStart: function (name) { + test.ok(false, 'testStart should not be called'); + }, + testDone: function (name, assertions) { + test.ok(false, 'testDone should not be called'); + }, + moduleDone: function (name, assertions) { + test.equals(assertions.length, 0); + test.equals(assertions.failures(), 0); + test.equals(name, 'module with no exports'); + test.ok(typeof assertions.duration === "number"); + } + }, test.done); +}; + + +exports.testNestedTests = function (test) { + var call_order = []; + var m = { + test1: function (test) { + test.done(); + }, + suite: { + t1: function (test) { + test.done(); + }, + t2: function (test) { + test.done(); + }, + another_suite: { + t3: function (test) { + test.done(); + } + } + } + }; + nodeunit.runModule('modulename', m, { + testStart: function (name) { + call_order.push(['testStart'].concat(name)); + }, + testDone: function (name, assertions) { + call_order.push(['testDone'].concat(name)); + } + }, function () { + test.same(call_order, [ + ['testStart', 'test1'], ['testDone', 'test1'], + ['testStart', 'suite', 't1'], ['testDone', 'suite', 't1'], + ['testStart', 'suite', 't2'], ['testDone', 'suite', 't2'], + ['testStart', 'suite', 'another_suite', 't3'], + ['testDone', 'suite', 'another_suite', 't3'] + ]); + test.done(); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runtest.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runtest.js new file mode 100644 index 0000000..8fc3d52 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-runtest.js @@ -0,0 +1,46 @@ +/* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +var nodeunit = require('../lib/nodeunit'); // @REMOVE_LINE_FOR_BROWSER + + +exports.testArgs = function (test) { + test.ok(test.expect instanceof Function, 'test.expect'); + test.ok(test.done instanceof Function, 'test.done'); + test.ok(test.ok instanceof Function, 'test.ok'); + test.ok(test.same instanceof Function, 'test.same'); + test.ok(test.equals instanceof Function, 'test.equals'); + test.done(); +}; + +exports.testDoneCallback = function (test) { + test.expect(4); + nodeunit.runTest('testname', exports.testArgs, { + testDone: function (name, assertions) { + test.equals(assertions.failures(), 0, 'failures'); + test.equals(assertions.length, 5, 'length'); + test.ok(typeof assertions.duration === "number"); + test.equals(name, 'testname'); + } + }, test.done); +}; + +exports.testThrowError = function (test) { + test.expect(3); + var err = new Error('test'); + var testfn = function (test) { + throw err; + }; + nodeunit.runTest('testname', testfn, { + log: function (assertion) { + test.same(assertion.error, err, 'assertion.error'); + }, + testDone: function (name, assertions) { + test.equals(assertions.failures(), 1); + test.equals(assertions.length, 1); + } + }, test.done); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-sandbox.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-sandbox.js new file mode 100644 index 0000000..1b249d7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-sandbox.js @@ -0,0 +1,31 @@ +var nodeunit = require('../lib/nodeunit'); +var sandbox = require('../lib/utils').sandbox; +var testCase = nodeunit.testCase; + +exports.testSimpleSandbox = function (test) { + var raw_jscode1 = sandbox(__dirname + '/fixtures/raw_jscode1.js'); + test.equal(raw_jscode1.hello_world('foo'), '_foo_', 'evaluation ok'); + test.done(); +}; + +exports.testSandboxContext = function (test) { + var a_variable = 42; // should not be visible in the sandbox + var raw_jscode2 = sandbox(__dirname + '/fixtures/raw_jscode2.js'); + a_variable = 42; // again for the win + test.equal( + raw_jscode2.get_a_variable(), + 'undefined', + 'the variable should not be defined' + ); + test.done(); +}; + +exports.testSandboxMultiple = function (test) { + var raw_jscode3 = sandbox([ + __dirname + '/fixtures/raw_jscode3.js', + __dirname + '/fixtures/raw_jscode3.js', + __dirname + '/fixtures/raw_jscode3.js' + ]); + test.equal(raw_jscode3.t, 3, 'two files loaded'); + test.done(); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase-legacy.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase-legacy.js new file mode 100644 index 0000000..1dfd9a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase-legacy.js @@ -0,0 +1,257 @@ +/* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +var nodeunit = require('../lib/nodeunit'); // @REMOVE_LINE_FOR_BROWSER +var testCase = nodeunit.testCase; + +exports.testTestCase = function (test) { + test.expect(7); + var call_order = []; + var s = testCase({ + setUp: function (callback) { + call_order.push('setUp'); + test.equals(this.one, undefined); + this.one = 1; + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + test.ok(true, 'tearDown called'); + callback(); + }, + test1: function (t) { + call_order.push('test1'); + test.equals(this.one, 1); + this.one = 2; + t.done(); + }, + test2: function (t) { + call_order.push('test2'); + test.equals(this.one, 1); + t.done(); + } + }); + nodeunit.runSuite(null, s, {}, function () { + test.same(call_order, [ + 'setUp', 'test1', 'tearDown', + 'setUp', 'test2', 'tearDown' + ]); + test.done(); + }); +}; + +exports.tearDownAfterError = function (test) { + test.expect(1); + var s = testCase({ + tearDown: function (callback) { + test.ok(true, 'tearDown called'); + callback(); + }, + test: function (t) { + throw new Error('some error'); + } + }); + nodeunit.runSuite(null, s, {}, function () { + test.done(); + }); +}; + +exports.catchSetUpError = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = testCase({ + setUp: function (callback) { + throw test_error; + }, + test: function (t) { + test.ok(false, 'test function should not be called'); + t.done(); + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.setUpErrorCallback = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = testCase({ + setUp: function (callback) { + callback(test_error); + }, + test: function (t) { + test.ok(false, 'test function should not be called'); + t.done(); + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.catchTearDownError = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = testCase({ + tearDown: function (callback) { + throw test_error; + }, + test: function (t) { + t.done(); + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.tearDownErrorCallback = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = testCase({ + tearDown: function (callback) { + callback(test_error); + }, + test: function (t) { + t.done(); + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.testErrorAndtearDownError = function (test) { + test.expect(3); + var error1 = new Error('test error one'); + var error2 = new Error('test error two'); + var s = testCase({ + tearDown: function (callback) { + callback(error2); + }, + test: function (t) { + t.done(error1); + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 2); + test.equal(assertions[0].error, error1); + test.equal(assertions[1].error, error2); + test.done(); + }); +}; + +exports.testCaseGroups = function (test) { + var call_order = []; + var s = testCase({ + setUp: function (callback) { + call_order.push('setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + callback(); + }, + test1: function (test) { + call_order.push('test1'); + test.done(); + }, + group1: { + test2: function (test) { + call_order.push('group1.test2'); + test.done(); + } + } + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.same(call_order, [ + 'setUp', + 'test1', + 'tearDown', + 'setUp', + 'group1.test2', + 'tearDown' + ]); + test.done(); + }); +}; + +exports.nestedTestCases = function (test) { + var call_order = []; + var s = testCase({ + setUp: function (callback) { + call_order.push('setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + callback(); + }, + test1: function (test) { + call_order.push('test1'); + test.done(); + }, + group1: testCase({ + setUp: function (callback) { + call_order.push('group1.setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('group1.tearDown'); + callback(); + }, + test2: function (test) { + call_order.push('group1.test2'); + test.done(); + } + }) + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.same(call_order, [ + 'setUp', + 'test1', + 'tearDown', + 'setUp', + 'group1.setUp', + 'group1.test2', + 'group1.tearDown', + 'tearDown' + ]); + test.done(); + }); +}; + +exports.deepNestedTestCases = function (test) { + var val = 'foo'; + var s = testCase({ + setUp: function (callback) { + val = 'bar'; + callback(); + }, + group1: testCase({ + test: testCase({ + test2: function (test) { + test.equal(val, 'bar'); + test.done(); + } + }) + }) + }); + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.ok(!assertions[0].failed()); + test.equal(assertions.length, 1); + test.done(); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase.js new file mode 100644 index 0000000..5d33b0b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test-testcase.js @@ -0,0 +1,256 @@ +/* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build. + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +var nodeunit = require('../lib/nodeunit'); // @REMOVE_LINE_FOR_BROWSER + +exports.testTestCase = function (test) { + test.expect(7); + var call_order = []; + var s = { + setUp: function (callback) { + call_order.push('setUp'); + test.equals(this.one, undefined, 'in setUp, this.one not set'); + this.one = 1; + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + test.ok(true, 'tearDown called'); + callback(); + }, + test1: function (t) { + call_order.push('test1'); + test.equals(this.one, 1, 'in test1, this.one is 1'); + this.one = 2; + t.done(); + }, + test2: function (t) { + call_order.push('test2'); + test.equals(this.one, 1, 'in test2, this.one is still 1'); + t.done(); + } + }; + nodeunit.runSuite(null, s, {}, function () { + test.same(call_order, [ + 'setUp', 'test1', 'tearDown', + 'setUp', 'test2', 'tearDown' + ]); + test.done(); + }); +}; + +exports.tearDownAfterError = function (test) { + test.expect(1); + var s = { + tearDown: function (callback) { + test.ok(true, 'tearDown called'); + callback(); + }, + test: function (t) { + throw new Error('some error'); + } + }; + nodeunit.runSuite(null, s, {}, function () { + test.done(); + }); +}; + +exports.catchSetUpError = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = { + setUp: function (callback) { + throw test_error; + }, + test: function (t) { + test.ok(false, 'test function should not be called'); + t.done(); + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.setUpErrorCallback = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = { + setUp: function (callback) { + callback(test_error); + }, + test: function (t) { + test.ok(false, 'test function should not be called'); + t.done(); + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.catchTearDownError = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = { + tearDown: function (callback) { + throw test_error; + }, + test: function (t) { + t.done(); + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.tearDownErrorCallback = function (test) { + test.expect(2); + var test_error = new Error('test error'); + var s = { + tearDown: function (callback) { + callback(test_error); + }, + test: function (t) { + t.done(); + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 1); + test.equal(assertions[0].error, test_error); + test.done(); + }); +}; + +exports.testErrorAndtearDownError = function (test) { + test.expect(3); + var error1 = new Error('test error one'); + var error2 = new Error('test error two'); + var s = { + tearDown: function (callback) { + callback(error2); + }, + test: function (t) { + t.done(error1); + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.equal(assertions.length, 2); + test.equal(assertions[0].error, error1); + test.equal(assertions[1].error, error2); + test.done(); + }); +}; + +exports.testCaseGroups = function (test) { + var call_order = []; + var s = { + setUp: function (callback) { + call_order.push('setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + callback(); + }, + test1: function (test) { + call_order.push('test1'); + test.done(); + }, + group1: { + test2: function (test) { + call_order.push('group1.test2'); + test.done(); + } + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.same(call_order, [ + 'setUp', + 'test1', + 'tearDown', + 'setUp', + 'group1.test2', + 'tearDown' + ]); + test.done(); + }); +}; + +exports.nestedTestCases = function (test) { + var call_order = []; + var s = { + setUp: function (callback) { + call_order.push('setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('tearDown'); + callback(); + }, + test1: function (test) { + call_order.push('test1'); + test.done(); + }, + group1: { + setUp: function (callback) { + call_order.push('group1.setUp'); + callback(); + }, + tearDown: function (callback) { + call_order.push('group1.tearDown'); + callback(); + }, + test2: function (test) { + call_order.push('group1.test2'); + test.done(); + } + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.same(call_order, [ + 'setUp', + 'test1', + 'tearDown', + 'setUp', + 'group1.setUp', + 'group1.test2', + 'group1.tearDown', + 'tearDown' + ]); + test.done(); + }); +}; + +exports.deepNestedTestCases = function (test) { + var val = 'foo'; + var s = { + setUp: function (callback) { + val = 'bar'; + callback(); + }, + group1: { + test: { + test2: function (test) { + test.equal(val, 'bar'); + test.done(); + } + } + } + }; + nodeunit.runSuite(null, s, {}, function (err, assertions) { + test.ok(!assertions[0].failed()); + test.equal(assertions.length, 1); + test.done(); + }); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test.html new file mode 100644 index 0000000..e0826de --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nodeunit/test/test.html @@ -0,0 +1,28 @@ + + + Nodeunit Test Suite + + + + + + + + + + +

    Nodeunit Test Suite

    + + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/README.md new file mode 100644 index 0000000..eeddfd4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/README.md @@ -0,0 +1,208 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/bin/nopt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000..df90c72 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/examples/my-program.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/lib/nopt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..ff802da --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/lib/nopt.js @@ -0,0 +1,552 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + data.argv.toString = function () { + return this.original.map(JSON.stringify).join(" ") + } + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = false + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = no || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know the-rules --and so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate 2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} 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/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. 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 new file mode 100644 index 0000000..bee4132 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,111 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") +var util = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} 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 new file mode 100644 index 0000000..3056f1e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,25 @@ +{ + "name": "abbrev", + "version": "1.0.4", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "readmeFilename": "README.md", + "_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 new file mode 100644 index 0000000..6d4bc5e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/nopt/package.json @@ -0,0 +1,32 @@ +{ + "name": "nopt", + "version": "1.0.10", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null.\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/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/.npmignore new file mode 100644 index 0000000..e3bc275 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/.npmignore @@ -0,0 +1,3 @@ +node_modules/ +node_modules/* +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/.travis.yml new file mode 100644 index 0000000..63e4183 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +node_js: + - 0.4 + - 0.6 + +notifications: + email: + - travis@nodejitsu.com + irc: "irc.freenode.org#nodejitsu" + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/LICENSE new file mode 100644 index 0000000..56217ca --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Nodejitsu Inc. + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/README.md new file mode 100644 index 0000000..e49fdcd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/README.md @@ -0,0 +1,238 @@ +# prompt [![Build Status](https://secure.travis-ci.org/flatiron/prompt.png)](http://travis-ci.org/flatiron/prompt) + +A beautiful command-line prompt for node.js + +## Features + +* prompts the user for input +* supports validation and defaults +* hides passwords + +## Installation + +### Installing npm (node package manager) +``` +curl http://npmjs.org/install.sh | sh +``` + +### Installing prompt +``` +[sudo] npm install prompt +``` + +## Usage +Using 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. + +### Getting Basic Prompt Information +Getting started with `prompt` is easy. Lets take a look at `examples/simple-prompt.js`: + +``` js +var prompt = require('prompt'); + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: username and email +// +prompt.get(['username', 'email'], function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' username: ' + result.username); + console.log(' email: ' + result.email); +}) +``` + +This will result in the following command-line output: + +``` +$ node examples/simple-prompt.js +prompt: username: some-user +prompt: email: some-user@some-place.org +Command-line input received: + username: some-user + email: some-user@some-place.org +``` + +### Prompting with Validation, Default Values, and More (Complex Properties) +In 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: + +``` js +var properties = [ + { + name: 'name', + validator: /^[a-zA-Z\s\-]+$/, + warning: 'Name must be only letters, spaces, or dashes', + empty: false + }, + { + name: 'password', + hidden: true + } +]; + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: email, password +// +prompt.get(properties, function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' name: ' + result.name); + console.log(' password: ' + result.password); +}); +``` + +Pretty easy right? The output from the above script is: + +``` +$ node examples/property-prompt.js +prompt: name: nodejitsu000 +error: Invalid input for name +error: Name must be only letters, spaces, or dashes +prompt: name: Nodejitsu Inc +prompt: password: +Command-line input received: + name: Nodejitsu Inc + password: some-password +``` + +## Valid Property Settings +`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. + +Lets examine the anatomy of a prompt property: + +``` js +{ + message: 'Enter your password', // Prompt displayed to the user. If not supplied name will be used. + name: 'password' // Key in the JSON object returned from `.get()`. + validator: /^\w+$/ // Regular expression that input must be valid against. + warning: 'Password must be letters' // Warning message to display if validation fails. + hidden: true // If true, characters entered will not be output to console. + default: 'lamepassword' // Default value to use if no value is entered. + empty: false // If false, value entered must be non-empty. +} +``` +### skipping prompts + +Sometimes power users may wish to skip promts and specify all data as command line options. +if a value is set as a property of `prompt.override` prompt will use that instead of +prompting the user. + +``` js +//prompt-everride.js + +var prompt = require('prompt'), + optimist = require('optimist') + +// +// set the overrides +// +prompt.override = optimist.argv + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: username and email +// +prompt.get(['username', 'email'], function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' username: ' + result.username); + console.log(' email: ' + result.email); +}) + +//: node prompt-everride.js --username USER --email EMAIL + +``` + + +### Adding Properties to an Object +A 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: + +``` js +var obj = { + password: 'lamepassword', + mindset: 'NY' +} + +// +// Log the initial object. +// +console.log('Initial object to be extended:'); +console.dir(obj); + +// +// Add two properties to the empty object: username and email +// +prompt.addProperties(obj, ['username', 'email'], function (err) { + // + // Log the results. + // + console.log('Updated object received:'); + console.dir(obj); +}); +``` + +## Customizing your prompt +Aside from changing `property.message`, you can also change `prompt.message` +and `prompt.delimiter` to change the appearance of your prompt. + +The basic structure of a prompt is this: + +``` js +prompt.message + prompt.delimiter + property.message + prompt.delimiter; +``` + +The default `prompt.message` is "prompt," the default `prompt.delimiter` is +": ", and the default `property.message` is `property.name`. +Changing these allows you to customize the appearance of your prompts! In +addition, prompt supports ANSI color codes via the +[colors module](https://github.com/Marak/colors.js) for custom colors. For a +very colorful example: + +``` js +var prompt = require("prompt"); +// +// The colors module adds color properties to String.prototype +// +require("colors"); + +// +// Setting these properties customizes the prompt. +// +prompt.message = "Question!".rainbow; +prompt.delimiter = "><".green; + +prompt.start(); + +prompt.get([{ name: "name", + message: "What is your name?".magenta }], function (err, result) { + console.log("You said your name is: ".cyan + result.name.cyan); +}); +``` + +## Running tests +``` +vows test/*-test.js --spec +``` + +#### Author: [Charlie Robbins][1] + +[0]: https://github.com/flatiron/prompt/tree/master/examples +[1]: http://nodejitsu.com diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/docco.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/docco.css new file mode 100644 index 0000000..bd54134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/docco.css @@ -0,0 +1,194 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h4, h5, h6 { + color: #333; + margin: 6px 0 6px 0; + font-size: 13px; +} + h2, h3 { + margin-bottom: 0; + color: #000; + } + h1 { + margin-top: 40px; + margin-bottom: 15px; + color: #000; + } +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/prompt.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/prompt.html new file mode 100644 index 0000000..7776f5b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/docs/prompt.html @@ -0,0 +1,296 @@ + prompt.js

    prompt.js

    /*
    + * prompt.js: Simple prompt for prompting information from the command line 
    + *
    + * (C) 2010, Nodejitsu Inc.
    + *
    + */
    +
    +var events = require('events'),
    +    async = require('async'),
    +    colors = require('colors'),
    +    winston = require('winston'),
    +    stdio = process.binding('stdio');

    @private function capitalize (str)

    + +

    str {string} String to capitalize

    + +

    Capitalizes the string supplied.

    function capitalize(str) {
    +  return str.charAt(0).toUpperCase() + str.slice(1);
    +}
    +
    +var prompt = module.exports = Object.create(events.EventEmitter.prototype);
    +
    +var logger = prompt.logger = new winston.Logger({
    +  transports: [
    +    new (winston.transports.Console)()
    +  ]
    +});
    +    
    +prompt.started    = false;
    +prompt.paused     = false;
    +prompt.allowEmpty = false; 
    +
    +var stdin, stdout;

    Create an empty object for the properties +known to prompt

    prompt.properties = {};

    Setup the default winston logger to use +the cli levels and colors.

    logger.cli();

    function start (options)

    + +

    @options {Object} Optional Options to consume by prompt

    + +

    Starts the prompt by listening to the appropriate events on options.stdin +and options.stdout. If no streams are supplied, then process.stdin +and process.stdout are used, respectively.

    prompt.start = function (options) {
    +  if (prompt.started) {
    +    return;
    +  }
    +  
    +  options = options        || {};
    +  stdin   = options.stdin  || process.openStdin();
    +  stdout  = options.stdout || process.stdout;
    +  
    +  prompt.allowEmpty = options.allowEmpty || false;
    +  
    +  process.on('SIGINT', function () {
    +    stdout.write('\n');
    +    process.exit(1);
    +  })
    +  
    +  prompt.emit('start');
    +  prompt.started = true;
    +  return prompt;
    +};

    function pause ()

    + +

    Pauses input coming in from stdin

    prompt.pause = function () {
    +  if (!prompt.started || prompt.paused) {
    +    return;
    +  }
    +  
    +  stdin.pause();
    +  prompt.emit('pause');
    +  prompt.paused = true;
    +  return prompt;
    +};

    function resume ()

    + +

    Resumes input coming in from stdin

    prompt.resume = function () {
    +  if (!prompt.started || !prompt.paused) {
    +    return;
    +  }
    +  
    +  stdin.resume();
    +  prompt.emit('resume');
    +  prompt.paused = false;
    +  return prompt;
    +};

    function get (msg, [validator,] callback)

    + +

    @msg {Array|Object|string} Set of variables to get input for.

    + +

    @callback {function} Continuation to pass control to when complete.

    + +

    Gets input from the user via stdin for the specified message(s) msg.

    prompt.get = function (msg, callback) {
    +  var vars = !Array.isArray(msg) ? [msg] : msg,
    +      result = {};
    +  
    +  vars = vars.map(function (v) {
    +    if (typeof v === 'string') {
    +      v = v.toLowerCase();
    +    }
    +    
    +    return prompt.properties[v] || v;
    +  });
    +  
    +  function get(target, next) {
    +    prompt.getInput(target, function (err, line) {
    +      if (err) {
    +        return next(err);
    +      }
    +      
    +      var name = target.name || target;
    +      result[name] = line;
    +      next();
    +    });
    +  }
    +  
    +  async.forEachSeries(vars, get, function (err) {
    +    return err ? callback(err) : callback(null, result);
    +  });
    +  
    +  return prompt;
    +};

    function getInput (msg, validator, callback)

    + +

    @msg {Object|string} Variable to get input for.

    + +

    @callback {function} Continuation to pass control to when complete.

    + +

    Gets input from the user via stdin for the specified message msg.

    prompt.getInput = function (prop, callback) {
    +  var name   = prop.message || prop.name || prop,
    +      raw    = ['prompt', ': ' + name.grey, ': '.grey],
    +      read   = prop.hidden ? prompt.readLineHidden : prompt.readLine,
    +      length, msg;
    +  
    +  if (prop.default) {
    +    raw.splice(2, -1, ' (' + prop.default + ')');
    +  }
    +  

    Calculate the raw length and colorize the prompt

      length = raw.join('').length;
    +  raw[0] = raw[0];
    +  msg = raw.join('');
    +  
    +  if (prop.help) {
    +    prop.help.forEach(function (line) {
    +      logger.help(line);
    +    });
    +  }
    +  
    +  stdout.write(msg); 
    +  prompt.emit('prompt', prop);
    +  
    +  read.call(null, function (err, line) {
    +    if (err) {
    +      return callback(err);
    +    }
    +  
    +    if (!line || line === '') {
    +      line = prop.default || line;
    +    }
    +    
    +    if (prop.validator || prop.empty === false) {
    +      var valid;
    +      
    +      if (prop.validator) {
    +        valid = prop.validator.test 
    +         ? prop.validator.test(line)
    +         : prop.validator(line);
    +      }
    +      
    +      if (prop.empty === false && valid) {
    +        valid = line.length > 0;
    +        prop.warning = prop.warning || 'You must supply a value.';
    +      }
    +      
    +      if (!valid) {
    +        logger.error('Invalid input for ' + name.grey);
    +        if (prop.warning) {
    +          logger.error(prop.warning);
    +        }
    +        
    +        prompt.emit('invalid', prop, line);
    +        return prompt.getInput(prop, callback);
    +      }
    +    }
    +        
    +    logger.input(line.yellow);
    +    callback(null, line);
    +  });
    +
    +  return prompt;
    +};

    function addProperties (obj, properties, callback)

    + +

    @obj {Object} Object to add properties to

    + +

    @properties {Array} List of properties to get values for

    + +

    @callback {function} Continuation to pass control to when complete.

    + +

    Prompts the user for values each of the properties if obj does not already +have a value for the property. Responds with the modified object.

    prompt.addProperties = function (obj, properties, callback) {
    +  properties = properties.filter(function (prop) {
    +    return typeof obj[prop] === 'undefined';
    +  });
    +  
    +  if (properties.length === 0) {
    +    return callback(obj);
    +  }
    +  
    +  prompt.get(properties, function (err, results) {
    +    if (err) {
    +      return callback(err);
    +    }
    +    else if (!results) {
    +      return callback(null, obj);
    +    }
    +    
    +    function putNested (obj, path, value) {
    +      var last = obj, key; 
    +      
    +      while (path.length > 1) {
    +        key = path.shift();
    +        if (!last[key]) {
    +          last[key] = {};
    +        }
    +        
    +        last = last[key];
    +      }
    +      
    +      last[path.shift()] = value;
    +    }
    +    
    +    Object.keys(results).forEach(function (key) {
    +      putNested(obj, key.split('.'), results[key]);
    +    });
    +    
    +    callback(null, obj);
    +  });
    +  
    +  return prompt;
    +};

    function readLine (callback)

    + +

    @callback {function} Continuation to respond to when complete

    + +

    Gets a single line of input from the user.

    prompt.readLine = function (callback) {
    +  var value = '', buffer = '';
    +  prompt.resume();
    +  stdin.setEncoding('utf8');
    +  stdin.on('error', callback);
    +  stdin.on('data', function data (chunk) {
    +    value += buffer + chunk;
    +    buffer = '';
    +    value = value.replace(/\r/g, '');
    +    if (value.indexOf('\n') !== -1) {
    +      if (value !== '\n') {
    +        value = value.replace(/^\n+/, '');
    +      }
    +      
    +      buffer = value.substr(value.indexOf('\n'));
    +      val = value.substr(0, value.indexOf('\n'));
    +      prompt.pause();
    +      stdin.removeListener('data', data);
    +      stdin.removeListener('error', callback);
    +      value = value.trim();
    +      callback(null, value);
    +    }
    +  });
    +  
    +  return prompt;
    +};

    function readLineHidden (callback)

    + +

    @callback {function} Continuation to respond to when complete

    + +

    Gets a single line of hidden input (i.e. rawMode = true) from the user.

    prompt.readLineHidden = function (callback) {
    +  var value = '', buffer = '';
    +  stdio.setRawMode(true);
    +  prompt.resume();
    +  stdin.on('error', callback);
    +  stdin.on('data', function data (c) {
    +    c = '' + c;
    +    switch (c) {
    +      case '\n': case '\r': case '\r\n': case '\u0004':
    +        stdio.setRawMode(false);
    +        stdin.removeListener('data', data);
    +        stdin.removeListener('error', callback);
    +        value = value.trim();
    +        stdout.write('\n');
    +        stdout.flush();
    +        prompt.pause();
    +        return callback(null, value)
    +      case '\u0003': case '\0':
    +        stdout.write('\n');
    +        process.exit(1);
    +        break;
    +      default:
    +        value += buffer + c
    +        buffer = '';
    +        break;
    +    }
    +  });
    +  
    +  return prompt;
    +};
    +
    +
    diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/add-properties.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/add-properties.js new file mode 100644 index 0000000..71860dd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/add-properties.js @@ -0,0 +1,35 @@ +/* + * add-properties.js: Example of how to add properties to an object using prompt. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +// +// Start the prompt +// +prompt.start(); + +var obj = { + password: 'lamepassword', + mindset: 'NY' +} + +// +// Log the initial object. +// +console.log('Initial object to be extended:'); +console.dir(obj); + +// +// Add two properties to the empty object: username and email +// +prompt.addProperties(obj, ['username', 'email'], function (err) { + // + // Log the results. + // + console.log('Updated object received:'); + console.dir(obj); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/existing-properties.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/existing-properties.js new file mode 100644 index 0000000..b1d6621 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/existing-properties.js @@ -0,0 +1,37 @@ +/* + * existing-properties.js: Example of using prompt with predefined properties. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +prompt.properties = { + email: { + name: 'email', + validator: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, + warning: 'Must be a valid email address' + }, + password: { + name: 'password', + hidden: true + } +}; + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: email, password +// +prompt.get(['email', 'password'], function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' email: ' + result.email); + console.log(' password: ' + result.password); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/history.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/history.js new file mode 100644 index 0000000..e60e59d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/history.js @@ -0,0 +1,44 @@ +/* + * history.js: Example of using the prompt history capabilities. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +// +// Start the prompt +// +prompt.start(); + +var properties = [ + { + name: 'animal', + description: 'Enter an animal', + default: 'dog', + validator: /dog|cat/ + }, + { + name: 'sound', + description: 'What sound does this animal make?', + validator: function (value) { + var animal = prompt.history(0).value; + + return animal === 'dog' && value === 'woof' + || animal === 'cat' && value === 'meow'; + } + } +] + +// +// Get two properties from the user +// +prompt.get(properties, function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' animal: ' + result.animal); + console.log(' sound: ' + result.sound); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/password.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/password.js new file mode 100644 index 0000000..90167ea --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/password.js @@ -0,0 +1,30 @@ +/* + * simple-prompt.js: Simple example of using prompt. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: username and password +// +prompt.get([{ + name:'password', + hidden: true, + validator: function (value, next) { + setTimeout(next, 200); + } + }], function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' password: ' + result.password); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/property-prompt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/property-prompt.js new file mode 100644 index 0000000..7f3453e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/property-prompt.js @@ -0,0 +1,45 @@ +/* + * property-prompt.js: Example of using prompt with complex properties. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +var properties = [ + { + name: 'name', + validator: /^[a-zA-Z\s-]+$/, + warning: 'Name must be only letters, spaces, or dashes', + empty: false + }, + { + name: 'email', + validator: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, + warning: 'Must be a valid email address' + }, + { + name: 'password', + empty: false, + hidden: true + } +]; + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: email, password +// +prompt.get(properties, function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' name: ' + result.name); + console.log(' email: ' + result.email); + console.log(' password: ' + result.password); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/simple-prompt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/simple-prompt.js new file mode 100644 index 0000000..6351656 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/examples/simple-prompt.js @@ -0,0 +1,25 @@ +/* + * simple-prompt.js: Simple example of using prompt. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var prompt = require('../lib/prompt'); + +// +// Start the prompt +// +prompt.start(); + +// +// Get two properties from the user: username and email +// +prompt.get(['username', 'email'], function (err, result) { + // + // Log the results. + // + console.log('Command-line input received:'); + console.log(' username: ' + result.username); + console.log(' email: ' + result.email); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/lib/prompt.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/lib/prompt.js new file mode 100644 index 0000000..d5a4e19 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/lib/prompt.js @@ -0,0 +1,442 @@ +/* + * prompt.js: Simple prompt for prompting information from the command line + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var events = require('events'), + async = require('async'), + colors = require('colors'), + winston = require('winston'), + tty = require('tty'); + +// +// ### @private function capitalize (str) +// #### str {string} String to capitalize +// Capitalizes the string supplied. +// +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +// +// Expose version using `pkginfo` +// +require('pkginfo')(module, 'version'); + +var stdin, stdout, history = []; +var prompt = module.exports = Object.create(events.EventEmitter.prototype); +var logger = prompt.logger = new winston.Logger({ + transports: [new (winston.transports.Console)()] +}); + +prompt.started = false; +prompt.paused = false; +prompt.allowEmpty = false; +prompt.message = 'prompt'; +prompt.delimiter = ': '; + +// +// Create an empty object for the properties +// known to `prompt` +// +prompt.properties = {}; + +// +// Setup the default winston logger to use +// the `cli` levels and colors. +// +logger.cli(); + +// +// ### function start (options) +// #### @options {Object} **Optional** Options to consume by prompt +// Starts the prompt by listening to the appropriate events on `options.stdin` +// and `options.stdout`. If no streams are supplied, then `process.stdin` +// and `process.stdout` are used, respectively. +// +prompt.start = function (options) { + if (prompt.started) { + return; + } + + options = options || {}; + stdin = options.stdin || process.openStdin(); + stdout = options.stdout || process.stdout; + + // + // By default: Remeber the last `10` prompt property / + // answer pairs and don't allow empty responses globally. + // + prompt.memory = options.memory || 10; + prompt.allowEmpty = options.allowEmpty || false; + prompt.message = options.message || prompt.message; + prompt.delimiter = options.delimiter || prompt.delimiter; + + if (process.platform !== 'win32') { + // windows falls apart trying to deal with SIGINT + process.on('SIGINT', function () { + stdout.write('\n'); + process.exit(1); + }); + } + + prompt.emit('start'); + prompt.started = true; + return prompt; +}; + +// +// ### function pause () +// Pauses input coming in from stdin +// +prompt.pause = function () { + if (!prompt.started || prompt.paused) { + return; + } + + stdin.pause(); + prompt.emit('pause'); + prompt.paused = true; + return prompt; +}; + +// +// ### function resume () +// Resumes input coming in from stdin +// +prompt.resume = function () { + if (!prompt.started || !prompt.paused) { + return; + } + + stdin.resume(); + prompt.emit('resume'); + prompt.paused = false; + return prompt; +}; + +// +// ### function history (search) +// #### @search {Number|string} Index or property name to find. +// Returns the `property:value` pair from within the prompts +// `history` array. +// +prompt.history = function (search) { + if (typeof search === 'number') { + return history[search] || {}; + } + + var names = history.map(function (pair) { + return typeof pair.property === 'string' + ? pair.property + : pair.property.name; + }); + + if (~names.indexOf(search)) { + return null; + } + + return history.filter(function (name) { + return typeof pair.property === 'string' + ? pair.property === name + : pair.property.name === name; + })[0]; +}; + +// +// ### function get (msg, [validator,] callback) +// #### @msg {Array|Object|string} Set of variables to get input for. +// #### @callback {function} Continuation to pass control to when complete. +// Gets input from the user via stdin for the specified message(s) `msg`. +// +prompt.get = function (msg, callback) { + var vars = !Array.isArray(msg) ? [msg] : msg, + result = {}; + + vars = vars.map(function (v) { + if (typeof v === 'string') { + v = v.toLowerCase(); + } + + return prompt.properties[v] || v; + }); + + function get(target, next) { + prompt.getInput(target, function (err, line) { + if (err) { + return next(err); + } + + var name = target.name || target; + result[name] = line; + next(); + }); + } + + async.forEachSeries(vars, get, function (err) { + return err ? callback(err) : callback(null, result); + }); + + return prompt; +}; + +// +// ### function getInput (msg, validator, callback) +// #### @msg {Object|string} Variable to get input for. +// #### @callback {function} Continuation to pass control to when complete. +// Gets input from the user via stdin for the specified message `msg`. +// +prompt.getInput = function (prop, callback) { + var name = prop.message || prop.name || prop, + propName = prop.name || prop, + delim = prompt.delimiter, + raw = [prompt.message, delim + name.grey, delim.grey], + read = prop.hidden ? prompt.readLineHidden : prompt.readLine, + length, msg; + + if (prompt.override && prompt.override[propName]) { + return callback (null, prompt.override[propName]) + } + + if (prop.default) { + raw.splice(2, -1, ' (' + prop.default + ')'); + } + + // Calculate the raw length and colorize the prompt + length = raw.join('').length; + raw[0] = raw[0]; + msg = raw.join(''); + + if (prop.help) { + prop.help.forEach(function (line) { + logger.help(line); + }); + } + + stdout.write(msg); + prompt.emit('prompt', prop); + + read.call(null, function (err, line) { + if (err) { + return callback(err); + } + + if (!line || line === '') { + line = prop.default || line; + } + + if (!prop.validator && prop.empty !== false) { + logger.input(line.yellow); + return callback(null, line); + } + + var valid = true, + validator = prop.validator; + + function next(valid) { + if (arguments.length < 1) { + valid = true; + } + + if (prop.empty === false && valid) { + valid = line.length > 0; + if (!valid) { + prop.warning = prop.warning || 'You must supply a value.'; + } + } + + if (!valid) { + logger.error('Invalid input for ' + name.grey); + if (prop.warning) { + logger.error(prop.warning); + } + + prompt.emit('invalid', prop, line); + return prompt.getInput(prop, callback); + } + + // + // Log the resulting line, append this `property:value` + // pair to the history for `prompt` and respond to + // the callback. + // + logger.input(line.yellow); + prompt._remember(prop, line); + callback(null, line); + } + + if (validator) { + if (validator.test) { + valid = validator.test(line) + } + else if (typeof validator === 'function') { + return validator.length < 2 + ? next(validator(line)) + : validator(line, next); + } + else { + return callback(new Error('Invalid valiator: ' + typeof validator)); + } + } + + next(valid); + }); + + return prompt; +}; + +// +// ### function addProperties (obj, properties, callback) +// #### @obj {Object} Object to add properties to +// #### @properties {Array} List of properties to get values for +// #### @callback {function} Continuation to pass control to when complete. +// Prompts the user for values each of the `properties` if `obj` does not already +// have a value for the property. Responds with the modified object. +// +prompt.addProperties = function (obj, properties, callback) { + properties = properties.filter(function (prop) { + return typeof obj[prop] === 'undefined'; + }); + + if (properties.length === 0) { + return callback(obj); + } + + prompt.get(properties, function (err, results) { + if (err) { + return callback(err); + } + else if (!results) { + return callback(null, obj); + } + + function putNested (obj, path, value) { + var last = obj, key; + + while (path.length > 1) { + key = path.shift(); + if (!last[key]) { + last[key] = {}; + } + + last = last[key]; + } + + last[path.shift()] = value; + } + + Object.keys(results).forEach(function (key) { + putNested(obj, key.split('.'), results[key]); + }); + + callback(null, obj); + }); + + return prompt; +}; + +// +// ### function readLine (callback) +// #### @callback {function} Continuation to respond to when complete +// Gets a single line of input from the user. +// +prompt.readLine = function (callback) { + var value = '', buffer = ''; + prompt.resume(); + stdin.setEncoding('utf8'); + stdin.on('error', callback); + stdin.on('data', function data (chunk) { + value += buffer + chunk; + buffer = ''; + value = value.replace(/\r/g, ''); + if (value.indexOf('\n') !== -1) { + if (value !== '\n') { + value = value.replace(/^\n+/, ''); + } + + buffer = value.substr(value.indexOf('\n')); + value = value.substr(0, value.indexOf('\n')); + prompt.pause(); + stdin.removeListener('data', data); + stdin.removeListener('error', callback); + value = value.trim(); + callback(null, value); + } + }); + + return prompt; +}; + +// +// ### function readLineHidden (callback) +// #### @callback {function} Continuation to respond to when complete +// Gets a single line of hidden input (i.e. `rawMode = true`) from the user. +// +prompt.readLineHidden = function (callback) { + var value = ''; + + // + // Ignore errors from `.setRawMode()` so that `prompt` can + // be scripted in child processes. + // + try { tty.setRawMode(true) } + catch (ex) { } + + prompt.resume(); + stdin.on('error', callback); + stdin.on('data', function data (line) { + line = line + ''; + for(var i = 0; i < line.length; i++) { + c = line[i]; + switch (c) { + case '\n': case '\r': case '\r\n': case '\u0004': + try { tty.setRawMode(false) } + catch (ex) { } + stdin.removeListener('data', data); + stdin.removeListener('error', callback); + value = value.trim(); + stdout.write('\n'); + stdout.flush && stdout.flush(); + prompt.pause(); + return callback(null, value); + case '\x7f': case'\x08': + value = value.slice(0,-1); + break; + case '\u0003': case '\0': + stdout.write('\n'); + process.exit(1); + break; + default: + value = value + c; + break; + } + } + }); + + return prompt; +}; + +// +// ### @private function _remember (property, value) +// #### @property {Object|string} Property that the value is in response to. +// #### @value {string} User input captured by `prompt`. +// Prepends the `property:value` pair into the private `history` Array +// for `prompt` so that it can be accessed later. +// +prompt._remember = function (property, value) { + history.unshift({ + property: property, + value: value + }); + + // + // If the length of the `history` Array + // has exceeded the specified length to remember, + // `prompt.memory`, truncate it. + // + if (history.length > prompt.memory) { + history.splice(prompt.memory, history.length - prompt.memory); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/README.md new file mode 100644 index 0000000..07ba942 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/README.md @@ -0,0 +1,85 @@ +# node-pkginfo + +An easy way to expose properties on a module from a package.json + +## Installation + +### Installing npm (node package manager) +``` + curl http://npmjs.org/install.sh | sh +``` + +### Installing pkginfo +``` + [sudo] npm install pkginfo +``` + +## Motivation +How often when writing node.js modules have you written the following line(s) of code? + +* Hard code your version string into your code + +``` js + exports.version = '0.1.0'; +``` + +* Programmatically expose the version from the package.json + +``` js + exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version; +``` + +In other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!** + +## Usage + +Using `pkginfo` is idiot-proof, just require and invoke it. + +``` js + var pkginfo = require('pkginfo')(module); + + console.dir(module.exports); +``` + +By 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`). + +Here's a sample of the output: + +``` + { name: 'simple-app', + description: 'A test fixture for pkginfo', + version: '0.1.0', + author: 'Charlie Robbins ', + keywords: [ 'test', 'fixture' ], + main: './index.js', + scripts: { test: 'vows test/*-test.js --spec' }, + engines: { node: '>= 0.4.0' } } +``` + +### Expose specific properties +If 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: + +``` js + var pkginfo = require('pkginfo')(module, 'version', 'author'); + + console.dir(module.exports); +``` + +``` + { version: '0.1.0', + author: 'Charlie Robbins ' } +``` + +If you're looking for further usage see the [examples][0] included in this repository. + +## Run Tests +Tests are written in [vows][1] and give complete coverage of all APIs. + +``` + vows test/*-test.js --spec +``` + +[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples +[1]: http://vowsjs.org + +#### Author: [Charlie Robbins](http://nodejitsu.com) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/docco.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/docco.css new file mode 100644 index 0000000..bd54134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/docco.css @@ -0,0 +1,194 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h4, h5, h6 { + color: #333; + margin: 6px 0 6px 0; + font-size: 13px; +} + h2, h3 { + margin-bottom: 0; + color: #000; + } + h1 { + margin-top: 40px; + margin-bottom: 15px; + color: #000; + } +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/pkginfo.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/pkginfo.html new file mode 100644 index 0000000..bf615fa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/docs/pkginfo.html @@ -0,0 +1,101 @@ + pkginfo.js

    pkginfo.js

    /*
    + * pkginfo.js: Top-level include for the pkginfo module
    + *
    + * (C) 2011, Charlie Robbins
    + *
    + */
    + 
    +var fs = require('fs'),
    +    path = require('path');

    function pkginfo ([options, 'property', 'property' ..])

    + +

    @pmodule {Module} Parent module to read from.

    + +

    @options {Object|Array|string} Optional Options used when exposing properties.

    + +

    @arguments {string...} Optional Specified properties to expose.

    + +

    Exposes properties from the package.json file for the parent module on +it's exports. Valid usage:

    + +

    require('pkginfo')()

    + +

    require('pkginfo')('version', 'author');

    + +

    require('pkginfo')(['version', 'author']);

    + +

    require('pkginfo')({ include: ['version', 'author'] });

    var pkginfo = module.exports = function (pmodule, options) {
    +  var args = [].slice.call(arguments, 2).filter(function (arg) {
    +    return typeof arg === 'string';
    +  });
    +  

    Parse variable arguments

      if (Array.isArray(options)) {

    If the options passed in is an Array assume that +it is the Array of properties to expose from the +on the package.json file on the parent module.

        options = { include: options };
    +  }
    +  else if (typeof options === 'string') {

    Otherwise if the first argument is a string, then +assume that it is the first property to expose from +the package.json file on the parent module.

        options = { include: [options] };
    +  }
    +  

    Setup default options

      options = options || { include: [] };
    +  
    +  if (args.length > 0) {

    If additional string arguments have been passed in +then add them to the properties to expose on the +parent module.

        options.include = options.include.concat(args);
    +  }
    +  
    +  var pkg = pkginfo.read(pmodule, options.dir).package;
    +  Object.keys(pkg).forEach(function (key) {
    +    if (options.include.length > 0 && !~options.include.indexOf(key)) {
    +      return;
    +    }
    +    
    +    if (!pmodule.exports[key]) {
    +      pmodule.exports[key] = pkg[key];
    +    }
    +  });
    +  
    +  return pkginfo;
    +};

    function find (dir)

    + +

    @pmodule {Module} Parent module to read from.

    + +

    @dir {string} Optional Directory to start search from.

    + +

    Searches up the directory tree from dir until it finds a directory +which contains a package.json file.

    pkginfo.find = function (pmodule, dir) {
    +  dir = dir || pmodule.filename;
    +  dir = path.dirname(dir); 
    +  
    +  var files = fs.readdirSync(dir);
    +  
    +  if (~files.indexOf('package.json')) {
    +    return path.join(dir, 'package.json');
    +  }
    +  
    +  if (dir === '/') {
    +    throw new Error('Could not find package.json up from: ' + dir);
    +  }
    +  
    +  return pkginfo.find(dir);
    +};

    function read (pmodule, dir)

    + +

    @pmodule {Module} Parent module to read from.

    + +

    @dir {string} Optional Directory to start search from.

    + +

    Searches up the directory tree from dir until it finds a directory +which contains a package.json file and returns the package information.

    pkginfo.read = function (pmodule, dir) { 
    +  dir = pkginfo.find(pmodule, dir);
    +  
    +  var data = fs.readFileSync(dir).toString();
    +      
    +  return {
    +    dir: dir, 
    +    package: JSON.parse(data)
    +  };
    +};

    Call pkginfo on this module and expose version.

    pkginfo(module, {
    +  dir: __dirname,
    +  include: ['version'],
    +  target: pkginfo
    +});
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/all-properties.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/all-properties.js new file mode 100644 index 0000000..fd1d831 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/all-properties.js @@ -0,0 +1,19 @@ +/* + * all-properties.js: Sample of including all properties from a package.json file + * + * (C) 2011, Charlie Robbins + * + */ + +var util = require('util'), + pkginfo = require('../lib/pkginfo')(module); + +exports.someFunction = function () { + console.log('some of your custom logic here'); +}; + +console.log('Inspecting module:'); +console.dir(module.exports); + +console.log('\nAll exports exposed:'); +console.error(Object.keys(module.exports)); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/array-argument.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/array-argument.js new file mode 100644 index 0000000..b1b6848 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/array-argument.js @@ -0,0 +1,20 @@ +/* + * array-argument.js: Sample of including specific properties from a package.json file + * using Array argument syntax. + * + * (C) 2011, Charlie Robbins + * + */ + +var util = require('util'), + pkginfo = require('../lib/pkginfo')(module, ['version', 'author']); + +exports.someFunction = function () { + console.log('some of your custom logic here'); +}; + +console.log('Inspecting module:'); +console.dir(module.exports); + +console.log('\nAll exports exposed:'); +console.error(Object.keys(module.exports)); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/multiple-properties.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/multiple-properties.js new file mode 100644 index 0000000..b4b5fd6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/multiple-properties.js @@ -0,0 +1,19 @@ +/* + * multiple-properties.js: Sample of including multiple properties from a package.json file + * + * (C) 2011, Charlie Robbins + * + */ + +var util = require('util'), + pkginfo = require('../lib/pkginfo')(module, 'version', 'author'); + +exports.someFunction = function () { + console.log('some of your custom logic here'); +}; + +console.log('Inspecting module:'); +console.dir(module.exports); + +console.log('\nAll exports exposed:'); +console.error(Object.keys(module.exports)); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/object-argument.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/object-argument.js new file mode 100644 index 0000000..28420c8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/object-argument.js @@ -0,0 +1,22 @@ +/* + * object-argument.js: Sample of including specific properties from a package.json file + * using Object argument syntax. + * + * (C) 2011, Charlie Robbins + * + */ + +var util = require('util'), + pkginfo = require('../lib/pkginfo')(module, { + include: ['version', 'author'] + }); + +exports.someFunction = function () { + console.log('some of your custom logic here'); +}; + +console.log('Inspecting module:'); +console.dir(module.exports); + +console.log('\nAll exports exposed:'); +console.error(Object.keys(module.exports)); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/package.json new file mode 100644 index 0000000..1f2f01c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/package.json @@ -0,0 +1,10 @@ +{ + "name": "simple-app", + "description": "A test fixture for pkginfo", + "version": "0.1.0", + "author": "Charlie Robbins ", + "keywords": ["test", "fixture"], + "main": "./index.js", + "scripts": { "test": "vows test/*-test.js --spec" }, + "engines": { "node": ">= 0.4.0" } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/single-property.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/single-property.js new file mode 100644 index 0000000..4f44561 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/examples/single-property.js @@ -0,0 +1,19 @@ +/* + * single-property.js: Sample of including a single specific properties from a package.json file + * + * (C) 2011, Charlie Robbins + * + */ + +var util = require('util'), + pkginfo = require('../lib/pkginfo')(module, 'version'); + +exports.someFunction = function () { + console.log('some of your custom logic here'); +}; + +console.log('Inspecting module:'); +console.dir(module.exports); + +console.log('\nAll exports exposed:'); +console.error(Object.keys(module.exports)); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/lib/pkginfo.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/lib/pkginfo.js new file mode 100644 index 0000000..a4a6227 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/lib/pkginfo.js @@ -0,0 +1,132 @@ +/* + * pkginfo.js: Top-level include for the pkginfo module + * + * (C) 2011, Charlie Robbins + * + */ + +var fs = require('fs'), + path = require('path'); + +// +// ### function pkginfo ([options, 'property', 'property' ..]) +// #### @pmodule {Module} Parent module to read from. +// #### @options {Object|Array|string} **Optional** Options used when exposing properties. +// #### @arguments {string...} **Optional** Specified properties to expose. +// Exposes properties from the package.json file for the parent module on +// it's exports. Valid usage: +// +// `require('pkginfo')()` +// +// `require('pkginfo')('version', 'author');` +// +// `require('pkginfo')(['version', 'author']);` +// +// `require('pkginfo')({ include: ['version', 'author'] });` +// +var pkginfo = module.exports = function (pmodule, options) { + var args = [].slice.call(arguments, 2).filter(function (arg) { + return typeof arg === 'string'; + }); + + // + // **Parse variable arguments** + // + if (Array.isArray(options)) { + // + // If the options passed in is an Array assume that + // it is the Array of properties to expose from the + // on the package.json file on the parent module. + // + options = { include: options }; + } + else if (typeof options === 'string') { + // + // Otherwise if the first argument is a string, then + // assume that it is the first property to expose from + // the package.json file on the parent module. + // + options = { include: [options] }; + } + + // + // **Setup default options** + // + options = options || { include: [] }; + + if (args.length > 0) { + // + // If additional string arguments have been passed in + // then add them to the properties to expose on the + // parent module. + // + options.include = options.include.concat(args); + } + + var pkg = pkginfo.read(pmodule, options.dir).package; + Object.keys(pkg).forEach(function (key) { + if (options.include.length > 0 && !~options.include.indexOf(key)) { + return; + } + + if (!pmodule.exports[key]) { + pmodule.exports[key] = pkg[key]; + } + }); + + return pkginfo; +}; + +// +// ### function find (dir) +// #### @pmodule {Module} Parent module to read from. +// #### @dir {string} **Optional** Directory to start search from. +// Searches up the directory tree from `dir` until it finds a directory +// which contains a `package.json` file. +// +pkginfo.find = function (pmodule, dir) { + dir = dir || pmodule.filename; + dir = path.dirname(dir); + + var files = fs.readdirSync(dir); + + if (~files.indexOf('package.json')) { + return path.join(dir, 'package.json'); + } + + if (dir === '/') { + throw new Error('Could not find package.json up from: ' + dir); + } + else if (!dir || dir === '.') { + throw new Error('Cannot find package.json from unspecified directory'); + } + + return pkginfo.find(pmodule, dir); +}; + +// +// ### function read (pmodule, dir) +// #### @pmodule {Module} Parent module to read from. +// #### @dir {string} **Optional** Directory to start search from. +// Searches up the directory tree from `dir` until it finds a directory +// which contains a `package.json` file and returns the package information. +// +pkginfo.read = function (pmodule, dir) { + dir = pkginfo.find(pmodule, dir); + + var data = fs.readFileSync(dir).toString(); + + return { + dir: dir, + package: JSON.parse(data) + }; +}; + +// +// Call `pkginfo` on this module and expose version. +// +pkginfo(module, { + dir: __dirname, + include: ['version'], + target: pkginfo +}); \ No newline at end of file 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 new file mode 100644 index 0000000..9f3cb69 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/package.json @@ -0,0 +1,32 @@ +{ + "name": "pkginfo", + "version": "0.2.3", + "description": "An easy way to expose properties on a module from a package.json", + "author": { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/indexzero/node-pkginfo.git" + }, + "keywords": [ + "info", + "tools", + "package.json" + ], + "devDependencies": { + "vows": "0.6.x" + }, + "main": "./lib/pkginfo", + "scripts": { + "test": "vows test/*-test.js --spec" + }, + "engines": { + "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/pkginfo/test/pkginfo-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/test/pkginfo-test.js new file mode 100644 index 0000000..3156c00 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/pkginfo/test/pkginfo-test.js @@ -0,0 +1,69 @@ +/* + * pkginfo-test.js: Tests for the pkginfo module. + * + * (C) 2011, Charlie Robbins + * + */ + +var assert = require('assert'), + exec = require('child_process').exec, + fs = require('fs'), + path = require('path'), + vows = require('vows'), + pkginfo = require('../lib/pkginfo'); + +function assertProperties (source, target) { + assert.lengthOf(source, target.length + 1); + target.forEach(function (prop) { + assert.isTrue(!!~source.indexOf(prop)); + }); +} + +function testExposes (options) { + return { + topic: function () { + exec('node ' + path.join(__dirname, '..', 'examples', options.script), this.callback); + }, + "should expose that property correctly": function (err, stdout, stderr) { + assert.isNull(err); + + var exposed = stderr.match(/'(\w+)'/ig).map(function (p) { + return p.substring(1, p.length - 1); + }); + + return !options.assert + ? assertProperties(exposed, options.properties) + : options.assert(exposed); + } + } +} + +vows.describe('pkginfo').addBatch({ + "When using the pkginfo module": { + "and passed a single `string` argument": testExposes({ + script: 'single-property.js', + properties: ['version'] + }), + "and passed multiple `string` arguments": testExposes({ + script: 'multiple-properties.js', + properties: ['version', 'author'] + }), + "and passed an `object` argument": testExposes({ + script: 'object-argument.js', + properties: ['version', 'author'] + }), + "and passed an `array` argument": testExposes({ + script: 'array-argument.js', + properties: ['version', 'author'] + }), + "and passed no arguments": testExposes({ + script: 'all-properties.js', + assert: function (exposed) { + var pkg = fs.readFileSync(path.join(__dirname, '..', 'examples', 'package.json')).toString(), + keys = Object.keys(JSON.parse(pkg)); + + assertProperties(exposed, keys); + } + }) + } +}).export(module); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.npmignore new file mode 100644 index 0000000..2c5c40a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.npmignore @@ -0,0 +1,6 @@ +test/*.log +test/fixtures/*.json +test/fixtures/logs/*.log +node_modules/ +node_modules/* +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.travis.yml new file mode 100644 index 0000000..c958222 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/.travis.yml @@ -0,0 +1,11 @@ +language: node_js +node_js: + - 0.4 + - 0.6 + - 0.7 + +notifications: + email: + - travis@nodejitsu.com + irc: "irc.freenode.org#nodejitsu" + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/LICENSE new file mode 100644 index 0000000..948d80d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Charlie Robbins + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/README.md new file mode 100644 index 0000000..ecf79f3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/README.md @@ -0,0 +1,732 @@ +# winston [![Build Status](https://secure.travis-ci.org/flatiron/winston.png)](http://travis-ci.org/flatiron/winston) + +A multi-transport async logging library for node.js. "CHILL WINSTON! ... I put it in the logs." + +## Installation + +### Installing npm (node package manager) +``` + curl http://npmjs.org/install.sh | sh +``` + +### Installing winston +``` + [sudo] npm install winston +``` + +## Motivation +Winston 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. + +There 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. + +## Usage +There 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. + +### Using the Default Logger +The 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: + +``` js + var winston = require('winston'); + + winston.log('info', 'Hello distributed log files!'); + winston.info('Hello again distributed logs'); +``` + +By default, only the Console transport is set on the default logger. You can add or remove transports via the add() and remove() methods: + +``` js + winston.add(winston.transports.File, { filename: 'somefile.log' }); + winston.remove(winston.transports.Console); +``` + +For more documenation about working with each individual transport supported by Winston see the "Working with Transports" section below. + +### Instantiating your own Logger +If you would prefer to manage the object lifetime of loggers you are free to instantiate them yourself: + +``` js + var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.Console)(), + new (winston.transports.File)({ filename: 'somefile.log' }) + ] + }); +``` + +You can work with this logger in the same way that you work with the default logger: + +``` js + // + // Logging + // + logger.log('info', 'Hello distributed log files!'); + logger.info('Hello again distributed logs'); + + // + // Adding / Removing Transports + // (Yes It's chainable) + // + logger.add(winston.transports.File) + .remove(winston.transports.Console); +``` + +### Handling Uncaught Exceptions with winston + +With `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. + +If you want to use this feature with the default logger simply call `.handleExceptions()` with a transport instance. + +``` js + // + // You can add a separate exception logger by passing it to `.handleExceptions` + // + winston.handleExceptions(new winston.transports.File({ filename: 'path/to/exceptions.log' })) + + // + // Alternatively you can set `.handleExceptions` to true when adding transports to winston + // + winston.add(winston.transports.File, { + filename: 'path/to/all-logs.log', + handleExceptions: true + }); +``` + +## to exit or not to exit + +by default, winston will exit after logging an uncaughtException. if this is not the behavior you want, +set `exitOnError = false` + +``` js + var logger = new (winston.Logger)({ exitOnError: false }); + + // + // or, like this: + // + logger.exitOnError = false; +``` + +When working with custom logger instances, you can pass in separate transports to the `exceptionHandlers` property or set `.handleExceptions` on any transport. + +``` js + var logger = new (winston.Logger)({ + transports: [ + new winston.transports.File({ filename: 'path/to/all-logs.log' }) + ] + exceptionHandlers: [ + new winston.transports.File({ filename: 'path/to/exceptions.log' }) + ] + }); +``` + +The `exitOnError` option can also be a function to prevent exit on only certain types of errors: + +``` js + function ignoreEpipe(err) { + return err.code !== 'EPIPE'; + } + + var logger = new (winston.Logger)({ exitOnError: ignoreEpipe }); + + // + // or, like this: + // + logger.exitOnError = ignoreEpipe; +``` + +### Using Logging Levels +Setting 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. + +``` js + // + // Any logger instance + // + logger.log('info', "127.0.0.1 - there's no place like home"); + logger.info("127.0.0.1 - there's no place like home"); + + // + // Default logger + // + winston.log('info', "127.0.0.1 - there's no place like home"); + winston.info("127.0.0.1 - there's no place like home"); +``` + +As of 0.2.0, winston supports customizable logging levels, defaulting to [npm][0] style logging levels. Changing logging levels is easy: + +``` js + // + // Change levels on the default winston logger + // + winston.setLevels(winston.config.syslog.levels); + + // + // Change levels on an instance of a logger + // + logger.setLevels(winston.config.syslog.levels); +``` + +Calling `.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: + +``` js + // + // Logger does not have 'silly' defined since that level is not in the syslog levels + // + logger.silly('some silly message'); +``` + +### Using Custom Logging Levels +In addition to the predefined `npm` and `syslog` levels available in Winston, you can also choose to define your own: + +``` js + var myCustomLevels = { + levels: { + foo: 0, + bar: 1, + baz: 2, + foobar: 3 + }, + colors: { + foo: 'blue', + bar: 'green', + baz: 'yellow', + foobar: 'red' + } + }; + + var customLevelLogger = new (winston.Logger)({ levels: myCustomLevels.levels }); + customLevelLogger.foobar('some foobar level-ed message'); +``` + +Although 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: + +``` js + // + // Make winston aware of these colors + // + winston.addColors(myCustomLevels.colors); +``` + +This enables transports with the 'colorize' option set to appropriately color the output of custom levels. + +### Events and Callbacks in Winston +Each 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: + +``` js + logger.on('logging', function (transport, level, msg, meta) { + // [msg] and [meta] have now been logged at [level] to [transport] + }); + + logger.info('CHILL WINSTON!', { seriously: true }); +``` + +It 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: + +``` js + // + // Handle errors + // + logger.on('error', function (err) { /* Do Something */ }); + + // + // Or just suppress them. + // + logger.emitErrs = false; +``` + +Every 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. + +``` js + logger.info('CHILL WINSTON!', { seriously: true }, function (err, level, msg, meta) { + // [msg] and [meta] have now been logged at [level] to **every** transport. + }); +``` + +### Working with multiple Loggers in winston + +Often 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`: + +``` js + var winston = require('winston'); + + // + // Configure the logger for `category1` + // + winston.loggers.add('category1', { + console: { + level: 'silly', + colorize: 'true' + }, + file: { + filename: '/path/to/some/file' + } + }); + + // + // Configure the logger for `category2` + // + winston.loggers.add('category2', { + couchdb: { + host: '127.0.0.1', + port: 5984 + } + }); +``` + +Now that your loggers are setup you can require winston _in any file in your application_ and access these pre-configured loggers: + +``` js + var winston = require('winston'); + + // + // Grab your preconfigured logger + // + var category1 = winston.loggers.get('category1'); + + category1.info('logging from your IoC container-based logger'); +``` + +If you prefer to manage the `Container` yourself you can simply instantiate one: + +``` js + var winston = require('winston'), + container = new winston.Container(); + + container.add('category1', { + console: { + level: 'silly', + colorize: 'true' + }, + file: { + filename: '/path/to/some/file' + } + }); +``` + +### Sharing transports between Loggers in winston + +``` js + var winston = require('winston'); + + // + // Setup transports to be shared across all loggers + // in three ways: + // + // 1. By setting it on the default Container + // 2. By passing `transports` into the constructor function of winston.Container + // 3. By passing `transports` into the `.get()` or `.add()` methods + // + + // + // 1. By setting it on the default Container + // + winston.loggers.options.transports = [ + // Setup your shared transports here + ]; + + // + // 2. By passing `transports` into the constructor function of winston.Container + // + var container = new winston.Container({ + transports: [ + // Setup your shared transports here + ] + }); + + // + // 3. By passing `transports` into the `.get()` or `.add()` methods + // + winston.loggers.add('some-category', { + transports: [ + // Setup your shared transports here + ] + }); + + container.add('some-category', { + transports: [ + // Setup your shared transports here + ] + }); +``` + +### Logging with Metadata +In addition to logging string messages, winston will also optionally log additional JSON metadata objects. Adding metadata is simple: + +``` js + winston.log('info', 'Test Log Message', { anything: 'This is metadata' }); +``` + +The 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: + +1. __Console:__ Logged via util.inspect(meta) +2. __File:__ Logged via util.inspect(meta) +3. __Loggly:__ Logged in suggested [Loggly format][2] + +### Profiling with Winston +In addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger: + +``` js + // + // Start profile of 'test' + // Remark: Consider using Date.now() with async operations + // + winston.profile('test'); + + setTimeout(function () { + // + // Stop profile of 'test'. Logging will now take place: + // "17 Jan 21:00:00 - info: test duration=1000ms" + // + winston.profile('test'); + }, 1000); +``` + +All 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. + +### Using winston in a CLI tool +A 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]: + +``` + info: require-analyzer starting in /Users/Charlie/Nodejitsu/require-analyzer + info: Found existing dependencies + data: { + data: colors: '0.x.x', + data: eyes: '0.1.x', + data: findit: '0.0.x', + data: npm: '1.0.x', + data: optimist: '0.2.x', + data: semver: '1.0.x', + data: winston: '0.2.x' + data: } + info: Analyzing dependencies... + info: Done analyzing raw dependencies + info: Retrieved packages from npm + warn: No additional dependencies found +``` + +Configuring output for this style is easy, just use the `.cli()` method on `winston` or an instance of `winston.Logger`: + +``` js + var winston = require('winston'); + + // + // Configure CLI output on the default logger + // + winston.cli(); + + // + // Configure CLI on an instance of winston.Logger + // + var logger = new winston.Logger({ + transports: [ + new (winston.transports.Console)() + ] + }); + + logger.cli(); +``` + +### Extending another object with Logging functionality +Often 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: + +``` js + var myObject = {}; + + logger.extend(myObject); + + // + // You can now call logger methods on 'myObject' + // + myObject.info('127.0.0.1 - there's no place like home'); +``` + +## Working with Transports +Right 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__ + +1. __Console:__ Output to the terminal +2. __Files:__ Append to a file +3. __Loggly:__ Log to Logging-as-a-Service platform Loggly + +### Console Transport +``` js + winston.add(winston.transports.Console, options) +``` + +The Console transport takes two simple options: + +* __level:__ Level of messages that this transport should log (default 'debug'). +* __silent:__ Boolean flag indicating whether to suppress output (default false). +* __colorize:__ Boolean flag indicating if we should colorize output (default false). +* __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. + +*Metadata:* Logged via util.inspect(meta); + +### File Transport +``` js + winston.add(winston.transports.File, options) +``` + +The 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: + +* __level:__ Level of messages that this transport should log. +* __silent:__ Boolean flag indicating whether to suppress output. +* __colorize:__ Boolean flag indicating if we should colorize output. +* __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. +* __filename:__ The filename of the logfile to write output to. +* __maxsize:__ Max size in bytes of the logfile, if the size is exceeded then a new file is created. +* __maxFiles:__ Limit the number of files created when the size of the logfile is exceeded. +* __stream:__ The WriteableStream to write output to. +* __json:__ If true, messages will be logged as JSON (default true). + +*Metadata:* Logged via util.inspect(meta); + +### Loggly Transport +``` js + winston.add(winston.transports.Loggly, options); +``` + +The 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: + +* __level:__ Level of messages that this transport should log. +* __subdomain:__ The subdomain of your Loggly account. *[required]* +* __auth__: The authentication information for your Loggly account. *[required with inputName]* +* __inputName:__ The name of the input this instance should log to. +* __inputToken:__ The input token of the input this instance should log to. +* __json:__ If true, messages will be sent to Loggly as JSON. + +*Metadata:* Logged in suggested [Loggly format][2] + +### Riak Transport +As of `0.3.0` the Riak transport has been broken out into a new module: [winston-riak][17]. Using it is just as easy: + +``` js + var Riak = require('winston-riak').Riak; + winston.add(Riak, options); +``` + +In 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: + +* __level:__ Level of messages that this transport should log. +* __bucket:__ The name of the Riak bucket you wish your logs to be in or a function to generate bucket names dynamically. + +``` js + // Use a single bucket for all your logs + var singleBucketTransport = new (Riak)({ bucket: 'some-logs-go-here' }); + + // Generate a dynamic bucket based on the date and level + var dynamicBucketTransport = new (Riak)({ + bucket: function (level, msg, meta, now) { + var d = new Date(now); + return level + [d.getDate(), d.getMonth(), d.getFullYear()].join('-'); + } + }); +``` + +*Metadata:* Logged as JSON literal in Riak + +### MongoDB Transport +As of `0.3.0` the MongoDB transport has been broken out into a new module: [winston-mongodb][16]. Using it is just as easy: + +``` js + var MongoDB = require('winston-mongodb').MongoDB; + winston.add(MongoDB, options); +``` + +The MongoDB transport takes the following options. 'db' is required: + +* __level:__ Level of messages that this transport should log. +* __silent:__ Boolean flag indicating whether to suppress output. +* __db:__ The name of the database you want to log to. *[required]* +* __collection__: The name of the collection you want to store log messages in, defaults to 'log'. +* __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. +* __host:__ The host running MongoDB, defaults to localhost. +* __port:__ The port on the host that MongoDB is running on, defaults to MongoDB's default port. + +*Metadata:* Logged as a native JSON object. + +### SimpleDB Transport + +The [winston-simpledb][18] transport is just as easy: + +``` js + var SimpleDB = require('winston-simpledb').SimpleDB; + winston.add(SimpleDB, options); +``` + +The SimpleDB transport takes the following options. All items marked with an asterisk are required: + +* __awsAccessKey__:* your AWS Access Key +* __secretAccessKey__:* your AWS Secret Access Key +* __awsAccountId__:* your AWS Account Id +* __domainName__:* a string or function that returns the domain name to log to +* __region__:* the region your domain resides in +* __itemName__: a string ('uuid', 'epoch', 'timestamp') or function that returns the item name to log + +*Metadata:* Logged as a native JSON object to the 'meta' attribute of the item. + +### Mail Transport + +The [winston-mail][19] is an email transport: + +``` js + var Mail = require('winston-mail').Mail; + winston.add(Mail, options); +``` + +The Mail transport uses [node-mail][20] behind the scenes. Options are the following, `to` and `host` are required: + +* __to:__ The address(es) you want to send to. *[required]* +* __from:__ The address you want to send from. (default: `winston@[server-host-name]`) +* __host:__ SMTP server hostname +* __port:__ SMTP port (default: 587 or 25) +* __secure:__ Use secure +* __username__ User for server auth +* __password__ Password for server auth +* __level:__ Level of messages that this transport should log. +* __silent:__ Boolean flag indicating whether to suppress output. + +*Metadata:* Stringified as JSON in email. + +### Amazon SNS (Simple Notification System) Transport + +The [winston-sns][21] transport uses amazon SNS to send emails, texts, or a bunch of other notifications. + +``` js + require('winston-sns').SNS; + winston.add(winston.transports.SNS, options); +``` + +Options: + +* __aws_key:__ Your Amazon Web Services Key. *[required]* +* __aws_secret:__ Your Amazon Web Services Secret. *[required]* +* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]* +* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]* +* __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`) +* __subject:__ Subject for notifications. (default: "Winston Error Report") +* __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") +* __level:__ lowest level this transport will log. (default: `info`) + +### Graylog2 Transport + +[winston-graylog2][22] is a Graylog2 transport: + +``` js + var Graylog2 = require('winston-graylog2').Graylog2; + winston.add(Graylog2, options); +``` + +The Graylog2 transport connects to a Graylog2 server over UDP using the following options: + +* __level:__ Level of messages this transport should log. (default: info) +* __silent:__ Boolean flag indicating whether to suppress output. (default: false) + +* __graylogHost:__ IP address or hostname of the graylog2 server. (default: localhost) +* __graylogPort:__ Port to send messages to on the graylog2 server. (default: 12201) +* __graylogHostname:__ The hostname associated with graylog2 messages. (default: require('os').hostname()) +* __graylogFacility:__ The graylog2 facility to send log messages.. (default: nodejs) + +*Metadata:* Stringified as JSON in the full message GELF field. + +### Adding Custom Transports +Adding 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. + +``` js + var util = require('util'), + winston = require('winston'); + + var CustomLogger = winston.transports.CustomerLogger = function (options) { + // + // Name this logger + // + this.name = 'customLogger'; + + // + // Set the level from your options + // + this.level = options.level || 'info'; + + // + // Configure your storage backing as you see fit + // + }; + + // + // Inherit from `winston.Transport` so you can take advantage + // of the base functionality and `.handleExceptions()`. + // + util.inherits(CustomLogger, winston.Transport); + + CustomLogger.prototype.log = function (level, msg, meta, callback) { + // + // Store this message and metadata, maybe use some custom logic + // then callback indicating success. + // + callback(null, true); + }; +``` + +## What's Next? +Winston is stable and under active development. It is supported by and used at [Nodejitsu][5]. + +### Inspirations +1. [npm][0] +2. [log.js][9] +3. [socket.io][10] +4. [node-rlog][11] +5. [BigBrother][12] +6. [Loggly][7] + +### Road Map +1. Improve support for adding custom Transports not defined in Winston core. +2. Create API for reading from logs across all transports. +3. Add more transports: Redis + +## Run Tests +All 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: + +``` js + { + "transports": { + "loggly": { + "subdomain": "your-subdomain", + "inputToken": "really-long-token-you-got-from-loggly", + "auth": { + "username": "your-username", + "password": "your-password" + } + } + } + } +``` + +Once you have valid configuration and credentials you can run tests with [vows][13]: + +``` + vows --spec --isolate +``` + +#### Author: [Charlie Robbins](http://twitter.com/indexzero) +#### Contributors: [Matthew Bergman](http://github.com/fotoverite), [Marak Squires](http://github.com/marak) + +[0]: https://github.com/isaacs/npm/blob/master/lib/utils/log.js +[1]: http://nodejs.org/docs/v0.3.5/api/events.html#events.EventEmitter +[2]: http://wiki.loggly.com/loggingfromcode +[3]: http://riakjs.org +[4]: https://github.com/frank06/riak-js/blob/master/src/http_client.coffee#L10 +[5]: http://nodejitsu.com +[6]: http://github.com/nodejitsu/node-loggly +[7]: http://loggly.com +[8]: http://www.loggly.com/product/ +[9]: https://github.com/visionmedia/log.js +[10]: http://socket.io +[11]: https://github.com/jbrisbin/node-rlog +[12]: https://github.com/feisty/BigBrother +[13]: http://vowsjs.org +[14]: http://nodejs.org/docs/v0.3.5/api/streams.html#writable_Stream +[15]: http://github.com/nodejitsu/require-analyzer +[16]: http://github.com/indexzero/winston-mongodb +[17]: http://github.com/indexzero/winston-riak +[18]: http://github.com/appsattic/winston-simpledb +[19]: http://github.com/wavded/winston-mail +[20]: https://github.com/weaver/node-mail +[21]: https://github.com/jesseditson/winston-sns +[22]: https://github.com/flite/winston-graylog2 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/docco.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/docco.css new file mode 100644 index 0000000..bd54134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/docco.css @@ -0,0 +1,194 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h4, h5, h6 { + color: #333; + margin: 6px 0 6px 0; + font-size: 13px; +} + h2, h3 { + margin-bottom: 0; + color: #000; + } + h1 { + margin-top: 40px; + margin-bottom: 15px; + color: #000; + } +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston.html new file mode 100644 index 0000000..0c7f087 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston.html @@ -0,0 +1,86 @@ + winston.js

    winston.js

    /*
    + * winston.js: Top-level include defining Winston.
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var winston = exports;

    Expose version using pkginfo

    require('pkginfo')(module, 'version');

    Include transports defined by default by winston

    winston.transports = require('./winston/transports');
    +
    +var common           = require('./winston/common');
    +winston.hash           = common.hash;
    +winston.clone          = common.clone;
    +winston.longestElement = common.longestElement;
    +winston.exception      = require('./winston/exception');
    +winston.config         = require('./winston/config');
    +winston.addColors      = winston.config.addColors; 
    +winston.Logger         = require('./winston/logger').Logger;
    +winston.Transport      = require('./winston/transports/transport').Transport;

    We create and expose a 'defaultLogger' so that the programmer may do the +following without the need to create an instance of winston.Logger directly:

    + +
    var winston = require('winston');
    +winston.log('info', 'some message');
    +winston.error('some error'); 
    +
    var defaultLogger = new winston.Logger({ 
    +  transports: [new winston.transports.Console()] 
    +});

    Pass through the target methods onto `winston.

    var methods = [
    +  'log', 
    +  'add', 
    +  'remove', 
    +  'profile', 
    +  'extend', 
    +  'cli', 
    +  'handleExceptions', 
    +  'unhandleExceptions'
    +];
    +common.setLevels(winston, null, defaultLogger.levels);
    +methods.forEach(function (method) {
    +  winston[method] = function () {
    +    return defaultLogger[method].apply(defaultLogger, arguments);
    +  };
    +});

    function cli ()

    + +

    Configures the default winston logger to have the +settings for command-line interfaces: no timestamp, +colors enabled, padded output, and additional levels.

    winston.cli = function () {
    +  winston.padLevels = true;
    +  common.setLevels(winston, defaultLogger.levels, winston.config.cli.levels);
    +  defaultLogger.setLevels(winston.config.cli.levels);
    +  winston.config.addColors(winston.config.cli.colors);
    +  
    +  if (defaultLogger.transports.console) {
    +    defaultLogger.transports.console.colorize = true;
    +    defaultLogger.transports.console.timestamp = false;
    +  }
    +  
    +  return winston;
    +};

    function setLevels (target)

    + +

    @target {Object} Target levels to use

    + +

    Sets the target levels specified on the default winston logger.

    winston.setLevels = function (target) {
    +  common.setLevels(winston, defaultLogger.levels, target);
    +  defaultLogger.setLevels(target);
    +};

    Define getters / setters for appropriate properties of the +default logger which need to be exposed by winston.

    ['emitErrs', 'padLevels', 'levelLength'].forEach(function (prop) {
    +  Object.defineProperty(winston, prop, {
    +    get: function () {
    +      return defaultLogger[prop];
    +    },
    +    set: function (val) {
    +      defaultLogger[prop] = val;
    +    }
    +  });
    +});

    @default {Object} +The default transports and exceptionHandlers for +the default winston logger.

    Object.defineProperty(winston, 'default', {
    +  get: function () {
    +    return {
    +      transports: defaultLogger.transports,
    +      exceptionHandlers: defaultLogger.exceptionHandlers
    +    };
    +  }
    +});
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/common.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/common.html new file mode 100644 index 0000000..1ab139c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/common.html @@ -0,0 +1,140 @@ + common.js

    common.js

    /*
    + * common.js: Internal helper and utility functions for winston
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var util = require('util'),
    +    crypto = require('crypto'),
    +    loggly = require('loggly'),
    +    config = require('./config');

    function setLevels (target, past, current)

    + +

    @target {Object} Object on which to set levels.

    + +

    @past {Object} Previous levels set on target.

    + +

    @current {Object} Current levels to set on target.

    + +

    Create functions on the target objects for each level +in current.levels. If past is defined, remove functions +for each of those levels.

    exports.setLevels = function (target, past, current, isDefault) {
    +  if (past) {
    +    Object.keys(past).forEach(function (level) {
    +      delete target[level];
    +    });
    +  }
    +
    +  target.levels = current || config.npm.levels;
    +  if (target.padLevels) {
    +    target.levelLength = exports.longestElement(Object.keys(target.levels));
    +  }
    +  

    Define prototype methods for each log level + e.g. target.log('info', msg) <=> target.info(msg)

      Object.keys(target.levels).forEach(function (level) {
    +    target[level] = function (msg) {
    +      var args     = Array.prototype.slice.call(arguments),
    +          callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
    +          meta     = args.length === 2 ? args.pop() : null;
    +
    +      return target.log(level, msg, meta, callback);
    +    };
    +  });
    +  
    +  return target;
    +};

    function longestElement

    + +

    @xs {Array} Array to calculate against

    + +

    Returns the longest element in the xs array.

    exports.longestElement = function (xs) {
    +  return Math.max.apply(
    +    null,
    +    xs.map(function (x) { return x.length })
    +  );
    +};

    function clone (obj)

    + +

    @obj {Object} Object to clone.

    + +

    Helper method for deep cloning pure JSON objects +i.e. JSON objects that are either literals or objects (no Arrays, etc)

    exports.clone = function (obj) {
    +  var copy = {};
    +  for (var i in obj) {
    +    if (Array.isArray(obj[i])) {
    +      copy[i] = obj[i].slice(0);
    +    }
    +    else {
    +      copy[i] = obj[i] instanceof Object ? exports.clone(obj[i]) : obj[i];
    +    }
    +  }
    +
    +  return copy;
    +};

    function log (options)

    + +

    @options {Object} All information about the log serialization.

    + +

    Generic logging function for returning timestamped strings +with the following options:

    + +

    { + level: 'level to add to serialized message', + message: 'message to serialize', + meta: 'additional logging metadata to serialize', + colorize: false, // Colorizes output (only if .json is false) + timestamp: true // Adds a timestamp to the serialized message + }

    exports.log = function (options) {
    +  var timestampFn = typeof options.timestamp === 'function' ? options.timestamp : exports.timestamp,
    +      timestamp   = options.timestamp ? timestampFn() : null,
    +      meta        = options.meta ? exports.clone(options.meta) : null,
    +      output;
    +
    +  if (options.json) {
    +    output         = meta || {};
    +    output.level   = options.level;
    +    output.message = options.message;
    +    
    +    if (timestamp) {
    +      output.timestamp = timestamp;
    +    }
    +    
    +    return JSON.stringify(output);
    +  }
    +
    +  output = timestamp ? timestamp + ' - ' : '';
    +  output += options.colorize ? config.colorize(options.level) : options.level;
    +  output += (': ' + options.message);
    +
    +  if (meta && typeof meta === 'object' && Object.keys(meta).length > 0) {
    +    output += ' ' + loggly.serialize(meta);
    +  }
    +
    +  return output;
    +};

    function hash (str)

    + +

    @str {string} String to hash.

    + +

    Utility function for creating unique ids +e.g. Profiling incoming HTTP requests on the same tick

    exports.hash = function (str) {
    +  return crypto.createHash('sha1').update(str).digest('hex');
    +};

    Borrowed from node.js core

    + +

    I wanted a universal lowercase header message, as opposed to the DEBUG +(i.e. all uppercase header) used only in util.debug()

    var months = ['Jan', 'Feb', 'Mar', 'Apr', 
    +              'May', 'Jun', 'Jul', 'Aug', 
    +              'Sep', 'Oct', 'Nov', 'Dec'];

    function pad (n)

    + +

    Returns a padded string if n < 10.

    exports.pad = function (n) {
    +  return n < 10 ? '0' + n.toString(10) : n.toString(10);
    +};

    function timestamp ()

    + +

    Returns a timestamp string for the current time.

    exports.timestamp = function () {
    +  var d = new Date();
    +  var time = [
    +    exports.pad(d.getHours()),
    +    exports.pad(d.getMinutes()),
    +    exports.pad(d.getSeconds())
    +  ].join(':');
    +              
    +  return [d.getDate(), months[d.getMonth()], time].join(' ');
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config.html new file mode 100644 index 0000000..c623d64 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config.html @@ -0,0 +1,37 @@ + config.js

    config.js

    /*
    + * config.js: Default settings for all levels that winston knows about 
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var colors = require('colors');
    +
    +var config = exports, 
    +    allColors = exports.allColors = {};
    +
    +config.addColors = function (colors) {
    +  mixin(allColors, colors);
    +};
    +
    +config.colorize = function (level) {
    +  return level[allColors[level]];
    +};

    Export config sets

    config.cli    = require('./config/cli-config');
    +config.npm    = require('./config/npm-config');
    +config.syslog = require('./config/syslog-config');

    Add colors for pre-defined config sets

    config.addColors(config.npm.colors);
    +config.addColors(config.syslog.colors);
    +
    +function mixin (target) {
    +  var args = Array.prototype.slice.call(arguments, 1);
    +
    +  args.forEach(function (a) {
    +    var keys = Object.keys(a);
    +    for (var i = 0; i < keys.length; i++) {
    +      target[keys[i]] = a[keys[i]];
    +    }
    +  });
    +  return target;
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/cli-config.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/cli-config.html new file mode 100644 index 0000000..075edd0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/cli-config.html @@ -0,0 +1,37 @@ + cli-config.js

    cli-config.js

    /*
    + * cli-config.js: Config that conform to commonly used CLI logging levels. 
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    + 
    +var cliConfig = exports;
    +
    +cliConfig.levels = {
    +  silly: 0,
    +  input: 1,
    +  verbose: 2,
    +  prompt: 3,
    +  info: 4,
    +  data: 5,
    +  help: 6,
    +  warn: 7,
    +  debug: 8,
    +  error: 9
    +};
    +
    +cliConfig.colors = {
    +  silly: 'magenta',
    +  input: 'grey',
    +  verbose: 'cyan',
    +  prompt: 'grey',
    +  info: 'green',
    +  data: 'grey',
    +  help: 'cyan',
    +  warn: 'yellow',
    +  debug: 'blue',
    +  error: 'red'
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/npm-config.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/npm-config.html new file mode 100644 index 0000000..8517430 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/npm-config.html @@ -0,0 +1,29 @@ + npm-config.js

    npm-config.js

    /*
    + * npm-config.js: Config that conform to npm logging levels. 
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    + 
    +var npmConfig = exports;
    +
    +npmConfig.levels = {
    +  silly: 0, 
    +  verbose: 1, 
    +  info: 2, 
    +  warn: 3,
    +  debug: 4, 
    +  error: 5
    +};
    +
    +npmConfig.colors = {
    +  silly: 'magenta',
    +  verbose: 'cyan',
    +  info: 'green',
    +  warn: 'yellow',
    +  debug: 'blue',
    +  error: 'red'
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/syslog-config.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/syslog-config.html new file mode 100644 index 0000000..6da0993 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/config/syslog-config.html @@ -0,0 +1,33 @@ + syslog-config.js

    syslog-config.js

    /*
    + * syslog-config.js: Config that conform to syslog logging levels. 
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    + 
    +var syslogConfig = exports;
    +
    +syslogConfig.levels = {
    +  debug: 0, 
    +  info: 1, 
    +  notice: 2, 
    +  warning: 3,
    +  error: 4, 
    +  crit: 5,
    +  alert: 6,
    +  emerg: 7
    +};
    +
    +syslogConfig.colors = {
    +  debug: 'blue',
    +  info: 'green',
    +  notice: 'yellow',
    +  warning: 'red',
    +  error: 'red', 
    +  crit: 'red',
    +  alert: 'yellow',
    +  emerg: 'red'
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/exception.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/exception.html new file mode 100644 index 0000000..f6a4a6c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/exception.html @@ -0,0 +1,56 @@ + exception.js

    exception.js

    /*
    + * exception.js: Utility methods for gathing information about uncaughtExceptions.
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    + 
    +var os = require('os'),
    +    stackTrace = require('stack-trace');
    +    
    +var exception = exports;
    +
    +exception.getAllInfo = function (err) {
    +  return {
    +    process: exception.getProcessInfo(),
    +    os:      exception.getOsInfo(),
    +    trace:   exception.getTrace(err)
    +  };
    +};
    +
    +exception.getProcessInfo = function () {
    +  return {
    +    pid:         process.pid,
    +    uid:         process.getuid(),
    +    gid:         process.getgid(),
    +    cwd:         process.cwd(),
    +    execPath:    process.execPath,
    +    version:     process.version,
    +    argv:        process.argv,
    +    memoryUsage: process.memoryUsage()
    +  };
    +};
    +
    +exception.getOsInfo = function () {
    +  return {
    +    loadavg: os.loadavg(),
    +    uptime:  os.uptime()
    +  };
    +};
    +
    +exception.getTrace = function (err) {
    +  var trace = err ? stackTrace.parse(err) : stackTrace.get();
    +  return trace.map(function (site) {
    +    return {
    +      column:   site.getColumnNumber(),
    +      file:     site.getFileName(),
    +      function: site.getFunctionName(),
    +      line:     site.getLineNumber(),
    +      method:   site.getMethodName(),
    +      native:   site.isNative(),
    +    }
    +  });
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/logger.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/logger.html new file mode 100644 index 0000000..de7038a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/logger.html @@ -0,0 +1,344 @@ + logger.js

    logger.js

    /*
    + * logger.js: Core logger object used by winston.
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    + 
    +var events = require('events'),
    +    util = require('util'),
    +    async = require('async'),
    +    config = require('./config'),
    +    common = require('./common'),
    +    exception = require('./exception');
    +
    +function capitalize(str) {
    +  return str && str[0].toUpperCase() + str.slice(1);
    +}

    Time constants

    var ticksPerMillisecond = 10000;

    function Logger (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Logger object responsible +for persisting log messages and metadata to one or more transports.

    var Logger = exports.Logger = function (options) {
    +  events.EventEmitter.call(this);
    +  options = options || {};
    +  
    +  var self = this,
    +      handleExceptions = false;
    +  

    Set Levels and default logging level

      this.padLevels = options.padLevels || false;
    +  this.setLevels(options.levels);
    +  

    Setup other intelligent default settings.

      this.level             = options.level || 'info';
    +  this.emitErrs          = options.emitErrs || false;
    +  this.stripColors       = options.stripColors || false;
    +  this.transports        = {};
    +  this.exceptionHandlers = {};
    +  this.profilers         = {};
    +  this._names            = [];
    +  this._hnames           = [];
    +  
    +  if (options.transports) {
    +    options.transports.forEach(function (transport) {
    +      self.add(transport, null, true);
    +      
    +      if (transport.handleExceptions) {
    +        handleExceptions = true;
    +      }
    +    });
    +  }
    +  
    +  if (options.exceptionHandlers) {
    +    options.exceptionHandlers.forEach(function (handler) {
    +      self._hnames.push(handler.name);
    +      self.exceptionHandlers[handler.name] = handler;
    +    });
    +  }
    +  
    +  if (options.handleExceptions || handleExceptions) {
    +    this.handleExceptions();
    +  }
    +};

    Inherit from events.EventEmitter.

    util.inherits(Logger, events.EventEmitter);

    function extend (target)

    + +

    @target {Object} Target to extend.

    + +

    Extends the target object with a 'log' method +along with a method for each level in this instance.

    Logger.prototype.extend = function (target) {
    +  var self = this;
    +  ['log', 'profile'].concat(Object.keys(this.levels)).forEach(function (method) {
    +    target[method] = function () {
    +      return self[method].apply(self, arguments);
    +    };
    +  });
    +  
    +  return this;
    +};

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    Logger.prototype.log = function (level, msg) {
    +  var self = this, 
    +      callback,
    +      meta;
    +  
    +  if (arguments.length === 3) {
    +    if (typeof arguments[2] === 'function') {
    +      meta = {};
    +      callback = arguments[2];
    +    }
    +    else if (typeof arguments[2] === 'object') {
    +      meta = arguments[2];
    +    }
    +  }
    +  else if (arguments.length === 4) {
    +    meta = arguments[2];
    +    callback = arguments[3];
    +  }

    If we should pad for levels, do so

      if (this.padLevels) {
    +    msg = new Array(this.levelLength - level.length).join(' ') + msg;
    +  }
    +
    +  function onError (err) {
    +    if (callback) {
    +      callback(err);
    +    }
    +    else if (self.emitErrs) {
    +      self.emit('error', err);
    +    };
    +  }
    +  
    +  if (this.transports.length === 0) {
    +    return onError(new Error('Cannot log with no transports.'));
    +  }
    +  else if (typeof self.levels[level] === 'undefined') {
    +    return onError(new Error('Unknown log level: ' + level));
    +  }
    +  

    For consideration of terminal 'color" programs like colors.js, +which can add ANSI escape color codes to strings, we destyle the +ANSI color escape codes when this.stripColors is set.

    + +

    see: http://en.wikipedia.org/wiki/ANSIescapecode

      if (this.stripColors) {
    +    var code = /\u001b\[\d+m/g;
    +    msg = ('' + msg).replace(code, '');
    +  }
    +  
    +  for (var i = 0, l = this._names.length; i < l; i++) {
    +    var transport = this.transports[this._names[i]];
    +    if ((transport.level && self.levels[transport.level] <= self.levels[level])
    +      || (!transport.level && self.levels[self.level] <= self.levels[level])) {
    +      transport.log(level, msg, meta, function (err) {
    +        self.emit('logging', transport, level, msg, meta);
    +      });
    +    }
    +  }
    +  

    Immediately respond to the callback

      if (callback) {
    +    callback(null, level, msg, meta);    
    +  }
    +  
    +  return this;
    +};

    function handleExceptions ()

    + +

    Handles uncaughtException events for the current process

    Logger.prototype.handleExceptions = function () {
    +  var args = Array.prototype.slice.call(arguments),
    +      handlers = [],
    +      self = this;
    +      
    +  args.forEach(function (a) {
    +    if (Array.isArray(a)) {
    +      handlers = handlers.concat(a);
    +    }
    +    else {
    +      handlers.push(a);
    +    }
    +  });
    +  
    +  handlers.forEach(function (handler) {
    +    self.exceptionHandlers[handler.name] = handler;
    +  });
    +  
    +  this._hnames = Object.keys(self.exceptionHandlers);
    +    
    +  if (!this.catchExceptions) {
    +    this.catchExceptions = this._uncaughtException.bind(this);
    +    process.on('uncaughtException', this.catchExceptions);
    +  }
    +};

    function unhandleExceptions ()

    + +

    Removes any handlers to uncaughtException events +for the current process

    Logger.prototype.unhandleExceptions = function () {
    +  var self = this;
    +  
    +  if (this.catchExceptions) {
    +    Object.keys(this.exceptionHandlers).forEach(function (name) {
    +      if (handler.close) {
    +        handler.close();
    +      }
    +    });
    +    
    +    this.exceptionHandlers = {};
    +    Object.keys(this.transports).forEach(function (name) {
    +      var transport = self.transports[name];
    +      if (transport.handleExceptions) {
    +        transport.handleExceptions = false;
    +      }
    +    })
    +    
    +    process.removeListener('uncaughtException', this.catchExceptions);
    +    this.catchExceptions = false;    
    +  }
    +};

    function add (transport, [options])

    + +

    @transport {Transport} Prototype of the Transport object to add.

    + +

    @options {Object} Optional Options for the Transport to add.

    + +

    @instance {Boolean} Optional Value indicating if transport is already instantiated.

    + +

    Adds a transport of the specified type to this instance.

    Logger.prototype.add = function (transport, options, created) {
    +  var instance = created ? transport : (new (transport)(options));
    +  
    +  if (!instance.name && !instance.log) {
    +    throw new Error('Unknown transport with no log() method');
    +  }
    +  else if (this.transports[instance.name]) {
    +    throw new Error('Transport already attached: ' + instance.name);
    +  }
    +  
    +  this.transports[instance.name] = instance;
    +  this._names = Object.keys(this.transports);
    +  

    Listen for the error event on the new Transport

      instance._onError = this._onError.bind(this, instance)
    +  instance.on('error', instance._onError);
    +
    +  return this;
    +};

    function remove (transport)

    + +

    @transport {Transport} Transport to remove.

    + +

    Removes a transport of the specified type from this instance.

    Logger.prototype.remove = function (transport) {
    +  var name = transport.name || transport.prototype.name;
    +    
    +  if (!this.transports[name]) {
    +    throw new Error('Transport ' + name + ' not attached to this instance');
    +  }
    +  
    +  var instance = this.transports[name];
    +  delete this.transports[name];
    +  this._names = Object.keys(this.transports);
    +  
    +  if (instance.close) {
    +    instance.close();
    +  }
    +  
    +  instance.removeListener('error', instance._onError);
    +  return this;
    +};

    function profile (id, [msg, meta, callback])

    + +

    @id {string} Unique id of the profiler

    + +

    @msg {string} Optional Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Optional Continuation to respond to when complete.

    + +

    Tracks the time inbetween subsequent calls to this method +with the same id parameter. The second call to this method +will log the difference in milliseconds along with the message.

    Logger.prototype.profile = function (id) {
    +  var now = Date.now(), then, args,
    +      msg, meta, callback;
    +  
    +  if (this.profilers[id] && arguments.length !== 1) {
    +    then = this.profilers[id];
    +    delete this.profilers[id];
    +    

    Support variable arguments: msg, meta, callback

        args     = Array.prototype.slice.call(arguments);
    +    callback = typeof args[args.length - 1] === 'function' ? args.pop() : null;
    +    meta     = typeof args[args.length - 1] === 'object' ? args.pop() : {};
    +    msg      = args.length === 2 ? args[1] : id; 
    +    

    Set the duration property of the metadata

        meta.duration = now - then + 'ms'; 
    +    return this.info(msg, meta, callback);
    +  }
    +  else {
    +    this.profilers[id] = now;
    +  }
    +  
    +  return this;
    +};

    function setLevels (target)

    + +

    @target {Object} Target levels to use on this instance

    + +

    Sets the target levels specified on this instance.

    Logger.prototype.setLevels = function (target) {
    +  return common.setLevels(this, this.levels, target);
    +};

    function cli ()

    + +

    Configures this instance to have the default +settings for command-line interfaces: no timestamp, +colors enabled, padded output, and additional levels.

    Logger.prototype.cli = function () {
    +  this.padLevels = true;
    +  this.setLevels(config.cli.levels);
    +  config.addColors(config.cli.colors);
    +  
    +  if (this.transports.console) {
    +    this.transports.console.colorize = true;
    +    this.transports.console.timestamp = false;
    +  }
    +  
    +  return this;
    +};

    @private function _uncaughtException (err)

    + +

    @err {Error} Error to handle

    + +

    Logs all relevant information around the err and +exits the current process.

    Logger.prototype._uncaughtException = function (err) {
    +  var self = this,
    +      responded = false,
    +      info = exception.getAllInfo(err),
    +      handlers = this._getExceptionHandlers(),
    +      timeout;
    +  
    +  function logAndWait (transport, next) {
    +    transport.logException('uncaughtException', info, next);
    +  }
    +  
    +  function gracefulExit () {
    +    if (!responded) {

    Remark: Currently ignoring any exceptions from transports + when catching uncaught exceptions.

          clearTimeout(timeout);
    +      responded = true;
    +      process.exit(1);
    +    }
    +  }
    +  
    +  if (!handlers || handlers.length === 0) {
    +    return gracefulExit();
    +  }
    +  

    Log to all transports and allow the operation to take +only up to 3000ms.

      async.forEach(handlers, logAndWait, gracefulExit);
    +  timeout = setTimeout(gracefulExit, 3000);
    +};

    @private function _getExceptionHandlers ()

    + +

    Returns the list of transports and exceptionHandlers +for this instance.

    Logger.prototype._getExceptionHandlers = function () {
    +  var self = this;
    +
    +  return this._hnames.map(function (name) {
    +    return self.exceptionHandlers[name];
    +  }).concat(this._names.map(function (name) {
    +    return self.transports[name].handleExceptions && self.transports[name];
    +  })).filter(Boolean);
    +};

    @private function _onError (transport, err)

    + +

    @transport {Object} Transport on which the error occured

    + +

    @err {Error} Error that occurred on the transport

    + +

    Bubbles the error, err, that occured on the specified transport +up from this instance if emitErrs has been set.

    Logger.prototype._onError = function (transport, err) {
    +  if (self.emitErrs) {
    +    self.emit('error', err, transport);
    +  }
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports.html new file mode 100644 index 0000000..bc92fc8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports.html @@ -0,0 +1,29 @@ + transports.js

    transports.js

    /*
    + * transports.js: Set of all transports Winston knows about
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var fs = require('fs'),
    +    path = require('path');
    +
    +var transports = exports;
    +
    +function capitalize (str) {
    +  return str && str[0].toUpperCase() + str.slice(1);
    +};

    Setup all transports as lazy-loaded getters.

    fs.readdirSync(path.join(__dirname, 'transports')).forEach(function (file) {
    +  var transport = file.replace('.js', ''),
    +      name  = capitalize(transport);
    +  
    +  if (transport === 'transport') {
    +    return;
    +  }
    +  
    +  transports.__defineGetter__(name, function () {
    +    return require('./transports/' + transport)[name];
    +  });
    +});
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/console.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/console.html new file mode 100644 index 0000000..3d45f36 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/console.html @@ -0,0 +1,59 @@ + console.js

    console.js

    /*
    + * console.js: Transport for outputting to the console
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var events = require('events'),
    +    util = require('util'),
    +    colors = require('colors'),
    +    common = require('../common'),
    +    Transport = require('./transport').Transport;

    function Console (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Console transport object responsible +for persisting log messages and metadata to a terminal or TTY.

    var Console = exports.Console = function (options) {
    +  Transport.call(this, options);
    +  options = options || {};
    +  
    +  this.name      = 'console';
    +  this.json      = options.json     || false;
    +  this.colorize  = options.colorize || false;
    +  this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;
    +};

    Inherit from winston.Transport.

    util.inherits(Console, Transport);

    Expose the name of this Transport on the prototype

    Console.prototype.name = 'console';

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    Console.prototype.log = function (level, msg, meta, callback) {
    +  if (this.silent) {
    +    return callback(null, true);
    +  }
    +    
    +  var self = this, output = common.log({
    +    level:     level,
    +    message:   msg,
    +    meta:      meta,
    +    colorize:  this.colorize, 
    +    timestamp: this.timestamp
    +  });
    +  
    +  if (level === 'error' || level === 'debug') {
    +    util.error(output);
    +  }
    +  else {
    +    util.puts(output);
    +  }

    Emit the logged event immediately because the event loop +will not exit until process.stdout has drained anyway.

      self.emit('logged');
    +  callback(null, true);
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/couchdb.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/couchdb.html new file mode 100644 index 0000000..b7690de --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/couchdb.html @@ -0,0 +1,84 @@ + couchdb.js

    couchdb.js

    /*
    + * Couchdb.js: Transport for logging to Couchdb
    + *
    + * (C) 2011 Max Ogden
    + * MIT LICENSE
    + *
    + */
    +
    +var events = require('events'),
    +    http = require('http'),
    +    util = require('util'),
    +    common = require('../common'),
    +    Transport = require('./transport').Transport; 

    function Couchdb (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Console transport object responsible +for making arbitrary HTTP requests whenever log messages and metadata +are received.

    var Couchdb = exports.Couchdb = function (options) {
    +  Transport.call(this, options);
    +
    +  this.name   = 'Couchdb'; 
    +  this.db     = options.db;
    +  this.user   = options.user;
    +  this.pass   = options.pass;
    +  this.host   = options.host   || 'localhost';
    +  this.port   = options.port   || 5984;
    +
    +  if (options.auth) {

    TODO: add http basic auth options for outgoing HTTP requests

      }
    +  
    +  if (options.ssl) {

    TODO: add ssl support for outgoing HTTP requests

      }  
    +};

    Inherit from winston.Transport.

    util.inherits(Couchdb, Transport);

    Expose the name of this Transport on the prototype

    Couchdb.prototype.name = 'Couchdb';

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    Couchdb.prototype.log = function (level, msg, meta, callback) {
    +  if (this.silent) {
    +    return callback(null, true);
    +  }
    +  
    +  var self = this,
    +      message = common.clone(meta),
    +      options,
    +      req;
    +      
    +  message.level = level;
    +  message.message = msg;

    Prepare options for outgoing HTTP request

      options = {
    +    host: this.host,
    +    port: this.port,
    +    path: "/" + this.db,
    +    method: "POST",
    +    headers: {"content-type": "application/json"}
    +  };
    +  
    +  if (options.user && options.pass) {
    +    options.headers["Authorization"] = "Basic " + new Buffer(options.user + ":" + options.pass).toString('base64');
    +  }
    +  

    Perform HTTP logging request

      req = http.request(options, function (res) { 

    No callback on request, fire and forget about the response

        self.emit('logged', res);
    +  }); 
    +
    +  req.on('error', function (err) {

    Propagate the error back up to the Logger that this +instance belongs to.

        self.emit('error', err);
    +  });
    +  

    Write logging event to the outgoing request body

      req.write(JSON.stringify({ 
    +    method: 'log', 
    +    params: { 
    +      timestamp: new Date(), // RFC3339/ISO8601 format instead of common.timestamp()
    +      msg: msg, 
    +      level: level, 
    +      meta: meta 
    +    } 
    +  }));
    +  
    +  req.end();
    +  

    Always return true, regardless of any errors

      callback(null, true);
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/file.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/file.html new file mode 100644 index 0000000..bba8459 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/file.html @@ -0,0 +1,211 @@ + file.js

    file.js

    /*
    + * file.js: Transport for outputting to a local log file
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var events = require('events'),
    +    fs = require('fs'),
    +    path = require('path'),
    +    util = require('util'),
    +    colors = require('colors'),
    +    common = require('../common'),
    +    Transport = require('./transport').Transport;
    +    

    function File (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the File transport object responsible +for persisting log messages and metadata to one or more files.

    var File = exports.File = function (options) {
    +  Transport.call(this, options);
    +  

    Helper function which throws an Error in the event +that any of the rest of the arguments is present in options.

      function throwIf (target /*, illegal... */) {
    +    Array.prototype.slice.call(arguments, 1).forEach(function (name) {
    +      if (options[name]) {
    +        throw new Error('Cannot set ' + name + ' and ' + target + 'together');
    +      }
    +    });
    +  }
    +  
    +  if (options.filename || options.dirname) {
    +    throwIf('filename or dirname', 'stream');
    +    this._basename = this.filename = path.basename(options.filename) || 'winston.log';
    +    this.dirname   = options.dirname || path.dirname(options.filename);
    +    this.options   = options.options || { flags: 'a' };    
    +  }
    +  else if (options.stream) {
    +    throwIf('stream', 'filename', 'maxsize');
    +    this.stream = options.stream;
    +  }
    +  else {
    +    throw new Error('Cannot log to file without filename or stream.');
    +  }
    +    
    +  this.json      = options.json !== false;
    +  this.colorize  = options.colorize  || false;
    +  this.maxsize   = options.maxsize   || null;
    +  this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;

    Internal state variables representing the number +of files this instance has created and the current +size (in bytes) of the current logfile.

      this._size    = 0;
    +  this._created = 0;
    +  this._buffer  = [];
    +};

    Inherit from winston.Transport.

    util.inherits(File, Transport);

    Expose the name of this Transport on the prototype

    File.prototype.name = 'file';

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    File.prototype.log = function (level, msg, meta, callback) {
    +  if (this.silent) {
    +    return callback(null, true);
    +  }
    +
    +  var self = this, output = common.log({
    +    level:     level,
    +    message:   msg,
    +    meta:      meta,
    +    json:      this.json,
    +    colorize:  this.colorize,
    +    timestamp: this.timestamp
    +  }) + '\n';
    +  
    +  this._size += output.length;
    +  
    +  function onDrain () {
    +    self.emit('logged');
    +  }
    +  
    +  if (!this.filename) {

    If there is no filename on this instance then it was configured +with a raw WriteableStream instance and we should not perform any +size restrictions.

        this.stream.write(output);
    +    this.stream.once('drain', onDrain);
    +  }
    +  else {
    +    this.open(function (err) {
    +      if (err) {

    If there was an error enqueue the message

            return self._buffer.push(output);
    +      }
    +      
    +      self.stream.write(output);
    +      self.stream.once('drain', onDrain);
    +    });
    +  }
    +
    +  callback(null, true);
    +};

    function open (callback)

    + +

    @callback {function} Continuation to respond to when complete

    + +

    Checks to see if a new file needs to be created based on the maxsize +(if any) and the current size of the file used.

    File.prototype.open = function (callback) {
    +  if (this.opening) {

    If we are already attempting to open the next +available file then respond with a value indicating +that the message should be buffered.

        return callback(true);
    +  }
    +  else if (!this.stream || (this.maxsize && this._size >= this.maxsize)) {

    If we dont have a stream or have exceeded our size, then create +the next stream and respond with a value indicating that +the message should be buffered.

        callback(true);
    +    return this._createStream();
    +  }
    +  

    Otherwise we have a valid (and ready) stream.

      callback();
    +};

    function close ()

    + +

    Closes the stream associated with this instance.

    File.prototype.close = function() {
    +  var self = this;
    +
    +  if (this.stream) {
    +    this.stream.end();
    +    this.stream.destroySoon();
    +    
    +    this.stream.once('drain', function () {
    +      self.emit('flush');
    +      self.emit('closed');
    +    });
    +  }
    +};

    function flush ()

    + +

    Flushes any buffered messages to the current stream +used by this instance.

    File.prototype.flush = function () {
    +  var self = this;

    Iterate over the _buffer of enqueued messaged +and then write them to the newly created stream.

      this._buffer.forEach(function (str) {
    +    process.nextTick(function () {
    +      self.stream.write(str);
    +      self._size += str.length;
    +    });
    +  });
    +  

    Quickly truncate the _buffer once the write operations +have been started

      self._buffer.length = 0;
    +  

    When the stream has drained we have flushed +our buffer.

      self.stream.once('drain', function () {
    +    self.emit('flush');
    +    self.emit('logged');
    +  });
    +};

    @private function _createStream ()

    + +

    Attempts to open the next appropriate file for this instance +based on the common state (such as maxsize and _basename).

    File.prototype._createStream = function () {
    +  var self = this;
    +  this.opening = true;
    +    
    +  (function checkFile (target) {
    +    var fullname = path.join(self.dirname, target);
    +    

    Creates the WriteStream and then flushes any +buffered messages.

        function createAndFlush (size) {
    +      if (self.stream) {
    +        self.stream.end();
    +        self.stream.destroySoon();
    +      }
    +      
    +      self._size = size;
    +      self.filename = target;
    +      self.stream = fs.createWriteStream(fullname, self.options);
    +      

    When the current stream has finished flushing +then we can be sure we have finished opening +and thus can emit the open event.

          self.once('flush', function () {
    +        self.opening = false;
    +        self.emit('open', fullname);
    +      });

    Remark: It is possible that in the time it has taken to find the +next logfile to be written more data than maxsize has been buffered, +but for sensible limits (10s - 100s of MB) this seems unlikely in less +than one second.

          self.flush();
    +    }
    +
    +    fs.stat(fullname, function (err, stats) {
    +      if (err) {
    +        if (err.code !== 'ENOENT') {
    +          return self.emit('error', err);
    +        }
    +        
    +        return createAndFlush(0);
    +      }
    +      
    +      if (!stats || (self.maxsize && stats.size >= self.maxsize)) {

    If stats.size is greater than the maxsize for +this instance then try again

            return checkFile(self._getFile(true));
    +      }
    +      
    +      createAndFlush(stats.size);
    +    });
    +  })(this._getFile());  
    +};

    @private function _getFile ()

    + +

    Gets the next filename to use for this instance +in the case that log filesizes are being capped.

    File.prototype._getFile = function (inc) {
    +  var self = this,
    +      ext = path.extname(this._basename),
    +      basename = path.basename(this._basename, ext);
    +  
    +  if (inc) {

    Increment the number of files created or +checked by this instance.

        this._created += 1;
    +  }
    +  
    +  return this._created 
    +    ? basename + this._created + ext
    +    : basename + ext;
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/loggly.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/loggly.html new file mode 100644 index 0000000..7652318 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/loggly.html @@ -0,0 +1,118 @@ + loggly.js

    loggly.js

    /*
    + * loggly.js: Transport for logginh to remote Loggly API
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var events = require('events'),
    +    loggly = require('loggly'),
    +    util = require('util'),
    +    async = require('async'),
    +    common = require('../common'),
    +    Transport = require('./transport').Transport; 

    function Loggly (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Loggly transport object responsible +for persisting log messages and metadata to Loggly; 'LaaS'.

    var Loggly = exports.Loggly = function (options) {
    +  Transport.call(this, options);
    +
    +  if (!options.subdomain) {
    +    throw new Error('Loggly Subdomain is required');
    +  }
    +  
    +  if (!options.inputToken && !options.inputName) {
    +    throw new Error('Target input token or name is required.');
    +  }
    +  
    +  if (!options.auth && options.inputName) {
    +    throw new Error('Loggly authentication is required');
    +  }
    +  
    +  this.name = 'loggly'; 
    +  this.logBuffer = [];
    +  
    +  this.client = loggly.createClient({
    +    subdomain: options.subdomain,
    +    auth: options.auth || null,
    +    json: options.json || false
    +  });
    +  
    +  if (options.inputToken) {
    +    this.inputToken = options.inputToken;
    +    this.ready = true;
    +  }
    +  else if (options.inputName) {
    +    this.ready = false;
    +    this.inputName = options.inputName;
    +    
    +    var self = this;
    +    this.client.getInput(this.inputName, function (err, input) {
    +      if (err) {
    +        throw err;
    +      }
    +      
    +      self.inputToken = input.input_token;
    +      self.ready = true;
    +    });
    +  }
    +};

    Inherit from winston.Transport.

    util.inherits(Loggly, Transport);

    Expose the name of this Transport on the prototype

    Loggly.prototype.name = 'loggly';

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    Loggly.prototype.log = function (level, msg, meta, callback) {
    +  if (this.silent) {
    +    return callback(null, true);
    +  }
    +
    +  var self = this,
    +      message = common.clone(meta);
    +      
    +  message.level = level;
    +  message.message = msg;
    +  
    +  if (!this.ready) {

    If we haven't gotten the input token yet +add this message to the log buffer.

        this.logBuffer.push(message);
    +  }
    +  else if (this.ready && this.logBuffer.length > 0) {

    Otherwise if we have buffered messages +add this message to the buffer and flush them.

        this.logBuffer.push(message);
    +    this.flush();
    +  }
    +  else {

    Otherwise just log the message as normal

        this.client.log(this.inputToken, message, function () {
    +      self.emit('logged');
    +    });
    +  }
    +  
    +  callback(null, true);
    +};

    function flush ()

    + +

    Flushes any buffered messages to the current stream +used by this instance.

    Loggly.prototype.flush = function () {
    +  var self = this;
    +  
    +  function logMsg (msg, next) {
    +    self.client.log(self.inputToken, msg, function (err) {
    +      if (err) {
    +        self.emit('error', err);
    +      }
    +      
    +      next();
    +    });
    +  }
    +  

    Initiate calls to loggly for each message in the buffer

      async.forEach(this.logBuffer, logMsg, function () {
    +    self.emit('logged');
    +  });
    +  
    +  process.nextTick(function () {

    Then quickly truncate the list

        self.logBuffer.length = 0;
    +  });
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/transport.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/transport.html new file mode 100644 index 0000000..f0cc4b9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/transport.html @@ -0,0 +1,50 @@ + transport.js

    transport.js

    /*
    + * transport.js: Base Transport object for all Winston transports.
    + *
    + * (C) 2010 Charlie Robbins
    + * MIT LICENCE
    + *
    + */
    +
    +var events = require('events'),
    +    util = require('util'); 

    function Transport (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Tranport object responsible +base functionality for all winston transports.

    var Transport = exports.Transport = function (options) {
    +  events.EventEmitter.call(this);
    +  
    +  options               = options        || {};  
    +  this.level            = options.level  || 'info';
    +  this.silent           = options.silent || false;
    +  this.handleExceptions = options.handleExceptions || false;
    +};

    Inherit from events.EventEmitter.

    util.inherits(Transport, events.EventEmitter);

    function logException (msg, meta, callback)

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Logs the specified msg, meta and responds to the callback once the log +operation is complete to ensure that the event loop will not exit before +all logging has completed.

    Transport.prototype.logException = function (msg, meta, callback) {
    +  var self = this;
    +  
    +  function onLogged () {
    +    self.removeListener('error', onError);
    +    callback();
    +  }
    +  
    +  function onError () {
    +    self.removeListener('logged', onLogged);
    +    callback();
    +  }
    +  
    +  this.once('logged', onLogged);
    +  this.once('error', onError);  
    +  this.log('error', msg, meta, function () { });
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/webhook.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/webhook.html new file mode 100644 index 0000000..7191495 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/docs/winston/transports/webhook.html @@ -0,0 +1,82 @@ + webhook.js

    webhook.js

    /*
    + * webhook.js: Transport for logging to remote http endpoints ( POST / RECEIVE webhooks )
    + *
    + * (C) 2011 Marak Squires
    + * MIT LICENCE
    + *
    + */
    +
    +var events = require('events'),
    +    http = require('http'),
    +    util = require('util'),
    +    common = require('../common'),
    +    Transport = require('./transport').Transport; 

    function WebHook (options)

    + +

    @options {Object} Options for this instance.

    + +

    Constructor function for the Console transport object responsible +for making arbitrary HTTP requests whenever log messages and metadata +are received.

    var Webhook = exports.Webhook = function (options) {
    +  Transport.call(this, options);
    +
    +  this.name   = 'webhook'; 
    +  this.host   = options.host   || 'localhost';
    +  this.port   = options.port   || 8080;
    +  this.method = options.method || 'POST';
    +  this.path   = options.path   || '/winston-log';
    +
    +  if (options.auth) {

    TODO: add http basic auth options for outgoing HTTP requests

      }
    +  
    +  if (options.ssl) {

    TODO: add ssl support for outgoing HTTP requests

      }  
    +};

    Inherit from winston.Transport.

    util.inherits(Webhook, Transport);

    Expose the name of this Transport on the prototype

    Webhook.prototype.name = 'webhook';

    function log (level, msg, [meta], callback)

    + +

    @level {string} Level at which to log the message.

    + +

    @msg {string} Message to log

    + +

    @meta {Object} Optional Additional metadata to attach

    + +

    @callback {function} Continuation to respond to when complete.

    + +

    Core logging method exposed to Winston. Metadata is optional.

    Webhook.prototype.log = function (level, msg, meta, callback) {
    +  if (this.silent) {
    +    return callback(null, true);
    +  }
    +  
    +  var self = this,
    +      message = common.clone(meta),
    +      options,
    +      req;
    +      
    +  message.level = level;
    +  message.message = msg;

    Prepare options for outgoing HTTP request

      options = {
    +    host: this.host,
    +    port: this.port,
    +    path: this.path,
    +    method: this.method
    +  };
    +  

    Perform HTTP logging request

      req = http.request(options, function (res) { 

    No callback on request, fire and forget about the response

        self.emit('logged');
    +  }); 
    +
    +  req.on('error', function (err) {

    Propagate the error back up to the Logger that this +instance belongs to.

        self.emit('error', err);
    +  });
    +  

    Write logging event to the outgoing request body

    + +

    jsonMessage is currently conforming to JSON-RPC v1.0, +but without the unique id since there is no anticipated response +see: http://en.wikipedia.org/wiki/JSON-RPC

      req.write(JSON.stringify({ 
    +    method: 'log', 
    +    params: { 
    +      timestamp: common.timestamp(), 
    +      msg: msg, 
    +      level: level, 
    +      meta: meta 
    +    } 
    +  }));
    +  
    +  req.end();
    +  

    Always return true, regardless of any errors

      callback(null, true);
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/couchdb.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/couchdb.js new file mode 100644 index 0000000..ce2d960 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/couchdb.js @@ -0,0 +1,18 @@ +var winston = require('../lib/winston'); + +// +// Create a new winston logger instance with two tranports: Console, and Couchdb +// +// +// The Console transport will simply output to the console screen +// The Couchdb tranport will perform an HTTP POST request to the specified CouchDB instance +// +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.Console)(), + new (winston.transports.Couchdb)({ 'host': 'localhost', 'db': 'logs' }) + // if you need auth do this: new (winston.transports.Couchdb)({ 'user': 'admin', 'pass': 'admin', 'host': 'localhost', 'db': 'logs' }) + ] +}); + +logger.log('info', 'Hello webhook log files!', { 'foo': 'bar' }); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/raw-mode.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/raw-mode.js new file mode 100644 index 0000000..89e070d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/raw-mode.js @@ -0,0 +1,10 @@ +var winston = require('../lib/winston'); + +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.Console)({ raw: true }), + ] +}); + +logger.log('info', 'Hello, this is a raw logging event', { 'foo': 'bar' }); +logger.log('info', 'Hello, this is a raw logging event 2', { 'foo': 'bar' }); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/webhook-post.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/webhook-post.js new file mode 100644 index 0000000..0fa1c8d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/examples/webhook-post.js @@ -0,0 +1,17 @@ +var winston = require('../lib/winston'); + +// +// Create a new winston logger instance with two tranports: Console, and Webhook +// +// +// The Console transport will simply output to the console screen +// The Webhook tranports will perform an HTTP POST request to an abritrary end-point ( for post/recieve webhooks ) +// +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.Console)(), + new (winston.transports.Webhook)({ 'host': 'localhost', 'port': 8080, 'path': '/collectdata' }) + ] +}); + +logger.log('info', 'Hello webhook log files!', { 'foo': 'bar' }); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston.js new file mode 100644 index 0000000..51bfb45 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston.js @@ -0,0 +1,143 @@ +/* + * winston.js: Top-level include defining Winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var winston = exports; + +// +// Expose version using `pkginfo` +// +require('pkginfo')(module, 'version'); + +// +// Include transports defined by default by winston +// +winston.transports = require('./winston/transports'); + +// +// Expose utility methods +// +var common = require('./winston/common'); +winston.hash = common.hash; +winston.clone = common.clone; +winston.longestElement = common.longestElement; +winston.exception = require('./winston/exception'); +winston.config = require('./winston/config'); +winston.addColors = winston.config.addColors; + +// +// Expose core Logging-related prototypes. +// +winston.Container = require('./winston/container').Container; +winston.Logger = require('./winston/logger').Logger; +winston.Transport = require('./winston/transports/transport').Transport; + +// +// We create and expose a default `Container` to `winston.loggers` so that the +// programmer may manage multiple `winston.Logger` instances without any additional overhead. +// +// ### some-file1.js +// +// var logger = require('winston').loggers.get('something'); +// +// ### some-file2.js +// +// var logger = require('winston').loggers.get('something'); +// +winston.loggers = new winston.Container(); + +// +// We create and expose a 'defaultLogger' so that the programmer may do the +// following without the need to create an instance of winston.Logger directly: +// +// var winston = require('winston'); +// winston.log('info', 'some message'); +// winston.error('some error'); +// +var defaultLogger = new winston.Logger({ + transports: [new winston.transports.Console()] +}); + +// +// Pass through the target methods onto `winston. +// +var methods = [ + 'log', + 'add', + 'remove', + 'profile', + 'startTimer', + 'extend', + 'cli', + 'handleExceptions', + 'unhandleExceptions' +]; +common.setLevels(winston, null, defaultLogger.levels); +methods.forEach(function (method) { + winston[method] = function () { + return defaultLogger[method].apply(defaultLogger, arguments); + }; +}); + +// +// ### function cli () +// Configures the default winston logger to have the +// settings for command-line interfaces: no timestamp, +// colors enabled, padded output, and additional levels. +// +winston.cli = function () { + winston.padLevels = true; + common.setLevels(winston, defaultLogger.levels, winston.config.cli.levels); + defaultLogger.setLevels(winston.config.cli.levels); + winston.config.addColors(winston.config.cli.colors); + + if (defaultLogger.transports.console) { + defaultLogger.transports.console.colorize = true; + defaultLogger.transports.console.timestamp = false; + } + + return winston; +}; + +// +// ### function setLevels (target) +// #### @target {Object} Target levels to use +// Sets the `target` levels specified on the default winston logger. +// +winston.setLevels = function (target) { + common.setLevels(winston, defaultLogger.levels, target); + defaultLogger.setLevels(target); +}; + +// +// Define getters / setters for appropriate properties of the +// default logger which need to be exposed by winston. +// +['emitErrs', 'exitOnError', 'padLevels', 'level', 'levelLength', 'stripColors'].forEach(function (prop) { + Object.defineProperty(winston, prop, { + get: function () { + return defaultLogger[prop]; + }, + set: function (val) { + defaultLogger[prop] = val; + } + }); +}); + +// +// @default {Object} +// The default transports and exceptionHandlers for +// the default winston logger. +// +Object.defineProperty(winston, 'default', { + get: function () { + return { + transports: defaultLogger.transports, + exceptionHandlers: defaultLogger.exceptionHandlers + }; + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/common.js new file mode 100644 index 0000000..9b8abeb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/common.js @@ -0,0 +1,264 @@ +/* + * common.js: Internal helper and utility functions for winston + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var util = require('util'), + crypto = require('crypto'), + config = require('./config'); + +// +// ### function setLevels (target, past, current) +// #### @target {Object} Object on which to set levels. +// #### @past {Object} Previous levels set on target. +// #### @current {Object} Current levels to set on target. +// Create functions on the target objects for each level +// in current.levels. If past is defined, remove functions +// for each of those levels. +// +exports.setLevels = function (target, past, current, isDefault) { + if (past) { + Object.keys(past).forEach(function (level) { + delete target[level]; + }); + } + + target.levels = current || config.npm.levels; + if (target.padLevels) { + target.levelLength = exports.longestElement(Object.keys(target.levels)); + } + + // + // Define prototype methods for each log level + // e.g. target.log('info', msg) <=> target.info(msg) + // + Object.keys(target.levels).forEach(function (level) { + target[level] = function (msg) { + var args = Array.prototype.slice.call(arguments), + callback = typeof args[args.length - 1] === 'function' || !args[args.length - 1] ? args.pop() : null, + meta = args.length === 2 ? args.pop() : null; + + return target.log(level, msg, meta, callback); + }; + }); + + return target; +}; + +// +// ### function longestElement +// #### @xs {Array} Array to calculate against +// Returns the longest element in the `xs` array. +// +exports.longestElement = function (xs) { + return Math.max.apply( + null, + xs.map(function (x) { return x.length; }) + ); +}; + +// +// ### function clone (obj) +// #### @obj {Object} Object to clone. +// Helper method for deep cloning pure JSON objects +// i.e. JSON objects that are either literals or objects (no Arrays, etc) +// +exports.clone = function (obj) { + // we only need to clone refrence types (Object) + if (!(obj instanceof Object)) { + return obj; + } + else if (obj instanceof Date) { + return obj; + } + + var copy = {}; + for (var i in obj) { + if (Array.isArray(obj[i])) { + copy[i] = obj[i].slice(0); + } + else if (obj[i] instanceof Buffer) { + copy[i] = obj[i].slice(0); + } + else if (typeof obj[i] != 'function') { + copy[i] = obj[i] instanceof Object ? exports.clone(obj[i]) : obj[i]; + } + } + + return copy; +}; + +// +// ### function log (options) +// #### @options {Object} All information about the log serialization. +// Generic logging function for returning timestamped strings +// with the following options: +// +// { +// level: 'level to add to serialized message', +// message: 'message to serialize', +// meta: 'additional logging metadata to serialize', +// colorize: false, // Colorizes output (only if `.json` is false) +// timestamp: true // Adds a timestamp to the serialized message +// } +// +exports.log = function (options) { + var timestampFn = typeof options.timestamp === 'function' ? options.timestamp : exports.timestamp, + timestamp = options.timestamp ? timestampFn() : null, + meta = options.meta ? exports.clone(options.meta) : null, + output; + + // + // raw mode is intended for outputing winston as streaming JSON to STDOUT + // + if (options.raw) { + output = meta || {}; + output.level = options.level; + output.message = options.message.stripColors; + return JSON.stringify(output); + } + + // + // json mode is intended for pretty printing multi-line json to the terminal + // + if (options.json) { + output = meta || {}; + output.level = options.level; + output.message = options.message; + + if (timestamp) { + output.timestamp = timestamp; + } + + return typeof options.stringify === 'function' + ? options.stringify(output) + : JSON.stringify(output, function(key, value) { + if (value instanceof Buffer) { + return value.toString('base64'); + } + return value; + }); + } + + output = timestamp ? timestamp + ' - ' : ''; + output += options.colorize ? config.colorize(options.level) : options.level; + output += (': ' + options.message); + + if (meta) { + if (typeof meta !== 'object') { + output += ' ' + meta; + } + else if (Object.keys(meta).length > 0) { + output += ' ' + exports.serialize(meta); + } + } + + return output; +}; + +exports.capitalize = function (str) { + return str && str[0].toUpperCase() + str.slice(1); +}; + +// +// ### function hash (str) +// #### @str {string} String to hash. +// Utility function for creating unique ids +// e.g. Profiling incoming HTTP requests on the same tick +// +exports.hash = function (str) { + return crypto.createHash('sha1').update(str).digest('hex'); +}; + +// +// ## Borrowed from node.js core +// I wanted a universal lowercase header message, as opposed to the `DEBUG` +// (i.e. all uppercase header) used only in `util.debug()` +// +var months = ['Jan', 'Feb', 'Mar', 'Apr', + 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec']; + +// +// ### function pad (n) +// Returns a padded string if `n < 10`. +// +exports.pad = function (n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +}; + +// +// ### function timestamp () +// Returns a timestamp string for the current time. +// +exports.timestamp = function () { + var d = new Date(); + var time = [ + exports.pad(d.getHours()), + exports.pad(d.getMinutes()), + exports.pad(d.getSeconds()) + ].join(':'); + + return [d.getDate(), months[d.getMonth()], time].join(' '); +}; + +// +// ### function serialize (obj, key) +// #### @obj {Object|literal} Object to serialize +// #### @key {string} **Optional** Optional key represented by obj in a larger object +// Performs simple comma-separated, `key=value` serialization for Loggly when +// logging to non-JSON inputs. +// +exports.serialize = function (obj, key) { + if (obj === null) { + obj = 'null'; + } + else if (obj === undefined) { + obj = 'undefined'; + } + else if (obj === false) { + obj = 'false'; + } + + if (typeof obj !== 'object') { + return key ? key + '=' + obj : obj; + } + + if (obj instanceof Buffer) { + return key ? key + '=' + obj.toString('base64') : obj.toString('base64'); + } + + var msg = '', + keys = Object.keys(obj), + length = keys.length; + + for (var i = 0; i < length; i++) { + if (Array.isArray(obj[keys[i]])) { + msg += keys[i] + '=['; + + for (var j = 0, l = obj[keys[i]].length; j < l; j++) { + msg += exports.serialize(obj[keys[i]][j]); + if (j < l - 1) { + msg += ', '; + } + } + + msg += ']'; + } + else if (obj[keys[i]] instanceof Date) { + msg += keys[i] + '=' + obj[keys[i]]; + } + else { + msg += exports.serialize(obj[keys[i]], keys[i]); + } + + if (i < length - 1) { + msg += ', '; + } + } + + return msg; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config.js new file mode 100644 index 0000000..45e9283 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config.js @@ -0,0 +1,45 @@ +/* + * config.js: Default settings for all levels that winston knows about + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var colors = require('colors'); + +var config = exports, + allColors = exports.allColors = {}; + +config.addColors = function (colors) { + mixin(allColors, colors); +}; + +config.colorize = function (level) { + return level[allColors[level]]; +}; + +// +// Export config sets +// +config.cli = require('./config/cli-config'); +config.npm = require('./config/npm-config'); +config.syslog = require('./config/syslog-config'); + +// +// Add colors for pre-defined config sets +// +config.addColors(config.npm.colors); +config.addColors(config.syslog.colors); + +function mixin (target) { + var args = Array.prototype.slice.call(arguments, 1); + + args.forEach(function (a) { + var keys = Object.keys(a); + for (var i = 0; i < keys.length; i++) { + target[keys[i]] = a[keys[i]]; + } + }); + return target; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/cli-config.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/cli-config.js new file mode 100644 index 0000000..9798ddc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/cli-config.js @@ -0,0 +1,35 @@ +/* + * cli-config.js: Config that conform to commonly used CLI logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var cliConfig = exports; + +cliConfig.levels = { + silly: 0, + input: 1, + verbose: 2, + prompt: 3, + info: 4, + data: 5, + help: 6, + warn: 7, + debug: 8, + error: 9 +}; + +cliConfig.colors = { + silly: 'magenta', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/npm-config.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/npm-config.js new file mode 100644 index 0000000..464f735 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/npm-config.js @@ -0,0 +1,27 @@ +/* + * npm-config.js: Config that conform to npm logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var npmConfig = exports; + +npmConfig.levels = { + silly: 0, + verbose: 1, + info: 2, + warn: 3, + debug: 4, + error: 5 +}; + +npmConfig.colors = { + silly: 'magenta', + verbose: 'cyan', + info: 'green', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/syslog-config.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/syslog-config.js new file mode 100644 index 0000000..a198abc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/config/syslog-config.js @@ -0,0 +1,31 @@ +/* + * syslog-config.js: Config that conform to syslog logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var syslogConfig = exports; + +syslogConfig.levels = { + debug: 0, + info: 1, + notice: 2, + warning: 3, + error: 4, + crit: 5, + alert: 6, + emerg: 7 +}; + +syslogConfig.colors = { + debug: 'blue', + info: 'green', + notice: 'yellow', + warning: 'red', + error: 'red', + crit: 'red', + alert: 'yellow', + emerg: 'red' +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/container.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/container.js new file mode 100644 index 0000000..0e67b20 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/container.js @@ -0,0 +1,101 @@ +/* + * container.js: Inversion of control container for winston logger instances + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var common = require('./common'), + winston = require('../winston'); + +// +// ### function Container (options) +// #### @options {Object} Default pass-thru options for Loggers +// Constructor function for the Container object responsible for managing +// a set of `winston.Logger` instances based on string ids. +// +var Container = exports.Container = function (options) { + this.loggers = {}; + this.options = options || {}; + this.default = { + transports: [ + new winston.transports.Console({ + level: 'silly', + colorize: false + }) + ] + } +}; + +// +// ### function get / add (id, options) +// #### @id {string} Id of the Logger to get +// #### @options {Object} **Optional** Options for the Logger instance +// Retreives a `winston.Logger` instance for the specified `id`. If +// an instance does not exist, one is created. +// +Container.prototype.get = Container.prototype.add = function (id, options) { + if (!this.loggers[id]) { + options = common.clone(options || this.options || this.default); + options.transports = options.transports || []; + + if (options.transports.length === 0 && (!options || !options['console'])) { + options.transports.push(this.default.transports[0]); + } + + Object.keys(options).forEach(function (key) { + if (key === 'transports') { + return; + } + + var name = common.capitalize(key); + + if (!winston.transports[name]) { + throw new Error('Cannot add unknown transport: ' + name); + } + + var namedOptions = options[key]; + namedOptions.id = id; + options.transports.push(new (winston.transports[name])(namedOptions)); + }); + + this.loggers[id] = new winston.Logger(options); + } + + return this.loggers[id]; +}; + +// +// ### function close (id) +// #### @id {string} **Optional** Id of the Logger instance to find +// Returns a boolean value indicating if this instance +// has a logger with the specified `id`. +// +Container.prototype.has = function (id) { + return !!this.loggers[id]; +}; + +// +// ### function close (id) +// #### @id {string} **Optional** Id of the Logger instance to close +// Closes a `Logger` instance with the specified `id` if it exists. +// If no `id` is supplied then all Loggers are closed. +// +Container.prototype.close = function (id) { + var self = this; + + function _close (id) { + if (!self.loggers[id]) { + return; + } + + self.loggers[id].close(); + delete self.loggers[id]; + } + + return id ? _close(id) : Object.keys(this.loggers).forEach(function (id) { + _close(id); + }); +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/exception.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/exception.js new file mode 100644 index 0000000..2a01e91 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/exception.js @@ -0,0 +1,55 @@ +/* + * exception.js: Utility methods for gathing information about uncaughtExceptions. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var os = require('os'), + stackTrace = require('stack-trace'); + +var exception = exports; + +exception.getAllInfo = function (err) { + return { + process: exception.getProcessInfo(), + os: exception.getOsInfo(), + trace: exception.getTrace(err), + stack: err.stack.split('\n') + }; +}; + +exception.getProcessInfo = function () { + return { + pid: process.pid, + uid: process.getuid(), + gid: process.getgid(), + cwd: process.cwd(), + execPath: process.execPath, + version: process.version, + argv: process.argv, + memoryUsage: process.memoryUsage() + }; +}; + +exception.getOsInfo = function () { + return { + loadavg: os.loadavg(), + uptime: os.uptime() + }; +}; + +exception.getTrace = function (err) { + var trace = err ? stackTrace.parse(err) : stackTrace.get(); + return trace.map(function (site) { + return { + column: site.getColumnNumber(), + file: site.getFileName(), + function: site.getFunctionName(), + line: site.getLineNumber(), + method: site.getMethodName(), + native: site.isNative(), + } + }); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/logger.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/logger.js new file mode 100644 index 0000000..baaa057 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/logger.js @@ -0,0 +1,515 @@ +/* + * logger.js: Core logger object used by winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var events = require('events'), + util = require('util'), + async = require('async'), + config = require('./config'), + common = require('./common'), + exception = require('./exception'); + +// +// Time constants +// +var ticksPerMillisecond = 10000; + +// +// ### function Logger (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Logger object responsible +// for persisting log messages and metadata to one or more transports. +// +var Logger = exports.Logger = function (options) { + events.EventEmitter.call(this); + options = options || {}; + + var self = this, + handleExceptions = false; + + // + // Set Levels and default logging level + // + this.padLevels = options.padLevels || false; + this.setLevels(options.levels); + if (options.colors) { + config.addColors(options.colors); + } + + // + // Hoist other options onto this instance. + // + this.level = options.level || 'info'; + this.emitErrs = options.emitErrs || false; + this.stripColors = options.stripColors || false; + this.exitOnError = typeof options.exitOnError !== 'undefined' + ? options.exitOnError + : true; + + // + // Setup other intelligent default settings. + // + this.transports = {}; + this.rewriters = []; + this.exceptionHandlers = {}; + this.profilers = {}; + this._names = []; + this._hnames = []; + + if (options.transports) { + options.transports.forEach(function (transport) { + self.add(transport, null, true); + + if (transport.handleExceptions) { + handleExceptions = true; + } + }); + } + + if (options.rewriters) { + options.rewriters.forEach(function(rewriter) { + self.addRewriter(rewriter); + }); + } + + if (options.exceptionHandlers) { + handleExceptions = true; + options.exceptionHandlers.forEach(function (handler) { + self._hnames.push(handler.name); + self.exceptionHandlers[handler.name] = handler; + }); + } + + if (options.handleExceptions || handleExceptions) { + this.handleExceptions(); + } +}; + +// +// Inherit from `events.EventEmitter`. +// +util.inherits(Logger, events.EventEmitter); + +// +// ### function extend (target) +// #### @target {Object} Target to extend. +// Extends the target object with a 'log' method +// along with a method for each level in this instance. +// +Logger.prototype.extend = function (target) { + var self = this; + ['log', 'profile', 'startTimer'].concat(Object.keys(this.levels)).forEach(function (method) { + target[method] = function () { + return self[method].apply(self, arguments); + }; + }); + + return this; +}; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +Logger.prototype.log = function (level, msg) { + var self = this, + callback, + meta; + + if (arguments.length === 3) { + if (typeof arguments[2] === 'function') { + meta = {}; + callback = arguments[2]; + } + else if (typeof arguments[2] === 'object') { + meta = arguments[2]; + } + } + else if (arguments.length === 4) { + meta = arguments[2]; + callback = arguments[3]; + } + + // If we should pad for levels, do so + if (this.padLevels) { + msg = new Array(this.levelLength - level.length).join(' ') + msg; + } + + function onError (err) { + if (callback) { + callback(err); + } + else if (self.emitErrs) { + self.emit('error', err); + }; + } + + if (this.transports.length === 0) { + return onError(new Error('Cannot log with no transports.')); + } + else if (typeof self.levels[level] === 'undefined') { + return onError(new Error('Unknown log level: ' + level)); + } + + this.rewriters.forEach(function(rewriter) { + meta = rewriter(level, msg, meta); + }); + + // + // For consideration of terminal 'color" programs like colors.js, + // which can add ANSI escape color codes to strings, we destyle the + // ANSI color escape codes when `this.stripColors` is set. + // + // see: http://en.wikipedia.org/wiki/ANSI_escape_code + // + if (this.stripColors) { + var code = /\u001b\[\d+m/g; + msg = ('' + msg).replace(code, ''); + } + + for (var i = 0, l = this._names.length; i < l; i++) { + var transport = this.transports[this._names[i]]; + if ((transport.level && self.levels[transport.level] <= self.levels[level]) + || (!transport.level && self.levels[self.level] <= self.levels[level])) { + transport.log(level, msg, meta, function (err) { + self.emit('logging', transport, level, msg, meta); + }); + } + } + + // + // Immediately respond to the callback + // + if (callback) { + callback(null, level, msg, meta); + } + + return this; +}; + +// +// ### function close () +// Cleans up resources (streams, event listeners) for all +// transports associated with this instance (if necessary). +// +Logger.prototype.close = function () { + var self = this; + + this._names.forEach(function (name) { + var transport = self.transports[name]; + if (transport && transport.close) { + transport.close(); + } + }); +}; + +// +// ### function handleExceptions () +// Handles `uncaughtException` events for the current process +// +Logger.prototype.handleExceptions = function () { + var args = Array.prototype.slice.call(arguments), + handlers = [], + self = this; + + args.forEach(function (a) { + if (Array.isArray(a)) { + handlers = handlers.concat(a); + } + else { + handlers.push(a); + } + }); + + handlers.forEach(function (handler) { + self.exceptionHandlers[handler.name] = handler; + }); + + this._hnames = Object.keys(self.exceptionHandlers); + + if (!this.catchExceptions) { + this.catchExceptions = this._uncaughtException.bind(this); + process.on('uncaughtException', this.catchExceptions); + } +}; + +// +// ### function unhandleExceptions () +// Removes any handlers to `uncaughtException` events +// for the current process +// +Logger.prototype.unhandleExceptions = function () { + var self = this; + + if (this.catchExceptions) { + Object.keys(this.exceptionHandlers).forEach(function (name) { + if (handler.close) { + handler.close(); + } + }); + + this.exceptionHandlers = {}; + Object.keys(this.transports).forEach(function (name) { + var transport = self.transports[name]; + if (transport.handleExceptions) { + transport.handleExceptions = false; + } + }) + + process.removeListener('uncaughtException', this.catchExceptions); + this.catchExceptions = false; + } +}; + +// +// ### function add (transport, [options]) +// #### @transport {Transport} Prototype of the Transport object to add. +// #### @options {Object} **Optional** Options for the Transport to add. +// #### @instance {Boolean} **Optional** Value indicating if `transport` is already instantiated. +// Adds a transport of the specified type to this instance. +// +Logger.prototype.add = function (transport, options, created) { + var instance = created ? transport : (new (transport)(options)); + + if (!instance.name && !instance.log) { + throw new Error('Unknown transport with no log() method'); + } + else if (this.transports[instance.name]) { + throw new Error('Transport already attached: ' + instance.name); + } + + this.transports[instance.name] = instance; + this._names = Object.keys(this.transports); + + // + // Listen for the `error` event on the new Transport + // + instance._onError = this._onError.bind(this, instance) + instance.on('error', instance._onError); + + // + // If this transport has `handleExceptions` set to `true` + // and we are not already handling exceptions, do so. + // + if (transport.handleExceptions && !this.catchExceptions) { + this.handleExceptions(); + } + + return this; +}; + +// +// ### function addRewriter (transport, [options]) +// #### @transport {Transport} Prototype of the Transport object to add. +// #### @options {Object} **Optional** Options for the Transport to add. +// #### @instance {Boolean} **Optional** Value indicating if `transport` is already instantiated. +// Adds a transport of the specified type to this instance. +// +Logger.prototype.addRewriter = function(rewriter) { + this.rewriters.push(rewriter); +} + +// +// ### function clear () +// Remove all transports from this instance +// +Logger.prototype.clear = function () { + for (var name in this.transports) { + this.remove({ name: name }); + } +}; + +// +// ### function remove (transport) +// #### @transport {Transport} Transport to remove. +// Removes a transport of the specified type from this instance. +// +Logger.prototype.remove = function (transport) { + var name = transport.name || transport.prototype.name; + + if (!this.transports[name]) { + throw new Error('Transport ' + name + ' not attached to this instance'); + } + + var instance = this.transports[name]; + delete this.transports[name]; + this._names = Object.keys(this.transports); + + if (instance.close) { + instance.close(); + } + + instance.removeListener('error', instance._onError); + return this; +}; + +var ProfileHandler = function (logger) { + this.logger = logger; + + this.start = Date.now(); + + this.done = function (msg) { + var args, callback, meta; + args = Array.prototype.slice.call(arguments); + callback = typeof args[args.length - 1] === 'function' ? args.pop() : null; + meta = typeof args[args.length - 1] === 'object' ? args.pop() : {}; + + meta.duration = (Date.now()) - this.start + 'ms'; + + return this.logger.info(msg, meta, callback); + } +} + +Logger.prototype.startTimer = function () { + return new ProfileHandler(this); +} + +// +// ### function profile (id, [msg, meta, callback]) +// #### @id {string} Unique id of the profiler +// #### @msg {string} **Optional** Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} **Optional** Continuation to respond to when complete. +// Tracks the time inbetween subsequent calls to this method +// with the same `id` parameter. The second call to this method +// will log the difference in milliseconds along with the message. +// +Logger.prototype.profile = function (id) { + var now = Date.now(), then, args, + msg, meta, callback; + + if (this.profilers[id]) { + then = this.profilers[id]; + delete this.profilers[id]; + + // Support variable arguments: msg, meta, callback + args = Array.prototype.slice.call(arguments); + callback = typeof args[args.length - 1] === 'function' ? args.pop() : null; + meta = typeof args[args.length - 1] === 'object' ? args.pop() : {}; + msg = args.length === 2 ? args[1] : id; + + // Set the duration property of the metadata + meta.duration = now - then + 'ms'; + return this.info(msg, meta, callback); + } + else { + this.profilers[id] = now; + } + + return this; +}; + +// +// ### function setLevels (target) +// #### @target {Object} Target levels to use on this instance +// Sets the `target` levels specified on this instance. +// +Logger.prototype.setLevels = function (target) { + return common.setLevels(this, this.levels, target); +}; + +// +// ### function cli () +// Configures this instance to have the default +// settings for command-line interfaces: no timestamp, +// colors enabled, padded output, and additional levels. +// +Logger.prototype.cli = function () { + this.padLevels = true; + this.setLevels(config.cli.levels); + config.addColors(config.cli.colors); + + if (this.transports.console) { + this.transports.console.colorize = true; + this.transports.console.timestamp = false; + } + + return this; +}; + +// +// ### @private function _uncaughtException (err) +// #### @err {Error} Error to handle +// Logs all relevant information around the `err` and +// exits the current process. +// +Logger.prototype._uncaughtException = function (err) { + var self = this, + responded = false, + info = exception.getAllInfo(err), + handlers = this._getExceptionHandlers(), + timeout, + doExit; + + // + // Calculate if we should exit on this error + // + doExit = typeof this.exitOnError === 'function' + ? this.exitOnError(err) + : this.exitOnError; + + function logAndWait(transport, next) { + transport.logException('uncaughtException', info, next, err); + } + + function gracefulExit() { + if (doExit && !responded) { + // + // Remark: Currently ignoring any exceptions from transports + // when catching uncaught exceptions. + // + clearTimeout(timeout); + responded = true; + process.exit(1); + } + } + + if (!handlers || handlers.length === 0) { + return gracefulExit(); + } + + // + // Log to all transports and allow the operation to take + // only up to `3000ms`. + // + async.forEach(handlers, logAndWait, gracefulExit); + if (doExit) { + timeout = setTimeout(gracefulExit, 3000); + } +}; + +// +// ### @private function _getExceptionHandlers () +// Returns the list of transports and exceptionHandlers +// for this instance. +// +Logger.prototype._getExceptionHandlers = function () { + var self = this; + + return this._hnames.map(function (name) { + return self.exceptionHandlers[name]; + }).concat(this._names.map(function (name) { + return self.transports[name].handleExceptions && self.transports[name]; + })).filter(Boolean); +}; + +// +// ### @private function _onError (transport, err) +// #### @transport {Object} Transport on which the error occured +// #### @err {Error} Error that occurred on the transport +// Bubbles the error, `err`, that occured on the specified `transport` +// up from this instance if `emitErrs` has been set. +// +Logger.prototype._onError = function (transport, err) { + if (this.emitErrs) { + this.emit('error', err, transport); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports.js new file mode 100644 index 0000000..5080634 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports.js @@ -0,0 +1,29 @@ +/* + * transports.js: Set of all transports Winston knows about + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var fs = require('fs'), + path = require('path'), + common = require('./common'); + +var transports = exports; + +// +// Setup all transports as lazy-loaded getters. +// +fs.readdirSync(path.join(__dirname, 'transports')).forEach(function (file) { + var transport = file.replace('.js', ''), + name = common.capitalize(transport); + + if (transport === 'transport') { + return; + } + + transports.__defineGetter__(name, function () { + return require('./transports/' + transport)[name]; + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/console.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/console.js new file mode 100644 index 0000000..835d075 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/console.js @@ -0,0 +1,87 @@ +/* + * console.js: Transport for outputting to the console + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var events = require('events'), + util = require('util'), + colors = require('colors'), + common = require('../common'), + Transport = require('./transport').Transport; + +// +// ### function Console (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Console transport object responsible +// for persisting log messages and metadata to a terminal or TTY. +// +var Console = exports.Console = function (options) { + Transport.call(this, options); + options = options || {}; + + this.name = 'console'; + this.json = options.json || false; + this.colorize = options.colorize || false; + this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false; + + if (this.json) { + this.stringify = options.stringify || function (obj) { + return JSON.stringify(obj, null, 2); + }; + } +}; + +// +// Inherit from `winston.Transport`. +// +util.inherits(Console, Transport); + +// +// Expose the name of this Transport on the prototype +// +Console.prototype.name = 'console'; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +Console.prototype.log = function (level, msg, meta, callback) { + if (this.silent) { + return callback(null, true); + } + + var self = this, + output; + + output = common.log({ + colorize: this.colorize, + json: this.json, + level: level, + message: msg, + meta: meta, + stringify: this.stringify, + timestamp: this.timestamp, + raw: this.raw + }); + + if (level === 'error' || level === 'debug') { + util.error(output); + } + else { + util.puts(output); + } + + // + // Emit the `logged` event immediately because the event loop + // will not exit until `process.stdout` has drained anyway. + // + self.emit('logged'); + callback(null, true); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/couchdb.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/couchdb.js new file mode 100644 index 0000000..61ad74a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/couchdb.js @@ -0,0 +1,122 @@ +/* + * Couchdb.js: Transport for logging to Couchdb + * + * (C) 2011 Max Ogden + * MIT LICENSE + * + */ + +var events = require('events'), + http = require('http'), + util = require('util'), + common = require('../common'), + Transport = require('./transport').Transport; + +// +// ### function Couchdb (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Console transport object responsible +// for making arbitrary HTTP requests whenever log messages and metadata +// are received. +// +var Couchdb = exports.Couchdb = function (options) { + Transport.call(this, options); + + this.name = 'Couchdb'; + this.db = options.db; + this.user = options.user; + this.pass = options.pass; + this.host = options.host || 'localhost'; + this.port = options.port || 5984; + + if (options.auth) { + // + // TODO: add http basic auth options for outgoing HTTP requests + // + } + + if (options.ssl) { + // + // TODO: add ssl support for outgoing HTTP requests + // + } +}; + +// +// Inherit from `winston.Transport`. +// +util.inherits(Couchdb, Transport); + +// +// Expose the name of this Transport on the prototype +// +Couchdb.prototype.name = 'Couchdb'; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +Couchdb.prototype.log = function (level, msg, meta, callback) { + if (this.silent) { + return callback(null, true); + } + + var self = this, + message = common.clone(meta || {}), + options, + req; + + message.level = level; + message.message = msg; + + // Prepare options for outgoing HTTP request + options = { + host: this.host, + port: this.port, + path: "/" + this.db, + method: "POST", + headers: {"content-type": "application/json"} + }; + + if (options.user && options.pass) { + options.headers["Authorization"] = "Basic " + new Buffer(options.user + ":" + options.pass).toString('base64'); + } + + // Perform HTTP logging request + req = http.request(options, function (res) { + // + // No callback on request, fire and forget about the response + // + self.emit('logged', res); + }); + + req.on('error', function (err) { + // + // Propagate the `error` back up to the `Logger` that this + // instance belongs to. + // + self.emit('error', err); + }); + + // + // Write logging event to the outgoing request body + // + req.write(JSON.stringify({ + method: 'log', + params: { + timestamp: new Date(), // RFC3339/ISO8601 format instead of common.timestamp() + msg: msg, + level: level, + meta: meta + } + })); + + req.end(); + + // Always return true, regardless of any errors + callback(null, true); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/file.js new file mode 100644 index 0000000..0a96c01 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/file.js @@ -0,0 +1,332 @@ +/* + * file.js: Transport for outputting to a local log file + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var events = require('events'), + fs = require('fs'), + path = require('path'), + util = require('util'), + colors = require('colors'), + common = require('../common'), + Transport = require('./transport').Transport; + +// +// ### function File (options) +// #### @options {Object} Options for this instance. +// Constructor function for the File transport object responsible +// for persisting log messages and metadata to one or more files. +// +var File = exports.File = function (options) { + Transport.call(this, options); + + // + // Helper function which throws an `Error` in the event + // that any of the rest of the arguments is present in `options`. + // + function throwIf (target /*, illegal... */) { + Array.prototype.slice.call(arguments, 1).forEach(function (name) { + if (options[name]) { + throw new Error('Cannot set ' + name + ' and ' + target + 'together'); + } + }); + } + + if (options.filename || options.dirname) { + throwIf('filename or dirname', 'stream'); + this._basename = this.filename = path.basename(options.filename) || 'winston.log'; + this.dirname = options.dirname || path.dirname(options.filename); + this.options = options.options || { flags: 'a' }; + } + else if (options.stream) { + throwIf('stream', 'filename', 'maxsize'); + this.stream = options.stream; + } + else { + throw new Error('Cannot log to file without filename or stream.'); + } + + this.json = options.json !== false; + this.colorize = options.colorize || false; + this.maxsize = options.maxsize || null; + this.maxFiles = options.maxFiles || null; + this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false; + + // + // Internal state variables representing the number + // of files this instance has created and the current + // size (in bytes) of the current logfile. + // + this._size = 0; + this._created = 0; + this._buffer = []; + this._draining = false; +}; + +// +// Inherit from `winston.Transport`. +// +util.inherits(File, Transport); + +// +// Expose the name of this Transport on the prototype +// +File.prototype.name = 'file'; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +File.prototype.log = function (level, msg, meta, callback) { + if (this.silent) { + return callback(null, true); + } + + var self = this, output = common.log({ + level: level, + message: msg, + meta: meta, + json: this.json, + colorize: this.colorize, + timestamp: this.timestamp + }) + '\n'; + + this._size += output.length; + + if (!this.filename) { + // + // If there is no `filename` on this instance then it was configured + // with a raw `WriteableStream` instance and we should not perform any + // size restrictions. + // + this.stream.write(output); + self._lazyDrain(); + } + else { + this.open(function (err) { + if (err) { + // + // If there was an error enqueue the message + // + return self._buffer.push(output); + } + + self.stream.write(output); + self._lazyDrain(); + }); + } + + callback(null, true); +}; + +// +// ### function open (callback) +// #### @callback {function} Continuation to respond to when complete +// Checks to see if a new file needs to be created based on the `maxsize` +// (if any) and the current size of the file used. +// +File.prototype.open = function (callback) { + if (this.opening) { + // + // If we are already attempting to open the next + // available file then respond with a value indicating + // that the message should be buffered. + // + return callback(true); + } + else if (!this.stream || (this.maxsize && this._size >= this.maxsize)) { + // + // If we dont have a stream or have exceeded our size, then create + // the next stream and respond with a value indicating that + // the message should be buffered. + // + callback(true); + return this._createStream(); + } + + // + // Otherwise we have a valid (and ready) stream. + // + callback(); +}; + +// +// ### function close () +// Closes the stream associated with this instance. +// +File.prototype.close = function () { + var self = this; + + if (this.stream) { + this.stream.end(); + this.stream.destroySoon(); + + this.stream.once('drain', function () { + self.emit('flush'); + self.emit('closed'); + }); + } +}; + +// +// ### function flush () +// Flushes any buffered messages to the current `stream` +// used by this instance. +// +File.prototype.flush = function () { + var self = this; + + // + // Iterate over the `_buffer` of enqueued messaged + // and then write them to the newly created stream. + // + this._buffer.forEach(function (str) { + process.nextTick(function () { + self.stream.write(str); + self._size += str.length; + }); + }); + + // + // Quickly truncate the `_buffer` once the write operations + // have been started + // + self._buffer.length = 0; + + // + // When the stream has drained we have flushed + // our buffer. + // + self.stream.once('drain', function () { + self.emit('flush'); + self.emit('logged'); + }); +}; + +// +// ### @private function _createStream () +// Attempts to open the next appropriate file for this instance +// based on the common state (such as `maxsize` and `_basename`). +// +File.prototype._createStream = function () { + var self = this; + this.opening = true; + + (function checkFile (target) { + var fullname = path.join(self.dirname, target); + + // + // Creates the `WriteStream` and then flushes any + // buffered messages. + // + function createAndFlush (size) { + if (self.stream) { + self.stream.end(); + self.stream.destroySoon(); + } + + self._size = size; + self.filename = target; + self.stream = fs.createWriteStream(fullname, self.options); + + // + // When the current stream has finished flushing + // then we can be sure we have finished opening + // and thus can emit the `open` event. + // + self.once('flush', function () { + self.opening = false; + self.emit('open', fullname); + }); + + // + // Remark: It is possible that in the time it has taken to find the + // next logfile to be written more data than `maxsize` has been buffered, + // but for sensible limits (10s - 100s of MB) this seems unlikely in less + // than one second. + // + self.flush(); + } + + fs.stat(fullname, function (err, stats) { + if (err) { + if (err.code !== 'ENOENT') { + return self.emit('error', err); + } + + return createAndFlush(0); + } + + if (!stats || (self.maxsize && stats.size >= self.maxsize)) { + // + // If `stats.size` is greater than the `maxsize` for + // this instance then try again + // + return checkFile(self._getFile(true)); + } + + createAndFlush(stats.size); + }); + })(this._getFile()); +}; + +// +// ### @private function _getFile () +// Gets the next filename to use for this instance +// in the case that log filesizes are being capped. +// +File.prototype._getFile = function (inc) { + var self = this, + ext = path.extname(this._basename), + basename = path.basename(this._basename, ext), + remaining; + + if (inc) { + // + // Increment the number of files created or + // checked by this instance. + // + // Check for maxFiles option and delete file + if (this.maxFiles && (this._created >= (this.maxFiles - 1))) { + remaining = this._created - (this.maxFiles - 1); + if (remaining === 0) { + fs.unlinkSync(path.join(this.dirname, basename + ext)); + } + else { + fs.unlinkSync(path.join(this.dirname, basename + remaining + ext)); + } + } + + this._created += 1; + } + + return this._created + ? basename + this._created + ext + : basename + ext; +}; + +// +// ### @private function _lazyDrain () +// Lazily attempts to emit the `logged` event when `this.stream` has +// drained. This is really just a simple mutex that only works because +// Node.js is single-threaded. +// +File.prototype._lazyDrain = function () { + var self = this; + + if (!this._draining && this.stream) { + this._draining = true; + + this.stream.once('drain', function () { + this._draining = false; + self.emit('logged'); + }); + } +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/loggly.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/loggly.js new file mode 100644 index 0000000..dd5762b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/loggly.js @@ -0,0 +1,161 @@ +/* + * loggly.js: Transport for logginh to remote Loggly API + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var events = require('events'), + loggly = require('loggly'), + util = require('util'), + async = require('async'), + common = require('../common'), + Transport = require('./transport').Transport; + +// +// ### function Loggly (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Loggly transport object responsible +// for persisting log messages and metadata to Loggly; 'LaaS'. +// +var Loggly = exports.Loggly = function (options) { + Transport.call(this, options); + + function valid() { + return options.inputToken + || options.inputName && options.auth + || options.inputName && options.inputs && options.inputs[options.inputName] + || options.id && options.inputs && options.inputs[options.id]; + } + + if (!options.subdomain) { + throw new Error('Loggly Subdomain is required'); + } + + if (!valid()) { + throw new Error('Target input token or name is required.'); + } + + this.name = 'loggly'; + this.logBuffer = []; + + this.client = loggly.createClient({ + subdomain: options.subdomain, + auth: options.auth || null, + json: options.json || false + }); + + if (options.inputToken) { + this.inputToken = options.inputToken; + this.ready = true; + } + else if (options.inputs && (options.inputs[options.inputName] + || options.inputs[options.id])) { + this.inputToken = options.inputs[options.inputName] || options.inputs[options.id]; + this.ready = true; + } + else if (options.inputName) { + this.ready = false; + this.inputName = options.inputName; + + var self = this; + this.client.getInput(this.inputName, function (err, input) { + if (err) { + throw err; + } + + self.inputToken = input.input_token; + self.ready = true; + }); + } +}; + +// +// Inherit from `winston.Transport`. +// +util.inherits(Loggly, Transport); + +// +// Expose the name of this Transport on the prototype +// +Loggly.prototype.name = 'loggly'; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +Loggly.prototype.log = function (level, msg, meta, callback) { + if (this.silent) { + return callback(null, true); + } + + var self = this, + message = common.clone(meta || {}); + + message.level = level; + message.message = msg; + + if (!this.ready) { + // + // If we haven't gotten the input token yet + // add this message to the log buffer. + // + this.logBuffer.push(message); + } + else if (this.ready && this.logBuffer.length > 0) { + // + // Otherwise if we have buffered messages + // add this message to the buffer and flush them. + // + this.logBuffer.push(message); + this.flush(); + } + else { + // + // Otherwise just log the message as normal + // + this.client.log(this.inputToken, message, function () { + self.emit('logged'); + }); + } + + callback(null, true); +}; + +// +// ### function flush () +// Flushes any buffered messages to the current `stream` +// used by this instance. +// +Loggly.prototype.flush = function () { + var self = this; + + function logMsg (msg, next) { + self.client.log(self.inputToken, msg, function (err) { + if (err) { + self.emit('error', err); + } + + next(); + }); + } + + // + // Initiate calls to loggly for each message in the buffer + // + async.forEach(this.logBuffer, logMsg, function () { + self.emit('logged'); + }); + + process.nextTick(function () { + // + // Then quickly truncate the list + // + self.logBuffer.length = 0; + }); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/transport.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/transport.js new file mode 100644 index 0000000..1489cb5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/transport.js @@ -0,0 +1,59 @@ +/* + * transport.js: Base Transport object for all Winston transports. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + * + */ + +var events = require('events'), + util = require('util'); + +// +// ### function Transport (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Tranport object responsible +// base functionality for all winston transports. +// +var Transport = exports.Transport = function (options) { + events.EventEmitter.call(this); + + options = options || {}; + this.level = options.level || 'info'; + this.silent = options.silent || false; + this.raw = options.raw || false; + + this.handleExceptions = options.handleExceptions || false; +}; + +// +// Inherit from `events.EventEmitter`. +// +util.inherits(Transport, events.EventEmitter); + +// +// ### function logException (msg, meta, callback) +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Logs the specified `msg`, `meta` and responds to the callback once the log +// operation is complete to ensure that the event loop will not exit before +// all logging has completed. +// +Transport.prototype.logException = function (msg, meta, callback) { + var self = this; + + function onLogged () { + self.removeListener('error', onError); + callback(); + } + + function onError () { + self.removeListener('logged', onLogged); + callback(); + } + + this.once('logged', onLogged); + this.once('error', onError); + this.log('error', msg, meta, function () { }); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/webhook.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/webhook.js new file mode 100644 index 0000000..bf8eb27 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/lib/winston/transports/webhook.js @@ -0,0 +1,136 @@ +/* + * webhook.js: Transport for logging to remote http endpoints ( POST / RECEIVE webhooks ) + * + * (C) 2011 Marak Squires + * MIT LICENCE + * + */ + +var events = require('events'), + http = require('http'), + https = require('https'), + util = require('util'), + common = require('../common'), + Transport = require('./transport').Transport; + +// +// ### function WebHook (options) +// #### @options {Object} Options for this instance. +// Constructor function for the Console transport object responsible +// for making arbitrary HTTP requests whenever log messages and metadata +// are received. +// +var Webhook = exports.Webhook = function (options) { + Transport.call(this, options); + + this.name = 'webhook'; + this.host = options.host || 'localhost'; + this.port = options.port || 8080; + this.method = options.method || 'POST'; + this.path = options.path || '/winston-log'; + + if (options.auth) { + this.auth = {}; + this.auth.username = options.auth.username || ''; + this.auth.password = options.auth.password || ''; + } + + if (options.ssl) { + this.ssl = {}; + this.ssl.key = options.ssl.key || null; + this.ssl.cert = options.ssl.cert || null; + this.ssl.ca = options.ssl.ca; + } +}; + +// +// Inherit from `winston.Transport`. +// +util.inherits(Webhook, Transport); + +// +// Expose the name of this Transport on the prototype +// +Webhook.prototype.name = 'webhook'; + +// +// ### function log (level, msg, [meta], callback) +// #### @level {string} Level at which to log the message. +// #### @msg {string} Message to log +// #### @meta {Object} **Optional** Additional metadata to attach +// #### @callback {function} Continuation to respond to when complete. +// Core logging method exposed to Winston. Metadata is optional. +// +Webhook.prototype.log = function (level, msg, meta, callback) { + if (this.silent) { + return callback(null, true); + } + + var self = this, + message = common.clone(meta), + options, + req; + + message.level = level; + message.message = msg; + + // Prepare options for outgoing HTTP request + options = { + host: this.host, + port: this.port, + path: this.path, + method: this.method, + headers: { 'Content-Type': 'application/json' } + }; + + if (this.ssl) { + options.ca = this.ssl.ca; + options.key = this.ssl.key; + options.cert = this.ssl.cert; + } + + if (this.auth) { + // Encode `Authorization` header used by Basic Auth + options.headers['Authorization'] = 'Basic ' + new Buffer( + this.auth.username + ':' + this.auth.password, 'utf8' + ).toString('base64'); + } + + // Perform HTTP logging request + req = (self.ssl ? https : http).request(options, function (res) { + // + // No callback on request, fire and forget about the response + // + self.emit('logged'); + }); + + req.on('error', function (err) { + // + // Propagate the `error` back up to the `Logger` that this + // instance belongs to. + // + self.emit('error', err); + }); + + // + // Write logging event to the outgoing request body + // + // jsonMessage is currently conforming to JSON-RPC v1.0, + // but without the unique id since there is no anticipated response + // see: http://en.wikipedia.org/wiki/JSON-RPC + // + req.write(JSON.stringify({ + method: 'log', + params: { + timestamp: new Date(), + msg: msg, + level: level, + meta: meta + } + })); + + req.end(); + + // Always return true, regardless of any errors + callback(null, true); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/LICENSE new file mode 100644 index 0000000..a1edd93 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009 cloudhead + +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/prompt/node_modules/winston/node_modules/eyes/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/Makefile new file mode 100644 index 0000000..a121dea --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/Makefile @@ -0,0 +1,4 @@ +test: + @@node test/eyes-test.js + +.PHONY: test diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/README.md new file mode 100644 index 0000000..c4f6f76 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/README.md @@ -0,0 +1,73 @@ +eyes +==== + +a customizable value inspector for Node.js + +synopsis +-------- + +I was tired of looking at cluttered output in the console -- something needed to be done, +`sys.inspect()` didn't display regexps correctly, and was too verbose, and I had an hour or two to spare. +So I decided to have some fun. _eyes_ were born. + +![eyes-ss](http://dl.dropbox.com/u/251849/eyes-js-ss.gif) + +_example of the output of a user-customized eyes.js inspector_ + +*eyes* also deals with circular objects in an intelligent way, and can pretty-print object literals. + +usage +----- + + var inspect = require('eyes').inspector({styles: {all: 'magenta'}}); + + inspect(something); // inspect with the settings passed to `inspector` + +or + + var eyes = require('eyes'); + + eyes.inspect(something); // inspect with the default settings + +you can pass a _label_ to `inspect()`, to keep track of your inspections: + + eyes.inspect(something, "a random value"); + +If you want to return the output of eyes without printing it, you can set it up this way: + + var inspect = require('eyes').inspector({ stream: null }); + + sys.puts(inspect({ something: 42 })); + +customization +------------- + +These are the default styles and settings used by _eyes_. + + styles: { // Styles applied to stdout + all: 'cyan', // Overall style applied to everything + label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]` + other: 'inverted', // Objects which don't have a literal representation, such as functions + key: 'bold', // The keys in object literals, like 'a' in `{a: 1}` + special: 'grey', // null, undefined... + string: 'green', + number: 'magenta', + bool: 'blue', // true false + regexp: 'green', // /\d+/ + }, + + pretty: true, // Indent object literals + hideFunctions: false, // Don't output functions at all + stream: process.stdout, // Stream to write to, or null + maxLength: 2048 // Truncate output if longer + +You can overwrite them with your own, by passing a similar object to `inspector()` or `inspect()`. + + var inspect = require('eyes').inspector({ + styles: { + all: 'magenta', + special: 'bold' + }, + maxLength: 512 + }); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/lib/eyes.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/lib/eyes.js new file mode 100644 index 0000000..10d964b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/lib/eyes.js @@ -0,0 +1,236 @@ +// +// Eyes.js - a customizable value inspector for Node.js +// +// usage: +// +// var inspect = require('eyes').inspector({styles: {all: 'magenta'}}); +// inspect(something); // inspect with the settings passed to `inspector` +// +// or +// +// var eyes = require('eyes'); +// eyes.inspect(something); // inspect with the default settings +// +var eyes = exports, + stack = []; + +eyes.defaults = { + styles: { // Styles applied to stdout + all: 'cyan', // Overall style applied to everything + label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]` + other: 'inverted', // Objects which don't have a literal representation, such as functions + key: 'bold', // The keys in object literals, like 'a' in `{a: 1}` + special: 'grey', // null, undefined... + string: 'green', + number: 'magenta', + bool: 'blue', // true false + regexp: 'green', // /\d+/ + }, + pretty: true, // Indent object literals + hideFunctions: false, + showHidden: false, + stream: process.stdout, + maxLength: 2048 // Truncate output if longer +}; + +// Return a curried inspect() function, with the `options` argument filled in. +eyes.inspector = function (options) { + var that = this; + return function (obj, label, opts) { + return that.inspect.call(that, obj, label, + merge(options || {}, opts || {})); + }; +}; + +// If we have a `stream` defined, use it to print a styled string, +// if not, we just return the stringified object. +eyes.inspect = function (obj, label, options) { + options = merge(this.defaults, options || {}); + + if (options.stream) { + return this.print(stringify(obj, options), label, options); + } else { + return stringify(obj, options) + (options.styles ? '\033[39m' : ''); + } +}; + +// Output using the 'stream', and an optional label +// Loop through `str`, and truncate it after `options.maxLength` has been reached. +// Because escape sequences are, at this point embeded within +// the output string, we can't measure the length of the string +// in a useful way, without separating what is an escape sequence, +// versus a printable character (`c`). So we resort to counting the +// length manually. +eyes.print = function (str, label, options) { + for (var c = 0, i = 0; i < str.length; i++) { + if (str.charAt(i) === '\033') { i += 4 } // `4` because '\033[25m'.length + 1 == 5 + else if (c === options.maxLength) { + str = str.slice(0, i - 1) + '…'; + break; + } else { c++ } + } + return options.stream.write.call(options.stream, (label ? + this.stylize(label, options.styles.label, options.styles) + ': ' : '') + + this.stylize(str, options.styles.all, options.styles) + '\033[0m' + "\n"); +}; + +// Apply a style to a string, eventually, +// I'd like this to support passing multiple +// styles. +eyes.stylize = function (str, style, styles) { + var codes = { + 'bold' : [1, 22], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'cyan' : [36, 39], + 'magenta' : [35, 39], + 'blue' : [34, 39], + 'yellow' : [33, 39], + 'green' : [32, 39], + 'red' : [31, 39], + 'grey' : [90, 39] + }, endCode; + + if (style && codes[style]) { + endCode = (codes[style][1] === 39 && styles.all) ? codes[styles.all][0] + : codes[style][1]; + return '\033[' + codes[style][0] + 'm' + str + + '\033[' + endCode + 'm'; + } else { return str } +}; + +// Convert any object to a string, ready for output. +// When an 'array' or an 'object' are encountered, they are +// passed to specialized functions, which can then recursively call +// stringify(). +function stringify(obj, options) { + var that = this, stylize = function (str, style) { + return eyes.stylize(str, options.styles[style], options.styles) + }, index, result; + + if ((index = stack.indexOf(obj)) !== -1) { + return stylize(new(Array)(stack.length - index + 1).join('.'), 'special'); + } + stack.push(obj); + + result = (function (obj) { + switch (typeOf(obj)) { + case "string" : obj = stringifyString(obj.indexOf("'") === -1 ? "'" + obj + "'" + : '"' + obj + '"'); + return stylize(obj, 'string'); + case "regexp" : return stylize('/' + obj.source + '/', 'regexp'); + case "number" : return stylize(obj + '', 'number'); + case "function" : return options.stream ? stylize("Function", 'other') : '[Function]'; + case "null" : return stylize("null", 'special'); + case "undefined": return stylize("undefined", 'special'); + case "boolean" : return stylize(obj + '', 'bool'); + case "date" : return stylize(obj.toUTCString()); + case "array" : return stringifyArray(obj, options, stack.length); + case "object" : return stringifyObject(obj, options, stack.length); + } + })(obj); + + stack.pop(); + return result; +}; + +// Escape invisible characters in a string +function stringifyString (str, options) { + return str.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/[\u0001-\u001F]/g, function (match) { + return '\\0' + match[0].charCodeAt(0).toString(8); + }); +} + +// Convert an array to a string, such as [1, 2, 3]. +// This function calls stringify() for each of the elements +// in the array. +function stringifyArray(ary, options, level) { + var out = []; + var pretty = options.pretty && (ary.length > 4 || ary.some(function (o) { + return (o !== null && typeof(o) === 'object' && Object.keys(o).length > 0) || + (Array.isArray(o) && o.length > 0); + })); + var ws = pretty ? '\n' + new(Array)(level * 4 + 1).join(' ') : ' '; + + for (var i = 0; i < ary.length; i++) { + out.push(stringify(ary[i], options)); + } + + if (out.length === 0) { + return '[]'; + } else { + return '[' + ws + + out.join(',' + (pretty ? ws : ' ')) + + (pretty ? ws.slice(0, -4) : ws) + + ']'; + } +}; + +// Convert an object to a string, such as {a: 1}. +// This function calls stringify() for each of its values, +// and does not output functions or prototype values. +function stringifyObject(obj, options, level) { + var out = []; + var pretty = options.pretty && (Object.keys(obj).length > 2 || + Object.keys(obj).some(function (k) { return typeof(obj[k]) === 'object' })); + var ws = pretty ? '\n' + new(Array)(level * 4 + 1).join(' ') : ' '; + + var keys = options.showHidden ? Object.keys(obj) : Object.getOwnPropertyNames(obj); + keys.forEach(function (k) { + if (Object.prototype.hasOwnProperty.call(obj, k) + && !(obj[k] instanceof Function && options.hideFunctions)) { + out.push(eyes.stylize(k, options.styles.key, options.styles) + ': ' + + stringify(obj[k], options)); + } + }); + + if (out.length === 0) { + return '{}'; + } else { + return "{" + ws + + out.join(',' + (pretty ? ws : ' ')) + + (pretty ? ws.slice(0, -4) : ws) + + "}"; + } +}; + +// A better `typeof` +function typeOf(value) { + var s = typeof(value), + types = [Object, Array, String, RegExp, Number, Function, Boolean, Date]; + + if (s === 'object' || s === 'function') { + if (value) { + types.forEach(function (t) { + if (value instanceof t) { s = t.name.toLowerCase() } + }); + } else { s = 'null' } + } + return s; +} + +function merge(/* variable args */) { + var objs = Array.prototype.slice.call(arguments); + var target = {}; + + objs.forEach(function (o) { + Object.keys(o).forEach(function (k) { + if (k === 'styles') { + if (! o.styles) { + target.styles = false; + } else { + target.styles = {} + for (var s in o.styles) { + target.styles[s] = o.styles[s]; + } + } + } else { + target[k] = o[k]; + } + }); + }); + return target; +} + 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 new file mode 100644 index 0000000..4f3d459 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/package.json @@ -0,0 +1,40 @@ +{ + "name": "eyes", + "description": "a customizable value inspector", + "url": "http://github.com/cloudhead/eyes.js", + "keywords": [ + "inspector", + "debug", + "inspect", + "print" + ], + "author": { + "name": "Alexis Sellier", + "email": "self@cloudhead.net" + }, + "contributors": [ + { + "name": "Charlie Robbins", + "email": "charlie@nodejitsu.com" + } + ], + "licenses": [ + "MIT" + ], + "main": "./lib/eyes", + "version": "0.1.8", + "scripts": { + "test": "node test/*-test.js" + }, + "directories": { + "lib": "./lib", + "test": "./test" + }, + "engines": { + "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/eyes/test/eyes-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/test/eyes-test.js new file mode 100644 index 0000000..1f9606a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/eyes/test/eyes-test.js @@ -0,0 +1,56 @@ +var util = require('util'); +var eyes = require('../lib/eyes'); + +eyes.inspect({ + number: 42, + string: "John Galt", + regexp: /[a-z]+/, + array: [99, 168, 'x', {}], + func: function () {}, + bool: false, + nil: null, + undef: undefined, + object: {attr: []} +}, "native types"); + +eyes.inspect({ + number: new(Number)(42), + string: new(String)("John Galt"), + regexp: new(RegExp)(/[a-z]+/), + array: new(Array)(99, 168, 'x', {}), + bool: new(Boolean)(false), + object: new(Object)({attr: []}), + date: new(Date) +}, "wrapped types"); + +var obj = {}; +obj.that = { self: obj }; +obj.self = obj; + +eyes.inspect(obj, "circular object"); +eyes.inspect({hello: 'moto'}, "small object"); +eyes.inspect({hello: new(Array)(6) }, "big object"); +eyes.inspect(["hello 'world'", 'hello "world"'], "quotes"); +eyes.inspect({ + recommendations: [{ + id: 'a7a6576c2c822c8e2bd81a27e41437d8', + key: [ 'spree', 3.764316258020699 ], + value: { + _id: 'a7a6576c2c822c8e2bd81a27e41437d8', + _rev: '1-2e2d2f7fd858c4a5984bcf809d22ed98', + type: 'domain', + domain: 'spree', + weight: 3.764316258020699, + product_id: 30 + } + }] +}, 'complex'); + +eyes.inspect([null], "null in array"); + +var inspect = eyes.inspector({ stream: null }); + +util.puts(inspect('something', "something")); +util.puts(inspect("something else")); + +util.puts(inspect(["no color"], null, { styles: false })); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/.npmignore new file mode 100644 index 0000000..8f08029 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/.npmignore @@ -0,0 +1,4 @@ +test/data +test/data/* +node_modules +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/README.md new file mode 100644 index 0000000..926cb63 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/README.md @@ -0,0 +1,227 @@ +# node-loggly + +A client implementation for Loggly in node.js + +## Installation + +### Installing npm (node package manager) +``` bash + $ curl http://npmjs.org/install.sh | sh +``` + +### Installing node-loggly +``` bash + $ [sudo] npm install loggly +``` + +## Usage + +The 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. + +### Getting Started +Before we can do anything with Loggly, we have to create a client with valid credentials. We will authenticate for you automatically: + +``` js + var loggly = require('loggly'); + var config = { + subdomain: "your-subdomain", + auth: { + username: "your-username", + password: "your-password" + } + }; + var client = loggly.createClient(config); +``` + +### Logging +There 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: + +``` js + client.log('your-really-long-input-token', '127.0.0.1 - Theres no place like home', function (err, result) { + // Do something once you've logged + }); +``` + +Note that the callback in the above example is optional, if you prefer the 'fire and forget' method of logging: + +``` js + client.log('your-really-long-input-token', '127.0.0.1 - Theres no place like home'); +``` + +The second way to send log information to Loggly is to do so once you've retrieved an input directly from Loggly: + +``` js + client.getInput('your-input-name', function (err, input) { + input.log('127.0.0.1 - Theres no place like home'); + }); +``` + +Again the callback in the above example is optional and you can pass it if you'd like to. + +### Logging Shallow JSON Object Literals as a String +In 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 + +``` js + var source = { + foo: 1, + bar: 2, + buzz: 3 + }; + + input.log(source); +``` + +will be logged as: + +``` + foo=1,bar=2,buzz=3 +``` + +### Logging Objects to JSON Enabled Loggly Inputs +It 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: + +``` js + var config = { + subdomain: "your-subdomain", + auth: { + username: "your-username", + password: "your-password" + }, + json: true + }; +``` + +When the json flag is enabled, objects will be converted to JSON using JSON.stringify before being transmitted to Loggly. So + +``` js + var source = { + foo: 1, + bar: 2, + buzz: { + sheep: 'jumped', + times: 10 + } + }; + + input.log(source); +``` + +will be logged as: + +``` json + { "foo": 1, "bar": 2, "buzz": {"sheep": "jumped", "times": 10 }} +``` + +### Searching +[Searching][3] with node-loggly is easy. All you have to do is use the search() method defined on each Loggly client: + +``` js + var util = require('util'); + + client.search('404', function (err, results) { + // Inspect the result set + util.inspect(results.data); + }); +``` + +The search() exposes a chainable interface that allows you to set additional search parameters such as: ip, input name, rows, start, end, etc. + +``` js + var util = require('util'); + + client.search('404') + .meta({ ip: '127.0.0.1', inputname: test }) + .context({ rows: 10 }) + .run(function (err, results) { + // Inspect the result set + util.inspect(results.data); + }); +``` + +The 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. + +Metadata 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]. + +### Facet Searching +Loggly 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: + +``` js + var util = require('util'); + + client.facet('ip', '404') + .context({ buckets: 10 }) + .run(function (err, results) { + // Inspect the result set + util.inspect(results.data); + }); +``` + +The chaining and options for the facet method(s) are the same as the search method above. + +### Working with Devices and Inputs +Loggly 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: + +``` js + // + // Returns all inputs associated with your account + // + client.getInputs(function (err, inputs) { /* ... */ }); + + // + // Returns an input with the specified name + // + client.getInput('input-name', function (err, input) { /* ... */ }); + + // + // Returns all devices associated with your account + // + client.getDevices(function (err, devices) { /* ... */ }); +``` + +## Run Tests +All 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: + +``` js + { + "subdomain": "your-subdomain", + "auth": { + "username": "your-username", + "password": "your-password" + }, + "inputs": { + "test": { + // + // Token and ID of your plain-text input. + // + "token": "your-really-long-token-you-got-when-you-created-an-http-input", + "id": 000 + }, + "test_json": { + // + // Token and ID of your JSON input. + // + "token": "your-really-long-token-you-got-when-you-created-an-http-input", + "id": 001 + }, + } + } +``` + +Once you have valid Loggly credentials you can run tests with [vows][8]: + +``` bash + $ npm test +``` + +#### Author: [Charlie Robbins](http://www.github.com/indexzero) +#### Contributors: [Marak Squires](http://github.com/marak), [hij1nx](http://github.com/hij1nx), [Kord Campbell](http://loggly.com), [Erik Hedenström](http://github.com/ehedenst), + +[0]: http://wiki.loggly.com/apidocumentation +[1]: http://wiki.loggly.com/loggingfromcode +[3]: http://wiki.loggly.com/retrieve_events#search_uri +[4]: http://wiki.loggly.com/searchguide +[5]: http://wiki.loggly.com/ +[6]: http://wiki.loggly.com/retrieve_events#facet_uris +[7]: http://wiki.loggly.com/loggingjargon +[8]: http://vowsjs.org +[9]: http://wiki.loggly.com/retrieve_events#optional diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/docco.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/docco.css new file mode 100644 index 0000000..bd54134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/docco.css @@ -0,0 +1,194 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h4, h5, h6 { + color: #333; + margin: 6px 0 6px 0; + font-size: 13px; +} + h2, h3 { + margin-bottom: 0; + color: #000; + } + h1 { + margin-top: 40px; + margin-bottom: 15px; + color: #000; + } +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly.html new file mode 100644 index 0000000..7afcf68 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly.html @@ -0,0 +1,16 @@ + loggly.js

    loggly.js

    /*
    + * loggly.js: Wrapper for node-loggly object
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    +
    +var loggly = exports;

    Export node-loggly core client APIs

    loggly.createClient  = require('./loggly/core').createClient;
    +loggly.Loggly        = require('./loggly/core').Loggly;
    +loggly.Config        = require('./loggly/config').Config;

    Export Resources for node-loggly

    loggly.Input  = require('./loggly/input').Input;
    +loggly.Facet  = require('./loggly/facet').Facet;
    +loggly.Device = require('./loggly/device').Device;
    +loggly.Search = require('./loggly/search').Search;
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/common.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/common.html new file mode 100644 index 0000000..94336be --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/common.html @@ -0,0 +1,126 @@ + common.js

    common.js

    /*
    + * common.js: Common utility functions for requesting against Loggly APIs
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    +
    +var request = require('request'),
    +    loggly = require('../loggly');
    +
    +var common = exports;

    Failure HTTP Response codes based +off Loggly specification.

    var failCodes = common.failCodes = {
    +  400: "Bad Request",
    +  401: "Unauthorized",
    +  403: "Forbidden",
    +  404: "Not Found",
    +  409: "Conflict / Duplicate",
    +  410: "Gone",
    +  500: "Internal Server Error",
    +  501: "Not Implemented",
    +  503: "Throttled"
    +};

    Success HTTP Response codes based +off Loggly specification.

    var successCodes = common.successCodes = {
    +  200: "OK",
    +  201: "Created", 
    +  202: "Accepted",
    +  203: "Non-authoritative information",
    +  204: "Deleted",
    +};

    Core method that actually sends requests to Loggly. +This method is designed to be flexible w.r.t. arguments +and continuation passing given the wide range of different +requests required to fully implement the Loggly API.

    + +

    Continuations: + 1. 'callback': The callback passed into every node-loggly method + 2. 'success': A callback that will only be called on successful requests. + This is used throughout node-loggly to conditionally + do post-request processing such as JSON parsing.

    + +

    Possible Arguments (1 & 2 are equivalent): + 1. common.loggly('some-fully-qualified-url', auth, callback, success) + 2. common.loggly('GET', 'some-fully-qualified-url', auth, callback, success) + 3. common.loggly('DELETE', 'some-fully-qualified-url', auth, callback, success) + 4. common.loggly({ method: 'POST', uri: 'some-url', body: { some: 'body'} }, callback, success)

    common.loggly = function () {
    +  var args = Array.prototype.slice.call(arguments),
    +      success = args.pop(),
    +      callback = args.pop(),
    +      requestBody, 
    +      headers,
    +      method, 
    +      auth, 
    +      uri;
    +  

    Now that we've popped off the two callbacks +We can make decisions about other arguments

      if (args.length == 1) {
    +    if (typeof args[0] === 'string') {

    If we got a string assume that it's the URI

          method = 'GET';
    +      uri    = args[0];
    +    }
    +    else {
    +      method      = args[0]['method'] || 'GET',
    +      uri         = args[0]['uri'];
    +      requestBody = args[0]['body'];
    +      auth        = args[0]['auth'];
    +      headers     = args[0]['headers'];
    +    }
    +  }
    +  else if (args.length == 2) {
    +    method = 'GET';
    +    uri    = args[0];
    +    auth   = args[1];
    +  }
    +  else {
    +    method = args[0];
    +    uri    = args[1];
    +    auth   = args[2];
    +  }
    +  
    +  function onError (err) {
    +    if (callback) {
    +      callback(err);
    +    }
    +  }
    +  
    +  var requestOptions = {
    +    uri: uri,
    +    method: method,
    +    headers: headers || {}
    +  };
    +  
    +  if (auth) {
    +    requestOptions.headers['authorization'] = 'Basic ' + new Buffer(auth.username + ':' + auth.password).toString('base64');
    +  }
    +  
    +  if (requestBody) {
    +    requestOptions.body = requestBody;
    +  }
    +  
    +  try {
    +    request(requestOptions, function (err, res, body) {
    +      if (err) {
    +        return onError(err);
    +      }
    +
    +      var statusCode = res.statusCode.toString();
    +      if (Object.keys(failCodes).indexOf(statusCode) !== -1) {
    +        return onError((new Error('Loggly Error (' + statusCode + '): ' + failCodes[statusCode])));
    +      }
    +
    +      success(res, body);
    +    });
    +  }
    +  catch (ex) {
    +    onError(ex);
    +  }
    +};

    function clone (obj) + Helper method for deep cloning pure JSON objects + i.e. JSON objects that are either literals or objects (no Arrays, etc)

    common.clone = function (obj) {
    +  var clone = {};
    +  for (var i in obj) {
    +    clone[i] = obj[i] instanceof Object ? common.clone(obj[i]) : obj[i];
    +  }
    +
    +  return clone;
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/config.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/config.html new file mode 100644 index 0000000..0f39f4a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/config.html @@ -0,0 +1,41 @@ + config.js

    config.js

    /*
    + * config.js: Configuration information for your Loggly account.
    + *            This information is only used for require('loggly')./\.+/ methods
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */

    function createConfig (defaults) + Creates a new instance of the configuration + object based on default values

    exports.createConfig = function (defaults) {
    +  return new Config(defaults);
    +};

    Config (defaults) + Constructor for the Config object

    var Config = exports.Config = function (defaults) {
    +  if (!defaults.subdomain) {
    +    throw new Error('Subdomain is required to create an instance of Config');
    +  }
    +  
    +  this.subdomain = defaults.subdomain;
    +  this.json = defaults.json || null;
    +  this.auth = defaults.auth || null;
    +};
    + 
    +Config.prototype = {
    +  get subdomain () {
    +   return this._subdomain; 
    +  },
    +
    +  set subdomain (value) {
    +    this._subdomain = value;
    +  },
    +  
    +  get logglyUrl () {
    +    return 'https://' + [this._subdomain, 'loggly', 'com'].join('.') + '/api';
    +  },
    +  
    +  get inputUrl () {
    +    return 'https://logs.loggly.com/inputs/';
    +  }
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/core.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/core.html new file mode 100644 index 0000000..7d1a4bf --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/core.html @@ -0,0 +1,150 @@ + core.js

    core.js

    /*
    + * core.js: Core functions for accessing Loggly
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    +
    +var events = require('events'),
    +    qs = require('querystring'),
    +    config = require('./config'),
    +    common = require('./common'),
    +    Search = require('./search').Search,
    +    Facet = require('./facet').Facet,
    +    loggly = require('../loggly');

    function createClient (options) + Creates a new instance of a Loggly client.

    exports.createClient = function (options) {
    +  return new Loggly(config.createConfig(options));
    +};

    Loggly (config) + Constructor for the Loggly object

    var Loggly = exports.Loggly = function (config) {
    +  this.config = config;
    +};

    function log (callback) + logs args to input device

    Loggly.prototype.log = function (inputId, msg, callback) {
    +  var emitter = new (events.EventEmitter)(),
    +      message;
    +      
    +  if (msg instanceof Object) {
    +    message = this.config.json ? JSON.stringify(msg) : qs.unescape(qs.stringify(msg, ','));
    +  } else {
    +    message = this.config.json ? JSON.stringify({ message : msg }) : msg;
    +  }
    +
    +  var logOptions = {
    +    uri: this.config.inputUrl + inputId,
    +    method: 'POST', 
    +    body: message,
    +    headers: {
    +      'Content-Type': this.config.json ? 'application/json' : 'text/plain'
    +    }
    +  };
    +
    +  common.loggly(logOptions, callback, function (res, body) {
    +    try {
    +      var result = JSON.parse(body);
    +      if (callback) {
    +        callback(null, result);
    +      }
    +      
    +      emitter.emit('log', result);
    +    }
    +    catch (ex) {
    +      if (callback) {
    +        callback(new Error('Unspecified error from Loggly: ' + ex));
    +      }
    +    }
    +  }); 
    +  
    +  return emitter; 
    +};

    function search (query, callback) + Returns a new search object which can be chained + with options or called directly if @callback is passed + initially.

    + +

    Sample Usage:

    + +

    client.search('404') + .meta({ ip: '127.0.0.1' }) + .context({ rows: 100 }) + .run(function () { /* ... */ });

    Loggly.prototype.search = function (query, callback) {
    +  return new Search(query, this, callback);
    +};

    function facet (facet, query, [options], callback) + Performs a facet search against loggly with the + specified facet, query and options.

    Loggly.prototype.facet = function (facet, query, callback) {
    +  return new Facet(facet, query, this, callback);
    +};

    function getInputs ([raw], callback) + Returns a list of all inputs for the authenicated account

    Loggly.prototype.getInputs = function () {
    +  var self = this,
    +      args = Array.prototype.slice.call(arguments),
    +      callback = args.pop(),
    +      raw = args.length > 0 ? args[0] : false;
    +  
    +  common.loggly(this.logglyUrl('inputs'), this.config.auth, callback, function (res, body) {
    +    var inputs = [], 
    +        results = JSON.parse(body);
    +        
    +    if (!raw) {
    +      results.forEach(function (result) {
    +        inputs.push(new (loggly.Input)(self, result));
    +      });
    +      
    +      return callback(null, inputs);
    +    }
    +    
    +    callback(null, results);
    +  });
    +};

    function getInput (name, callback) + Returns the input with the specified name

    Loggly.prototype.getInput = function (name, callback) {
    +  var self = this;
    +  this.getInputs(true, function (err, results) {
    +    if (err) {
    +      return callback(err);
    +    }
    +    
    +    var matches = results.filter(function (r) { return r.name === name }),
    +        input = null;
    +        
    +    if (matches.length > 0) {
    +      input = new (loggly.Input)(self, matches[0]);
    +    }
    +    
    +    callback(null, input);
    +  });
    +};

    function addDevice (inputId, address, callback) + Adds the device at address to the input specified by inputId

    Loggly.prototype.addDeviceToInput = function (inputId, address, callback) {
    +  var addOptions = {
    +    uri: this.logglyUrl('devices'),
    +    auth: this.config.auth,
    +    method: 'POST', 
    +    headers: {
    +      'Content-Type': 'application/x-www-form-urlencoded'
    +    },
    +    body: qs.stringify({ 'input_id': inputId, 'ip': address }).replace('"', '')
    +  };
    +
    +  common.loggly(addOptions, callback, function (res, body) {
    +    callback(null, res);
    +  });
    +};

    function addDevice (inputId, callback) + Adds the calling device to the input

    Loggly.prototype.addDevice = function (inputId, callback) {

    Remark: This is not fully implemented yet

      callback(new Error('Not Implemented Yet...'));
    +  

    common.loggly(this.logglyUrl('inputs', inputId, 'adddevice'), this.config.auth, callback, function (res, body) { +});

    };

    function getDevices (callback) + Returns a list of all devices for the authenicated account

    Loggly.prototype.getDevices = function (callback) {
    +  var self = this;
    +  common.loggly(this.logglyUrl('devices'), this.config.auth, callback, function (res, body) {
    +    var results = JSON.parse(body),
    +        devices = [];
    +        
    +    results.forEach(function (result) {
    +      devices.push(new (loggly.Device)(self, result));
    +    });
    +    
    +    callback(null, devices);
    +  });
    +};

    function logglyUrl ([path, to, resource]) + Helper method that concats the string params into a url + to request against a loggly serverUrl.

    Loggly.prototype.logglyUrl = function (/* path, to, resource */) {
    +  var args = Array.prototype.slice.call(arguments);
    +  return [this.config.logglyUrl].concat(args).join('/');
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/device.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/device.html new file mode 100644 index 0000000..3cc7fc5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/device.html @@ -0,0 +1,26 @@ + device.js

    device.js

    /*
    + * device.js: Instance of a single Loggly device
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    + 
    +var Device = exports.Device = function (client, details) {
    +  if (!details) throw new Error("Device must be constructed with at least basic details.")
    +
    +  this.client = client;
    +  this._setProperties(details);
    +};
    +
    +Device.prototype.addToInput = function (inputId, callback) {
    +  this.client.addDeviceToInput(inputId, this.id, callback);
    +};
    +  

    Sets the properties for this instance +Parameters: details

    Device.prototype._setProperties = function (details) {

    Copy the properties to this instance

      var self = this;
    +  Object.keys(details).forEach(function (key) {
    +    self[key] = details[key];
    +  });
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/facet.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/facet.html new file mode 100644 index 0000000..39fe2b3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/facet.html @@ -0,0 +1,26 @@ + facet.js

    facet.js

    /*
    + * facet.js: Chainable search functions for Loggly facet searches.
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    +
    +var util = require('util'),
    +    Search = require('./search').Search;

    function Facet (facet, query, client, callback) + Chainable facet search object for Loggly API

    var Facet = exports.Facet = function (facet, query, client, callback) {
    +  if (['date', 'ip', 'input'].indexOf(facet) === -1) {
    +    var error = new Error('Cannot search with unknown facet: ' + facet); 
    +    
    +    if (callback) {
    +      return callback(error);
    +    }
    +    else {
    +      throw error;
    +    }
    +  }
    +  

    Set the baseUrl to be facet/:facet?

      this.baseUrl = ['facets', facet + '?'].join('/');
    +  

    Call the base constructor.

      Search.call(this, query, client, callback);
    +};

    Inherit from loggly.Search.

    util.inherits(Facet, Search);
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/input.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/input.html new file mode 100644 index 0000000..22bcac2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/input.html @@ -0,0 +1,32 @@ + input.js

    input.js

    /*
    + * input.js: Instance of a single Loggly input
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    + 
    +var Input = exports.Input = function (client, details) {
    +  if (!details) {
    +    throw new Error("Input must be constructed with at least basic details.");
    +  }
    +  
    +  this.client = client;
    +  this._setProperties(details);
    +};
    +
    +Input.prototype.log = function (msg, callback) {
    +  return this.client.log(this.input_token, msg, callback);
    +};
    +  
    +Input.prototype.addDevice = function (address, callback) {
    +  this.client.addDeviceToInput(this.id, address, callback);
    +};
    +  

    Sets the properties for this instance +Parameters: details

    Input.prototype._setProperties = function (details) {

    Copy the properties to this instance

      var self = this;
    +  Object.keys(details).forEach(function (key) {
    +    self[key] = details[key];
    +  });
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/search.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/search.html new file mode 100644 index 0000000..0a13c0e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/docs/loggly/search.html @@ -0,0 +1,89 @@ + search.js

    search.js

    /*
    + * search.js: chainable search functions for Loggly
    + *
    + * (C) 2010 Nodejitsu Inc.
    + * MIT LICENSE
    + *
    + */
    +
    +var qs = require('querystring'),
    +    timespan = require('timespan'),
    +    common = require('./common');

    function Search (query, client, callback) + Chainable search object for Loggly API

    var Search = exports.Search = function (query, client, callback) {
    +  this.query = query;
    +  this.client = client;
    +  
    +  if (!this.baseUrl) {
    +    this.baseUrl = 'search?';
    +  }
    +  

    If we're passed a callback, run immediately.

      if (callback) {
    +    this.callback = callback;
    +    this.run();
    +  }
    +};

    function meta (meta) + Sets the appropriate metadata for this search query: + e.g. ip, inputname

    Search.prototype.meta = function (meta) {
    +  this._meta = meta;
    +  return this;
    +};

    function context (context) + Sets the appropriate context for this search query: + e.g. rows, start, from, until, order, format, fields

    Search.prototype.context = function (context) {
    +  this._context = context;
    +  return this;
    +};

    function run (callback)

    + +

    @callback {function} Continuation to respond to when complete

    + +

    Runs the search query for for this instance with the query, metadata, +context, and other parameters that have been configured on it.

    Search.prototype.run = function (callback) {
    +  var rangeError;
    +  

    Trim the search query

      this.query.trim();
    +  

    Update the callback for this instance if it's passed

      this.callback = callback || this.callback;
    +  if (!this.callback) {
    +    throw new Error('Cannot run search without a callback function.');
    +  }
    +  

    If meta was passed, update the search query appropriately

      if (this._meta) {
    +    this.query += ' ' + qs.unescape(qs.stringify(this._meta, ' ', ':'));
    +  }

    Set the context for the query string

      this._context = this._context || {};
    +  this._context.q = this.query;
    +  this._checkRange();
    +
    +  var self = this, searchOptions = {
    +    uri: this.client.logglyUrl(this.baseUrl + qs.stringify(this._context)),
    +    auth: this.client.config.auth
    +  };
    +  
    +  common.loggly(searchOptions, this.callback, function (res, body) {
    +    self.callback(null, JSON.parse(body));
    +  });
    +  
    +  return this;
    +};

    function _checkRange ()

    + +

    Checks if the range that has been configured for this +instance is valid and updates if it is not.

    Search.prototype._checkRange = function () {
    +  if (!this._context || (!this._context.until && !this._context.from)) {
    +    return;
    +  }
    +  
    +  this._context.until = this._context.until || 'NOW';
    +  this._context.from  = this._context.from  || 'NOW-24HOURS';
    +  
    +  if (!timespan.parseDate(this._context.until)) {
    +    this._context.until = 'NOW';
    +  }
    +  
    +  if (!timespan.parseDate(this._context.from)) {
    +    this._context.from = 'NOW-24HOURS';
    +  }
    +  
    +  if (timespan.fromDates(this._context.from, this._context.until) < 0
    +    || this._context.until === this._context.from) {

    If the length of the timespan for this Search instance is +negative then set it to default values

        this._context.until = 'NOW';
    +    this._context.from = 'NOW-24HOURS';
    +  }
    +  
    +  return this;
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly.js new file mode 100644 index 0000000..e55d2c2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly.js @@ -0,0 +1,25 @@ +/* + * loggly.js: Wrapper for node-loggly object + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var loggly = exports; + +// +// Export node-loggly core client APIs +// +loggly.createClient = require('./loggly/core').createClient; +loggly.serialize = require('./loggly/common').serialize; +loggly.Loggly = require('./loggly/core').Loggly; +loggly.Config = require('./loggly/config').Config; + +// +// Export Resources for node-loggly +// +loggly.Input = require('./loggly/input').Input; +loggly.Facet = require('./loggly/facet').Facet; +loggly.Device = require('./loggly/device').Device; +loggly.Search = require('./loggly/search').Search; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/common.js new file mode 100644 index 0000000..dae938e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/common.js @@ -0,0 +1,204 @@ +/* + * common.js: Common utility functions for requesting against Loggly APIs + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var util = require('util'), + request = require('request'), + loggly = require('../loggly'); + +var common = exports; + +// +// Failure HTTP Response codes based +// off Loggly specification. +// +var failCodes = common.failCodes = { + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 409: "Conflict / Duplicate", + 410: "Gone", + 500: "Internal Server Error", + 501: "Not Implemented", + 503: "Throttled" +}; + +// +// Success HTTP Response codes based +// off Loggly specification. +// +var successCodes = common.successCodes = { + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-authoritative information", + 204: "Deleted", +}; + +// +// Core method that actually sends requests to Loggly. +// This method is designed to be flexible w.r.t. arguments +// and continuation passing given the wide range of different +// requests required to fully implement the Loggly API. +// +// Continuations: +// 1. 'callback': The callback passed into every node-loggly method +// 2. 'success': A callback that will only be called on successful requests. +// This is used throughout node-loggly to conditionally +// do post-request processing such as JSON parsing. +// +// Possible Arguments (1 & 2 are equivalent): +// 1. common.loggly('some-fully-qualified-url', auth, callback, success) +// 2. common.loggly('GET', 'some-fully-qualified-url', auth, callback, success) +// 3. common.loggly('DELETE', 'some-fully-qualified-url', auth, callback, success) +// 4. common.loggly({ method: 'POST', uri: 'some-url', body: { some: 'body'} }, callback, success) +// +common.loggly = function () { + var args = Array.prototype.slice.call(arguments), + success = args.pop(), + callback = args.pop(), + requestBody, + headers, + method, + auth, + uri; + + // + // Now that we've popped off the two callbacks + // We can make decisions about other arguments + // + if (args.length == 1) { + if (typeof args[0] === 'string') { + // + // If we got a string assume that it's the URI + // + method = 'GET'; + uri = args[0]; + } + else { + method = args[0]['method'] || 'GET', + uri = args[0]['uri']; + requestBody = args[0]['body']; + auth = args[0]['auth']; + headers = args[0]['headers']; + } + } + else if (args.length == 2) { + method = 'GET'; + uri = args[0]; + auth = args[1]; + } + else { + method = args[0]; + uri = args[1]; + auth = args[2]; + } + + function onError (err) { + if (callback) { + callback(err); + } + } + + var requestOptions = { + uri: uri, + method: method, + headers: headers || {} + }; + + if (auth) { + requestOptions.headers['authorization'] = 'Basic ' + new Buffer(auth.username + ':' + auth.password).toString('base64'); + } + + if (requestBody) { + requestOptions.body = requestBody; + } + + try { + request(requestOptions, function (err, res, body) { + if (err) { + return onError(err); + } + + var statusCode = res.statusCode.toString(); + if (Object.keys(failCodes).indexOf(statusCode) !== -1) { + return onError((new Error('Loggly Error (' + statusCode + '): ' + failCodes[statusCode]))); + } + + success(res, body); + }); + } + catch (ex) { + onError(ex); + } +}; + +// +// ### function serialize (obj, key) +// #### @obj {Object|literal} Object to serialize +// #### @key {string} **Optional** Optional key represented by obj in a larger object +// Performs simple comma-separated, `key=value` serialization for Loggly when +// logging to non-JSON inputs. +// +common.serialize = function (obj, key) { + if (obj === null) { + obj = 'null'; + } + else if (obj === undefined) { + obj = 'undefined'; + } + else if (obj === false) { + obj = 'false'; + } + + if (typeof obj !== 'object') { + return key ? key + '=' + obj : obj; + } + + var msg = '', + keys = Object.keys(obj), + length = keys.length; + + for (var i = 0; i < length; i++) { + if (Array.isArray(obj[keys[i]])) { + msg += keys[i] + '=[' + + for (var j = 0, l = obj[keys[i]].length; j < l; j++) { + msg += common.serialize(obj[keys[i]][j]); + if (j < l - 1) { + msg += ', '; + } + } + + msg += ']'; + } + else { + msg += common.serialize(obj[keys[i]], keys[i]); + } + + if (i < length - 1) { + msg += ', '; + } + } + + return msg; +}; + +// +// function clone (obj) +// Helper method for deep cloning pure JSON objects +// i.e. JSON objects that are either literals or objects (no Arrays, etc) +// +common.clone = function (obj) { + var clone = {}; + for (var i in obj) { + clone[i] = obj[i] instanceof Object ? common.clone(obj[i]) : obj[i]; + } + + return clone; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/config.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/config.js new file mode 100644 index 0000000..2156ceb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/config.js @@ -0,0 +1,49 @@ +/* + * config.js: Configuration information for your Loggly account. + * This information is only used for require('loggly')./\.+/ methods + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +// +// function createConfig (defaults) +// Creates a new instance of the configuration +// object based on default values +// +exports.createConfig = function (defaults) { + return new Config(defaults); +}; + +// +// Config (defaults) +// Constructor for the Config object +// +var Config = exports.Config = function (defaults) { + if (!defaults.subdomain) { + throw new Error('Subdomain is required to create an instance of Config'); + } + + this.subdomain = defaults.subdomain; + this.json = defaults.json || null; + this.auth = defaults.auth || null; +}; + +Config.prototype = { + get subdomain () { + return this._subdomain; + }, + + set subdomain (value) { + this._subdomain = value; + }, + + get logglyUrl () { + return 'https://' + [this._subdomain, 'loggly', 'com'].join('.') + '/api'; + }, + + get inputUrl () { + return 'https://logs.loggly.com/inputs/'; + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/core.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/core.js new file mode 100644 index 0000000..9be1553 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/core.js @@ -0,0 +1,211 @@ +/* + * core.js: Core functions for accessing Loggly + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var events = require('events'), + qs = require('querystring'), + config = require('./config'), + common = require('./common'), + Search = require('./search').Search, + Facet = require('./facet').Facet, + loggly = require('../loggly'); + +// +// function createClient (options) +// Creates a new instance of a Loggly client. +// +exports.createClient = function (options) { + return new Loggly(config.createConfig(options)); +}; + +// +// Loggly (config) +// Constructor for the Loggly object +// +var Loggly = exports.Loggly = function (config) { + this.config = config; +}; + +// +// function log (callback) +// logs args to input device +// +Loggly.prototype.log = function (inputId, msg, callback) { + var emitter = new (events.EventEmitter)(), + message; + + if (msg instanceof Object) { + message = this.config.json ? JSON.stringify(msg) : common.serialize(msg); + } + else { + message = this.config.json ? JSON.stringify({ message : msg }) : msg; + } + + var logOptions = { + uri: this.config.inputUrl + inputId, + method: 'POST', + body: message, + headers: { + 'Content-Type': this.config.json ? 'application/json' : 'text/plain' + } + }; + + common.loggly(logOptions, callback, function (res, body) { + try { + var result = JSON.parse(body); + if (callback) { + callback(null, result); + } + + emitter.emit('log', result); + } + catch (ex) { + if (callback) { + callback(new Error('Unspecified error from Loggly: ' + ex)); + } + } + }); + + return emitter; +}; + +// +// function search (query, callback) +// Returns a new search object which can be chained +// with options or called directly if @callback is passed +// initially. +// +// Sample Usage: +// +// client.search('404') +// .meta({ ip: '127.0.0.1' }) +// .context({ rows: 100 }) +// .run(function () { /* ... */ }); +// +Loggly.prototype.search = function (query, callback) { + return new Search(query, this, callback); +}; + +// +// function facet (facet, query, [options], callback) +// Performs a facet search against loggly with the +// specified facet, query and options. +// +Loggly.prototype.facet = function (facet, query, callback) { + return new Facet(facet, query, this, callback); +}; + + +// +// function getInputs ([raw], callback) +// Returns a list of all inputs for the authenicated account +// +Loggly.prototype.getInputs = function () { + var self = this, + args = Array.prototype.slice.call(arguments), + callback = args.pop(), + raw = args.length > 0 ? args[0] : false; + + common.loggly(this.logglyUrl('inputs'), this.config.auth, callback, function (res, body) { + var inputs = [], + results = JSON.parse(body); + + if (!raw) { + results.forEach(function (result) { + inputs.push(new (loggly.Input)(self, result)); + }); + + return callback(null, inputs); + } + + callback(null, results); + }); +}; + +// +// function getInput (name, callback) +// Returns the input with the specified name +// +Loggly.prototype.getInput = function (name, callback) { + var self = this; + this.getInputs(true, function (err, results) { + if (err) { + return callback(err); + } + + var matches = results.filter(function (r) { return r.name === name }), + input = null; + + if (matches.length > 0) { + input = new (loggly.Input)(self, matches[0]); + } + + callback(null, input); + }); +}; + +// +// function addDevice (inputId, address, callback) +// Adds the device at address to the input specified by inputId +// +Loggly.prototype.addDeviceToInput = function (inputId, address, callback) { + var addOptions = { + uri: this.logglyUrl('devices'), + auth: this.config.auth, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: qs.stringify({ 'input_id': inputId, 'ip': address }).replace('"', '') + }; + + common.loggly(addOptions, callback, function (res, body) { + callback(null, res); + }); +}; + +// +// function addDevice (inputId, callback) +// Adds the calling device to the input +// +Loggly.prototype.addDevice = function (inputId, callback) { + // + // Remark: This is not fully implemented yet + // + callback(new Error('Not Implemented Yet...')); + + //common.loggly(this.logglyUrl('inputs', inputId, 'adddevice'), this.config.auth, callback, function (res, body) { + //}); +}; + +// +// function getDevices (callback) +// Returns a list of all devices for the authenicated account +// +Loggly.prototype.getDevices = function (callback) { + var self = this; + common.loggly(this.logglyUrl('devices'), this.config.auth, callback, function (res, body) { + var results = JSON.parse(body), + devices = []; + + results.forEach(function (result) { + devices.push(new (loggly.Device)(self, result)); + }); + + callback(null, devices); + }); +}; + +// +// function logglyUrl ([path, to, resource]) +// Helper method that concats the string params into a url +// to request against a loggly serverUrl. +// +Loggly.prototype.logglyUrl = function (/* path, to, resource */) { + var args = Array.prototype.slice.call(arguments); + return [this.config.logglyUrl].concat(args).join('/'); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/device.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/device.js new file mode 100644 index 0000000..a06d74a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/device.js @@ -0,0 +1,30 @@ +/* + * device.js: Instance of a single Loggly device + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var Device = exports.Device = function (client, details) { + if (!details) throw new Error("Device must be constructed with at least basic details.") + + this.client = client; + this._setProperties(details); +}; + +Device.prototype.addToInput = function (inputId, callback) { + this.client.addDeviceToInput(inputId, this.id, callback); +}; + +// +// Sets the properties for this instance +// Parameters: details +// +Device.prototype._setProperties = function (details) { + // Copy the properties to this instance + var self = this; + Object.keys(details).forEach(function (key) { + self[key] = details[key]; + }); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/facet.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/facet.js new file mode 100644 index 0000000..a17abf9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/facet.js @@ -0,0 +1,42 @@ +/* + * facet.js: Chainable search functions for Loggly facet searches. + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var util = require('util'), + Search = require('./search').Search; + +// +// function Facet (facet, query, client, callback) +// Chainable facet search object for Loggly API +// +var Facet = exports.Facet = function (facet, query, client, callback) { + if (['date', 'ip', 'input'].indexOf(facet) === -1) { + var error = new Error('Cannot search with unknown facet: ' + facet); + + if (callback) { + return callback(error); + } + else { + throw error; + } + } + + // + // Set the baseUrl to be facet/:facet? + // + this.baseUrl = ['facets', facet + '?'].join('/'); + + // + // Call the base constructor. + // + Search.call(this, query, client, callback); +}; + +// +// Inherit from `loggly.Search`. +// +util.inherits(Facet, Search); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/input.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/input.js new file mode 100644 index 0000000..1e02b85 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/input.js @@ -0,0 +1,36 @@ +/* + * input.js: Instance of a single Loggly input + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var Input = exports.Input = function (client, details) { + if (!details) { + throw new Error("Input must be constructed with at least basic details."); + } + + this.client = client; + this._setProperties(details); +}; + +Input.prototype.log = function (msg, callback) { + return this.client.log(this.input_token, msg, callback); +}; + +Input.prototype.addDevice = function (address, callback) { + this.client.addDeviceToInput(this.id, address, callback); +}; + +// +// Sets the properties for this instance +// Parameters: details +// +Input.prototype._setProperties = function (details) { + // Copy the properties to this instance + var self = this; + Object.keys(details).forEach(function (key) { + self[key] = details[key]; + }); +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/search.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/search.js new file mode 100644 index 0000000..09dd437 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/lib/loggly/search.js @@ -0,0 +1,130 @@ +/* + * search.js: chainable search functions for Loggly + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var qs = require('querystring'), + timespan = require('timespan'), + common = require('./common'); + +// +// function Search (query, client, callback) +// Chainable search object for Loggly API +// +var Search = exports.Search = function (query, client, callback) { + this.query = query; + this.client = client; + + if (!this.baseUrl) { + this.baseUrl = 'search?'; + } + + // + // If we're passed a callback, run immediately. + // + if (callback) { + this.callback = callback; + this.run(); + } +}; + +// +// function meta (meta) +// Sets the appropriate metadata for this search query: +// e.g. ip, inputname +// +Search.prototype.meta = function (meta) { + this._meta = meta; + return this; +}; + +// +// function context (context) +// Sets the appropriate context for this search query: +// e.g. rows, start, from, until, order, format, fields +// +Search.prototype.context = function (context) { + this._context = context; + return this; +}; + +// +// ### function run (callback) +// #### @callback {function} Continuation to respond to when complete +// Runs the search query for for this instance with the query, metadata, +// context, and other parameters that have been configured on it. +// +Search.prototype.run = function (callback) { + var rangeError; + + // + // Trim the search query + // + this.query.trim(); + + // + // Update the callback for this instance if it's passed + // + this.callback = callback || this.callback; + if (!this.callback) { + throw new Error('Cannot run search without a callback function.'); + } + + // If meta was passed, update the search query appropriately + if (this._meta) { + this.query += ' ' + qs.unescape(qs.stringify(this._meta, ' ', ':')); + } + + // Set the context for the query string + this._context = this._context || {}; + this._context.q = this.query; + this._checkRange(); + + var self = this, searchOptions = { + uri: this.client.logglyUrl(this.baseUrl + qs.stringify(this._context)), + auth: this.client.config.auth + }; + + common.loggly(searchOptions, this.callback, function (res, body) { + self.callback(null, JSON.parse(body)); + }); + + return this; +}; + +// +// ### function _checkRange () +// Checks if the range that has been configured for this +// instance is valid and updates if it is not. +// +Search.prototype._checkRange = function () { + if (!this._context || (!this._context.until && !this._context.from)) { + return; + } + + this._context.until = this._context.until || 'NOW'; + this._context.from = this._context.from || 'NOW-24HOURS'; + + if (!timespan.parseDate(this._context.until)) { + this._context.until = 'NOW'; + } + + if (!timespan.parseDate(this._context.from)) { + this._context.from = 'NOW-24HOURS'; + } + + if (timespan.fromDates(this._context.from, this._context.until) < 0 + || this._context.until === this._context.from) { + // + // If the length of the timespan for this Search instance is + // negative then set it to default values + // + this._context.until = 'NOW'; + this._context.from = 'NOW-24HOURS'; + } + + return this; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/README.md new file mode 100644 index 0000000..8713a80 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/README.md @@ -0,0 +1,287 @@ +# Request -- Simplified HTTP request method + +## Install + +
    +  npm install request
    +
    + +Or from source: + +
    +  git clone git://github.com/mikeal/request.git 
    +  cd request
    +  npm link
    +
    + +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You 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. + +```javascript +fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You 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: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` + +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Assume by some stretch of magic you aquired the verifier + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: VERIFIER + , token_secret: access_token.oauth_token_secret + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `qs` - object containing querystring values to be appended to the uri +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for POST and PUT requests. Must be buffer or string. +* `form` - sets `body` but to querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer. +* `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. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `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. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `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. +* `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) + + +The 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. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.iriscouch.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies 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). + +```javascript +var request = request.defaults({jar: false}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If 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: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws.js new file mode 100644 index 0000000..4e87bff --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws.js @@ -0,0 +1,190 @@ + +/*! + * knox - auth + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , parse = require('url').parse; + +/** + * Valid keys. + */ + +var keys = [ + 'acl' + , 'location' + , 'logging' + , 'notification' + , 'partNumber' + , 'policy' + , 'requestPayment' + , 'torrent' + , 'uploadId' + , 'uploads' + , 'versionId' + , 'versioning' + , 'versions' + , 'website' +]; + +/** + * Return an "Authorization" header value with the given `options` + * in the form of "AWS :" + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.authorization = function(options){ + return 'AWS ' + options.key + ':' + exports.sign(options); +}; + +/** + * Simple HMAC-SHA1 Wrapper + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.hmacSha1 = function(options){ + return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64'); +}; + +/** + * Create a base64 sha1 HMAC for `options`. + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.sign = function(options){ + options.message = exports.stringToSign(options); + return exports.hmacSha1(options); +}; + +/** + * Create a base64 sha1 HMAC for `options`. + * + * Specifically to be used with S3 presigned URLs + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.signQuery = function(options){ + options.message = exports.queryStringToSign(options); + return exports.hmacSha1(options); +}; + +/** + * Return a string for sign() with the given `options`. + * + * Spec: + * + * \n + * \n + * \n + * \n + * [headers\n] + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.stringToSign = function(options){ + var headers = options.amazonHeaders || ''; + if (headers) headers += '\n'; + return [ + options.verb + , options.md5 + , options.contentType + , options.date.toUTCString() + , headers + options.resource + ].join('\n'); +}; + +/** + * Return a string for sign() with the given `options`, but is meant exclusively + * for S3 presigned URLs + * + * Spec: + * + * \n + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.queryStringToSign = function(options){ + return 'GET\n\n\n' + + options.date + '\n' + + options.resource; +}; + +/** + * Perform the following: + * + * - ignore non-amazon headers + * - lowercase fields + * - sort lexicographically + * - trim whitespace between ":" + * - join with newline + * + * @param {Object} headers + * @return {String} + * @api private + */ + +exports.canonicalizeHeaders = function(headers){ + var buf = [] + , fields = Object.keys(headers); + for (var i = 0, len = fields.length; i < len; ++i) { + var field = fields[i] + , val = headers[field] + , field = field.toLowerCase(); + if (0 !== field.indexOf('x-amz')) continue; + buf.push(field + ':' + val); + } + return buf.sort().join('\n'); +}; + +/** + * Perform the following: + * + * - ignore non sub-resources + * - sort lexicographically + * + * @param {String} resource + * @return {String} + * @api private + */ + +exports.canonicalizeResource = function(resource){ + var url = parse(resource, true) + , path = url.pathname + , buf = []; + + Object.keys(url.query).forEach(function(key){ + if (!~keys.indexOf(key)) return; + var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]); + buf.push(key + val); + }); + + return path + (buf.length + ? '?' + buf.sort().join('&') + : ''); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws2.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws2.js new file mode 100644 index 0000000..eb683f7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/aws2.js @@ -0,0 +1,128 @@ +var crypto = require('crypto') + +// The Authentication Header +// +// The Amazon S3 REST API uses the standard HTTPAuthorization header to pass authentication information. (The name of the standard header is unfortunate because it carries authentication information, not authorization).Under the Amazon S3 authentication scheme, the Authorization header has the following form. +// +// Authorization: AWS AWSAccessKeyId:Signature +// +// Developers are issued an AWS Access Key ID and AWS SecretAccess Key when they register. For request authentication, theAWSAccessKeyId element identifies the secret key that was used to compute the signature, and (indirectly) the developer making the request. +// +// The Signature element is the RFC 2104HMAC-SHA1 of selected elements from the request, and so theSignature part of the Authorization header will vary from request to request. If the request signature calculated by the system matches theSignature included with the request, then the requester will have demonstrated possession to the AWSSecret Access Key. The request will then be processed under the identity, and with the authority, of the developer to whom the key was issued. +// +// Following is pseudo-grammar that illustrates the construction of the Authorization request header (\nmeans the Unicode code point U+000A commonly called newline). + +function authorizationHeader (accessKey) { + // Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature; + + var authorization = 'AWS' + " " + accessKey + ":" + signature() + + return authorization +} + +// + +function signature (secret, verb, md5, contenttype, date, amzheaders, bucket, path) { + // Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of( YourSecretAccessKeyID, StringToSign ) ) ); + + function encodeSignature (stringToSign) { + return crypto.createHash('sha1').update(stringToSign).digest('base64') + } + + // + // StringToSign = HTTP-Verb + "\n" + + // Content-MD5 + "\n" + + // Content-Type + "\n" + + // Date + "\n" + + // CanonicalizedAmzHeaders + + // CanonicalizedResource; + + function compileStringToSign () { + var s = + verb + '\n' + (md5 || '') + '\n' + (contenttype || '') + '\n' + date.toUTCString() + '\n' + canonicalizeAmzHeaders(amzheaders) + + canonicalizeResource() + return s + } + + // + // CanonicalizedResource = [ "/" + Bucket ] + + // + + // [ sub-resource, if present. For example "?acl", "?location", "?logging", or "?torrent"]; + + function canonicalizeResource () { + return '/' + bucket + path + } + + // + // CanonicalizedAmzHeaders = + // + // HMAC-SHA1 is an algorithm defined by RFC 2104 (go to RFC 2104 - Keyed-Hashing for Message Authentication ). The algorithm takes as input two byte-strings: a key and a message. For Amazon S3 Request authentication, use your AWS Secret Access Key (YourSecretAccessKeyID) as the key, and the UTF-8 encoding of the StringToSign as the message. The output of HMAC-SHA1 is also a byte string, called the digest. The Signature request parameter is constructed by Base64 encoding this digest. + // Request Canonicalization for Signing + // + // Recall that when the system receives an authenticated request, it compares the computed request signature with the signature provided in the request in StringToSign. For that reason, you must compute the signature using the same method used by Amazon S3. We call the process of putting a request in an agreed-upon form for signing "canonicalization". + +} + + + +// Constructing the CanonicalizedResource Element +// +// CanonicalizedResource represents the Amazon S3 resource targeted by the request. Construct it for a REST request as follows: +// +// Launch Process +// +// 1 +// +// +// Start with the empty string (""). +// +// 2 +// +// +// If the request specifies a bucket using the HTTP Host header (virtual hosted-style), append the bucket name preceded by a "/" (e.g., "/bucketname"). For path-style requests and requests that don't address a bucket, do nothing. For more information on virtual hosted-style requests, see Virtual Hosting of Buckets. +// +// 3 +// +// +// Append the path part of the un-decoded HTTP Request-URI, up-to but not including the query string. +// +// 4 +// +// +// If the request addresses a sub-resource, like ?versioning, ?location, ?acl, ?torrent, ?lifecycle, or ?versionid append the sub-resource, its value if it has one, and the question mark. Note that in case of multiple sub-resources, sub-resources must be lexicographically sorted by sub-resource name and separated by '&'. e.g. ?acl&versionId=value. +// +// The list of sub-resources that must be included when constructing the CanonicalizedResource Element are: acl, lifecycle, location, logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions and website. +// +// If the request specifies query string parameters overriding the response header values (see Get Object), append the query string parameters, and its values. When signing you do not encode these values. However, when making the request, you must encode these parameter values. The query string parameters in a GET request include response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, response-content-encoding. +// +// The delete query string parameter must be including when creating the CanonicalizedResource for a Multi-Object Delete request. +// +// Elements of the CanonicalizedResource that come from the HTTP Request-URI should be signed literally as they appear in the HTTP request, including URL-Encoding meta characters. +// +// The CanonicalizedResource might be different than the HTTP Request-URI. In particular, if your request uses the HTTP Host header to specify a bucket, the bucket does appear in the HTTP Request-URI. However, the CanonicalizedResource continues to include the bucket. Query string parameters might also appear in the Request-URI but are not included in CanonicalizedResource. For more information, see Virtual Hosting of Buckets. +// Constructing the CanonicalizedAmzHeaders Element +// +// To construct the CanonicalizedAmzHeaders part of StringToSign, select all HTTP request headers that start with 'x-amz-' (using a case-insensitive comparison) and use the following process. +// +// CanonicalizedAmzHeaders Process +// 1 Convert each HTTP header name to lower-case. For example, 'X-Amz-Date' becomes 'x-amz-date'. +// 2 Sort the collection of headers lexicographically by header name. +// 3 Combine header fields with the same name into one "header-name:comma-separated-value-list" pair as prescribed by RFC 2616, section 4.2, without any white-space between values. For example, the two metadata headers 'x-amz-meta-username: fred' and 'x-amz-meta-username: barney' would be combined into the single header 'x-amz-meta-username: fred,barney'. +// 4 "Unfold" long headers that span multiple lines (as allowed by RFC 2616, section 4.2) by replacing the folding white-space (including new-line) by a single space. +// 5 Trim any white-space around the colon in the header. For example, the header 'x-amz-meta-username: fred,barney' would become 'x-amz-meta-username:fred,barney' +// 6 Finally, append a new-line (U+000A) to each canonicalized header in the resulting list. Construct the CanonicalizedResource element by concatenating all headers in this list into a single string. +// +// Positional versus Named HTTP Header StringToSign Elements +// +// The first few header elements of StringToSign (Content-Type, Date, and Content-MD5) are positional in nature. StringToSign does not include the names of these headers, only their values from the request. In contrast, the 'x-amz-' elements are named; Both the header names and the header values appear in StringToSign. +// +// If a positional header called for in the definition of StringToSign is not present in your request, (Content-Type or Content-MD5, for example, are optional for PUT requests, and meaningless for GET requests), substitute the empty string ("") in for that position. +// Time Stamp Requirement +// +// A valid time stamp (using either the HTTP Date header or an x-amz-date alternative) is mandatory for authenticated requests. Furthermore, the client time-stamp included with an authenticated request must be within 15 minutes of the Amazon S3 system time when the request is received. If not, the request will fail with the RequestTimeTooSkewed error status code. The intention of these restrictions is to limit the possibility that intercepted requests could be replayed by an adversary. For stronger protection against eavesdropping, use the HTTPS transport for authenticated requests. +// +// Some HTTP client libraries do not expose the ability to set the Date header for a request. If you have trouble including the value of the 'Date' header in the canonicalized headers, you can set the time-stamp for the request using an 'x-amz-date' header instead. The value of the x-amz-date header must be in one of the RFC 2616 formats (http://www.ietf.org/rfc/rfc2616.txt). When an x-amz-date header is present in a request, the system will ignore any Date header when computing the request signature. Therefore, if you include the x-amz-date header, use the empty string for the Date when constructing the StringToSign. See the next section for an example. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/forever.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/forever.js new file mode 100644 index 0000000..ac853c0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/forever.js @@ -0,0 +1,103 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = host + ':' + port + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + function onIdleError() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy(); + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = host + ':' + port + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s); + if (index !== -1) { + this.sockets[name].splice(index, 1); + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name]; + delete this.requests[name]; + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free'); + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + options.port = port + options.host = host + return tls.connect(options) +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/main.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/main.js new file mode 100644 index 0000000..2407a93 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/main.js @@ -0,0 +1,974 @@ +// Copyright 2010-2012 Mikeal Rogers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('querystring') + , mimetypes = require('./mimetypes') + , oauth = require('./oauth') + , uuid = require('./uuid') + , ForeverAgent = require('./forever') + , Cookie = require('./vendor/cookie') + , CookieJar = require('./vendor/cookie/jar') + , cookieJar = new CookieJar + , tunnel = require('./tunnel') + , aws = require('./aws') + ; + +if (process.logging) { + var log = process.logging('request') +} + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function (host, port, cb) { + var s = tls.connect(port, host, this.options, function () { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function copy (obj) { + var o = {} + Object.keys(obj).forEach(function (i) { + o[i] = obj[i] + }) + return o +} + +var isUrl = /^https?:/ + +var globalPool = {} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + var reserved = Object.keys(Request.prototype) + for (var i in options) { + if (reserved.indexOf(i) === -1) { + this[i] = options[i] + } else { + if (typeof options[i] === 'function') { + delete options[i] + } + } + } + options = copy(options) + + this.init(options) +} +util.inherits(Request, stream.Stream) +Request.prototype.init = function (options) { + var self = this + + if (!options) options = {} + + if (!self.pool && self.pool !== false) self.pool = globalPool + self.dests = [] + self.__isRequestRequest = true + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callback.apply(self, arguments) + self._callbackCalled = true + } + self.on('error', self.callback.bind()) + self.on('complete', self.callback.bind(self, null)) + } + + if (self.url) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + throw new Error("options.uri is a required argument") + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + self.tunnel = true + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } + } + + if (!self.uri.host || !self.uri.pathname) { + // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar + // Detect and reject it as soon as possible + var faultyUri = url.format(self.uri) + var message = 'Invalid URI "' + faultyUri + '"' + if (Object.keys(options).length === 0) { + // No option ? This can be the sign of a redirect + // As this is a case where the user cannot do anything (he didn't call request directly with this URL) + // he should be warned that it can be caused by a redirection (can save some hair) + message += '. This can be caused by a crappy redirection.' + } + self.emit('error', new Error(message)) + return // This error was fatal + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false; + if (self.followRedirect || self.followAllRedirects) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + self.setHost = false + if (!self.headers.host) { + self.headers.host = self.uri.hostname + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.headers.host += (':'+self.uri.port) + } + self.setHost = true + } + + self.jar(self._jar || options.jar) + + if (!self.uri.pathname) {self.uri.pathname = '/'} + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy && !self.tunnel) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + self.clientErrorHandler = function (error) { + if (self._aborted) return + + if (self.setHost) delete self.headers.host + if (self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } + self.start() + self.req.end() + return + } + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + self.emit('error', error) + } + + if (options.form) { + self.form(options.form) + } + + if (options.oauth) { + self.oauth(options.oauth) + } + + if (options.aws) { + self.aws(options.aws) + } + + if (self.uri.auth && !self.headers.authorization) { + self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { + self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + + if (options.qs) self.qs(options.qs) + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (options.json) { + self.json(options.json) + } else if (options.multipart) { + self.boundary = uuid() + self.multipart(options.multipart) + } + + if (self.body) { + var length = 0 + if (!Buffer.isBuffer(self.body)) { + if (Array.isArray(self.body)) { + for (var i = 0; i < self.body.length; i++) { + length += self.body[i].length + } + } else { + self.body = new Buffer(self.body) + length = self.body.length + } + } else { + length = self.body.length + } + if (length) { + self.headers['content-length'] = length + } else { + throw new Error('Argument error, options.body.') + } + } + + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol + , defaultModules = {'http:':http, 'https:':https} + , httpModules = self.httpModules || {} + ; + self.httpModule = httpModules[protocol] || defaultModules[protocol] + + if (!self.httpModule) throw new Error("Invalid protocol") + + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + + if (self.pool === false) { + self.agent = false + } else { + self.agent = self.agent || self.getAgent() + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.once('pipe', function (src) { + if (self.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.") + self.src = src + if (isReadStream(src)) { + if (!self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = mimetypes.lookup(src.path.slice(src.path.lastIndexOf('.')+1)) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.headers[i]) { + self.headers[i] = src.headers[i] + } + } + } + if (src.method && !self.method) { + self.method = src.method + } + } + + self.on('pipe', function () { + console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + }) + }) + + process.nextTick(function () { + if (self._aborted) return + + if (self.body) { + if (Array.isArray(self.body)) { + self.body.forEach(function (part) { + self.write(part) + }) + } else { + self.write(self.body) + } + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + if (self.method !== 'GET' && typeof self.method !== 'undefined') { + self.headers['content-length'] = 0; + } + self.end(); + } + self.ntick = true + }) +} + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port + } + + if (options.ca) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) +} + +Request.prototype.start = function () { + var self = this + + if (self._aborted) return + + self._started = true + self.method = self.method || 'GET' + self.href = self.uri.href + if (log) log('%method %href', self) + + if (self.src && self.src.stat && self.src.stat.size) { + self.headers['content-length'] = self.src.stat.size + } + if (self._aws) { + self.aws(self._aws, true) + } + + self.req = self.httpModule.request(self, function (response) { + if (self._aborted) return + if (self._paused) response.pause() + + self.response = response + response.request = self + response.toJSON = toJSON + + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (self.setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + + var addCookie = function (cookie) { + if (self._jar) self._jar.add(new Cookie(cookie)) + else cookieJar.add(new Cookie(cookie)) + } + + if (response.headers['set-cookie'] && (!self._disableCookies)) { + if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie) + else addCookie(response.headers['set-cookie']) + } + + if (response.statusCode >= 300 && response.statusCode < 400 && + (self.followAllRedirects || + (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST' && self.method !== 'DELETE'))) && + response.headers.location) { + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop.")) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(response.headers.location)) { + response.headers.location = url.resolve(self.uri.href, response.headers.location) + } + self.uri = response.headers.location + self.redirects.push( + { statusCode : response.statusCode + , redirectUri: response.headers.location + } + ) + if (self.followAllRedirects) self.method = 'GET' + // self.method = 'GET'; // Force all redirects to use GET || commented out fixes #215 + delete self.req + delete self.agent + delete self._started + delete self.body + if (self.headers) { + delete self.headers.host + } + if (log) log('Redirect to %uri', self) + self.init() + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + self.emit('response', response) + + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + if (self._aborted) return + + if (buffer.length && Buffer.isBuffer(buffer[0])) { + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + if (self.encoding === null) { + response.body = body + } else { + response.body = body.toString() + } + } else if (buffer.length) { + response.body = buffer.join('') + } + + if (self._json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + + self.emit('complete', response, response.body) + }) + } + } + }) + + if (self.timeout && !self.timeoutTimer) { + self.timeoutTimer = setTimeout(function () { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + + // Set additional timeout on socket - in case if remote + // server freeze after sending headers + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function () { + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } + } + + self.req.on('error', self.clientErrorHandler) + self.req.on('drain', function() { + self.emit('drain') + }) + + self.emit('request', self.req) +} + +Request.prototype.abort = function () { + this._aborted = true; + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + +Request.prototype.pipeDest = function (dest) { + var response = this.response + // Called after the response is received + if (dest.headers) { + dest.headers['content-type'] = response.headers['content-type'] + if (response.headers['content-length']) { + dest.headers['content-length'] = response.headers['content-length'] + } + } + if (dest.setHeader) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (this.pipefilter) this.pipefilter(response, dest) +} + +// Composable API +Request.prototype.setHeader = function (name, value, clobber) { + if (clobber === undefined) clobber = true + if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value + else this.headers[name] += ',' + value + return this +} +Request.prototype.setHeaders = function (headers) { + for (var i in headers) {this.setHeader(i, headers[i])} + return this +} +Request.prototype.qs = function (q, clobber) { + var base + if (!clobber && this.uri.query) base = qs.parse(this.uri.query) + else base = {} + + for (var i in q) { + base[i] = q[i] + } + + this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base)) + this.url = this.uri + + return this +} +Request.prototype.form = function (form) { + this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + this.body = qs.stringify(form).toString('utf8') + return this +} +Request.prototype.multipart = function (multipart) { + var self = this + self.body = [] + + if (!self.headers['content-type']) { + self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary; + } else { + self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary; + } + + console.log('boundary >> ' + self.boundary) + + if (!multipart.forEach) throw new Error('Argument error, options.multipart.') + + multipart.forEach(function (part) { + var body = part.body + if(body == null) throw Error('Body attribute missing in multipart.') + delete part.body + var preamble = '--' + self.boundary + '\r\n' + Object.keys(part).forEach(function (key) { + preamble += key + ': ' + part[key] + '\r\n' + }) + preamble += '\r\n' + self.body.push(new Buffer(preamble)) + self.body.push(new Buffer(body)) + self.body.push(new Buffer('\r\n')) + }) + self.body.push(new Buffer('--' + self.boundary + '--')) + return self +} +Request.prototype.json = function (val) { + this.setHeader('content-type', 'application/json') + this.setHeader('accept', 'application/json') + this._json = true + if (typeof val === 'boolean') { + if (typeof this.body === 'object') this.body = JSON.stringify(this.body) + } else { + this.body = JSON.stringify(val) + } + return this +} +Request.prototype.aws = function (opts, now) { + if (!now) { + this._aws = opts + return this + } + var date = new Date() + this.setHeader('date', date.toUTCString()) + this.setHeader('authorization', aws.authorization( + { key: opts.key + , secret: opts.secret + , verb: this.method + , date: date + , resource: aws.canonicalizeResource('/' + opts.bucket + this.path) + , contentType: this.headers['content-type'] || '' + , md5: this.headers['content-md5'] || '' + , amazonHeaders: aws.canonicalizeHeaders(this.headers) + } + )) + + return this +} + +Request.prototype.oauth = function (_oauth) { + var form + if (this.headers['content-type'] && + this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === + 'application/x-www-form-urlencoded' + ) { + form = qs.parse(this.body) + } + if (this.uri.query) { + form = qs.parse(this.uri.query) + } + if (!form) form = {} + var oa = {} + for (var i in form) oa[i] = form[i] + for (var i in _oauth) oa['oauth_'+i] = _oauth[i] + if (!oa.oauth_version) oa.oauth_version = '1.0' + if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() + if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') + + oa.oauth_signature_method = 'HMAC-SHA1' + + var consumer_secret = oa.oauth_consumer_secret + delete oa.oauth_consumer_secret + var token_secret = oa.oauth_token_secret + delete oa.oauth_token_secret + + var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname + var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret) + + // oa.oauth_signature = signature + for (var i in form) { + if ( i.slice(0, 'oauth_') in _oauth) { + // skip + } else { + delete oa['oauth_'+i] + } + } + this.headers.Authorization = + 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',') + this.headers.Authorization += ',oauth_signature="'+oauth.rfc3986(signature)+'"' + return this +} +Request.prototype.jar = function (jar) { + var cookies + + if (this._redirectsFollowed === 0) { + this.originalCookieHeader = this.headers.cookie + } + + if (jar === false) { + // disable cookies + cookies = false; + this._disableCookies = true; + } else if (jar) { + // fetch cookie from the user defined cookie jar + cookies = jar.get({ url: this.uri.href }) + } else { + // fetch cookie from the global cookie jar + cookies = cookieJar.get({ url: this.uri.href }) + } + + if (cookies && cookies.length) { + var cookieString = cookies.map(function (c) { + return c.name + "=" + c.value + }).join("; ") + + if (this.originalCookieHeader) { + // Don't overwrite existing Cookie header + this.headers.cookie = this.originalCookieHeader + '; ' + cookieString + } else { + this.headers.cookie = cookieString + } + } + this._jar = jar + return this +} + + +// Stream API +Request.prototype.pipe = function (dest, opts) { + if (this.response) { + if (this._destdata) { + throw new Error("You cannot pipe after data has been emitted from the response.") + } else if (this._ended) { + throw new Error("You cannot pipe after the response has been ended.") + } else { + stream.Stream.prototype.pipe.call(this, dest, opts) + this.pipeDest(dest) + return dest + } + } else { + this.dests.push(dest) + stream.Stream.prototype.pipe.call(this, dest, opts) + return dest + } +} +Request.prototype.write = function () { + if (!this._started) this.start() + return this.req.write.apply(this.req, arguments) +} +Request.prototype.end = function (chunk) { + if (chunk) this.write(chunk) + if (!this._started) this.start() + this.req.end() +} +Request.prototype.pause = function () { + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) +} +Request.prototype.resume = function () { + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) +} +Request.prototype.destroy = function () { + if (!this._ended) this.end() +} + +// organize params for post, put, head, del +function initParams(uri, options, callback) { + if ((typeof options === 'function') && !callback) callback = options; + if (options && typeof options === 'object') { + options.uri = uri; + } else if (typeof uri === 'string') { + options = {uri:uri}; + } else { + options = uri; + uri = options.uri; + } + return { uri: uri, options: options, callback: callback }; +} + +function request (uri, options, callback) { + if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.') + if ((typeof options === 'function') && !callback) callback = options; + if (options && typeof options === 'object') { + options.uri = uri; + } else if (typeof uri === 'string') { + options = {uri:uri}; + } else { + options = uri; + } + + if (callback) options.callback = callback; + var r = new Request(options) + return r +} + +module.exports = request + +request.defaults = function (options) { + var def = function (method) { + var d = function (uri, opts, callback) { + var params = initParams(uri, opts, callback); + for (var i in options) { + if (params.options[i] === undefined) params.options[i] = options[i] + } + return method(params.options, params.callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = def(request.jar) + return de +} + +request.forever = function (agentOptions, optionsArg) { + var options = {} + if (optionsArg) { + for (option in optionsArg) { + options[option] = optionsArg[option] + } + } + if (agentOptions) options.agentOptions = agentOptions + options.forever = true + return request.defaults(options) +} + +request.get = request +request.post = function (uri, options, callback) { + var params = initParams(uri, options, callback); + params.options.method = 'POST'; + return request(params.uri || null, params.options, params.callback) +} +request.put = function (uri, options, callback) { + var params = initParams(uri, options, callback); + params.options.method = 'PUT' + return request(params.uri || null, params.options, params.callback) +} +request.head = function (uri, options, callback) { + var params = initParams(uri, options, callback); + params.options.method = 'HEAD' + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(params.uri || null, params.options, params.callback) +} +request.del = function (uri, options, callback) { + var params = initParams(uri, options, callback); + params.options.method = 'DELETE' + return request(params.uri || null, params.options, params.callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (str && str.uri) str = str.uri + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} + +// Safe toJSON + +function getSafe (self, uuid) { + if (typeof self === 'object' || typeof self === 'function') var safe = {} + if (Array.isArray(self)) var safe = [] + + var recurse = [] + + Object.defineProperty(self, uuid, {}) + + var attrs = Object.keys(self).filter(function (i) { + if (i === uuid) return false + if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true + return !(Object.getOwnPropertyDescriptor(self[i], uuid)) + }) + + + for (var i=0;i= 0.3.6" + ], + "main": "./main", + "scripts": { + "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/request/tests/googledoodle.png b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/googledoodle.png new file mode 100644 index 0000000..f80c9c5 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/googledoodle.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/run.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/run.js new file mode 100644 index 0000000..f3a30d3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/run.js @@ -0,0 +1,39 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + ; + +var tests = [ + 'test-body.js' + , 'test-cookie.js' + , 'test-cookiejar.js' + , 'test-defaults.js' + , 'test-errors.js' + , 'test-headers.js' + , 'test-httpModule.js' + , 'test-https.js' + , 'test-https-strict.js' + , 'test-oauth.js' + , 'test-pipes.js' + , 'test-pool.js' + , 'test-proxy.js' + , 'test-qs.js' + , 'test-redirect.js' + , 'test-timeout.js' + , 'test-toJSON.js' + , 'test-tunnel.js' +] + +var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + exitCode += code || 0 + next() + }) +} +next() diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/server.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/server.js new file mode 100644 index 0000000..921f512 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/server.js @@ -0,0 +1,82 @@ +var fs = require('fs') + , http = require('http') + , path = require('path') + , https = require('https') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createSSLServer = function(port, opts) { + port = port || 16767 + + var options = { 'key' : path.join(__dirname, 'ssl', 'test.key') + , 'cert': path.join(__dirname, 'ssl', 'test.crt') + } + if (opts) { + for (var i in opts) options[i] = opts[i] + } + + for (var i in options) { + options[i] = fs.readFileSync(options[i]) + } + + var s = https.createServer(options, function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'https://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (r !== text) console.log(r, text); + assert.equal(r, text) + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/squid.conf b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/squid.conf new file mode 100644 index 0000000..0d4a3b6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/squid.conf @@ -0,0 +1,77 @@ +# +# Recommended minimum configuration: +# +acl manager proto cache_object +acl localhost src 127.0.0.1/32 ::1 +acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1 + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 10.0.0.0/8 # RFC1918 possible internal network +acl localnet src 172.16.0.0/12 # RFC1918 possible internal network +acl localnet src 192.168.0.0/16 # RFC1918 possible internal network +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +# +# Recommended minimum Access Permission configuration: +# +# Only allow cachemgr access from localhost +http_access allow manager localhost +http_access deny manager + +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +#http_access deny CONNECT !SSL_ports + +# We strongly recommend the following be uncommented to protect innocent +# web applications running on the proxy server who think the only +# one who can access services on "localhost" is a local user +#http_access deny to_localhost + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +# Example rule allowing access from your local networks. +# Adapt localnet in the ACL section to list your (internal) IP networks +# from where browsing should be allowed +http_access allow localnet +http_access allow localhost + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# We recommend you to use at least the following line. +hierarchy_stoplist cgi-bin ? + +# Uncomment and adjust the following to add a disk cache directory. +#cache_dir ufs /usr/local/var/cache 100 16 256 + +# Leave coredumps in the first cache dir +coredump_dir /usr/local/var/cache + +# Add any of your own refresh_pattern entries above these. +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern . 0 20% 4320 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.cnf b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.cnf new file mode 100644 index 0000000..425a889 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.cnf @@ -0,0 +1,20 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = password + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = request Certificate Authority +CN = requestCA +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.crl b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.crl new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.crt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.crt new file mode 100644 index 0000000..b4524e4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl +YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4 +5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ +5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD +xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm +D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo +88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj +-----END CERTIFICATE----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.csr b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.csr new file mode 100644 index 0000000..e48c56e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG +SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0 +deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br +44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB +AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3 +DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj +bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia +SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.key b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.key new file mode 100644 index 0000000..a53e7f7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C8B5887048377F02 + +nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q +nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+ +GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH +gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38 +VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3 +/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb +4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U +gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR +Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh +FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf +dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC +uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb +EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.srl b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.srl new file mode 100644 index 0000000..17128db --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/ca.srl @@ -0,0 +1 @@ +ADF62016AA40C9C3 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.cnf b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.cnf new file mode 100644 index 0000000..cd1fd1e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.cnf @@ -0,0 +1,19 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = testing +CN = testing.request.mikealrogers.com +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.crt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.crt new file mode 100644 index 0000000..efe96ce --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx +dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr +ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM +20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh +DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj +7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB +kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC +yapjN3RxZbInGhWR+jA= +-----END CERTIFICATE----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.csr b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.csr new file mode 100644 index 0000000..a8e7595 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp +MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq +hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB +BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU +ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw +7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A +HidVJ/3u +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.js new file mode 100644 index 0000000..05e21c1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.js @@ -0,0 +1,28 @@ +var fs = require("fs") +var https = require("https") +var options = { key: fs.readFileSync("./server.key") + , cert: fs.readFileSync("./server.crt") } + +var server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end() + server.close() +}) +server.listen(1337) + +var ca = fs.readFileSync("./ca.crt") +var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca }) + +https.request({ host: "localhost" + , method: "HEAD" + , port: 1337 + , headers: { host: "testing.request.mikealrogers.com" } + , agent: agent + , ca: [ ca ] + , path: "/" }, function (res) { + if (res.client.authorized) { + console.log("node test: OK") + } else { + throw new Error(res.client.authorizationError) + } +}).end() diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.key b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.key new file mode 100644 index 0000000..72d8698 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/ca/server.key @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB +iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW +gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0 +JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ +rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ +0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/npm-ca.crt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/npm-ca.crt new file mode 100644 index 0000000..fde2fe9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/npm-ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x +IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w +bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y +MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV +BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj +YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA +aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE +OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz +Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl +y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC +l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv +yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl +ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op +-----END CERTIFICATE----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.crt b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.crt new file mode 100644 index 0000000..b357f86 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU +SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo +ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx +MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV +BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz +dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto +wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj +eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV +l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4 +L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE +c7U8F6MWLQ== +-----END CERTIFICATE----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.key b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.key new file mode 100644 index 0000000..b85810d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/ssl/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt +NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE +mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB +AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt +Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ +fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb +rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6 +V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF ++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb +G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf +Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ +fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w +kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-body.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..e3fc75d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-body.js @@ -0,0 +1,80 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookie.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookie.js new file mode 100644 index 0000000..6c6a7a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../vendor/cookie') + , assert = require('assert'); + +var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'Sid'); + +// test .value +assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookiejar.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookiejar.js new file mode 100644 index 0000000..76fcd71 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-defaults.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-defaults.js new file mode 100644 index 0000000..6c8b58f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-defaults.js @@ -0,0 +1,68 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed.") + s.close() + }); + +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-errors.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..1986a59 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../main.js') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-headers.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-headers.js new file mode 100644 index 0000000..31fe3f4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-httpModule.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-httpModule.js new file mode 100644 index 0000000..1866de2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to SSL worked') + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to plaintext server worked') + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https-strict.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https-strict.js new file mode 100644 index 0000000..f53fc14 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--frontier\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--frontier\r\n\r\n' + + 'Oh hi.' + + '\r\n--frontier--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https.js new file mode 100644 index 0000000..df7330b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-https.js @@ -0,0 +1,86 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--frontier\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--frontier\r\n\r\n' + + 'Oh hi.' + + '\r\n--frontier--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-oauth.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..72ca923 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('../oauth').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../main') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-params.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-params.js new file mode 100644 index 0000000..8354f6d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-params.js @@ -0,0 +1,92 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--frontier\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--frontier\r\n\r\n' + + 'Oh hi.' + + '\r\n--frontier--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pipes.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..1869874 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pipes.js @@ -0,0 +1,202 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/png'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.png')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.png')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.png')), fs.readFileSync(path.join(__dirname, 'test.png'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.png')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pool.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pool.js new file mode 100644 index 0000000..1e7d578 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-proxy.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..647157c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-qs.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-qs.js new file mode 100644 index 0000000..1aac22b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-qs.js @@ -0,0 +1,28 @@ +var request = request = require('../main.js') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-redirect.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-redirect.js new file mode 100644 index 0000000..b84844a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-redirect.js @@ -0,0 +1,154 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-s3.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-s3.js new file mode 100644 index 0000000..5f59c4a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../main') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-timeout.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..673f8ad --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-toJSON.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-toJSON.js new file mode 100644 index 0000000..b7c67ef --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-tunnel.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-tunnel.js new file mode 100644 index 0000000..58131b9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,61 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('exit', function (c) { + console.error('exit '+c) + if (c && !ready) { + console.error('squid must be installed to run this test.') + c = null + hadError = null + process.exit(0) + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/request/' + , proxy: 'http://localhost:3128' + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tunnel.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tunnel.js new file mode 100644 index 0000000..453786c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/tunnel.js @@ -0,0 +1,229 @@ +'use strict'; + +var net = require('net'); +var tls = require('tls'); +var http = require('http'); +var https = require('https'); +var events = require('events'); +var assert = require('assert'); +var util = require('util'); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this; + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, host, port); + } + + function onCloseOrRemove(err) { + self.removeSocket(); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false + }); + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode === 200) { + assert.equal(head.length, 0); + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + cb(socket); + } else { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + var error = new Error('tunneling socket could not be established, ' + + 'sutatusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, { + socket: socket + })); + cb(secureSocket); + }); +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/uuid.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/uuid.js new file mode 100644 index 0000000..1d83bd5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/uuid.js @@ -0,0 +1,19 @@ +module.exports = function () { + var s = [], itoh = '0123456789ABCDEF'; + + // Make array of random hex digits. The UUID only has 32 digits in it, but we + // allocate an extra items to make room for the '-'s we'll be inserting. + for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10); + + // Conform to RFC-4122, section 4.4 + s[14] = 4; // Set 4 high bits of time_high field to version + s[19] = (s[19] & 0x3) | 0x8; // Specify 2 high bits of clock sequence + + // Convert to hex chars + for (var i = 0; i <36; i++) s[i] = itoh[s[i]]; + + // Insert '-'s + s[8] = s[13] = s[18] = s[23] = '-'; + + return s.join(''); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/index.js new file mode 100644 index 0000000..ff44b3e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/index.js @@ -0,0 +1,65 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + var p = pair.indexOf('='); + var key = p > 0 ? pair.substring(0, p).trim() : pair.trim(); + var lowerCasedKey = key.toLowerCase(); + var value = p > 0 ? pair.substring(p + 1).trim() : true; + + if (!obj.name) { + // First key is the name + obj.name = key; + obj.value = value; + } + else if (lowerCasedKey === 'httponly') { + obj.httpOnly = value; + } + else { + obj[lowerCasedKey] = value; + } + return obj; + }, this); + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim(): req + ? url.parse(req.url).pathname: '/'; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/jar.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/jar.js new file mode 100644 index 0000000..34920e0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/request/vendor/cookie/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/.npmignore new file mode 100644 index 0000000..e3bc275 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/.npmignore @@ -0,0 +1,3 @@ +node_modules/ +node_modules/* +npm-debug.log \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/CHANGELOG.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/CHANGELOG.md new file mode 100644 index 0000000..1effdd2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/CHANGELOG.md @@ -0,0 +1,15 @@ +#VERSION HISTORY + +##2.0 +* [Breaking] Refactored this to work in node.js. Backwards compatibility to existing browser API coming in future 2.x releases. (indexzero) + +## 1.2 +* Added TimeSpan.FromDates Constructor to take two dates + and create a TimeSpan from the difference. (mstum) + +## 1.1 +* Changed naming to follow JavaScript standards (mstum) +* Added Documentation (mstum) + +## 1.0 +* Initial Revision (mstum) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/LICENSE new file mode 100644 index 0000000..071d8fb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Michael Stum, Charlie Robbins + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/README.md new file mode 100644 index 0000000..2bb9904 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/README.md @@ -0,0 +1,199 @@ +# timespan + +A simple implementation of TimeSpans in Javascript. + +## Installation in node.js + +### Installing npm (node package manager) +``` bash + $ curl http://npmjs.org/install.sh | sh +``` + +### Installing timespan +``` bash + [sudo] npm install timespan +``` + +## Usage +You 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. + +### Using the new constructor + +``` js + var timespan = require('timespan'); + var ts = new timespan.TimeSpan(); +``` + +The 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`. + +``` js + // + // Initializes the TimeSpan to 4 Minutes, 16 Seconds and 0 Milliseconds. + // + var ts = new TimeSpan(0,16,4) + + // + // Initializes the TimeSpan to 3 hours, 4 minutes, 10 seconds and 0 msecs. + // + var ts = new TimeSpan(0,10,64,2); +``` + +### Using Construction Helper Method(s) +You can initialize a new TimeSpan by calling one of these Functions: + +``` js + timespan.FromSeconds(/* seconds */); + timespan.FromMinutes(/* minutes */); + timespan.FromHours(/* hours */); + timespan.FromDays(/* hours */); + + // + // This behaves differently, see below + // + timespan.FromDates(start, end); +``` + +The 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. + +`timespan.FromDates()` is different as it takes two dates. The TimeSpan will be the difference between these dates. + +If 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. + +``` js + var date1 = new Date(2010, 3, 1, 10, 10, 5, 0); + var date2 = new Date(2010, 3, 1, 10, 10, 10, 0); + var ts = TimeSpan.FromDates(date2, date1); + var ts2 = TimeSpan.FromDates(date2, date1, true); + + // + // -5, because we put the later date first + // + console.log(ts.totalSeconds()); + + // + // 5, because we passed true as third parameter + // + console.log(ts2.totalSeconds()); +``` + + +### Adding / Subtracting TimeSpans +There are several functions to add or subtract time: + +``` js + ts.addMilliseconds() + ts.addSeconds() + ts.addMinutes() + ts.addHours() + ts.addDays() + ts.subtractMilliseconds() + ts.subtractSeconds() + ts.subtractMinutes() + ts.subtractHours() + ts.subtractDays() +``` + +All 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. + +``` js + var ts = new TimeSpan(); + ts.addSeconds(30); + ts.addMinutes(2); + ts.subtractSeconds(60); + + // + // ts will now be a timespan of 1 minute and 30 seconds + // +``` + +The parameter can be negative to negate the operation `ts.addSeconds(-30)` is equivalent to `ts.subtractSeconds(30)`. + +### Interacting with Other TimeSpan instances +These are the functions that interact with another TimeSpan: + +``` js + ts.add() + ts.subtract() + ts.equals() +``` + +add and subtract add/subtract the other TimeSpan to the current one: + +``` js + var ts = TimeSpan.FromSeconds(30); + var ts2 = TimeSpan.FromMinutes(2); + ts.add(ts2); + + // + // ts is now a TimeSpan of 2 Minutes, 30 Seconds + // ts2 is unchanged + // +``` + +equals checks if two TimeSpans have the same time: + +``` js + var ts = TimeSpan.FromSeconds(30); + var ts2 = TimeSpan.FromSeconds(30); + var eq = ts.equals(ts2); // true + ts2.addSeconds(1); + var eq2 = ts.equals(ts2); // false +``` + +### Retrieving the Value of a TimeSpan +There 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. + +#### Retrieve the full value + +``` js + ts.totalMilliseconds() + ts.totalSeconds() + ts.totalMinutes() + ts.totalHours() + ts.totalDays() +``` + +These 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. + +``` js + var ts = TimeSpan.fromSeconds(90); + console.log(ts.totalMilliseconds()); // 90000 + console.log(ts.totalSeconds()); // 90 + console.log(ts.totalMinutes()); // 1.5 + console.log(ts.totalMinutes(true)); // 1 +``` + +#### Retrieve a component of the TimeSpan + +``` js + ts.milliseconds + ts.seconds + ts.minutes + ts.hours + ts.days +``` + +These functions return a component of the TimeSpan that could be used to represent a clock. + +``` js + var ts = TimeSpan.FromSeconds(90); + console.log(ts.seconds()); // 30 + console.log(ts.minutes()); // 1 +``` + +Basically 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: + +``` js + var ts = TimeSpan.FromDays(2); + ts.addHours(12); + console.log(ts.days()); // 2 + console.log(ts.hours()); // 12 +``` + +## Remark about Backwards Compatibility +Version 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`. + +#### Author: [Michael Stum](http://www.stum.de) +#### Contributors: [Charlie Robbins](http://github.com/indexzero) + +[0]: http://nodejs.org \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.js new file mode 100644 index 0000000..bc8149d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.js @@ -0,0 +1,226 @@ +/*! +* JavaScript TimeSpan Library +* +* Copyright (c) 2010 Michael Stum, http://www.Stum.de/ +* +* 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. +*/ + +/*global window: false */ +"use strict"; +(function () { + // Constructor function, all parameters are optional + var TimeSpan = window.TimeSpan = function (milliseconds, seconds, minutes, hours, days) { + var version = "1.2", + // Millisecond-constants + msecPerSecond = 1000, + msecPerMinute = 60000, + msecPerHour = 3600000, + msecPerDay = 86400000, + // Internally we store the TimeSpan as Milliseconds + msecs = 0, + + // Helper functions + isNumeric = function (input) { + return !isNaN(parseFloat(input)) && isFinite(input); + }; + + // Constructor Logic + if (isNumeric(days)) { + msecs += (days * msecPerDay); + } + if (isNumeric(hours)) { + msecs += (hours * msecPerHour); + } + if (isNumeric(minutes)) { + msecs += (minutes * msecPerMinute); + } + if (isNumeric(seconds)) { + msecs += (seconds * msecPerSecond); + } + if (isNumeric(milliseconds)) { + msecs += milliseconds; + } + + // Addition Functions + this.addMilliseconds = function (milliseconds) { + if (!isNumeric(milliseconds)) { + return; + } + msecs += milliseconds; + }; + this.addSeconds = function (seconds) { + if (!isNumeric(seconds)) { + return; + } + msecs += (seconds * msecPerSecond); + }; + this.addMinutes = function (minutes) { + if (!isNumeric(minutes)) { + return; + } + msecs += (minutes * msecPerMinute); + }; + this.addHours = function (hours) { + if (!isNumeric(hours)) { + return; + } + msecs += (hours * msecPerHour); + }; + this.addDays = function (days) { + if (!isNumeric(days)) { + return; + } + msecs += (days * msecPerDay); + }; + + // Subtraction Functions + this.subtractMilliseconds = function (milliseconds) { + if (!isNumeric(milliseconds)) { + return; + } + msecs -= milliseconds; + }; + this.subtractSeconds = function (seconds) { + if (!isNumeric(seconds)) { + return; + } + msecs -= (seconds * msecPerSecond); + }; + this.subtractMinutes = function (minutes) { + if (!isNumeric(minutes)) { + return; + } + msecs -= (minutes * msecPerMinute); + }; + this.subtractHours = function (hours) { + if (!isNumeric(hours)) { + return; + } + msecs -= (hours * msecPerHour); + }; + this.subtractDays = function (days) { + if (!isNumeric(days)) { + return; + } + msecs -= (days * msecPerDay); + }; + + // Functions to interact with other TimeSpans + this.isTimeSpan = true; + this.add = function (otherTimeSpan) { + if (!otherTimeSpan.isTimeSpan) { + return; + } + msecs += otherTimeSpan.totalMilliseconds(); + }; + this.subtract = function (otherTimeSpan) { + if (!otherTimeSpan.isTimeSpan) { + return; + } + msecs -= otherTimeSpan.totalMilliseconds(); + }; + this.equals = function (otherTimeSpan) { + if (!otherTimeSpan.isTimeSpan) { + return; + } + return msecs === otherTimeSpan.totalMilliseconds(); + }; + + // Getters + this.totalMilliseconds = function (roundDown) { + var result = msecs; + if (roundDown === true) { + result = Math.floor(result); + } + return result; + }; + this.totalSeconds = function (roundDown) { + var result = msecs / msecPerSecond; + if (roundDown === true) { + result = Math.floor(result); + } + return result; + }; + this.totalMinutes = function (roundDown) { + var result = msecs / msecPerMinute; + if (roundDown === true) { + result = Math.floor(result); + } + return result; + }; + this.totalHours = function (roundDown) { + var result = msecs / msecPerHour; + if (roundDown === true) { + result = Math.floor(result); + } + return result; + }; + this.totalDays = function (roundDown) { + var result = msecs / msecPerDay; + if (roundDown === true) { + result = Math.floor(result); + } + return result; + }; + // Return a Fraction of the TimeSpan + this.milliseconds = function () { + return msecs % 1000; + }; + this.seconds = function () { + return Math.floor(msecs / msecPerSecond) % 60; + }; + this.minutes = function () { + return Math.floor(msecs / msecPerMinute) % 60; + }; + this.hours = function () { + return Math.floor(msecs / msecPerHour) % 24; + }; + this.days = function () { + return Math.floor(msecs / msecPerDay); + }; + + // Misc. Functions + this.getVersion = function () { + return version; + }; + }; + + // "Static Constructors" + TimeSpan.FromSeconds = function (seconds) { + return new TimeSpan(0, seconds, 0, 0, 0); + }; + TimeSpan.FromMinutes = function (minutes) { + return new TimeSpan(0, 0, minutes, 0, 0); + }; + TimeSpan.FromHours = function (hours) { + return new TimeSpan(0, 0, 0, hours, 0); + }; + TimeSpan.FromDays = function (days) { + return new TimeSpan(0, 0, 0, 0, days); + }; + TimeSpan.FromDates = function (firstDate, secondDate, forcePositive) { + var differenceMsecs = secondDate.valueOf() - firstDate.valueOf(); + if(forcePositive === true) { + differenceMsecs = Math.abs(differenceMsecs); + } + return new TimeSpan(differenceMsecs, 0, 0, 0, 0); + }; +}()); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.min.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.min.js new file mode 100644 index 0000000..0326cbb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/browser/TimeSpan-1.2.min.js @@ -0,0 +1 @@ +"use strict";(function(){var a=window.TimeSpan=function(g,i,h,j,k){var l="1.2",d=1e3,c=6e4,e=3.6e6,f=8.64e7,a=0,b=function(a){return !isNaN(parseFloat(a))&&isFinite(a)};if(b(k))a+=k*f;if(b(j))a+=j*e;if(b(h))a+=h*c;if(b(i))a+=i*d;if(b(g))a+=g;this.addMilliseconds=function(c){if(!b(c))return;a+=c};this.addSeconds=function(c){if(!b(c))return;a+=c*d};this.addMinutes=function(d){if(!b(d))return;a+=d*c};this.addHours=function(c){if(!b(c))return;a+=c*e};this.addDays=function(c){if(!b(c))return;a+=c*f};this.subtractMilliseconds=function(c){if(!b(c))return;a-=c};this.subtractSeconds=function(c){if(!b(c))return;a-=c*d};this.subtractMinutes=function(d){if(!b(d))return;a-=d*c};this.subtractHours=function(c){if(!b(c))return;a-=c*e};this.subtractDays=function(c){if(!b(c))return;a-=c*f};this.isTimeSpan=true;this.add=function(b){if(!b.isTimeSpan)return;a+=b.totalMilliseconds()};this.subtract=function(b){if(!b.isTimeSpan)return;a-=b.totalMilliseconds()};this.equals=function(b){if(!b.isTimeSpan)return;return a===b.totalMilliseconds()};this.totalMilliseconds=function(c){var b=a;if(c===true)b=Math.floor(b);return b};this.totalSeconds=function(c){var b=a/d;if(c===true)b=Math.floor(b);return b};this.totalMinutes=function(d){var b=a/c;if(d===true)b=Math.floor(b);return b};this.totalHours=function(c){var b=a/e;if(c===true)b=Math.floor(b);return b};this.totalDays=function(c){var b=a/f;if(c===true)b=Math.floor(b);return b};this.milliseconds=function(){return a%1e3};this.seconds=function(){return Math.floor(a/d)%60};this.minutes=function(){return Math.floor(a/c)%60};this.hours=function(){return Math.floor(a/e)%24};this.days=function(){return Math.floor(a/f)};this.getVersion=function(){return l}};a.FromSeconds=function(b){return new a(0,b,0,0,0)};a.FromMinutes=function(b){return new a(0,0,b,0,0)};a.FromHours=function(b){return new a(0,0,0,b,0)};a.FromDays=function(b){return new a(0,0,0,0,b)};a.FromDates=function(e,d,c){var b=d.valueOf()-e.valueOf();if(c===true)b=Math.abs(b);return new a(b,0,0,0,0)}})() \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/docco.css b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/docco.css new file mode 100644 index 0000000..bd54134 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/docco.css @@ -0,0 +1,194 @@ +/*--------------------- Layout and Typography ----------------------------*/ +body { + font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; + font-size: 15px; + line-height: 22px; + color: #252519; + margin: 0; padding: 0; +} +a { + color: #261a3b; +} + a:visited { + color: #261a3b; + } +p { + margin: 0 0 15px 0; +} +h4, h5, h6 { + color: #333; + margin: 6px 0 6px 0; + font-size: 13px; +} + h2, h3 { + margin-bottom: 0; + color: #000; + } + h1 { + margin-top: 40px; + margin-bottom: 15px; + color: #000; + } +#container { + position: relative; +} +#background { + position: fixed; + top: 0; left: 525px; right: 0; bottom: 0; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + z-index: -1; +} +#jump_to, #jump_page { + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 10px Arial; + text-transform: uppercase; + cursor: pointer; + text-align: right; +} +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 5px 10px; +} + #jump_wrapper { + padding: 0; + display: none; + } + #jump_to:hover #jump_wrapper { + display: block; + } + #jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; + } + #jump_page .source { + display: block; + padding: 5px 10px; + text-decoration: none; + border-top: 1px solid #eee; + } + #jump_page .source:hover { + background: #f5f5ff; + } + #jump_page .source:first-child { + } +table td { + border: 0; + outline: 0; +} + td.docs, th.docs { + max-width: 450px; + min-width: 450px; + min-height: 5px; + padding: 10px 25px 1px 50px; + overflow-x: hidden; + vertical-align: top; + text-align: left; + } + .docs pre { + margin: 15px 0 15px; + padding-left: 15px; + } + .docs p tt, .docs p code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } + .pilwrap { + position: relative; + } + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + td.docs:hover .pilcrow { + opacity: 1; + } + td.code, th.code { + padding: 14px 15px 16px 25px; + width: 100%; + vertical-align: top; + background: #f5f5ff; + border-left: 1px solid #e5e5ee; + } + pre, tt, code { + font-size: 12px; line-height: 18px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; + } + + +/*---------------------- Syntax Highlighting -----------------------------*/ +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +body .hll { background-color: #ffffcc } +body .c { color: #408080; font-style: italic } /* Comment */ +body .err { border: 1px solid #FF0000 } /* Error */ +body .k { color: #954121 } /* Keyword */ +body .o { color: #666666 } /* Operator */ +body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +body .cp { color: #BC7A00 } /* Comment.Preproc */ +body .c1 { color: #408080; font-style: italic } /* Comment.Single */ +body .cs { color: #408080; font-style: italic } /* Comment.Special */ +body .gd { color: #A00000 } /* Generic.Deleted */ +body .ge { font-style: italic } /* Generic.Emph */ +body .gr { color: #FF0000 } /* Generic.Error */ +body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body .gi { color: #00A000 } /* Generic.Inserted */ +body .go { color: #808080 } /* Generic.Output */ +body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +body .gs { font-weight: bold } /* Generic.Strong */ +body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body .gt { color: #0040D0 } /* Generic.Traceback */ +body .kc { color: #954121 } /* Keyword.Constant */ +body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ +body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ +body .kp { color: #954121 } /* Keyword.Pseudo */ +body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ +body .kt { color: #B00040 } /* Keyword.Type */ +body .m { color: #666666 } /* Literal.Number */ +body .s { color: #219161 } /* Literal.String */ +body .na { color: #7D9029 } /* Name.Attribute */ +body .nb { color: #954121 } /* Name.Builtin */ +body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +body .no { color: #880000 } /* Name.Constant */ +body .nd { color: #AA22FF } /* Name.Decorator */ +body .ni { color: #999999; font-weight: bold } /* Name.Entity */ +body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +body .nf { color: #0000FF } /* Name.Function */ +body .nl { color: #A0A000 } /* Name.Label */ +body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +body .nt { color: #954121; font-weight: bold } /* Name.Tag */ +body .nv { color: #19469D } /* Name.Variable */ +body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +body .w { color: #bbbbbb } /* Text.Whitespace */ +body .mf { color: #666666 } /* Literal.Number.Float */ +body .mh { color: #666666 } /* Literal.Number.Hex */ +body .mi { color: #666666 } /* Literal.Number.Integer */ +body .mo { color: #666666 } /* Literal.Number.Oct */ +body .sb { color: #219161 } /* Literal.String.Backtick */ +body .sc { color: #219161 } /* Literal.String.Char */ +body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ +body .s2 { color: #219161 } /* Literal.String.Double */ +body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +body .sh { color: #219161 } /* Literal.String.Heredoc */ +body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +body .sx { color: #954121 } /* Literal.String.Other */ +body .sr { color: #BB6688 } /* Literal.String.Regex */ +body .s1 { color: #219161 } /* Literal.String.Single */ +body .ss { color: #19469D } /* Literal.String.Symbol */ +body .bp { color: #954121 } /* Name.Builtin.Pseudo */ +body .vc { color: #19469D } /* Name.Variable.Class */ +body .vg { color: #19469D } /* Name.Variable.Global */ +body .vi { color: #19469D } /* Name.Variable.Instance */ +body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/time-span.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/time-span.html new file mode 100644 index 0000000..9eb2cc9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/docs/time-span.html @@ -0,0 +1,692 @@ + time-span.js

    time-span.js

    /*
    +* JavaScript TimeSpan Library
    +*
    +* Copyright (c) 2010 Michael Stum, Charlie Robbins
    +* 
    +* 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.
    +*/

    Time constants

    var msecPerSecond = 1000,
    +    msecPerMinute = 60000,
    +    msecPerHour = 3600000,
    +    msecPerDay = 86400000;

    Timespan Parsers

    var timeSpanWithDays = /^(\d+):(\d+):(\d+):(\d+)(\.\d+)?/,
    +    timeSpanNoDays = /^(\d+):(\d+):(\d+)(\.\d+)?/;

    function TimeSpan (milliseconds, seconds, minutes, hours, days)

    + +

    @milliseconds {Number} Number of milliseconds for this instance.

    + +

    @seconds {Number} Number of seconds for this instance.

    + +

    @minutes {Number} Number of minutes for this instance.

    + +

    @hours {Number} Number of hours for this instance.

    + +

    @days {Number} Number of days for this instance.

    + +

    Constructor function for the TimeSpan object which represents a length +of positive or negative milliseconds componentized into milliseconds, +seconds, hours, and days.

    var TimeSpan = exports.TimeSpan = function (milliseconds, seconds, minutes, hours, days) {
    +  this.msecs = 0;
    +  
    +  if (isNumeric(days)) {
    +    this.msecs += (days * msecPerDay);
    +  }
    +  
    +  if (isNumeric(hours)) {
    +    this.msecs += (hours * msecPerHour);
    +  }
    +  
    +  if (isNumeric(minutes)) {
    +    this.msecs += (minutes * msecPerMinute);
    +  }
    +  
    +  if (isNumeric(seconds)) {
    +    this.msecs += (seconds * msecPerSecond);
    +  }
    +  
    +  if (isNumeric(milliseconds)) {
    +    this.msecs += milliseconds;
    +  }
    +};

    Factory methods

    + +

    Helper methods for creating new TimeSpan objects +from various criteria: milliseconds, seconds, minutes, +hours, days, strings and other TimeSpan instances.

    function fromMilliseconds (milliseconds)

    + +

    @milliseconds {Number} Amount of milliseconds for the new TimeSpan instance.

    + +

    Creates a new TimeSpan instance with the specified milliseconds.

    exports.fromMilliseconds = function (milliseconds) {
    +  if (!isNumeric(milliseconds)) {
    +    return;
    +  }
    +  
    +  return new TimeSpan(milliseconds, 0, 0, 0, 0);
    +}

    function fromSeconds (seconds)

    + +

    @milliseconds {Number} Amount of seconds for the new TimeSpan instance.

    + +

    Creates a new TimeSpan instance with the specified seconds.

    exports.fromSeconds = function (seconds) {
    +  if (!isNumeric(seconds)) {
    +    return;
    +  }
    +  
    +  return new TimeSpan(0, seconds, 0, 0, 0);
    +};

    function fromMinutes (milliseconds)

    + +

    @milliseconds {Number} Amount of minutes for the new TimeSpan instance.

    + +

    Creates a new TimeSpan instance with the specified minutes.

    exports.fromMinutes = function (minutes) {
    +  if (!isNumeric(minutes)) {
    +    return;
    +  }
    +  
    +  return new TimeSpan(0, 0, minutes, 0, 0);
    +};

    function fromHours (hours)

    + +

    @milliseconds {Number} Amount of hours for the new TimeSpan instance.

    + +

    Creates a new TimeSpan instance with the specified hours.

    exports.fromHours = function (hours) {
    +  if (!isNumeric(hours)) {
    +    return;
    +  }
    +  
    +  return new TimeSpan(0, 0, 0, hours, 0);
    +};

    function fromDays (days)

    + +

    @milliseconds {Number} Amount of days for the new TimeSpan instance.

    + +

    Creates a new TimeSpan instance with the specified days.

    exports.fromDays = function (days) {
    +  if (!isNumeric(days)) {
    +    return;
    +  }
    +  
    +  return new TimeSpan(0, 0, 0, 0, days);
    +};

    function parse (str)

    + +

    @str {string} Timespan string to parse.

    + +

    Creates a new TimeSpan instance from the specified +string, str.

    exports.parse = function (str) {
    +  var match, milliseconds;
    +  
    +  function parseMilliseconds (value) {
    +    return value ? parseFloat('0' + value) * 1000 : 0;
    +  }
    +  

    If we match against a full TimeSpan:

      if ((match = str.match(timeSpanWithDays))) {
    +    return new TimeSpan(parseMilliseconds(match[5]), match[4], match[3], match[2], match[1]);
    +  }
    +  

    If we match against a partial TimeSpan:

      if ((match = str.match(timeSpanNoDays))) {
    +    return new TimeSpan(parseMilliseconds(match[4]), match[3], match[2], match[1], 0);
    +  }
    +  
    +  return null;
    +};
    +
    +var months  = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    List of default singular time modifiers and associated +computation algoritm. Assumes in order, smallest to greatest +performing carry forward additiona / subtraction for each +Date-Time component.

    var parsers = {
    +  'milliseconds': {
    +    exp: /(\d+)milli[second]?[s]?/i,
    +    get: function (date) { return date.getMilliseconds(date) },
    +    set: function (val, date) { date.setMilliseconds(val) },
    +    compute: function (delta, date, computed) {
    +      var round = delta > 0 ? Math.floor : Math.ceil;
    +      if (delta) {
    +        computed.seconds += round.call(null, delta / 1000);
    +        computed.milliseconds += delta % 1000;
    +      }
    +      
    +      if (Math.abs(computed.milliseconds) >= 1000) {
    +        computed.seconds += round.call(null, computed.milliseconds / 1000)
    +        computed.milliseconds = computed.milliseconds % 1000;
    +      }
    +
    +      return computed;
    +    }
    +  },
    +  'seconds': {
    +    exp: /(\d+)second[s]?/i,
    +    get: function (date) { return date.getSeconds(date) },
    +    set: function (val, date) { date.setSeconds(val) },
    +    compute: function (delta, date, computed) {
    +      var round = delta > 0 ? Math.floor : Math.ceil;
    +      if (delta) {
    +        computed.minutes += round.call(null, delta / 60);
    +        computed.seconds += delta % 60;
    +      }
    +      
    +      if (Math.abs(computed.seconds) >= 60) {
    +        computed.minutes += round.call(null, computed.seconds / 60);
    +        computed.seconds = computed.seconds % 60; 
    +      }
    +      
    +      return computed;
    +    }
    +  },
    +  'minutes': {
    +    exp: /(\d+)minute[s]?/i,
    +    get: function (date) { return date.getMinutes(date) },
    +    set: function (val, date) { date.setMinutes(val) },
    +    compute: function (delta, date, computed) {
    +      var round = delta > 0 ? Math.floor : Math.ceil;
    +      if (delta) { 
    +        computed.hours += round.call(null, delta / 60);
    +        computed.minutes += delta % 60;
    +      }
    +      
    +      if (Math.abs(computed.minutes) >= 60) {
    +        computed.hours += round.call(null, computed.minutes / 60);
    +        computed.minutes = computed.minutes % 60; 
    +      }
    +      
    +      return computed;
    +    }
    +  },
    +  'hours': {
    +    exp: /(\d+)hour[s]?/i,
    +    get: function (date) { return date.getHours(date) },
    +    set: function (val, date) { date.setHours(val) },
    +    compute: function (delta, date, computed) {
    +      var round = delta > 0 ? Math.floor : Math.ceil;
    +      if (delta) { 
    +        computed.days += round.call(null, delta / 24);
    +        computed.hours += delta % 24;
    +      }
    +      
    +      if (Math.abs(computed.hours) >= 24) {
    +        computed.days += round.call(null, computed.hours / 24);
    +        computed.hours = computed.hours % 24;
    +      }
    +      
    +      return computed;
    +    }
    +  },
    +  'days': {
    +    exp: /(\d+)day[s]?/i,
    +    get: function (date) { return date.getDate(date) },
    +    set: function (val, date) { date.setDate(val) },
    +    compute: function (delta, date, computed) {
    +      var sign     = delta >= 0 ? 1 : -1,
    +          opsign   = delta >= 0 ? -1 : 1,
    +          clean    = 0,
    +          original = delta,
    +          month    = computed.months,
    +          days     = months[month];
    +      
    +      if (delta) {          
    +        while (Math.abs(delta) >= days) {
    +          month += sign * 1;
    +          computed.months += sign * 1;
    +          delta += opsign * days;
    +        
    +          if (month < 0) { month = 11 }
    +          else if (month > 11) { month = 0 }
    +        
    +          days = months[month];
    +        }
    +      
    +        computed.days += (sign * delta);
    +      }
    +      
    +      if (computed.days < 0) {
    +        clean = -1;
    +      }
    +      else if (computed.days > months[computed.months]) {
    +        clean = 1;
    +      }
    +      
    +      if (clean !== 0) {
    +        computed.months += clean;
    +        if (computed.months < 0) { computed.months = 11 }
    +        else if (computed.months > 11) { computed.months = 0 }
    +        computed.days = months[computed.months] + computed.days;
    +      }
    +            
    +      return computed;
    +    }
    +  },
    +  'months': {
    +    exp: /(\d+)month[s]?/i,
    +    get: function (date) { return date.getMonth(date) },
    +    set: function (val, date) { date.setMonth(val) },
    +    compute: function (delta, date, computed) {
    +      var round = delta > 0 ? Math.floor : Math.ceil;
    +      if (delta) { 
    +        computed.years += round.call(null, delta / 12);
    +        computed.months += delta % 12;
    +      }
    +      
    +      if (computed.months > 11) {
    +        computed.years += Math.floor((computed.months + 1) / 12);
    +        computed.months = ((computed.months + 1) % 12) - 1;
    +      }
    +      
    +      return computed;
    +    }
    +  },
    +  'years': {
    +    exp: /(\d+)year[s]?/i,
    +    get: function (date) { return date.getFullYear(date) },
    +    set: function (val, date) { date.setFullYear(val) },
    +    compute: function (delta, date, computed) {
    +      if (delta) { 
    +        computed.years += delta;
    +      }
    +      
    +      return computed;
    +    }
    +  }
    +};

    Compute the list of parser names for +later use.

    var parserNames = Object.keys(parsers);

    function parseDate (str)

    + +

    @str {string} String to parse into a date

    + +

    Parses the specified liberal Date-Time string according to +ISO8601 and:

    + +
      +
    1. 2010-04-03T12:34:15Z+12MINUTES
    2. +
    3. NOW-4HOURS
    4. +
    + +

    Valid modifiers for the more liberal Date-Time string(s):

    + +
    YEAR, YEARS
    +MONTH, MONTHS
    +DAY, DAYS
    +HOUR, HOURS
    +MINUTE, MINUTES
    +SECOND, SECONDS
    +MILLI, MILLIS, MILLISECOND, MILLISECONDS
    +
    exports.parseDate = function (str) {
    +  var simple = Date.parse(str),
    +      iso = '^([^Z]+)',
    +      zulu = 'Z([\\+|\\-])?',
    +      diff = {},
    +      base,
    +      sign,
    +      complex,
    +      inspect,
    +      dateTime,
    +      modifiers;
    +
    +  if (/now/i.test(str)) {
    +    iso = '^(NOW)';
    +    zulu = zulu.replace(/Z/, 'NOW');
    +  }

    If Date string supplied actually conforms +to UTC Time (ISO8601), return a new Date.

      if (!isNaN(simple)) {
    +    return new Date(simple);
    +  }
    +  

    Create the RegExp for the end component +of the target str to parse.

      parserNames.forEach(function (group) {
    +    zulu += '(\\d+[a-zA-Z]+)?';
    +  });
    +  

    Parse the ISO8601 component, and the end +component from the target str.

      dateTime = str.match(new RegExp(iso, 'i'));
    +  modifiers = str.match(new RegExp(zulu, 'i'));
    +  

    If there was no match on either part then +it must be a bad value.

      if (!dateTime || !modifiers) {
    +    return null;
    +  }
    +    

    Create a new Date object from the ISO8601 +component of the target str.

      base = /now/i.test(dateTime[1]) ? Date.now() : Date.parse(dateTime[1]);
    +  complex = new Date(base);
    +  sign = modifiers[1] === '+' ? 1 : -1;
    +  

    Parse the individual component spans (months, years, etc) +from the modifier strings that we parsed from the end +of the target str.

      modifiers.slice(2).filter(Boolean).forEach(function (modifier) {
    +    parserNames.forEach(function (name) {
    +      var match;
    +      if (!(match = modifier.match(parsers[name].exp))) {
    +        return;
    +      }
    +      
    +      diff[name] = sign * parseInt(match[1], 10);
    +    })
    +  });
    +  

    Compute the total diff by iteratively computing +the partial components from smallest to largest.

      var computed = {
    +    milliseconds: complex.getMilliseconds(),
    +    seconds: complex.getSeconds(),
    +    minutes: complex.getMinutes(),
    +    hours: complex.getHours(),
    +    days: complex.getDate(),
    +    months: complex.getMonth(),
    +    years: complex.getFullYear()
    +  };
    +  
    +  parserNames.forEach(function (name) {    
    +    computed = parsers[name].compute(diff[name], complex, computed);
    +  });
    +  
    +  return new Date(
    +    Date.UTC(
    +      computed.years,
    +      computed.months,
    +      computed.days,
    +      computed.hours,
    +      computed.minutes,
    +      computed.seconds,
    +      computed.milliseconds
    +    )
    +  );
    +};

    function fromDates (start, end, abs)

    + +

    @start {Date} Start date of the TimeSpan instance to return

    + +

    @end {Date} End date of the TimeSpan instance to return

    + +

    @abs {boolean} Value indicating to return an absolute value

    + +

    Returns a new TimeSpan instance representing the difference between +the start and end Dates.

    exports.fromDates = function (start, end, abs) {
    +  if (!start instanceof Date) {
    +    start = exports.parseDate(start);
    +  }
    +  
    +  if (!end instanceof Date) {
    +    end = exports.parseDate(end);
    +  }
    +  
    +  var differenceMsecs = end.valueOf() - start.valueOf();
    +  if (abs) {
    +    differenceMsecs = Math.abs(differenceMsecs);
    +  }
    +
    +  return new TimeSpan(differenceMsecs, 0, 0, 0, 0);
    +};

    Module Helpers

    + +

    Module-level helpers for various utilities such as: +instanceOf, parsability, and cloning.

    function test (str)

    + +

    @str {string} String value to test if it is a TimeSpan

    + +

    Returns a value indicating if the specified string, str, +is a parsable TimeSpan value.

    exports.test = function (str) {
    +  return timeSpanWithDays.test(str) || timeSpanNoDays.test(str);
    +};

    function instanceOf (timeSpan)

    + +

    @timeSpan {Object} Object to check TimeSpan quality.

    + +

    Returns a value indicating if the specified timeSpan is +in fact a TimeSpan instance.

    exports.instanceOf = function (timeSpan) {
    +  return timeSpan instanceof TimeSpan;
    +};

    function clone (timeSpan)

    + +

    @timeSpan {TimeSpan} TimeSpan object to clone.

    + +

    Returns a new TimeSpan instance with the same value +as the timeSpan object supplied.

    exports.clone = function (timeSpan) {
    +  if (!(timeSpan instanceof TimeSpan)) {
    +    return;
    +  }
    +  
    +  return exports.fromMilliseconds(timeSpan.totalMilliseconds());
    +};

    Addition

    + +

    Methods for adding TimeSpan instances, +milliseconds, seconds, hours, and days to other +TimeSpan instances.

    function add (timeSpan)

    + +

    @timeSpan {TimeSpan} TimeSpan to add to this instance

    + +

    Adds the specified timeSpan to this instance.

    TimeSpan.prototype.add = function (timeSpan) {
    +  if (!(timeSpan instanceof TimeSpan)) {
    +    return;
    +  }
    +  
    +  this.msecs += timeSpan.totalMilliseconds();
    +};

    function addMilliseconds (milliseconds)

    + +

    @milliseconds {Number} Number of milliseconds to add.

    + +

    Adds the specified milliseconds to this instance.

    TimeSpan.prototype.addMilliseconds = function (milliseconds) {
    +  if (!isNumeric(milliseconds)) {
    +    return;
    +  }
    +  
    +  this.msecs += milliseconds;
    +};

    function addSeconds (seconds)

    + +

    @seconds {Number} Number of seconds to add.

    + +

    Adds the specified seconds to this instance.

    TimeSpan.prototype.addSeconds = function (seconds) {
    +  if (!isNumeric(seconds)) {
    +    return;
    +  }
    +  
    +  this.msecs += (seconds * msecPerSecond);
    +};

    function addMinutes (minutes)

    + +

    @minutes {Number} Number of minutes to add.

    + +

    Adds the specified minutes to this instance.

    TimeSpan.prototype.addMinutes = function (minutes) {
    +  if (!isNumeric(minutes)) {
    +    return;
    +  }
    +  
    +  this.msecs += (minutes * msecPerMinute);
    +};

    function addHours (hours)

    + +

    @hours {Number} Number of hours to add.

    + +

    Adds the specified hours to this instance.

    TimeSpan.prototype.addHours = function (hours) {
    +  if (!isNumeric(hours)) {
    +    return;
    +  }
    +  
    +  this.msecs += (hours * msecPerHour);
    +};

    function addDays (days)

    + +

    @days {Number} Number of days to add.

    + +

    Adds the specified days to this instance.

    TimeSpan.prototype.addDays = function (days) {
    +  if (!isNumeric(days)) {
    +    return;
    +  }
    +  
    +  this.msecs += (days * msecPerDay);
    +};

    Subtraction

    + +

    Methods for subtracting TimeSpan instances, +milliseconds, seconds, hours, and days from other +TimeSpan instances.

    function subtract (timeSpan)

    + +

    @timeSpan {TimeSpan} TimeSpan to subtract from this instance.

    + +

    Subtracts the specified timeSpan from this instance.

    TimeSpan.prototype.subtract = function (timeSpan) {
    +  if (!(timeSpan instanceof TimeSpan)) {
    +    return;
    +  }
    +  
    +  this.msecs -= timeSpan.totalMilliseconds();
    +};

    function subtractMilliseconds (milliseconds)

    + +

    @milliseconds {Number} Number of milliseconds to subtract.

    + +

    Subtracts the specified milliseconds from this instance.

    TimeSpan.prototype.subtractMilliseconds = function (milliseconds) {
    +  if (!isNumeric(milliseconds)) {
    +    return;
    +  }
    +  
    +  this.msecs -= milliseconds;
    +};

    function subtractSeconds (seconds)

    + +

    @seconds {Number} Number of seconds to subtract.

    + +

    Subtracts the specified seconds from this instance.

    TimeSpan.prototype.subtractSeconds = function (seconds) {
    +  if (!isNumeric(seconds)) {
    +    return;
    +  }
    +  
    +  this.msecs -= (seconds * msecPerSecond);
    +};

    function subtractMinutes (minutes)

    + +

    @minutes {Number} Number of minutes to subtract.

    + +

    Subtracts the specified minutes from this instance.

    TimeSpan.prototype.subtractMinutes = function (minutes) {
    +  if (!isNumeric(minutes)) {
    +    return;
    +  }
    +  
    +  this.msecs -= (minutes * msecPerMinute);
    +};

    function subtractHours (hours)

    + +

    @hours {Number} Number of hours to subtract.

    + +

    Subtracts the specified hours from this instance.

    TimeSpan.prototype.subtractHours = function (hours) {
    +  if (!isNumeric(hours)) {
    +    return;
    +  }
    +  
    +  this.msecs -= (hours * msecPerHour);
    +};

    function subtractDays (days)

    + +

    @days {Number} Number of days to subtract.

    + +

    Subtracts the specified days from this instance.

    TimeSpan.prototype.subtractDays = function (days) {
    +  if (!isNumeric(days)) {
    +    return;
    +  }
    +  
    +  this.msecs -= (days * msecPerDay);
    +};

    Getters

    + +

    Methods for retrieving components of a TimeSpan +instance: milliseconds, seconds, minutes, hours, and days.

    function totalMilliseconds (roundDown)

    + +

    @roundDown {boolean} Value indicating if the value should be rounded down.

    + +

    Returns the total number of milliseconds for this instance, rounding down +to the nearest integer if roundDown is set.

    TimeSpan.prototype.totalMilliseconds = function (roundDown) {
    +  var result = this.msecs;
    +  if (roundDown === true) {
    +    result = Math.floor(result);
    +  }
    +  
    +  return result;
    +};

    function totalSeconds (roundDown)

    + +

    @roundDown {boolean} Value indicating if the value should be rounded down.

    + +

    Returns the total number of seconds for this instance, rounding down +to the nearest integer if roundDown is set.

    TimeSpan.prototype.totalSeconds = function (roundDown) {
    +  var result = this.msecs / msecPerSecond;
    +  if (roundDown === true) {
    +    result = Math.floor(result);
    +  }
    +  
    +  return result;
    +};

    function totalMinutes (roundDown)

    + +

    @roundDown {boolean} Value indicating if the value should be rounded down.

    + +

    Returns the total number of minutes for this instance, rounding down +to the nearest integer if roundDown is set.

    TimeSpan.prototype.totalMinutes = function (roundDown) {
    +  var result = this.msecs / msecPerMinute;
    +  if (roundDown === true) {
    +    result = Math.floor(result);
    +  }
    +  
    +  return result;
    +};

    function totalHours (roundDown)

    + +

    @roundDown {boolean} Value indicating if the value should be rounded down.

    + +

    Returns the total number of hours for this instance, rounding down +to the nearest integer if roundDown is set.

    TimeSpan.prototype.totalHours = function (roundDown) {
    +  var result = this.msecs / msecPerHour;
    +  if (roundDown === true) {
    +    result = Math.floor(result);
    +  }
    +  
    +  return result;
    +};

    function totalDays (roundDown)

    + +

    @roundDown {boolean} Value indicating if the value should be rounded down.

    + +

    Returns the total number of days for this instance, rounding down +to the nearest integer if roundDown is set.

    TimeSpan.prototype.totalDays = function (roundDown) {
    +  var result = this.msecs / msecPerDay;
    +  if (roundDown === true) {
    +    result = Math.floor(result);
    +  }
    +  
    +  return result;
    +};

    @milliseconds

    + +

    Returns the length of this TimeSpan instance in milliseconds.

    TimeSpan.prototype.__defineGetter__('milliseconds', function () {
    +  return this.msecs % 1000;
    +});

    @seconds

    + +

    Returns the length of this TimeSpan instance in seconds.

    TimeSpan.prototype.__defineGetter__('seconds', function () {
    +  return Math.floor(this.msecs / msecPerSecond) % 60;
    +});

    @minutes

    + +

    Returns the length of this TimeSpan instance in minutes.

    TimeSpan.prototype.__defineGetter__('minutes', function () {
    +  return Math.floor(this.msecs / msecPerMinute) % 60;
    +});

    @hours

    + +

    Returns the length of this TimeSpan instance in hours.

    TimeSpan.prototype.__defineGetter__('hours', function () {
    +  return Math.floor(this.msecs / msecPerHour) % 24;
    +});

    @days

    + +

    Returns the length of this TimeSpan instance in days.

    TimeSpan.prototype.__defineGetter__('days', function () {
    +  return Math.floor(this.msecs / msecPerDay);
    +});

    Instance Helpers

    + +

    Various help methods for performing utilities +such as equality and serialization

    function equals (timeSpan)

    + +

    @timeSpan {TimeSpan} TimeSpan instance to assert equal

    + +

    Returns a value indicating if the specified timeSpan is equal +in milliseconds to this instance.

    TimeSpan.prototype.equals = function (timeSpan) {
    +  if (!(timeSpan instanceof TimeSpan)) {
    +    return;
    +  }
    +  
    +  return this.msecs === timeSpan.totalMilliseconds();
    +};

    function toString ()

    + +

    Returns a string representation of this TimeSpan +instance according to current format.

    TimeSpan.prototype.toString = function () {
    +  if (!this.format) {
    +    return this._format();
    +  };
    +  
    +  return this.format(this);
    +};

    @private function _format ()

    + +

    Returns the default string representation of this instance.

    TimeSpan.prototype._format = function () {
    +  return [
    +    this.days,
    +    this.hours,
    +    this.minutes,
    +    this.seconds + '.' + this.milliseconds
    +  ].join(':')
    +};

    @private function isNumeric (input)

    + +

    @input {Number} Value to check numeric quality of.

    + +

    Returns a value indicating the numeric quality of the +specified input.

    function isNumeric (input) {
    +  return input && !isNaN(parseFloat(input)) && isFinite(input);
    +};
    +
    +
    \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/lib/time-span.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/lib/time-span.js new file mode 100644 index 0000000..23a9cc8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/lib/time-span.js @@ -0,0 +1,827 @@ +/* +* JavaScript TimeSpan Library +* +* Copyright (c) 2010 Michael Stum, Charlie Robbins +* +* 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. +*/ + +// +// ### Time constants +// +var msecPerSecond = 1000, + msecPerMinute = 60000, + msecPerHour = 3600000, + msecPerDay = 86400000; + +// +// ### Timespan Parsers +// +var timeSpanWithDays = /^(\d+):(\d+):(\d+):(\d+)(\.\d+)?/, + timeSpanNoDays = /^(\d+):(\d+):(\d+)(\.\d+)?/; + +// +// ### function TimeSpan (milliseconds, seconds, minutes, hours, days) +// #### @milliseconds {Number} Number of milliseconds for this instance. +// #### @seconds {Number} Number of seconds for this instance. +// #### @minutes {Number} Number of minutes for this instance. +// #### @hours {Number} Number of hours for this instance. +// #### @days {Number} Number of days for this instance. +// Constructor function for the `TimeSpan` object which represents a length +// of positive or negative milliseconds componentized into milliseconds, +// seconds, hours, and days. +// +var TimeSpan = exports.TimeSpan = function (milliseconds, seconds, minutes, hours, days) { + this.msecs = 0; + + if (isNumeric(days)) { + this.msecs += (days * msecPerDay); + } + + if (isNumeric(hours)) { + this.msecs += (hours * msecPerHour); + } + + if (isNumeric(minutes)) { + this.msecs += (minutes * msecPerMinute); + } + + if (isNumeric(seconds)) { + this.msecs += (seconds * msecPerSecond); + } + + if (isNumeric(milliseconds)) { + this.msecs += milliseconds; + } +}; + +// +// ## Factory methods +// Helper methods for creating new TimeSpan objects +// from various criteria: milliseconds, seconds, minutes, +// hours, days, strings and other `TimeSpan` instances. +// + +// +// ### function fromMilliseconds (milliseconds) +// #### @milliseconds {Number} Amount of milliseconds for the new TimeSpan instance. +// Creates a new `TimeSpan` instance with the specified `milliseconds`. +// +exports.fromMilliseconds = function (milliseconds) { + if (!isNumeric(milliseconds)) { return } + return new TimeSpan(milliseconds, 0, 0, 0, 0); +} + +// +// ### function fromSeconds (seconds) +// #### @milliseconds {Number} Amount of seconds for the new TimeSpan instance. +// Creates a new `TimeSpan` instance with the specified `seconds`. +// +exports.fromSeconds = function (seconds) { + if (!isNumeric(seconds)) { return } + return new TimeSpan(0, seconds, 0, 0, 0); +}; + +// +// ### function fromMinutes (milliseconds) +// #### @milliseconds {Number} Amount of minutes for the new TimeSpan instance. +// Creates a new `TimeSpan` instance with the specified `minutes`. +// +exports.fromMinutes = function (minutes) { + if (!isNumeric(minutes)) { return } + return new TimeSpan(0, 0, minutes, 0, 0); +}; + +// +// ### function fromHours (hours) +// #### @milliseconds {Number} Amount of hours for the new TimeSpan instance. +// Creates a new `TimeSpan` instance with the specified `hours`. +// +exports.fromHours = function (hours) { + if (!isNumeric(hours)) { return } + return new TimeSpan(0, 0, 0, hours, 0); +}; + +// +// ### function fromDays (days) +// #### @milliseconds {Number} Amount of days for the new TimeSpan instance. +// Creates a new `TimeSpan` instance with the specified `days`. +// +exports.fromDays = function (days) { + if (!isNumeric(days)) { return } + return new TimeSpan(0, 0, 0, 0, days); +}; + +// +// ### function parse (str) +// #### @str {string} Timespan string to parse. +// Creates a new `TimeSpan` instance from the specified +// string, `str`. +// +exports.parse = function (str) { + var match, milliseconds; + + function parseMilliseconds (value) { + return value ? parseFloat('0' + value) * 1000 : 0; + } + + // If we match against a full TimeSpan: + // [days]:[hours]:[minutes]:[seconds].[milliseconds]? + if ((match = str.match(timeSpanWithDays))) { + return new TimeSpan(parseMilliseconds(match[5]), match[4], match[3], match[2], match[1]); + } + + // If we match against a partial TimeSpan: + // [hours]:[minutes]:[seconds].[milliseconds]? + if ((match = str.match(timeSpanNoDays))) { + return new TimeSpan(parseMilliseconds(match[4]), match[3], match[2], match[1], 0); + } + + return null; +}; + +// +// List of default singular time modifiers and associated +// computation algoritm. Assumes in order, smallest to greatest +// performing carry forward additiona / subtraction for each +// Date-Time component. +// +var parsers = { + 'milliseconds': { + exp: /(\d+)milli(?:second)?[s]?/i, + compute: function (delta, computed) { + return _compute(delta, computed, { + current: 'milliseconds', + next: 'seconds', + max: 1000 + }); + } + }, + 'seconds': { + exp: /(\d+)second[s]?/i, + compute: function (delta, computed) { + return _compute(delta, computed, { + current: 'seconds', + next: 'minutes', + max: 60 + }); + } + }, + 'minutes': { + exp: /(\d+)minute[s]?/i, + compute: function (delta, computed) { + return _compute(delta, computed, { + current: 'minutes', + next: 'hours', + max: 60 + }); + } + }, + 'hours': { + exp: /(\d+)hour[s]?/i, + compute: function (delta, computed) { + return _compute(delta, computed, { + current: 'hours', + next: 'days', + max: 24 + }); + } + }, + 'days': { + exp: /(\d+)day[s]?/i, + compute: function (delta, computed) { + var days = monthDays(computed.months, computed.years), + sign = delta >= 0 ? 1 : -1, + opsign = delta >= 0 ? -1 : 1, + clean = 0; + + function update (months) { + if (months < 0) { + computed.years -= 1; + return 11; + } + else if (months > 11) { + computed.years += 1; + return 0 + } + + return months; + } + + if (delta) { + while (Math.abs(delta) >= days) { + computed.months += sign * 1; + computed.months = update(computed.months); + delta += opsign * days; + days = monthDays(computed.months, computed.years); + } + + computed.days += (opsign * delta); + } + + if (computed.days < 0) { clean = -1 } + else if (computed.days > months[computed.months]) { clean = 1 } + + if (clean === -1 || clean === 1) { + computed.months += clean; + computed.months = update(computed.months); + computed.days = months[computed.months] + computed.days; + } + + return computed; + } + }, + 'months': { + exp: /(\d+)month[s]?/i, + compute: function (delta, computed) { + var round = delta > 0 ? Math.floor : Math.ceil; + if (delta) { + computed.years += round.call(null, delta / 12); + computed.months += delta % 12; + } + + if (computed.months > 11) { + computed.years += Math.floor((computed.months + 1) / 12); + computed.months = ((computed.months + 1) % 12) - 1; + } + + return computed; + } + }, + 'years': { + exp: /(\d+)year[s]?/i, + compute: function (delta, computed) { + if (delta) { computed.years += delta; } + return computed; + } + } +}; + +// +// Compute the list of parser names for +// later use. +// +var parserNames = Object.keys(parsers); + +// +// ### function parseDate (str) +// #### @str {string} String to parse into a date +// Parses the specified liberal Date-Time string according to +// ISO8601 **and**: +// +// 1. `2010-04-03T12:34:15Z+12MINUTES` +// 2. `NOW-4HOURS` +// +// Valid modifiers for the more liberal Date-Time string(s): +// +// YEAR, YEARS +// MONTH, MONTHS +// DAY, DAYS +// HOUR, HOURS +// MINUTE, MINUTES +// SECOND, SECONDS +// MILLI, MILLIS, MILLISECOND, MILLISECONDS +// +exports.parseDate = function (str) { + var dateTime = Date.parse(str), + iso = '^([^Z]+)', + zulu = 'Z([\\+|\\-])?', + diff = {}, + computed, + modifiers, + sign; + + // + // If Date string supplied actually conforms + // to UTC Time (ISO8601), return a new Date. + // + if (!isNaN(dateTime)) { + return new Date(dateTime); + } + + // + // Create the `RegExp` for the end component + // of the target `str` to parse. + // + parserNames.forEach(function (group) { + zulu += '(\\d+[a-zA-Z]+)?'; + }); + + if (/^NOW/i.test(str)) { + // + // If the target `str` is a liberal `NOW-*`, + // then set the base `dateTime` appropriately. + // + dateTime = Date.now(); + zulu = zulu.replace(/Z/, 'NOW'); + } + else { + // + // Parse the `ISO8601` component, and the end + // component from the target `str`. + // + dateTime = str.match(new RegExp(iso, 'i')); + dateTime = Date.parse(dateTime[1]); + } + + // + // If there was no match on either part then + // it must be a bad value. + // + if (!dateTime || !(modifiers = str.match(new RegExp(zulu, 'i')))) { + return null; + } + + // + // Create a new `Date` object from the `ISO8601` + // component of the target `str`. + // + dateTime = new Date(dateTime); + sign = modifiers[1] === '+' ? 1 : -1; + + // + // Create an Object-literal for consistently accessing + // the various components of the computed Date. + // + var computed = { + milliseconds: dateTime.getMilliseconds(), + seconds: dateTime.getSeconds(), + minutes: dateTime.getMinutes(), + hours: dateTime.getHours(), + days: dateTime.getDate(), + months: dateTime.getMonth(), + years: dateTime.getFullYear() + }; + + // + // Parse the individual component spans (months, years, etc) + // from the modifier strings that we parsed from the end + // of the target `str`. + // + modifiers.slice(2).filter(Boolean).forEach(function (modifier) { + parserNames.forEach(function (name) { + var match; + if (!(match = modifier.match(parsers[name].exp))) { + return; + } + + diff[name] = sign * parseInt(match[1], 10); + }) + }); + + // + // Compute the total `diff` by iteratively computing + // the partial components from smallest to largest. + // + parserNames.forEach(function (name) { + computed = parsers[name].compute(diff[name], computed); + }); + + return new Date( + Date.UTC( + computed.years, + computed.months, + computed.days, + computed.hours, + computed.minutes, + computed.seconds, + computed.milliseconds + ) + ); +}; + +// +// ### function fromDates (start, end, abs) +// #### @start {Date} Start date of the `TimeSpan` instance to return +// #### @end {Date} End date of the `TimeSpan` instance to return +// #### @abs {boolean} Value indicating to return an absolute value +// Returns a new `TimeSpan` instance representing the difference between +// the `start` and `end` Dates. +// +exports.fromDates = function (start, end, abs) { + if (typeof start === 'string') { + start = exports.parseDate(start); + } + + if (typeof end === 'string') { + end = exports.parseDate(end); + } + + if (!(start instanceof Date && end instanceof Date)) { + return null; + } + + var differenceMsecs = end.valueOf() - start.valueOf(); + if (abs) { + differenceMsecs = Math.abs(differenceMsecs); + } + + return new TimeSpan(differenceMsecs, 0, 0, 0, 0); +}; + +// +// ## Module Helpers +// Module-level helpers for various utilities such as: +// instanceOf, parsability, and cloning. +// + +// +// ### function test (str) +// #### @str {string} String value to test if it is a TimeSpan +// Returns a value indicating if the specified string, `str`, +// is a parsable `TimeSpan` value. +// +exports.test = function (str) { + return timeSpanWithDays.test(str) || timeSpanNoDays.test(str); +}; + +// +// ### function instanceOf (timeSpan) +// #### @timeSpan {Object} Object to check TimeSpan quality. +// Returns a value indicating if the specified `timeSpan` is +// in fact a `TimeSpan` instance. +// +exports.instanceOf = function (timeSpan) { + return timeSpan instanceof TimeSpan; +}; + +// +// ### function clone (timeSpan) +// #### @timeSpan {TimeSpan} TimeSpan object to clone. +// Returns a new `TimeSpan` instance with the same value +// as the `timeSpan` object supplied. +// +exports.clone = function (timeSpan) { + if (!(timeSpan instanceof TimeSpan)) { return } + return exports.fromMilliseconds(timeSpan.totalMilliseconds()); +}; + +// +// ## Addition +// Methods for adding `TimeSpan` instances, +// milliseconds, seconds, hours, and days to other +// `TimeSpan` instances. +// + +// +// ### function add (timeSpan) +// #### @timeSpan {TimeSpan} TimeSpan to add to this instance +// Adds the specified `timeSpan` to this instance. +// +TimeSpan.prototype.add = function (timeSpan) { + if (!(timeSpan instanceof TimeSpan)) { return } + this.msecs += timeSpan.totalMilliseconds(); +}; + +// +// ### function addMilliseconds (milliseconds) +// #### @milliseconds {Number} Number of milliseconds to add. +// Adds the specified `milliseconds` to this instance. +// +TimeSpan.prototype.addMilliseconds = function (milliseconds) { + if (!isNumeric(milliseconds)) { return } + this.msecs += milliseconds; +}; + +// +// ### function addSeconds (seconds) +// #### @seconds {Number} Number of seconds to add. +// Adds the specified `seconds` to this instance. +// +TimeSpan.prototype.addSeconds = function (seconds) { + if (!isNumeric(seconds)) { return } + + this.msecs += (seconds * msecPerSecond); +}; + +// +// ### function addMinutes (minutes) +// #### @minutes {Number} Number of minutes to add. +// Adds the specified `minutes` to this instance. +// +TimeSpan.prototype.addMinutes = function (minutes) { + if (!isNumeric(minutes)) { return } + this.msecs += (minutes * msecPerMinute); +}; + +// +// ### function addHours (hours) +// #### @hours {Number} Number of hours to add. +// Adds the specified `hours` to this instance. +// +TimeSpan.prototype.addHours = function (hours) { + if (!isNumeric(hours)) { return } + this.msecs += (hours * msecPerHour); +}; + +// +// ### function addDays (days) +// #### @days {Number} Number of days to add. +// Adds the specified `days` to this instance. +// +TimeSpan.prototype.addDays = function (days) { + if (!isNumeric(days)) { return } + this.msecs += (days * msecPerDay); +}; + +// +// ## Subtraction +// Methods for subtracting `TimeSpan` instances, +// milliseconds, seconds, hours, and days from other +// `TimeSpan` instances. +// + +// +// ### function subtract (timeSpan) +// #### @timeSpan {TimeSpan} TimeSpan to subtract from this instance. +// Subtracts the specified `timeSpan` from this instance. +// +TimeSpan.prototype.subtract = function (timeSpan) { + if (!(timeSpan instanceof TimeSpan)) { return } + this.msecs -= timeSpan.totalMilliseconds(); +}; + +// +// ### function subtractMilliseconds (milliseconds) +// #### @milliseconds {Number} Number of milliseconds to subtract. +// Subtracts the specified `milliseconds` from this instance. +// +TimeSpan.prototype.subtractMilliseconds = function (milliseconds) { + if (!isNumeric(milliseconds)) { return } + this.msecs -= milliseconds; +}; + +// +// ### function subtractSeconds (seconds) +// #### @seconds {Number} Number of seconds to subtract. +// Subtracts the specified `seconds` from this instance. +// +TimeSpan.prototype.subtractSeconds = function (seconds) { + if (!isNumeric(seconds)) { return } + this.msecs -= (seconds * msecPerSecond); +}; + +// +// ### function subtractMinutes (minutes) +// #### @minutes {Number} Number of minutes to subtract. +// Subtracts the specified `minutes` from this instance. +// +TimeSpan.prototype.subtractMinutes = function (minutes) { + if (!isNumeric(minutes)) { return } + this.msecs -= (minutes * msecPerMinute); +}; + +// +// ### function subtractHours (hours) +// #### @hours {Number} Number of hours to subtract. +// Subtracts the specified `hours` from this instance. +// +TimeSpan.prototype.subtractHours = function (hours) { + if (!isNumeric(hours)) { return } + this.msecs -= (hours * msecPerHour); +}; + +// +// ### function subtractDays (days) +// #### @days {Number} Number of days to subtract. +// Subtracts the specified `days` from this instance. +// +TimeSpan.prototype.subtractDays = function (days) { + if (!isNumeric(days)) { return } + this.msecs -= (days * msecPerDay); +}; + +// +// ## Getters +// Methods for retrieving components of a `TimeSpan` +// instance: milliseconds, seconds, minutes, hours, and days. +// + +// +// ### function totalMilliseconds (roundDown) +// #### @roundDown {boolean} Value indicating if the value should be rounded down. +// Returns the total number of milliseconds for this instance, rounding down +// to the nearest integer if `roundDown` is set. +// +TimeSpan.prototype.totalMilliseconds = function (roundDown) { + var result = this.msecs; + if (roundDown === true) { + result = Math.floor(result); + } + + return result; +}; + +// +// ### function totalSeconds (roundDown) +// #### @roundDown {boolean} Value indicating if the value should be rounded down. +// Returns the total number of seconds for this instance, rounding down +// to the nearest integer if `roundDown` is set. +// +TimeSpan.prototype.totalSeconds = function (roundDown) { + var result = this.msecs / msecPerSecond; + if (roundDown === true) { + result = Math.floor(result); + } + + return result; +}; + +// +// ### function totalMinutes (roundDown) +// #### @roundDown {boolean} Value indicating if the value should be rounded down. +// Returns the total number of minutes for this instance, rounding down +// to the nearest integer if `roundDown` is set. +// +TimeSpan.prototype.totalMinutes = function (roundDown) { + var result = this.msecs / msecPerMinute; + if (roundDown === true) { + result = Math.floor(result); + } + + return result; +}; + +// +// ### function totalHours (roundDown) +// #### @roundDown {boolean} Value indicating if the value should be rounded down. +// Returns the total number of hours for this instance, rounding down +// to the nearest integer if `roundDown` is set. +// +TimeSpan.prototype.totalHours = function (roundDown) { + var result = this.msecs / msecPerHour; + if (roundDown === true) { + result = Math.floor(result); + } + + return result; +}; + +// +// ### function totalDays (roundDown) +// #### @roundDown {boolean} Value indicating if the value should be rounded down. +// Returns the total number of days for this instance, rounding down +// to the nearest integer if `roundDown` is set. +// +TimeSpan.prototype.totalDays = function (roundDown) { + var result = this.msecs / msecPerDay; + if (roundDown === true) { + result = Math.floor(result); + } + + return result; +}; + +// +// ### @milliseconds +// Returns the length of this `TimeSpan` instance in milliseconds. +// +TimeSpan.prototype.__defineGetter__('milliseconds', function () { + return this.msecs % 1000; +}); + +// +// ### @seconds +// Returns the length of this `TimeSpan` instance in seconds. +// +TimeSpan.prototype.__defineGetter__('seconds', function () { + return Math.floor(this.msecs / msecPerSecond) % 60; +}); + +// +// ### @minutes +// Returns the length of this `TimeSpan` instance in minutes. +// +TimeSpan.prototype.__defineGetter__('minutes', function () { + return Math.floor(this.msecs / msecPerMinute) % 60; +}); + +// +// ### @hours +// Returns the length of this `TimeSpan` instance in hours. +// +TimeSpan.prototype.__defineGetter__('hours', function () { + return Math.floor(this.msecs / msecPerHour) % 24; +}); + +// +// ### @days +// Returns the length of this `TimeSpan` instance in days. +// +TimeSpan.prototype.__defineGetter__('days', function () { + return Math.floor(this.msecs / msecPerDay); +}); + +// +// ## Instance Helpers +// Various help methods for performing utilities +// such as equality and serialization +// + +// +// ### function equals (timeSpan) +// #### @timeSpan {TimeSpan} TimeSpan instance to assert equal +// Returns a value indicating if the specified `timeSpan` is equal +// in milliseconds to this instance. +// +TimeSpan.prototype.equals = function (timeSpan) { + if (!(timeSpan instanceof TimeSpan)) { return } + return this.msecs === timeSpan.totalMilliseconds(); +}; + +// +// ### function toString () +// Returns a string representation of this `TimeSpan` +// instance according to current `format`. +// +TimeSpan.prototype.toString = function () { + if (!this.format) { return this._format() } + return this.format(this); +}; + +// +// ### @private function _format () +// Returns the default string representation of this instance. +// +TimeSpan.prototype._format = function () { + return [ + this.days, + this.hours, + this.minutes, + this.seconds + '.' + this.milliseconds + ].join(':') +}; + +// +// ### @private function isNumeric (input) +// #### @input {Number} Value to check numeric quality of. +// Returns a value indicating the numeric quality of the +// specified `input`. +// +function isNumeric (input) { + return input && !isNaN(parseFloat(input)) && isFinite(input); +}; + +// +// ### @private function _compute (delta, date, computed, options) +// #### @delta {Number} Channge in this component of the date +// #### @computed {Object} Currently computed date. +// #### @options {Object} Options for the computation +// Performs carry forward addition or subtraction for the +// `options.current` component of the `computed` date, carrying +// it forward to `options.next` depending on the maximum value, +// `options.max`. +// +function _compute (delta, computed, options) { + var current = options.current, + next = options.next, + max = options.max, + round = delta > 0 ? Math.floor : Math.ceil; + + if (delta) { + computed[next] += round.call(null, delta / max); + computed[current] += delta % max; + } + + if (Math.abs(computed[current]) >= max) { + computed[next] += round.call(null, computed[current] / max) + computed[current] = computed[current] % max; + } + + return computed; +} + + +// +// ### @private monthDays (month, year) +// #### @month {Number} Month to get days for. +// #### @year {Number} Year of the month to get days for. +// Returns the number of days in the specified `month` observing +// leap years. +// +var months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; +function monthDays (month, year) { + if (((year % 100 !== 0 && year % 4 === 0) + || year % 400 === 0) && month === 1) { + return 29; + } + + return months[month]; +} \ No newline at end of file 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 new file mode 100644 index 0000000..5fb2082 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/package.json @@ -0,0 +1,39 @@ +{ + "name": "timespan", + "description": "A JavaScript TimeSpan library for node.js (and soon the browser)", + "version": "2.2.0", + "author": { + "name": "Michael Stum", + "email": "blog@stum.de" + }, + "contributors": [ + { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/indexzero/timespan.git" + }, + "keywords": [ + "time", + "dates", + "utilities", + "timespan" + ], + "devDependencies": { + "vows": ">= 0.5.2" + }, + "main": "./lib/time-span.js", + "scripts": { + "test": "vows test/*-test.js --spec" + }, + "engines": { + "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/node_modules/timespan/test/date-parser-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/date-parser-test.js new file mode 100644 index 0000000..6f08973 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/date-parser-test.js @@ -0,0 +1,72 @@ +/* + * time-span-test.js: Tests for the TimeSpan module. + * + * (C) Charlie Robbins + * MIT LICENSE + * + */ + +var vows = require('vows'), + assert = require('assert'), + timeSpan = require('../lib/time-span'); + +vows.describe('time-span/date-time').addBatch({ + "When using the TimeSpan module": { + "the parseDate() method": { + "when passed a TimeSpan string using ISO8601 with explicit time modifiers": { + "which do not carry over": { + "should return the correct value": function () { + var target = new Date(Date.parse('2010-04-03T10:04:15Z')), + parsed = timeSpan.parseDate('2010-04-03T12:34:15Z-2HOURS30MINUTES'); + + assert.equal(target.toString(), parsed.toString()); + } + }, + "which carry under": { + "should return the correct value": function () { + var target = new Date(Date.parse('2010-03-29T12:34:15Z')), + parsed = timeSpan.parseDate('2010-04-01T12:34:15Z-72HOURS'); + + assert.equal(target.toString(), parsed.toString()); + } + }, + "which carry under a leap year": { + "should return the correct value": function () { + var target = new Date(Date.parse('2007-03-31T12:00:00Z')), + parsed = timeSpan.parseDate('2010-03-31T12:00:00Z-1096DAYS'); + + assert.equal(target.toString(), parsed.toString()); + } + }, + "which carry over": { + "should return the correct value": function () { + var target = new Date(Date.parse('2013-04-03T12:34:15Z')), + parsed = timeSpan.parseDate('2010-04-03T12:34:15Z+2YEARS365DAYS'); + + assert.equal(target.toString(), parsed.toString()); + } + } + }, + "when passed a TimeSpan string using NOW with explicit time modifiers": { + "which do not carry over": { + "should return the correct value": function () { + var now = new Date(Date.now()), + parsed = timeSpan.parseDate('NOW-2HOURS'); + + now.setHours(now.getHours() - 2 - (now.getTimezoneOffset() / 60)); + assert.equal(now.getHours(), parsed.getHours()); + } + }, + "which carry under": { + "should return the correct value": function () { + var now = new Date(Date.now()), + parsed = timeSpan.parseDate('NOW-72HOURS'); + + now.setHours(now.getHours() - 72 - (now.getTimezoneOffset() / 60)); + assert.equal(now.getHours(), parsed.getHours()); + } + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/helpers.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/helpers.js new file mode 100644 index 0000000..4a1b84a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/helpers.js @@ -0,0 +1,36 @@ +/* + * helpers.js: Tests helpers for the TimeSpan module. + * + * (C) Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + timeSpan = require('../lib/time-span') + +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +var helpers = exports, + components = ['milliseconds', 'seconds', 'minutes', 'hours', 'days']; + +// +// Tests all of the factory methods for the `TimeSpan` object: +// `fromMilliseconds`, `fromSeconds`, etc. +// +exports.testFactories = function (num) { + var context = {}; + + components.forEach(function (component) { + var method = 'from' + capitalize(component); + + context['the ' + method + '() method'] = function () { + var value = timeSpan[method](num); + assert.equal(value[component], num); + } + }); + + return context; +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/time-span-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/time-span-test.js new file mode 100644 index 0000000..66a7be5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/node_modules/timespan/test/time-span-test.js @@ -0,0 +1,68 @@ +/* + * time-span-test.js: Tests for the TimeSpan module. + * + * (C) Charlie Robbins + * MIT LICENSE + * + */ + +var vows = require('vows'), + assert = require('assert'), + timeSpan = require('../lib/time-span'), + helpers = require('./helpers'); + +vows.describe('time-span').addBatch({ + "When using the TimeSpan module": { + "the parse() method": { + "when passed a TimeSpan string with no days": { + "should return a valid TimeSpan object": function () { + var ts = timeSpan.parse("04:03:02.10"); + assert.equal(ts.hours, 4); + assert.equal(ts.minutes, 3); + assert.equal(ts.seconds, 2); + assert.equal(ts.milliseconds, 100); + } + }, + "when passed a TimeSpan string with days": { + "should return a valid TimeSpan object": function () { + var ts = timeSpan.parse("01:04:03:02.10"); + assert.equal(ts.days, 1); + assert.equal(ts.hours, 4); + assert.equal(ts.minutes, 3); + assert.equal(ts.seconds, 2); + assert.equal(ts.milliseconds, 100); + } + } + }, + "the test() method": { + "when passed a TimeSpan string with no days": { + "should return true": function () { + assert.isTrue(timeSpan.test("04:03:02.10")); + } + }, + "when passed a TimeSpan string with days": { + "should return true": function () { + assert.isTrue(timeSpan.test("01:04:03:02.10")); + } + }, + "when passed an invalid TimeSpan string": { + "should return false": function () { + assert.isFalse(timeSpan.test('xx:00:invalid')); + } + } + }, + "the fromDates() method": { + "with two Date values": function () { + var diff = 1000 * 60 * 60 * 12, + end = new Date(), + start = new Date(end.getTime() - diff); + + assert.equal(12, timeSpan.fromDates(start, end).hours); + }, + "with two string values": function () { + assert.equal(2, timeSpan.fromDates('NOW-4DAYS', 'NOW-2DAYS').days); + } + }, + "the factory methods": helpers.testFactories(10) + } +}).export(module); \ No newline at end of file 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 new file mode 100644 index 0000000..31aee25 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/package.json @@ -0,0 +1,55 @@ +{ + "name": "loggly", + "description": "A client implementation for Loggly cloud Logging-as-a-Service API", + "version": "0.3.11", + "author": { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + }, + "contributors": [ + { + "name": "Marak Squires", + "email": "marak.squires@gmail.com" + }, + { + "name": "hij1nx", + "email": "hij1nx@me.com" + }, + { + "name": "Kord Campbell", + "email": "kordless@loggly.com" + }, + { + "name": "Erik Hedenstrom", + "email": "erik@hedenstroem.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/nodejitsu/node-loggly.git" + }, + "keywords": [ + "cloud computing", + "api", + "logging", + "loggly" + ], + "dependencies": { + "request": "2.9.x", + "timespan": "2.x.x" + }, + "devDependencies": { + "vows": "0.6.x" + }, + "main": "./lib/loggly", + "scripts": { + "test": "vows test/*-test.js --spec" + }, + "engines": { + "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/loggly/test/common-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/common-test.js new file mode 100644 index 0000000..51c6b4a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/common-test.js @@ -0,0 +1,32 @@ +/* + * common-test.js: Tests for Loggly `common` utility module + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + common = require('../lib/loggly/common'); + +vows.describe('node-loggly/common').addBatch({ + "When using the common module": { + "the clone() method": { + topic: function () { + this.obj = { + name: 'common', + deep: { + first: 'first', + second: 'second' + } + }; + return common.clone(this.obj); + }, + "should return a deep clone of the object": function (clone) { + assert.isFalse(this.obj.deep === clone.deep); + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/device-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/device-test.js new file mode 100644 index 0000000..8124180 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/device-test.js @@ -0,0 +1,41 @@ +/* + * device-test.js: Tests for Loggly device requests + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + helpers = require('./helpers'); + +var options = {}, + config = helpers.loadConfig(), + loggly = require('../lib/loggly').createClient(config); + +vows.describe('node-loggly/devices').addBatch({ + "When using the node-loggly client": { + "the getDevices() method": { + topic: function () { + loggly.getDevices(this.callback); + }, + "should return a list of valid devices": function (err, devices) { + assert.isNull(err); + devices.forEach(function (device) { + helpers.assertDevice(device); + }); + } + }, + "the addDeviceToInput() method": { + topic: function () { + loggly.addDeviceToInput(config.inputs.test.id, '127.0.0.1', this.callback); + }, + "should respond with 200 status code": function (err, res) { + assert.isNull(err); + assert.equal(res.statusCode, 200); + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/helpers.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/helpers.js new file mode 100644 index 0000000..b8ed45c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/helpers.js @@ -0,0 +1,79 @@ +/* + * helpers.js: Test helpers for node-loggly + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var fs = require('fs'), + util = require('util'), + path = require('path'), + vows = require('vows'), + assert = require('assert'), + loggly = require('../lib/loggly'); + +var helpers = exports; + +helpers.validConfig = function (config) { + return config + && config.subdomain !== 'test-subdomain' + && config.auth + && config.auth.username !== 'test-username' + && config.auth.password !== 'test-password' + && config.inputs + && config.inputs.test + && config.inputs.test_json; +}; + +helpers.loadConfig = function () { + try { + var configFile = path.join(__dirname, 'data', 'test-config.json'), + stats = fs.statSync(configFile) + config = JSON.parse(fs.readFileSync(configFile).toString()); + + if (!helpers.validConfig(config)) { + util.puts('Config file test-config.json must be updated with valid data before running tests'); + process.exit(0); + } + + helpers.config = config || {} + return config || {}; + } + catch (ex) { + util.puts('Error parsing test-config.json'); + ex.stack.split('\n').forEach(function (line) { + console.log(line); + }); + + process.exit(0); + } +}; + +helpers.assertInput = function (input) { + assert.instanceOf(input, loggly.Input); + assert.isNotNull(input.id); + assert.isNotNull(input.name); + assert.isNotNull(input.service); + assert.isNotNull(input.create); + assert.isNotNull(input.discover); + assert.isNotNull(input.discoverTime); + assert.isNotNull(input.description); +}; + +helpers.assertDevice = function (device) { + assert.instanceOf(device, loggly.Device); + assert.isNotNull(device.id); + assert.isNotNull(device.input); + assert.isNotNull(device.ipAddress); + assert.isNotNull(device.launched); + assert.isNotNull(device.resourceUri); +}; + +helpers.assertSearch = function (err, results) { + assert.isNull(err); + assert.isObject(results); + assert.isTrue(typeof results.data !== 'undefined'); + assert.isTrue(typeof results.numFound !== 'undefined'); + assert.isTrue(typeof results.context !== 'undefined'); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/input-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/input-test.js new file mode 100644 index 0000000..06cd763 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/input-test.js @@ -0,0 +1,197 @@ +/* + * input-test.js: Tests for Loggly input requests + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + helpers = require('./helpers'); + +var options = {}, + testContext = {}, + config = helpers.loadConfig(), + loggly = require('../lib/loggly').createClient(config), + logglyJSON = require('../lib/loggly').createClient(config); + +logglyJSON.config.json = true; + +vows.describe('node-loggly/inputs').addBatch({ + "When using the node-loggly client": { + "the getInputs() method": { + topic: function () { + loggly.getInputs(this.callback); + }, + "should return a list of valid inputs": function (err, inputs) { + assert.isNull(err); + inputs.forEach(function (input) { + helpers.assertInput(input); + }); + } + }, + "the getInput method": { + "when called with a plaintext input": { + topic: function () { + loggly.getInput('test', this.callback); + }, + "should return a valid input": function (err, input) { + assert.isNull(err); + helpers.assertInput(input); + }, + "of the format 'text'": function (err, input) { + assert.isNull(err); + assert.equal(input.format, 'text'); + }, + "that matches the first input in the test configuration": function (err, input) { + assert.equal(config.inputs.test.token,input.input_token); + assert.equal(config.inputs.test.id,input.id); + testContext.input = input; + } + }, + "when called with a json input": { + topic: function () { + logglyJSON.getInput('test_json', this.callback); + }, + "should return a valid input": function (err, input) { + assert.isNull(err); + helpers.assertInput(input); + }, + "of the format 'json'": function (err, input) { + assert.isNull(err); + assert.equal(input.format, 'json'); + }, + "that matches the second input in the test configuration": function (err, input) { + assert.equal(config.inputs.test_json.token,input.input_token); + assert.equal(config.inputs.test_json.id,input.id); + testContext.inputJSON = input; + } + } + } + } +}).addBatch({ + "When using the node-loggly client": { + "the log() method": { + "to a 'text' input": { + "when passed a callback": { + topic: function () { + loggly.log( + config.inputs.test.token, + 'this is a test logging message from /test/input-test.js', + this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = loggly.log(config.inputs.test.token, 'this is a test logging message from /test/input-test.js'); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + }, + "to a 'json' input": { + "when passed a callback": { + topic: function () { + logglyJSON.log( + config.inputs.test_json.token, + { + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + }, + this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = logglyJSON.log( + config.inputs.test_json.token, + { + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + } + ); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + } + } + } +}).addBatch({ + "When using an instance of an input": { + "the log() method of the 'text' instance": { + "when passed a callback": { + topic: function () { + testContext.input.log('this is a test logging message from /test/input-test.js', this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = testContext.input.log('this is a test logging message from /test/input-test.js'); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + }, + "the log() method of the 'json' instance": { + "when passed a callback": { + topic: function () { + testContext.inputJSON.log( + { + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + }, + this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = testContext.inputJSON.log({ + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + }); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/log-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/log-test.js new file mode 100644 index 0000000..876db63 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/log-test.js @@ -0,0 +1,84 @@ +/* + * log-test.js: Tests for vanilla logging with no authentication. + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + helpers = require('./helpers'); + +var config = helpers.loadConfig(), + loggly = require('../lib/loggly').createClient({ subdomain: config.subdomain }), + logglyJSON = require('../lib/loggly').createClient({ subdomain: config.subdomain, json: true }); + +vows.describe('node-loggly/inputs (no auth)').addBatch({ + "When using the node-loggly client without authentication": { + "the log() method": { + "to a 'text' input": { + "when passed a callback": { + topic: function () { + loggly.log( + config.inputs.test.token, + 'this is a test logging message from /test/input-test.js', + this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = loggly.log(config.inputs.test.token, 'this is a test logging message from /test/input-test.js'); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + }, + "to a 'json' input": { + "when passed a callback": { + topic: function () { + logglyJSON.log( + config.inputs.test_json.token, + { + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + }, + this.callback); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + }, + "when not passed a callback": { + topic: function () { + var emitter = logglyJSON.log( + config.inputs.test_json.token, + { + timestamp: new Date().getTime(), + message: 'this is a test logging message from /test/input-test.js' + } + ); + emitter.on('log', this.callback.bind(null, null)); + }, + "should log messages to loggly": function (err, result) { + assert.isNull(err); + assert.isObject(result); + assert.equal(result.response, 'ok'); + } + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/search-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/search-test.js new file mode 100644 index 0000000..dac9da7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/loggly/test/search-test.js @@ -0,0 +1,84 @@ +/* + * input-test.js: Tests for Loggly input requests + * + * (C) 2010 Nodejitsu Inc. + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + helpers = require('./helpers'); + +var options = {}, + testContext = {}, + config = helpers.loadConfig(), + loggly = require('../lib/loggly').createClient(config); + +vows.describe('node-loggly/search').addBatch({ + "When using the node-loggly client": { + "the search() method": { + "when searching without chaining": { + topic: function () { + loggly.search('logging message', this.callback); + }, + "should return a set of valid search results": function (err, results) { + helpers.assertSearch(err, results); + } + }, + "when searching with chaining": { + topic: function () { + loggly.search('logging message') + .meta({ inputname: 'test' }) + .run(this.callback); + }, + "should return a set of valid search results": function (err, results) { + helpers.assertSearch(err, results); + } + } + }, + "the facet() method": { + "when searching by ip": { + topic: function () { + loggly.facet('ip', 'test', this.callback); + }, + "should return a set of valid search results": function (err, results) { + helpers.assertSearch(err, results); + } + }, + "when using chained searches": { + topic: function () { + loggly.facet('ip', 'test') + .context({ from: 'NOW-1MONTH' }) + .run(this.callback); + }, + "should return a set of valid search results": function (err, results) { + helpers.assertSearch(err, results); + } + } + }, + "the _checkRange() method": { + "with invalid options set": { + "should correct them": function () { + var search = loggly.search('logging message') + .context({ from: 'NOW', until: '1DAY' }) + ._checkRange(); + + assert.equal(search._context.from, 'NOW-24HOURS'); + assert.equal(search._context.until, 'NOW'); + } + }, + "with valid options set": { + "should not modify them": function () { + var search = loggly.search('logging message') + .context({ from: 'NOW-2MONTHS', until: 'NOW' }) + ._checkRange(); + + assert.equal(search._context.from, 'NOW-2MONTHS'); + assert.equal(search._context.until, 'NOW'); + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/.npmignore new file mode 100644 index 0000000..3f31ac2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/.npmignore @@ -0,0 +1,2 @@ +*.un~ +/node_modules diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/License b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/License new file mode 100644 index 0000000..11ec094 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Felix Geisendörfer (felix@debuggable.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Makefile new file mode 100644 index 0000000..a7ce31d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Makefile @@ -0,0 +1,11 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +release: + git push + git push --tags + npm publish . + +.PHONY: test diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Readme.md new file mode 100644 index 0000000..fcd1b97 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/Readme.md @@ -0,0 +1,98 @@ +# stack-trace + +Get v8 stack traces as an array of CallSite objects. + +## Install + +``` bash +npm install stack-trace +``` + +## Usage + +The stack-trace module makes it easy for you to capture the current stack: + +``` javascript +var stackTrace = require('stack-trace'); +var trace = stackTrace.get(); + +require('assert').strictEqual(trace[0].getFileName(), __filename); +``` + +However, sometimes you have already popped the stack you are interested in, +and all you have left is an `Error` object. This module can help: + +``` javascript +var stackTrace = require('stack-trace'); +var err = new Error('something went wrong'); +var trace = stackTrace.parse(err); + +require('assert').strictEqual(trace[0].getFileName(), __filename); +``` + +Please note that parsing the `Error#stack` property is not perfect, only +certain properties can be retrieved with it as noted in the API docs below. + +## Long stack traces + +stack-trace works great with [long-stack-traces][], when parsing an `err.stack` +that has crossed the event loop boundary, a `CallSite` object returning +`'----------------------------------------'` for `getFileName()` is created. +All other methods of the event loop boundary call site return `null`. + +[long-stack-traces]: https://github.com/tlrobinson/long-stack-traces + +## API + +### stackTrace.get([belowFn]) + +Returns an array of `CallSite` objects, where element `0` is the current call +site. + +When passing a function on the current stack as the `belowFn` parameter, the +returned array will only include `CallSite` objects below this function. + +### stackTrace.parse(err) + +Parses the `err.stack` property of an `Error` object into an array compatible +with those returned by `stackTrace.get()`. However, only the following methods +are implemented on the returned `CallSite` objects. + +* getTypeName +* getFunctionName +* getMethodName +* getFileName +* getLineNumber +* getColumnNumber +* isNative + +Note: Except `getFunctionName()`, all of the above methods return exactly the +same values as you would get from `stackTrace.get()`. `getFunctionName()` +is sometimes a little different, but still useful. + +### CallSite + +The official v8 CallSite object API can be found [here][v8stackapi]. A quick +excerpt: + +> A CallSite object defines the following methods: +> +> * **getThis**: returns the value of this +> * **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. +> * **getFunction**: returns the current function +> * **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. +> * **getMethodName**: returns the name of the property of this or one of its prototypes that holds the current function +> * **getFileName**: if this function was defined in a script returns the name of the script +> * **getLineNumber**: if this function was defined in a script returns the current line number +> * **getColumnNumber**: if this function was defined in a script returns the current column number +> * **getEvalOrigin**: if this function was created using a call to eval returns a CallSite object representing the location where eval was called +> * **isToplevel**: is this a toplevel invocation, that is, is this the global object? +> * **isEval**: does this call take place in code defined by a call to eval? +> * **isNative**: is this call in native V8 code? +> * **isConstructor**: is this a constructor call? + +[v8stackapi]: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + +## License + +stack-trace is licensed under the MIT license. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/lib/stack-trace.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/lib/stack-trace.js new file mode 100644 index 0000000..085ff40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/lib/stack-trace.js @@ -0,0 +1,111 @@ +exports.get = function(belowFn) { + var oldLimit = Error.stackTraceLimit; + Error.stackTraceLimit = Infinity; + + var dummyObject = {}; + Error.captureStackTrace(dummyObject, belowFn || exports.get); + + var v8Handler = Error.prepareStackTrace; + Error.prepareStackTrace = function(dummyObject, v8StackTrace) { + return v8StackTrace; + }; + + var v8StackTrace = dummyObject.stack; + Error.prepareStackTrace = v8Handler; + Error.stackTraceLimit = oldLimit; + + return v8StackTrace; +}; + +exports.parse = function(err) { + if (!err.stack) { + return []; + } + + var self = this; + var lines = err.stack.split('\n').slice(1); + + return lines + .map(function(line) { + if (line.match(/^\s*[-]{4,}$/)) { + return self._createParsedCallSite({ + fileName: line, + lineNumber: null, + functionName: null, + typeName: null, + methodName: null, + columnNumber: null, + 'native': null, + }); + } + + var lineMatch = line.match(/at (?:([^\s]+)\s+)?\(?(?:(.+?):(\d+):(\d+)|([^)]+))\)?/); + if (!lineMatch) { + return; + } + + var object = null; + var method = null; + var functionName = null; + var typeName = null; + var methodName = null; + var isNative = (lineMatch[5] === 'native'); + + if (lineMatch[1]) { + var methodMatch = lineMatch[1].match(/([^\.]+)(?:\.(.+))?/); + object = methodMatch[1]; + method = methodMatch[2]; + functionName = lineMatch[1]; + typeName = 'Object'; + } + + if (method) { + typeName = object; + methodName = method; + } + + if (method === '') { + methodName = null; + functionName = ''; + } + + var properties = { + fileName: lineMatch[2] || null, + lineNumber: parseInt(lineMatch[3], 10) || null, + functionName: functionName, + typeName: typeName, + methodName: methodName, + columnNumber: parseInt(lineMatch[4], 10) || null, + 'native': isNative, + }; + + return self._createParsedCallSite(properties); + }) + .filter(function(callSite) { + return !!callSite; + }); +}; + +exports._createParsedCallSite = function(properties) { + var methods = {}; + for (var property in properties) { + var prefix = 'get'; + if (property === 'native') { + prefix = 'is'; + } + var method = prefix + property.substr(0, 1).toUpperCase() + property.substr(1); + + (function(property) { + methods[method] = function() { + return properties[property]; + } + })(property); + } + + var callSite = Object.create(methods); + for (var property in properties) { + callSite[property] = properties[property]; + } + + return callSite; +}; 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 new file mode 100644 index 0000000..7d63e43 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/package.json @@ -0,0 +1,28 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "stack-trace", + "description": "Get v8 stack traces as an array of CallSite objects.", + "version": "0.0.6", + "homepage": "https://github.com/felixge/node-stack-trace", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-stack-trace.git" + }, + "main": "./lib/stack-trace", + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": { + "far": "0.0.3", + "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/node_modules/stack-trace/test/common.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/common.js new file mode 100644 index 0000000..2985c2f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/common.js @@ -0,0 +1,10 @@ +var common = exports; + +var path = require('path'); +var root = path.dirname(__dirname); + +common.dir = { + lib: root + '/lib', +}; + +common.assert = require('assert'); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-get.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-get.js new file mode 100644 index 0000000..53b2e61 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-get.js @@ -0,0 +1,49 @@ +var common = require('../common'); +var assert = common.assert; +var stackTrace = require(common.dir.lib + '/stack-trace'); + +(function testBasic() { + var trace = stackTrace.get(); + + assert.strictEqual(trace[0].getFunction(), testBasic); + assert.strictEqual(trace[0].getFunctionName(), 'testBasic'); + assert.strictEqual(trace[0].getFileName(), __filename); +})(); + +(function testWrapper() { + (function testBelowFn() { + var trace = stackTrace.get(testBelowFn); + assert.strictEqual(trace[0].getFunction(), testWrapper); + assert.strictEqual(trace[0].getFunctionName(), 'testWrapper'); + })(); +})(); + + +(function deep1() { + (function deep2() { + (function deep3() { + (function deep4() { + (function deep5() { + (function deep6() { + (function deep7() { + (function deep8() { + (function deep9() { + (function deep10() { + (function deep10() { + var trace = stackTrace.get(); + var hasFirstCallSite = trace.some(function(callSite) { + return callSite.getFunctionName() === 'deep1'; + }); + + assert.ok(hasFirstCallSite); + })(); + })(); + })(); + })(); + })(); + })(); + })(); + })(); + })(); + })(); +})(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-long-stack-trace.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-long-stack-trace.js new file mode 100644 index 0000000..6106c4a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-long-stack-trace.js @@ -0,0 +1,14 @@ +var common = require('../common'); + +require('long-stack-traces'); +var assert = common.assert; +var stackTrace = require(common.dir.lib + '/stack-trace'); + +function badFn() { + var err = new Error('oh no'); + var trace = stackTrace.parse(err); + + assert.ok(trace[2].getFileName().match(/-----/)); +}; + +setTimeout(badFn, 10); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-parse.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-parse.js new file mode 100644 index 0000000..4171a68 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/integration/test-parse.js @@ -0,0 +1,135 @@ +var common = require('../common'); +var assert = common.assert; +var stackTrace = require(common.dir.lib + '/stack-trace'); + +(function testBasic() { + var err = new Error('something went wrong'); + var trace = stackTrace.parse(err); + + assert.strictEqual(trace[0].getFileName(), __filename); + assert.strictEqual(trace[0].getFunctionName(), 'testBasic'); +})(); + +(function testWrapper() { + (function testBelowFn() { + var err = new Error('something went wrong'); + var trace = stackTrace.parse(err); + assert.strictEqual(trace[0].getFunctionName(), 'testBelowFn'); + assert.strictEqual(trace[1].getFunctionName(), 'testWrapper'); + })(); +})(); + +(function testNoStack() { + var err = {stack: undefined}; + var trace = stackTrace.parse(err); + + assert.deepEqual(trace, []); +})(); + + +(function testCorruptStack() { + var err = {}; + err.stack = +'AssertionError: true == false\n' + +' fuck' + +' at Test.run (/Users/felix/code/node-fast-or-slow/lib/test.js:45:10)\n' + +'oh no' + +' at TestCase.run (/Users/felix/code/node-fast-or-slow/lib/test_case.js:61:8)\n'; + + var trace = stackTrace.parse(err); + assert.equal(trace.length, 2); +})(); + +(function testCompareRealWithParsedStackTrace() { + var realTrace = stackTrace.get(); var err = new Error('something went wrong'); + var parsedTrace = stackTrace.parse(err); + + realTrace.forEach(function(real, i) { + var parsed = parsedTrace[i]; + + function compare(method, exceptions) { + var realValue = real[method](); + var parsedValue = parsed[method](); + + if (exceptions && exceptions[i]) { + realValue = exceptions[i]; + } + + var realJson = JSON.stringify(realValue); + var parsedJson = JSON.stringify(parsedValue); + + var message = + method + ': ' + realJson + ' != ' + parsedJson + ' (#' + i + ')'; + + assert.strictEqual(realValue, parsedValue, message); + } + + compare('getFileName'); + compare('getFunctionName', { + 3: 'Object..js', + 5: 'Function._load', + 6: 'Array.0', + 7: 'EventEmitter._tickCallback', + }); + compare('getTypeName'); + compare('getMethodName'); + compare('getLineNumber'); + compare('getColumnNumber', { + 0: 47 + }); + compare('isNative'); + }); +})(); + +(function testStackWithNativeCall() { + var err = {}; + err.stack = +'AssertionError: true == false\n' + +' at Test.fn (/Users/felix/code/node-fast-or-slow/test/fast/example/test-example.js:6:10)\n' + +' at Test.run (/Users/felix/code/node-fast-or-slow/lib/test.js:45:10)\n' + +' at TestCase.runNext (/Users/felix/code/node-fast-or-slow/lib/test_case.js:73:8)\n' + +' at TestCase.run (/Users/felix/code/node-fast-or-slow/lib/test_case.js:61:8)\n' + +' at Array.0 (native)\n' + +' at EventEmitter._tickCallback (node.js:126:26)'; + + var trace = stackTrace.parse(err); + var nativeCallSite = trace[4]; + + assert.strictEqual(nativeCallSite.getFileName(), null); + assert.strictEqual(nativeCallSite.getFunctionName(), 'Array.0'); + assert.strictEqual(nativeCallSite.getTypeName(), 'Array'); + assert.strictEqual(nativeCallSite.getMethodName(), '0'); + assert.strictEqual(nativeCallSite.getLineNumber(), null); + assert.strictEqual(nativeCallSite.getColumnNumber(), null); + assert.strictEqual(nativeCallSite.isNative(), true); +})(); + +(function testStackWithFileOnly() { + var err = {}; + err.stack = +'AssertionError: true == false\n' + +' at /Users/felix/code/node-fast-or-slow/lib/test_case.js:80:10'; + + var trace = stackTrace.parse(err); + var callSite = trace[0]; + + assert.strictEqual(callSite.getFileName(), '/Users/felix/code/node-fast-or-slow/lib/test_case.js'); + assert.strictEqual(callSite.getFunctionName(), null); + assert.strictEqual(callSite.getTypeName(), null); + assert.strictEqual(callSite.getMethodName(), null); + assert.strictEqual(callSite.getLineNumber(), 80); + assert.strictEqual(callSite.getColumnNumber(), 10); + assert.strictEqual(callSite.isNative(), false); +})(); + +(function testStackWithMultilineMessage() { + var err = {}; + err.stack = +'AssertionError: true == false\nAnd some more shit\n' + +' at /Users/felix/code/node-fast-or-slow/lib/test_case.js:80:10'; + + var trace = stackTrace.parse(err); + var callSite = trace[0]; + + assert.strictEqual(callSite.getFileName(), '/Users/felix/code/node-fast-or-slow/lib/test_case.js'); +})(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/run.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/node_modules/stack-trace/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); 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 new file mode 100644 index 0000000..5729bd2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/package.json @@ -0,0 +1,50 @@ +{ + "name": "winston", + "description": "A multi-transport async logging library for Node.js", + "version": "0.5.11", + "author": { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + }, + "contributors": [ + { + "name": "Matthew Bergman", + "email": "mzbphoto@gmail.com" + }, + { + "name": "Marak Squires", + "email": "marak@nodejitsu.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/flatiron/winston.git" + }, + "keywords": [ + "logging", + "sysadmin", + "tools" + ], + "dependencies": { + "async": "0.1.x", + "colors": "0.x.x", + "eyes": "0.1.x", + "loggly": "0.3.x >=0.3.7", + "pkginfo": "0.2.x", + "stack-trace": "0.0.x" + }, + "devDependencies": { + "vows": "0.6.x" + }, + "main": "./lib/winston", + "scripts": { + "test": "vows --spec --isolate" + }, + "engines": { + "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/node_modules/winston/test/cli-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/cli-test.js new file mode 100644 index 0000000..365fba3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/cli-test.js @@ -0,0 +1,40 @@ +/* + * cli-test.js: Tests for the cli levels available in winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston/logger/cli').addBatch({ + "When an instance of winston.Logger": { + topic: function () { + return new winston.Logger({ + transports: [ + new winston.transports.Console() + ] + }) + }, + "the cli() method": { + "should set the appropriate values on the logger": function (logger) { + logger.cli(); + assert.isTrue(logger.padLevels); + assert.isTrue(logger.transports.console.colorize); + assert.isFalse(logger.transports.console.timestamp); + Object.keys(winston.config.cli.levels).forEach(function (level) { + assert.isNumber(logger.levels[level]); + }); + + Object.keys(winston.config.cli.colors).forEach(function (color) { + assert.isString(winston.config.allColors[color]); + }); + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/container-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/container-test.js new file mode 100644 index 0000000..2fcc26a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/container-test.js @@ -0,0 +1,99 @@ +/* + * container-test.js: Tests for the Container object + * + * (C) 2011 Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + fs = require('fs'), + http = require('http'), + path = require('path'), + vows = require('vows'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston/container').addBatch({ + "An instance of winston.Container": { + topic: new winston.Container(), + "the add() method": { + topic: function (container) { + return container.add('default-test'); + }, + "should correctly instantiate a Logger": function (logger) { + assert.instanceOf(logger, winston.Logger); + }, + "the get() method": { + topic: function (logger, container) { + this.callback.apply(this, arguments); + }, + "should respond with the logger previously created": function (existing, container) { + var logger = container.get('default-test'); + assert.isTrue(existing === logger); + } + }, + "the has() method": { + topic: function (logger, container) { + this.callback.apply(this, arguments); + }, + "should indicate `default-test` logger exists": function (existing, container) { + assert.isTrue(container.has('default-test')); + }, + "should indicate `not-has` logger doesnt exists": function (existing, container) { + assert.isFalse(container.has('not-has')); + } + }, + "the close() method": { + topic: function (logger, container) { + this.callback.apply(this, arguments); + }, + "should remove the specified logger": function (logger, container) { + container.close('default-test'); + assert.isTrue(!container.loggers['default-test']); + } + } + } + }, + "An instance of winston.Container with explicit transports": { + topic: function () { + this.port = 9412; + this.transports = [ + new winston.transports.Webhook({ + port: this.port + }) + ]; + + this.container = new winston.Container({ + transports: this.transports + }); + + return null; + }, + "the get() method": { + topic: function (container) { + var server = http.createServer(function (req, res) { + res.end(); + }); + + server.listen(this.port, this.callback.bind(this, null)); + }, + "should add the logger correctly": function () { + this.someLogger = this.container.get('some-logger'); + assert.isObject(this.someLogger.transports); + assert.instanceOf(this.someLogger.transports['webhook'], winston.transports.Webhook); + assert.strictEqual(this.someLogger.transports['webhook'], this.transports[0]); + }, + "a second call to get()": { + "should respond with the same transport object": function () { + this.someOtherLogger = this.container.get('some-other-logger'); + + assert.isObject(this.someOtherLogger.transports); + assert.instanceOf(this.someOtherLogger.transports['webhook'], winston.transports.Webhook); + assert.strictEqual(this.someOtherLogger.transports['webhook'], this.transports[0]); + assert.strictEqual(this.someOtherLogger.transports['webhook'], this.someLogger.transports['webhook']); + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/custom-timestamp-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/custom-timestamp-test.js new file mode 100644 index 0000000..c9753e2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/custom-timestamp-test.js @@ -0,0 +1,62 @@ +/* + * custom-timestamp-test.js: Test function as timestamp option for transport `{ timestamp: function () {} }` + * + * (C) 2011 Charlie Robbins, Tom Shinnick + * MIT LICENSE + * + */ + +var assert = require('assert'), + events = require('events'), + fs = require('fs'), + path = require('path'), + vows = require('vows'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +function assertTimestamp (basename, options) { + var filename = path.join(__dirname, 'fixtures', 'logs', basename + '.log'); + + try { fs.unlinkSync(filename) } + catch (ex) { } + + return { + topic: function () { + options.filename = filename; + var transport = new (winston.transports.File)(options); + + // We must wait until transport file has emitted the 'flush' + // event to be sure the file has been created and written + transport.once('flush', this.callback.bind(this, null, filename)); + transport.log('info', 'When a fake tree falls in the forest...', null, function () {}); + }, + "should log with the appropriate timestamp": function (_, filename) { + var data = fs.readFileSync(filename, 'utf8'); + assert.isNotNull(data.match(options.pattern)); + } + } +} + +vows.describe('winston/transport/timestamp').addBatch({ + "When timestamp option is used": { + "with file transport": { + "with value set to false": assertTimestamp('noTimestamp', { + pattern: /^info\:/, + json: false, + timestamp: false + }), + "with value set to true ": assertTimestamp('defaultTimestamp', { + pattern: /^\d\d? \w{3}/, + json: false, + timestamp: true + }), + "and function value": assertTimestamp('customTimestamp', { + pattern: /^\d{8}\./, + json: false, + timestamp: function () { + return '20110803.171657'; + } + }) + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/exception-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/exception-test.js new file mode 100644 index 0000000..6bc8aec --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/exception-test.js @@ -0,0 +1,46 @@ +/* + * exception-test.js: Tests for exception data gathering in winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston/exception').addBatch({ + "When using the winston exception module": { + "the getProcessInfo() method": { + topic: winston.exception.getProcessInfo(), + "should respond with the appropriate data": function (info) { + helpers.assertProcessInfo(info); + } + }, + "the getOsInfo() method": { + topic: winston.exception.getOsInfo(), + "should respond with the appropriate data": function (info) { + helpers.assertOsInfo(info); + } + }, + "the getTrace() method": { + topic: winston.exception.getTrace(new Error()), + "should have the appropriate info": function (trace) { + helpers.assertTrace(trace); + } + }, + "the getAllInfo() method": { + topic: winston.exception.getAllInfo(new Error()), + "should have the appropriate info": function (info) { + assert.isObject(info); + assert.isArray(info.stack); + helpers.assertProcessInfo(info.process); + helpers.assertOsInfo(info.os); + helpers.assertTrace(info.trace); + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/.gitkeep b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-cert.pem b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-cert.pem new file mode 100644 index 0000000..8e4354d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB7DCCAZYCCQC7gs0MDNn6MTANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJV +UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO +BgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEgMB4GCSqGSIb3DQEJARYR +cnlAdGlueWNsb3Vkcy5vcmcwHhcNMTEwMzE0MTgyOTEyWhcNMzgwNzI5MTgyOTEy +WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYD +VQQKEwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEg +MB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwXDANBgkqhkiG9w0BAQEF +AANLADBIAkEAyXb8FrRdKbhrKLgLSsn61i1C7w7fVVVd7OQsmV/7p9WB2lWFiDlC +WKGU9SiIz/A6wNZDUAuc2E+VwtpCT561AQIDAQABMA0GCSqGSIb3DQEBBQUAA0EA +C8HzpuNhFLCI3A5KkBS5zHAQax6TFUOhbpBCR0aTDbJ6F1liDTK1lmU/BjvPoj+9 +1LHwrmh29rK8kBPEjmymCQ== +-----END CERTIFICATE----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-key.pem b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-key.pem new file mode 100644 index 0000000..522903c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/keys/agent2-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOgIBAAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf+6fVgdpVhYg5 +QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAQJBAMT6Bf34+UHKY1ObpsbH +9u2jsVblFq1rWvs8GPMY6oertzvwm3DpuSUp7PTgOB1nLTLYtCERbQ4ovtN8tn3p +OHUCIQDzIEGsoCr5vlxXvy2zJwu+fxYuhTZWMVuo1397L0VyhwIhANQh+yzqUgaf +WRtSB4T2W7ADtJI35ET61jKBty3CqJY3AiAIwju7dVW3A5WeD6Qc1SZGKZvp9yCb +AFI2BfVwwaY11wIgXF3PeGcvACMyMWsuSv7aPXHfliswAbkWuzcwA4TW01ECIGWa +cgsDvVFxmfM5NPSuT/UDTa6R5BFISB5ea0N0AR3I +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/logs/.gitkeep b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/default-exceptions.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/default-exceptions.js new file mode 100644 index 0000000..ab26aa5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/default-exceptions.js @@ -0,0 +1,21 @@ +/* + * default-exceptions.js: A test fixture for logging exceptions with the default winston logger. + * + * (C) 2011 Charlie Robbins + * MIT LICENCE + * + */ + +var path = require('path'), + winston = require('../../../lib/winston'); + +winston.handleExceptions([ + new (winston.transports.File)({ + filename: path.join(__dirname, '..', 'logs', 'default-exception.log'), + handleExceptions: true + }) +]); + +setTimeout(function () { + throw new Error('OH NOES! It failed!'); +}, 1000); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/exit-on-error.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/exit-on-error.js new file mode 100644 index 0000000..fa3dd65 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/exit-on-error.js @@ -0,0 +1,25 @@ +/* + * default-exceptions.js: A test fixture for logging exceptions with the default winston logger. + * + * (C) 2011 Charlie Robbins + * MIT LICENCE + * + */ + +var path = require('path'), + winston = require('../../../lib/winston'); + +winston.exitOnError = function (err) { + return err.message !== 'Ignore this error'; +}; + +winston.handleExceptions([ + new (winston.transports.File)({ + filename: path.join(__dirname, '..', 'logs', 'exit-on-error.log'), + handleExceptions: true + }) +]); + +setTimeout(function () { + throw new Error('Ignore this error'); +}, 1000); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/log-exceptions.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/log-exceptions.js new file mode 100644 index 0000000..43ce7eb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/log-exceptions.js @@ -0,0 +1,25 @@ +/* + * log-exceptions.js: A test fixture for logging exceptions in winston. + * + * (C) 2011 Charlie Robbins + * MIT LICENCE + * + */ + +var path = require('path'), + winston = require('../../../lib/winston'); + +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.File)({ + filename: path.join(__dirname, '..', 'logs', 'exception.log'), + handleExceptions: true + }) + ] +}); + +logger.handleExceptions(); + +setTimeout(function () { + throw new Error('OH NOES! It failed!'); +}, 1000); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/unhandle-exceptions.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/unhandle-exceptions.js new file mode 100644 index 0000000..5d722a7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/fixtures/scripts/unhandle-exceptions.js @@ -0,0 +1,26 @@ +/* + * unhandle-exceptions.js: A test fixture for using `.unhandleExceptions()` winston. + * + * (C) 2011 Charlie Robbins + * MIT LICENCE + * + */ + +var path = require('path'), + winston = require('../../../lib/winston'); + +var logger = new (winston.Logger)({ + transports: [ + new (winston.transports.File)({ + filename: path.join(__dirname, '..', 'logs', 'unhandle-exception.log'), + handleExceptions: true + }) + ] +}); + +logger.handleExceptions(); +logger.unhandleExceptions(); + +setTimeout(function () { + throw new Error('OH NOES! It failed!'); +}, 1000); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/helpers.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/helpers.js new file mode 100644 index 0000000..f961f85 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/helpers.js @@ -0,0 +1,179 @@ +/* + * helpers.js: Test helpers for winston + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + fs = require('fs'), + path = require('path'), + spawn = require('child_process').spawn, + util = require('util'), + loggly = require('loggly'), + vows = require('vows'), + winston = require('../lib/winston'); + +var helpers = exports; + +helpers.loadConfig = function (dir) { + try { + if (helpers.config) return helpers.config; + var configFile = path.join(dir || __dirname, 'fixtures', 'test-config.json'), + stats = fs.statSync(configFile), + config = JSON.parse(fs.readFileSync(configFile).toString()); + + helpers.config = config; + return config; + } + catch (ex) { + console.error('test/fixtures/test-config.json must be created with valid data before running tests'); + return false; + } +}; + +helpers.size = function (obj) { + var size = 0, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + size++; + } + } + + return size; +}; + +helpers.tryUnlink = function (file) { + try { fs.unlinkSync(file) } + catch (ex) { } +}; + +helpers.assertProcessInfo = function (info) { + assert.isNumber(info.pid); + assert.isNumber(info.uid); + assert.isNumber(info.gid); + assert.isString(info.cwd); + assert.isString(info.execPath); + assert.isString(info.version); + assert.isArray(info.argv); + assert.isObject(info.memoryUsage); +}; + +helpers.assertOsInfo = function (info) { + assert.isArray(info.loadavg); + assert.isNumber(info.uptime); +}; + +helpers.assertTrace = function (trace) { + trace.forEach(function (site) { + assert.isTrue(!site.column || typeof site.column === 'number'); + assert.isTrue(!site.line || typeof site.line === 'number'); + assert.isTrue(!site.file || typeof site.file === 'string'); + assert.isTrue(!site.method || typeof site.method === 'string'); + assert.isTrue(!site.function || typeof site.function === 'string'); + assert.isTrue(typeof site.native === 'boolean'); + }); +}; + +helpers.assertLogger = function (logger, level) { + assert.instanceOf(logger, winston.Logger); + assert.isFunction(logger.log); + assert.isFunction(logger.add); + assert.isFunction(logger.remove); + assert.equal(logger.level, level || "info"); + Object.keys(logger.levels).forEach(function (method) { + assert.isFunction(logger[method]); + }); +}; + +helpers.assertConsole = function (transport) { + assert.instanceOf(transport, winston.transports.Console); + assert.isFunction(transport.log); +}; + +helpers.assertFile = function (transport) { + assert.instanceOf(transport, winston.transports.File); + assert.isFunction(transport.log); +} + +helpers.assertLoggly = function (transport) { + assert.instanceOf(transport, winston.transports.Loggly); + assert.isFunction(transport.log); +}; + +helpers.assertWebhook = function (transport) { + assert.instanceOf(transport, winston.transports.Webhook); + assert.isFunction(transport.log); +}; + +helpers.assertCouchdb = function (transport) { + assert.instanceOf(transport, winston.transports.Couchdb); + assert.isFunction(transport.log); +}; + +helpers.assertHandleExceptions = function (options) { + return { + topic: function () { + var that = this, + child = spawn('node', [options.script]); + + helpers.tryUnlink(options.logfile); + child.on('exit', function () { + fs.readFile(options.logfile, that.callback); + }); + }, + "should save the error information to the specified file": function (err, data) { + assert.isTrue(!err); + data = JSON.parse(data); + + assert.isObject(data); + helpers.assertProcessInfo(data.process); + helpers.assertOsInfo(data.os); + helpers.assertTrace(data.trace); + } + } +} + +helpers.testNpmLevels = function (transport, assertMsg, assertFn) { + return helpers.testLevels(winston.config.npm.levels, transport, assertMsg, assertFn); +}; + +helpers.testSyslogLevels = function (transport, assertMsg, assertFn) { + return helpers.testLevels(winston.config.syslog.levels, transport, assertMsg, assertFn); +}; + +helpers.testLevels = function (levels, transport, assertMsg, assertFn) { + var tests = {}; + + Object.keys(levels).forEach(function (level) { + var test = { + topic: function () { + transport.log(level, 'test message', {}, this.callback.bind(this, null)); + } + }; + + test[assertMsg] = assertFn; + tests['with the ' + level + ' level'] = test; + }); + + var metadatatest = { + topic: function () { + transport.log('info', 'test message', { metadata: true }, this.callback.bind(this, null)); + } + }; + + metadatatest[assertMsg] = assertFn; + tests['when passed metadata'] = metadatatest; + + var primmetadatatest = { + topic: function () { + transport.log('info', 'test message', 'metadata', this.callback.bind(this, null)); + } + }; + + primmetadatatest[assertMsg] = assertFn; + tests['when passed primitive metadata'] = primmetadatatest; + + return tests; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-exception-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-exception-test.js new file mode 100644 index 0000000..b077a0a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-exception-test.js @@ -0,0 +1,58 @@ +/* + * exception-test.js: Tests for exception data gathering in winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + path = require('path'), + spawn = require('child_process').spawn, + vows = require('vows'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston/logger/exceptions').addBatch({ + "When using winston": { + "the handleException() method": { + "with a custom winston.Logger instance": helpers.assertHandleExceptions({ + script: path.join(__dirname, 'fixtures', 'scripts', 'log-exceptions.js'), + logfile: path.join(__dirname, 'fixtures', 'logs', 'exception.log') + }), + "with the default winston logger": helpers.assertHandleExceptions({ + script: path.join(__dirname, 'fixtures', 'scripts', 'default-exceptions.js'), + logfile: path.join(__dirname, 'fixtures', 'logs', 'default-exception.log') + }), + "when a custom exitOnError function is set": { + topic: function () { + var that = this, + scriptDir = path.join(__dirname, 'fixtures', 'scripts'); + + that.child = spawn('node', [path.join(scriptDir, 'exit-on-error.js')]); + setTimeout(this.callback.bind(this), 1500); + }, + "should not exit the process": function () { + assert.isFalse(this.child.killed); + this.child.kill(); + } + } + }, + "the unhandleException() method": { + topic: function () { + var that = this, + child = spawn('node', [path.join(__dirname, 'fixtures', 'scripts', 'unhandle-exceptions.js')]), + exception = path.join(__dirname, 'fixtures', 'logs', 'unhandle-exception.log'); + + helpers.tryUnlink(exception); + child.on('exit', function () { + path.exists(exception, that.callback.bind(this, null)); + }); + }, + "should not write to the specified error file": function (err, exists) { + assert.isTrue(!err); + assert.isFalse(exists); + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-rewriter-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-rewriter-test.js new file mode 100644 index 0000000..4753fcc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/log-rewriter-test.js @@ -0,0 +1,98 @@ +/* + * log-rewriter-test.js: Tests for rewriting metadata in winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + vows = require('vows'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston/logger/rewriter').addBatch({ + "An instance of winston.Logger": { + topic: new (winston.Logger)({transports: [ + new (winston.transports.Console)({ level: 'info' }) + ]}), + "the addRewriter() method": { + topic: function(logger) { + logger.addRewriter(function(level, msg, meta) { + meta.level = level; + meta.msg = msg; + meta.foo = 'bar'; + return meta; + }); + return logger; + }, + "should add the rewriter": function(logger) { + assert.equal(helpers.size(logger.rewriters), 1); + }, + "the log() method": { + topic: function(logger) { + logger.once('logging', this.callback); + logger.log('info', 'test message', {"a": "b"}); + }, + "should run the rewriter": function(transport, level, msg, meta) { + assert.equal(meta.a, 'b'); + assert.equal(meta.level, 'info'); + assert.equal(meta.msg, 'test message'); + assert.equal(meta.foo, 'bar'); + } + } + } + } +}).addBatch({ + "An instance of winston.Logger with explicit rewriter": { + topic: new (winston.Logger)({transports: [ + new (winston.transports.Console)({ level: 'info'}) + ], rewriters: [ + function(level, msg, meta) { + meta.level = level; + meta.msg = msg; + meta.foo = 'bar'; + return meta; + } + ]}), + "should add the rewriter": function(logger) { + assert.equal(helpers.size(logger.rewriters), 1); + }, + "the log() method": { + topic: function(logger) { + logger.once('logging', this.callback); + logger.log('info', 'test message', {"a": "b"}); + }, + "should run the rewriter": function(transport, level, msg, meta) { + assert.equal(meta.a, 'b'); + assert.equal(meta.level, 'info'); + assert.equal(meta.msg, 'test message'); + assert.equal(meta.foo, 'bar'); + } + } + } +}).addBatch({ + "An instance of winston.Logger with rewriters": { + topic: new (winston.Logger)({transports: [ + new (winston.transports.Console)({ level: 'info' }) + ], rewriters: [ + function(level, msg, meta) { + meta.numbers.push(1); + return meta; + }, + function(level, msg, meta) { + meta.numbers.push(2); + return meta; + } + ]}), + "the log() method": { + topic: function(logger) { + logger.once('logging', this.callback); + logger.log('info', 'test message', {"numbers": [0]}); + }, + "should run the rewriters in correct order": function(transport, level, msg, meta) { + assert.deepEqual(meta.numbers, [0, 1, 2]); + } + } + } +}).export(module); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/logger-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/logger-test.js new file mode 100644 index 0000000..0105825 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/logger-test.js @@ -0,0 +1,199 @@ +/* + * logger-test.js: Tests for instances of the winston Logger + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winton/logger').addBatch({ + "An instance of winston.Logger": { + topic: new (winston.Logger)({ transports: [new (winston.transports.Console)({ level: 'info' })] }), + "should have the correct methods / properties defined": function (logger) { + helpers.assertLogger(logger); + }, + "the add() with an unsupported transport": { + "should throw an error": function () { + assert.throws(function () { logger.add('unsupported') }, Error); + } + } + } +}).addBatch({ + "An instance of winston.Logger with no transports": { + topic: new (winston.Logger)({ emitErrs: true }), + "the log() method should throw an error": function (logger) { + assert.throws(function () { logger.log('anything') }, Error); + }, + "the extend() method called on an empty object": { + topic: function (logger) { + var empty = {}; + logger.extend(empty); + return empty; + }, + "should define the appropriate methods": function (extended) { + ['log', 'profile', 'startTimer'].concat(Object.keys(winston.config.npm.levels)).forEach(function (method) { + assert.isFunction(extended[method]); + }); + } + }, + "the add() method with a supported transport": { + topic: function (logger) { + return logger.add(winston.transports.Console); + }, + "should add the console Transport onto transports": function (logger) { + assert.equal(helpers.size(logger.transports), 1); + helpers.assertConsole(logger.transports.console); + }, + "should throw an error when the same Transport is added": function (logger) { + assert.throws(function () { logger.add(winston.transports.Console) }, Error); + }, + "the log() method": { + topic: function (logger) { + logger.once('logging', this.callback); + logger.log('info', 'test message'); + }, + "should emit the 'log' event with the appropriate transport": function (transport, ign) { + helpers.assertConsole(transport); + } + }, + "the profile() method": { + "when passed a callback": { + topic: function (logger) { + var that = this; + logger.profile('test1'); + setTimeout(function () { + logger.profile('test1', function (err, level, msg, meta) { + that.callback(err, level, msg, meta, logger); + }); + }, 1000); + }, + "should respond with the appropriate profile message": function (err, level, msg, meta, logger) { + assert.isNull(err); + assert.equal(level, 'info'); + assert.match(meta.duration, /(\d+)ms/); + assert.isTrue(typeof logger.profilers['test'] === 'undefined'); + } + }, + "when not passed a callback": { + topic: function (logger) { + var that = this; + logger.profile('test2'); + logger.once('logging', that.callback.bind(null, null)); + setTimeout(function () { + logger.profile('test2'); + }, 1000); + }, + "should respond with the appropriate profile message": function (err, transport, level, msg, meta) { + assert.isNull(err); + assert.equal(level, 'info'); + assert.match(meta.duration, /(\d+)ms/); + } + } + }, + "the startTimer() method": { + "when passed a callback": { + topic: function (logger) { + var that = this; + var timer = logger.startTimer() + setTimeout(function () { + timer.done('test', function (err, level, msg, meta) { + that.callback(err, level, msg, meta, logger); + }); + }, 1000); + }, + "should respond with the appropriate message": function (err, level, msg, meta, logger) { + assert.isNull(err); + assert.equal(level, 'info'); + assert.match(meta.duration, /(\d+)ms/); + } + }, + "when not passed a callback": { + topic: function (logger) { + var that = this; + var timer = logger.startTimer() + logger.once('logging', that.callback.bind(null, null)); + setTimeout(function () { + timer.done(); + }, 1000); + }, + "should respond with the appropriate message": function (err, transport, level, msg, meta) { + assert.isNull(err); + assert.equal(level, 'info'); + assert.match(meta.duration, /(\d+)ms/); + + var duration = parseInt(meta.duration); + assert.isNumber(duration); + assert.isTrue(duration > 900 && duration < 1100); + } + } + }, + "and adding an additional transport": { + topic: function (logger) { + return logger.add(winston.transports.File, { + filename: path.join(__dirname, 'fixtures', 'logs', 'testfile2.log') + }); + }, + "should be able to add multiple transports": function (logger) { + assert.equal(helpers.size(logger.transports), 2); + helpers.assertConsole(logger.transports.console); + helpers.assertFile(logger.transports.file); + } + } + } + } +}).addBatch({ + "The winston logger": { + topic: new (winston.Logger)({ + transports: [ + new (winston.transports.Console)(), + new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog.log' )}) + ] + }), + "should return have two transports": function (logger) { + assert.equal(helpers.size(logger.transports), 2); + }, + "the remove() with an unadded transport": { + "should throw an Error": function (logger) { + assert.throws(function () { logger.remove(winston.transports.Loggly) }, Error); + } + }, + "the remove() method with an added transport": { + topic: function (logger) { + return logger.remove(winston.transports.Console); + }, + "should remove the Console transport from transports": function (logger) { + assert.equal(helpers.size(logger.transports), 1); + helpers.assertFile(logger.transports.file); + }, + "and removing an additional transport": { + topic: function (logger) { + return logger.remove(winston.transports.File); + }, + "should remove File transport from transports": function (logger) { + assert.equal(helpers.size(logger.transports), 0); + } + } + } + } +}).addBatch({ + "The winston logger": { + topic: new (winston.Logger)({ + transports: [ + new (winston.transports.Console)(), + new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog.log' )}) + ] + }), + "the clear() method": { + "should remove all transports": function (logger) { + logger.clear(); + assert.equal(helpers.size(logger.transports), 0); + } + } + } +}).export(module); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/console-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/console-test.js new file mode 100644 index 0000000..07f5a6e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/console-test.js @@ -0,0 +1,39 @@ +/* + * console-test.js: Tests for instances of the Console transport + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var npmTransport = new (winston.transports.Console)(), + syslogTransport = new (winston.transports.Console)({ levels: winston.config.syslog.levels }); + +vows.describe('winston/transports/console').addBatch({ + "An instance of the Console Transport": { + "with npm levels": { + "should have the proper methods defined": function () { + helpers.assertConsole(npmTransport); + }, + "the log() method": helpers.testNpmLevels(npmTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + }, + "with syslog levels": { + "should have the proper methods defined": function () { + helpers.assertConsole(syslogTransport); + }, + "the log() method": helpers.testSyslogLevels(syslogTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/couchdb-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/couchdb-test.js new file mode 100644 index 0000000..d0057e8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/couchdb-test.js @@ -0,0 +1,47 @@ +/* + * couchdb-test.js: Tests for instances of the Couchdb transport + * + * (C) 2011 Max Ogden + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + fs = require('fs'), + http = require('http'), + assert = require('assert'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var couchdbTransport = new (winston.transports.Couchdb)({ + "host": "localhost", + "port": 4567, + "db": "logs" +}); + +var server = http.createServer(function (req, res) { + res.end(); +}); + +server.listen(4567); + +vows.describe('winston/transports/couchdb').addBatch({ + "An instance of the Couchdb Transport": { + "when passed valid options": { + "should have the proper methods defined": function () { + helpers.assertCouchdb(couchdbTransport); + }, + "the log() method": helpers.testNpmLevels(couchdbTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + } +}).addBatch({ + "When the tests are over": { + "the server should cleanup": function () { + server.close(); + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxfiles-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxfiles-test.js new file mode 100644 index 0000000..a9fa89e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxfiles-test.js @@ -0,0 +1,102 @@ +/* + * file-maxfiles-test.js: Tests for instances of the File transport setting the max file size, + * and setting a number for max files created. + * maxSize * maxFiles = total storage used by winston. + * + * (C) 2011 Daniel Aristizabal + * MIT LICENSE + * + */ + +var assert = require('assert'), + exec = require('child_process').exec, + fs = require('fs'), + path = require('path'), + vows = require('vows'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var maxfilesTransport = new winston.transports.File({ + timestamp: false, + json: false, + filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxfiles.log'), + maxsize: 4096, + maxFiles: 3 +}); + +vows.describe('winston/transports/file/maxfiles').addBatch({ + "An instance of the File Transport": { + "when passed a valid filename": { + topic: maxfilesTransport, + "should be a valid transporter": function (transportTest) { + helpers.assertFile(transportTest); + }, + "should set the maxFiles option correctly": function (transportTest) { + assert.isNumber(transportTest.maxFiles); + } + }, + "when delete old test files": { + topic: function () { + exec('rm -rf ' + path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxfiles*'), this.callback); + }, + "and when passed more files than the maxFiles": { + topic: function () { + var that = this, + created = 0; + + function data(ch) { + return new Array(1018).join(String.fromCharCode(65 + ch)); + }; + + function logKbytes(kbytes, txt) { + // + // With no timestamp and at the info level, + // winston adds exactly 7 characters: + // [info](4)[ :](2)[\n](1) + // + for (var i = 0; i < kbytes; i++) { + maxfilesTransport.log('info', data(txt), null, function () { }); + } + } + + maxfilesTransport.on('logged', function () { + if (++created === 6) { + return that.callback(); + } + + logKbytes(4, created); + }); + + logKbytes(4, created); + }, + "should be only 3 files called 5.log, 4.log and 3.log": function () { + for (var num = 0; num < 6; num++) { + var file = !num ? 'testmaxfiles.log' : 'testmaxfiles' + num + '.log', + fullpath = path.join(__dirname, '..', 'fixtures', 'logs', file); + + // There should be no files with that name + if (num >= 0 && num < 3) { + return assert.throws(function () { + fs.statSync(file); + }, Error); + } + + // The other files should be exist + assert.doesNotThrow(function () { + fs.statSync(file); + }, Error); + } + }, + "should have the correct content": function () { + ['D', 'E', 'F'].forEach(function (name, inx) { + var counter = inx + 3, + logsDir = path.join(__dirname, '..', 'fixtures', 'logs'), + content = fs.readFileSync(path.join(logsDir, 'testmaxfiles' + counter + '.log'), 'utf-8'); + // The content minus the 7 characters added by winston + assert.lengthOf(content.match(new RegExp(name, 'g')), 4068); + }); + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxsize-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxsize-test.js new file mode 100644 index 0000000..7d20e08 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-maxsize-test.js @@ -0,0 +1,82 @@ +/* + * file-test.js: Tests for instances of the File transport + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var assert = require('assert'), + exec = require('child_process').exec, + fs = require('fs'), + path = require('path'), + vows = require('vows'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var maxsizeTransport = new winston.transports.File({ + timestamp: false, + json: false, + filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxsize.log'), + maxsize: 4096 +}); + +vows.describe('winston/transports/file/maxsize').addBatch({ + "An instance of the File Transport": { + "when passed a valid filename": { + "the log() method": { + topic: function () { + exec('rm -rf ' + path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxsize*'), this.callback); + }, + "when passed more than the maxsize": { + topic: function () { + var that = this, + data = new Array(1018).join('-'); + + // + // Setup a list of files which we will later stat. + // + that.files = []; + + function logKbytes (kbytes) { + // + // With no timestamp and at the info level, + // winston adds exactly 7 characters: + // [info](4)[ :](2)[\n](1) + // + for (var i = 0; i < kbytes; i++) { + maxsizeTransport.log('info', data, null, function () { }); + } + } + + maxsizeTransport.on('open', function (file) { + var match = file.match(/(\d+)\.log$/), + count = match ? match[1] : 0; + + that.files.push(file); + + if (that.files.length === 5) { + return that.callback(); + } + + logKbytes(4); + }); + + logKbytes(4); + }, + "should create multiple files correctly": function () { + this.files.forEach(function (file) { + try { + var stats = fs.statSync(file); + assert.equal(stats.size, 4096); + } + catch (ex) { + assert.isNull(ex); + } + }); + } + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-test.js new file mode 100644 index 0000000..c287794 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/file-test.js @@ -0,0 +1,50 @@ +/* + * file-test.js: Tests for instances of the File transport + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + fs = require('fs'), + assert = require('assert'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var stream = fs.createWriteStream(path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log')), + fileTransport = new (winston.transports.File)({ filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfilename.log') }), + streamTransport = new (winston.transports.File)({ stream: stream }); + +vows.describe('winston/transports/file').addBatch({ + "An instance of the File Transport": { + "when passed a valid filename": { + "should have the proper methods defined": function () { + helpers.assertFile(fileTransport); + }, + "the log() method": helpers.testNpmLevels(fileTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + }, + "when passed a valid file stream": { + "should have the proper methods defined": function () { + helpers.assertFile(streamTransport); + }, + "the log() method": helpers.testNpmLevels(streamTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + } +}).addBatch({ + "These tests have a non-deterministic end": { + topic: function () { + setTimeout(this.callback, 200); + }, + "and this should be fixed before releasing": function () { + assert.isTrue(true); + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/loggly-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/loggly-test.js new file mode 100644 index 0000000..8271b90 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/loggly-test.js @@ -0,0 +1,61 @@ +/* + * loggly-test.js: Tests for instances of the Loggly transport + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + assert = require('assert'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var config = helpers.loadConfig(); + +if (!config) { + return; +} + +var tokenTransport = new (winston.transports.Loggly)({ + subdomain: config.transports.loggly.subdomain, + inputToken: config.transports.loggly.inputToken + }), + nameTransport = new (winston.transports.Loggly)({ + subdomain: config.transports.loggly.subdomain, + inputName: config.transports.loggly.inputName, + auth: config.transports.loggly.auth + }); + +vows.describe('winston/transports/loggly').addBatch({ + "An instance of the Loggly Transport": { + "when passed an input token": { + "should have the proper methods defined": function () { + helpers.assertLoggly(tokenTransport); + }, + "the log() method": helpers.testNpmLevels(tokenTransport, "should log messages to loggly", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }), + "the log() method with no metadata": { + topic: function () { + tokenTransport.log('info', 'test-message', null, this.callback.bind(null, null)); + }, + "should respond immediately": function () { + assert.isTrue(true); + } + } + }, + "when passed an input name": { + "should have the proper methods defined": function () { + helpers.assertLoggly(nameTransport); + }, + "the log() method": helpers.testNpmLevels(nameTransport, "should log messages to loggly", function (ign, err, result) { + assert.isNull(err); + assert.isTrue(result === true || result.response === 'ok'); + }) + } + } +}).export(module); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/webhook-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/webhook-test.js new file mode 100644 index 0000000..e106374 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/transports/webhook-test.js @@ -0,0 +1,119 @@ +/* + * webhook-test.js: Tests for instances of the Webhook transport + * + * (C) 2011 Marak Squires + * MIT LICENSE + * + */ + +var path = require('path'), + vows = require('vows'), + fs = require('fs'), + http = require('http'), + https = require('https'), + assert = require('assert'), + winston = require('../../lib/winston'), + helpers = require('../helpers'); + +var webhookTransport = new (winston.transports.Webhook)({ + "host": "localhost", + "port": 8080, + "path": "/winston-test" +}); + +var httpsWebhookTransport = new (winston.transports.Webhook)({ + "host": "localhost", + "port": 8081, + "path": "/winston-test", + "ssl": true +}); + +var authWebhookTransport = new (winston.transports.Webhook)({ + "host": "localhost", + "port": 8080, + "path": "/winston-auth-test", + "auth": { + "username": "winston", + "password": "churchill" + } +}); + +var requestsAuthenticated = true; + +var server = http.createServer(function (req, res) { + if (req.url == '/winston-auth-test') { + // + // Test if request has been correctly authenticated + // + // Strip 'Basic' from Authorization header + var signature = req.headers['authorization'].substr(6); + requestsAuthenticated = requestsAuthenticated && + new Buffer(signature, 'base64').toString('utf8') == 'winston:churchill'; + } + res.end(); +}); + +server.listen(8080); + + +var httpsServer = https.createServer({ + cert: fs.readFileSync(path.join(__dirname, '..', 'fixtures', 'keys', 'agent2-cert.pem')), + key: fs.readFileSync(path.join(__dirname, '..', 'fixtures', 'keys', 'agent2-key.pem')) +}, function (req, res) { + res.end(); +}); + +httpsServer.listen(8081); + +vows.describe('winston/transports/webhook').addBatch({ + "An instance of the Webhook Transport": { + "when passed valid options": { + "should have the proper methods defined": function () { + helpers.assertWebhook(webhookTransport); + }, + "the log() method": helpers.testNpmLevels(webhookTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + }, + "An https instance of the Webhook Transport": { + "when passed valid options": { + "should have the proper methods defined": function () { + helpers.assertWebhook(httpsWebhookTransport); + }, + "the log() method": helpers.testNpmLevels(httpsWebhookTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + }, + "An http Basic Auth instance of the Webhook Transport": { + "when passed valid options": { + "should have the proper methods defined": function () { + helpers.assertWebhook(authWebhookTransport); + }, + "the log() method": helpers.testNpmLevels(authWebhookTransport, "should respond with true", function (ign, err, logged) { + assert.isNull(err); + assert.isTrue(logged); + }) + } + } +}).addBatch({ + "When the tests are over": { + topic: function () { + // + // Delay destruction of the server since the + // WebHook transport responds before the request + // has actually be completed. + // + setTimeout(this.callback, 1000); + }, + "the server should cleanup": function () { + server.close(); + }, + "requests have been correctly authenticated": function () { + assert.ok(requestsAuthenticated); + } + } +}).export(module); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/winston-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/winston-test.js new file mode 100644 index 0000000..e790cb9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/node_modules/winston/test/winston-test.js @@ -0,0 +1,100 @@ +/* + * logger-test.js: Tests for instances of the winston Logger + * + * (C) 2010 Charlie Robbins + * MIT LICENSE + * + */ + +var fs = require('fs'), + path = require('path'), + vows = require('vows'), + http = require('http'), + assert = require('assert'), + winston = require('../lib/winston'), + helpers = require('./helpers'); + +vows.describe('winston').addBatch({ + "The winston module": { + topic: function () { + winston.default.transports.console.level = 'silly'; + return null; + }, + "should have the correct methods defined": function () { + assert.isObject(winston.transports); + assert.isFunction(winston.Transport); + assert.isTrue(!winston.transports.Transport); + assert.isFunction(winston.transports.Console); + assert.isFunction(winston.transports.File); + assert.isFunction(winston.transports.Loggly); + assert.isFunction(winston.transports.Webhook); + assert.isObject(winston.default.transports.console); + assert.isFalse(winston.emitErrs); + assert.isObject(winston.config); + ['Logger', 'add', 'remove', 'extend'] + .concat(Object.keys(winston.config.npm.levels)) + .forEach(function (key) { + assert.isFunction(winston[key]); + }); + }, + "it should": { + topic: function () { + fs.readFile(path.join(__dirname, '..', 'package.json'), this.callback); + }, + "have the correct version set": function (err, data) { + assert.isNull(err); + data = JSON.parse(data.toString()); + assert.equal(winston.version, data.version); + } + }, + "the log() method": helpers.testNpmLevels(winston, "should respond without an error", function (err) { + assert.isNull(err); + }), + "the extend() method called on an empty object": { + topic: function (logger) { + var empty = {}; + winston.extend(empty); + return empty; + }, + "should define the appropriate methods": function (extended) { + ['log', 'profile', 'startTimer'].concat(Object.keys(winston.config.npm.levels)).forEach(function (method) { + assert.isFunction(extended[method]); + }); + } + } + } +}).addBatch({ + "The winston module": { + "the setLevels() method": { + topic: function () { + winston.setLevels(winston.config.syslog.levels); + return null; + }, + "should have the proper methods defined": function () { + assert.isObject(winston.transports); + assert.isFunction(winston.transports.Console); + assert.isFunction(winston.transports.Loggly); + assert.isFunction(winston.transports.Webhook); + assert.isObject(winston.default.transports.console); + assert.isFalse(winston.emitErrs); + assert.isObject(winston.config); + + var newLevels = Object.keys(winston.config.syslog.levels); + ['Logger', 'add', 'remove', 'extend'] + .concat(newLevels) + .forEach(function (key) { + assert.isFunction(winston[key]); + }); + + + Object.keys(winston.config.npm.levels) + .filter(function (key) { + return newLevels.indexOf(key) === -1; + }) + .forEach(function (key) { + assert.isTrue(typeof winston[key] === 'undefined'); + }); + } + } + } +}).export(module); 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 new file mode 100644 index 0000000..8992f92 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/package.json @@ -0,0 +1,52 @@ +{ + "name": "prompt", + "description": "A beautiful command-line prompt for node.js", + "version": "0.1.12", + "author": { + "name": "Nodejitsu Inc.", + "email": "info@nodejitsu.com" + }, + "contributors": [ + { + "name": "Charlie Robbins", + "email": "charlie@nodejitsu.com" + }, + { + "name": "Joshua Holbrook", + "email": "josh.holbrook@gmail.com" + }, + { + "name": "Bradley Meck", + "email": "bradley.meck@gmail.com" + }, + { + "name": "Maciej Malecki", + "email": "maciej@nodejitsu.com" + } + ], + "repository": { + "type": "git", + "url": "http://github.com/flatiron/prompt.git" + }, + "dependencies": { + "async": "0.1.x", + "colors": "0.x.x", + "pkginfo": "0.x.x", + "winston": "0.5.x" + }, + "devDependencies": { + "vows": "0.6.x" + }, + "main": "./lib/prompt", + "scripts": { + "test": "vows test/prompt-test.js --spec", + "test-all": "vows --spec" + }, + "engines": { + "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/prompt/test/helpers.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/helpers.js new file mode 100644 index 0000000..ff9f233 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/helpers.js @@ -0,0 +1,102 @@ +/* + * helpers.js: Test helpers for the prompt tests. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var events = require('events'), + stream = require('stream'), + util = require('util'), + prompt = require('../lib/prompt'); + +var helpers = exports; + +var MockReadWriteStream = helpers.MockReadWriteStream = function () { + // + // No need to do anything here, it's just a mock. + // +}; + +util.inherits(MockReadWriteStream, events.EventEmitter); + +['resume', 'pause', 'setEncoding', 'flush'].forEach(function (method) { + MockReadWriteStream.prototype[method] = function () { /* Mock */ }; +}); + +MockReadWriteStream.prototype.write = function (msg) { + this.emit('data', msg); +}; + +// +// Create some mock streams for asserting against +// in our prompt tests. +// +helpers.stdin = new MockReadWriteStream(); +helpers.stdout = new MockReadWriteStream(); +helpers.stderr = new MockReadWriteStream(); + +// +// Monkey punch `util.error` to silence console output +// and redirect to helpers.stderr for testing. +// +util.error = function () { + helpers.stderr.write.apply(helpers.stderr, arguments); +} + +helpers.properties = { + riffwabbles: { + name: 'riffwabbles', + validator: /^[\w|\-]+$/, + warning: 'riffwabbles can only be letters, numbers, and dashes', + default: 'foobizzles' + }, + username: { + name: 'username', + validator: /^[\w|\-]+$/, + warning: 'Username can only be letters, numbers, and dashes' + }, + notblank: { + name: 'notblank', + empty: false + }, + password: { + name: 'password', + hidden: true, + empty: false + }, + badValidator: { + name: 'bad-validator', + validator: ['cant', 'use', 'array'] + }, + animal: { + name: 'animal', + description: 'Enter an animal', + default: 'dog', + validator: /dog|cat/ + }, + sound: { + name: 'sound', + description: 'What sound does this animal make?', + validator: function (value) { + var animal = prompt.history(0).value; + + return animal === 'dog' && value === 'woof' + || animal === 'cat' && value === 'meow'; + } + }, + fnvalidator: { + name: 'fnvalidator', + validator: function (line) { + return line.slice(0,2) == 'fn'; + }, + warning: 'fnvalidator must start with "fn"' + }, + cbvalidator: { + name: 'cbvalidator', + validator: function (line, next) { + next(line.slice(0,2) == 'cb'); + }, + warning: 'cbvalidator must start with "cb"' + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/interactive-prompt-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/interactive-prompt-test.js new file mode 100644 index 0000000..75ccc0c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/interactive-prompt-test.js @@ -0,0 +1,39 @@ +/* + * prompt-test.js: Tests for prompt. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var assert = require('assert'), + vows = require('vows'), + prompt = require('../lib/prompt'), + winston = require('winston').cli(), + helpers = require('./helpers'); + +vows.describe('prompt/interactive').addBatch({ + "When using prompt": { + topic: function () { + // + // Reset the prompt for interactive testing + // + prompt.started = false; + prompt.start(); + winston.info('These prompt tests are interactive'); + winston.info('Not following instructions will result in test failure'); + return null; + }, + "the getInput() method": { + "when passed a complex property with `hidden: true`": { + topic: function () { + winston.info('When prompted, enter: 12345 [backspace] [backspace] [enter]'); + prompt.getInput(helpers.properties.password, this.callback); + }, + "should respond with `123`": function (err, result) { + assert.isNull(err); + assert.equal(result, '123'); + } + } + } + } +}).export(module); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/prompt-test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/prompt-test.js new file mode 100644 index 0000000..096f6ba --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/prompt/test/prompt-test.js @@ -0,0 +1,390 @@ +/* + * prompt-test.js: Tests for prompt. + * + * (C) 2010, Nodejitsu Inc. + * + */ + +var assert = require('assert'), + vows = require('vows'), + prompt = require('../lib/prompt'), + helpers = require('./helpers'); + +vows.describe('prompt').addBatch({ + "When using prompt": { + topic: function () { + // + // Reset the prompt for mock testing + // + prompt.started = false; + prompt.start({ + stdin: helpers.stdin, + stdout: helpers.stdout + }); + + return null; + }, + "the readLine() method": { + topic: function () { + prompt.readLine(this.callback); + helpers.stdin.write('testing\n'); + }, + "should respond with data from the stdin stream": function (err, input) { + assert.isNull(err); + assert.equal(input, 'testing'); + } + }, + "the readLineHidden() method": { + "when given backspaces": { + topic: function () { + prompt.readLineHidden(this.callback); + helpers.stdin.write('no-\x08backspace.\x7f'); + helpers.stdin.write('\n'); + }, + "should remove the proper characters": function (err,input) { + assert.isNull(err); + assert.equal(input, 'nobackspace'); + } + }, + topic: function () { + prompt.readLineHidden(this.callback); + helpers.stdin.write('testing'); + helpers.stdin.write('\r\n'); + }, + "should respond with data from the stdin stream": function (err, input) { + assert.isNull(err); + assert.equal(input, 'testing'); + } + }, + "the getInput() method": { + "with a simple string prompt": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }) + + prompt.getInput('test input', this.callback); + helpers.stdin.write('test value\n'); + }, + "should prompt to stdout and respond with data": function (err, input) { + assert.isNull(err); + assert.equal(input, 'test value'); + assert.isTrue(this.msg.indexOf('test input') !== -1); + } + }, + "with any field that is not supposed to be empty": { + "and we don't provide any input": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + helpers.stderr.once('data', function (msg) { + that.errmsg = msg; + }); + + prompt.getInput(helpers.properties.notblank, function () {}); + prompt.once('invalid', this.callback.bind(null, null)) + helpers.stdin.write('\n'); + }, + + "should prompt with an error": function (ign, prop, input) { + assert.isObject(prop); + assert.equal(input, ''); + assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1); + assert.isTrue(this.msg.indexOf('notblank') !== -1); + } + } + }, + "with a hidden field that is not supposed to be empty": { + "and we provide valid input": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + prompt.getInput('password', this.callback); + helpers.stdin.write('trustno1\n'); + }, + + "should prompt to stdout and respond with data": function (err, input) { + assert.isNull(err); + assert.equal(input, 'trustno1'); + assert.isTrue(this.msg.indexOf('password') !== -1); + } + }, + "and we don't provide an input": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + helpers.stderr.once('data', function (msg) { + that.errmsg = msg; + }); + + prompt.getInput(helpers.properties.password, function () {}); + prompt.once('invalid', this.callback.bind(null, null)) + helpers.stdin.write('\n'); + }, + "should prompt with an error": function (ign, prop, input) { + assert.isObject(prop); + assert.equal(input, ''); + assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1); + assert.isTrue(this.msg.indexOf('password') !== -1); + } + } + }, + "with a complex property prompt": { + "and a valid input": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + prompt.getInput(helpers.properties.username, this.callback); + helpers.stdin.write('some-user\n'); + }, + "should prompt to stdout and respond with data": function (err, input) { + assert.isNull(err); + assert.equal(input, 'some-user'); + assert.isTrue(this.msg.indexOf('username') !== -1); + } + }, + "and an invalid input": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + helpers.stderr.once('data', function (msg) { + that.errmsg = msg; + }) + + prompt.getInput(helpers.properties.username, this.callback); + + prompt.once('invalid', function () { + prompt.once('prompt', function () { + process.nextTick(function () { + helpers.stdin.write('some-user\n'); + }) + }) + }); + + helpers.stdin.write('some -user\n'); + }, + "should prompt with an error before completing the operation": function (err, input) { + assert.isNull(err); + assert.equal(input, 'some-user'); + assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1); + assert.isTrue(this.msg.indexOf('username') !== -1); + } + }, + "with an invalid validator (array)": { + topic: function () { + prompt.getInput(helpers.properties.badValidator, this.callback); + }, + "should respond with an error": function (err, ign) { + assert.isTrue(!!err); + } + } + } + }, + "the get() method": { + "with a simple string prompt": { + "that is not a property in prompt.properties": { + topic: function () { + var that = this; + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }) + + prompt.get('test input', this.callback); + helpers.stdin.write('test value\n'); + }, + "should prompt to stdout and respond with the value": function (err, result) { + assert.isNull(err); + assert.include(result, 'test input'); + assert.equal(result['test input'], 'test value'); + assert.isTrue(this.msg.indexOf('test input') !== -1); + } + }, + "that is a property name in prompt.properties": { + "with a default value": { + topic: function () { + var that = this; + + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + prompt.properties['riffwabbles'] = helpers.properties['riffwabbles']; + prompt.get('riffwabbles', this.callback); + helpers.stdin.write('\n'); + }, + "should prompt to stdout and respond with the default value": function (err, result) { + assert.isNull(err); + assert.isTrue(this.msg.indexOf('riffwabbles') !== -1); + assert.isTrue(this.msg.indexOf('(foobizzles)') !== -1); + assert.include(result, 'riffwabbles'); + assert.equal(result['riffwabbles'], helpers.properties['riffwabbles'].default); + } + }, + "with a sync function validator": { + topic: function () { + var that = this; + + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + prompt.get(helpers.properties.fnvalidator, this.callback); + helpers.stdin.write('fn123\n'); + }, + "should accept a value that is checked": function (err, result) { + assert.isNull(err); + assert.equal(result['fnvalidator'],'fn123'); + } + }, + "with a callback validator": { + topic: function () { + var that = this; + + helpers.stdout.once('data', function (msg) { + that.msg = msg; + }); + + prompt.get(helpers.properties.cbvalidator, this.callback); + helpers.stdin.write('cb123\n'); + }, + "should not accept a value that is correct": function (err, result) { + assert.isNull(err); + assert.equal(result['cbvalidator'],'cb123'); + } + } + } + }, + "skip prompt with prompt.overide": { + topic: function () { + prompt.override = { coconihet: 'whatever' } + prompt.get('coconihet', this.callback); + }, + "skips prompt and uses overide": function (err, results) { + assert.equal(results.coconihet, 'whatever') + } + } + }, + "the addProperties() method": { + topic: function () { + prompt.addProperties({}, ['foo', 'bar'], this.callback); + helpers.stdin.write('foo\n'); + helpers.stdin.write('bar\n'); + }, + "should add the properties to the object": function (err, obj) { + assert.isNull(err); + assert.isObject(obj); + assert.equal(obj.foo, 'foo'); + assert.equal(obj.bar, 'bar'); + } + } + } +}).addBatch({ + "When using prompt": { + "the history() method": { + "when used inside of a complex property": { + "with correct value(s)": { + topic: function () { + prompt.get([helpers.properties.animal, helpers.properties.sound], this.callback); + helpers.stdin.write('dog\n'); + helpers.stdin.write('woof\n'); + }, + "should respond with the values entered": function (err, result) { + assert.isTrue(!err); + assert.equal(result.animal, 'dog'); + assert.equal(result.sound, 'woof'); + } + }, + "with an incorrect value": { + topic: function () { + prompt.get([helpers.properties.animal, helpers.properties.sound], function () {}); + prompt.once('invalid', this.callback.bind(null, null)); + helpers.stdin.write('dog\n'); + helpers.stdin.write('meow\n'); + }, + "should prompt for the error": function (ign, property, line) { + assert.equal(property.name, 'sound'); + assert.equal(line, 'meow'); + } + } + } + } + } +}).addBatch({ + "when using prompt": { + topic: function () { + // + // Reset the prompt for mock testing + // + prompt.started = false; + prompt.start({ + stdin: helpers.stdin, + stdout: helpers.stdout + }); + + return null; + }, + "the get() method": { + topic: function () { + prompt.override = { xyz: 468, abc: 123 } + prompt.get(['xyz', 'abc'], this.callback); + }, + "should respond with overrides": function (err, results) { + assert.isNull(err); + assert.deepEqual(results, { xyz: 468, abc: 123 }); + } + } + } +}).addBatch({ + "when using prompt": { + topic: function () { + // + // Reset the prompt for mock testing + // + prompt.started = false; + prompt.start({ + stdin: helpers.stdin, + stdout: helpers.stdout + }); + + return null; + }, + "with fancy properties": { + "the get() method": { + topic: function () { + prompt.override = { UVW: 5423, DEF: 64235 } + prompt.get([{ + name:'UVW', + message: 'a custom message', + default: 6 + },{ + name:'DEF', + message: 'a custom message', + default: 6 + }], this.callback); + }, + "should respond with overrides": function (err, results) { + assert.isNull(err); + assert.deepEqual(results, { UVW: 5423, DEF: 64235 }); + } + } + } + } +}).export(module); + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/LICENSE b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/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/semver/README.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/README.md new file mode 100644 index 0000000..6fa37a3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/README.md @@ -0,0 +1,119 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Usage + + $ npm install semver + + semver.valid('1.2.3') // true + semver.valid('a.b.c') // false + semver.clean(' =v1.2.3 ') // '1.2.3' + semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true + semver.gt('1.2.3', '9.8.7') // false + semver.lt('1.2.3', '9.8.7') // true + +As a command-line utility: + + $ semver -h + + Usage: semver -v [-r ] + Test if version(s) satisfy the supplied range(s), + and sort them. + + Multiple versions or ranges may be supplied. + + Program exits successfully if any valid version satisfies + all supplied ranges, and prints all satisfying versions. + + If no versions are valid, or ranges are not satisfied, + then exits failure. + + Versions are printed in ascending order, so supplying + multiple versions to the utility will just sort them. + +## Versions + +A version is the following things, in this order: + +* a number (Major) +* a period +* a number (minor) +* a period +* a number (patch) +* OPTIONAL: a hyphen, followed by a number (build) +* OPTIONAL: a collection of pretty much any non-whitespace characters + (tag) + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Comparisons + +The ordering of versions is done using the following algorithm, given +two versions and asked to find the greater of the two: + +* If the majors are numerically different, then take the one + with a bigger major number. `2.3.4 > 1.3.4` +* If the minors are numerically different, then take the one + with the bigger minor number. `2.3.4 > 2.2.4` +* If the patches are numerically different, then take the one with the + bigger patch number. `2.3.4 > 2.3.3` +* If only one of them has a build number, then take the one with the + build number. `2.3.4-0 > 2.3.4` +* If they both have build numbers, and the build numbers are numerically + different, then take the one with the bigger build number. + `2.3.4-10 > 2.3.4-9` +* If only one of them has a tag, then take the one without the tag. + `2.3.4 > 2.3.4-beta` +* If they both have tags, then take the one with the lexicographically + larger tag. `2.3.4-beta > 2.3.4-alpha` +* At this point, they're equal. + +## Ranges + +The following range styles are supported: + +* `>1.2.3` Greater than a specific version. +* `<1.2.3` Less than +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` +* `~1.2.3` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <2.0.0` +* `~1` := `>=1.0.0 <2.0.0` +* `1.2.x` := `>=1.2.0 <1.3.0` +* `1.x` := `>=1.0.0 <2.0.0` + +Ranges can be joined with either a space (which implies "and") or a +`||` (which implies "or"). + +## Functions + +* valid(v): Return the parsed version, or null if it's not valid. +* inc(v, release): Return the version incremented by the release type + (major, minor, patch, or build), or null if it's not valid. + +### Comparison + +* gt(v1, v2): `v1 > v2` +* gte(v1, v2): `v1 >= v2` +* lt(v1, v2): `v1 < v2` +* lte(v1, v2): `v1 <= v2` +* eq(v1, v2): `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* neq(v1, v2): `v1 != v2` The opposite of eq. +* cmp(v1, comparator, v2): Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* compare(v1, v2): Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if + v2 is greater. Sorts in ascending order if passed to Array.sort(). +* rcompare(v1, v2): The reverse of compare. Sorts an array of versions + in descending order when passed to Array.sort(). + + +### Ranges + +* validRange(range): Return the valid range or null if it's not valid +* satisfies(version, range): Return true if the version satisfies the + range. +* maxSatisfying(versions, range): Return the highest version in the list + that satisfies the range, or null if none of them do. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/bin/semver b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/bin/semver new file mode 100755 index 0000000..3e6afb4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/bin/semver @@ -0,0 +1,71 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +var argv = process.argv.slice(2) + , versions = [] + , range = [] + , gt = [] + , lt = [] + , eq = [] + , semver = require("../semver") + +main() + +function main () { + if (!argv.length) return help() + while (argv.length) { + var a + switch (a = argv.shift()) { + case "-v": case "--version": + versions.push(argv.shift()) + break + case "-r": case "--range": + range.push(argv.shift()) + break + case "-h": case "--help": case "-?": + return help() + default: + versions.push(a) + break + } + } + + versions = versions.filter(semver.valid) + for (var i = 0, l = range.length; i < l ; i ++) { + versions = versions.filter(function (v) { + return semver.satisfies(v, range[i]) + }) + if (!versions.length) return fail() + } + return success(versions) +} + +function fail () { process.exit(1) } + +function success () { + versions.sort(semver.compare) + .map(semver.clean) + .forEach(function (v,i,_) { console.log(v) }) +} + +function help () { + console.log(["Usage: semver -v [-r ]" + ,"Test if version(s) satisfy the supplied range(s)," + ,"and sort them." + ,"" + ,"Multiple versions or ranges may be supplied." + ,"" + ,"Program exits successfully if any valid version satisfies" + ,"all supplied ranges, and prints all satisfying versions." + ,"" + ,"If no versions are valid, or ranges are not satisfied," + ,"then exits failure." + ,"" + ,"Versions are printed in ascending order, so supplying" + ,"multiple versions to the utility will just sort them." + ].join("\n")) +} + + 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 new file mode 100644 index 0000000..f5daec9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/package.json @@ -0,0 +1,27 @@ +{ + "name": "semver", + "version": "1.0.14", + "description": "The semantic version parser used by npm.", + "main": "semver.js", + "scripts": { + "test": "tap test.js" + }, + "devDependencies": { + "tap": "0.x >=0.0.4" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/semver/raw/master/LICENSE" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-semver.git" + }, + "bin": { + "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/semver/semver.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/semver.js new file mode 100644 index 0000000..8090e0c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/semver.js @@ -0,0 +1,305 @@ +;(function (exports) { // nothing in here is node-specific. + +// See http://semver.org/ +// This implementation is a *hair* less strict in that it allows +// v1.2.3 things, and also tags that don't begin with a char. + +var semver = "\\s*[v=]*\\s*([0-9]+)" // major + + "\\.([0-9]+)" // minor + + "\\.([0-9]+)" // patch + + "(-[0-9]+-?)?" // build + + "([a-zA-Z-][a-zA-Z0-9-\.:]*)?" // tag + , exprComparator = "^((<|>)?=?)\s*("+semver+")$|^$" + , xRangePlain = "[v=]*([0-9]+|x|X|\\*)" + + "(?:\\.([0-9]+|x|X|\\*)" + + "(?:\\.([0-9]+|x|X|\\*)" + + "([a-zA-Z-][a-zA-Z0-9-\.:]*)?)?)?" + , xRange = "((?:<|>)=?)?\\s*" + xRangePlain + , exprSpermy = "(?:~>?)"+xRange + , expressions = exports.expressions = + { parse : new RegExp("^\\s*"+semver+"\\s*$") + , parsePackage : new RegExp("^\\s*([^\/]+)[-@](" +semver+")\\s*$") + , parseRange : new RegExp( + "^\\s*(" + semver + ")\\s+-\\s+(" + semver + ")\\s*$") + , validComparator : new RegExp("^"+exprComparator+"$") + , parseXRange : new RegExp("^"+xRange+"$") + , parseSpermy : new RegExp("^"+exprSpermy+"$") + } + + +Object.getOwnPropertyNames(expressions).forEach(function (i) { + exports[i] = function (str) { + return ("" + (str || "")).match(expressions[i]) + } +}) + +exports.rangeReplace = ">=$1 <=$7" +exports.clean = clean +exports.compare = compare +exports.rcompare = rcompare +exports.satisfies = satisfies +exports.gt = gt +exports.gte = gte +exports.lt = lt +exports.lte = lte +exports.eq = eq +exports.neq = neq +exports.cmp = cmp +exports.inc = inc + +exports.valid = valid +exports.validPackage = validPackage +exports.validRange = validRange +exports.maxSatisfying = maxSatisfying + +exports.replaceStars = replaceStars +exports.toComparators = toComparators + +function stringify (version) { + var v = version + return [v[1]||'', v[2]||'', v[3]||''].join(".") + (v[4]||'') + (v[5]||'') +} + +function clean (version) { + version = exports.parse(version) + if (!version) return version + return stringify(version) +} + +function valid (version) { + if (typeof version !== "string") return null + return exports.parse(version) && version.trim().replace(/^[v=]+/, '') +} + +function validPackage (version) { + if (typeof version !== "string") return null + return version.match(expressions.parsePackage) && version.trim() +} + +// range can be one of: +// "1.0.3 - 2.0.0" range, inclusive, like ">=1.0.3 <=2.0.0" +// ">1.0.2" like 1.0.3 - 9999.9999.9999 +// ">=1.0.2" like 1.0.2 - 9999.9999.9999 +// "<2.0.0" like 0.0.0 - 1.9999.9999 +// ">1.0.2 <2.0.0" like 1.0.3 - 1.9999.9999 +var starExpression = /(<|>)?=?\s*\*/g + , starReplace = "" + , compTrimExpression = new RegExp("((<|>)?=?)\\s*(" + +semver+"|"+xRangePlain+")", "g") + , compTrimReplace = "$1$3" + +function toComparators (range) { + var ret = (range || "").trim() + .replace(expressions.parseRange, exports.rangeReplace) + .replace(compTrimExpression, compTrimReplace) + .split(/\s+/) + .join(" ") + .split("||") + .map(function (orchunk) { + return orchunk + .split(" ") + .map(replaceXRanges) + .map(replaceSpermies) + .map(replaceStars) + .join(" ").trim() + }) + .map(function (orchunk) { + return orchunk + .trim() + .split(/\s+/) + .filter(function (c) { return c.match(expressions.validComparator) }) + }) + .filter(function (c) { return c.length }) + return ret +} + +function replaceStars (stars) { + return stars.trim().replace(starExpression, starReplace) +} + +// "2.x","2.x.x" --> ">=2.0.0- <2.1.0-" +// "2.3.x" --> ">=2.3.0- <2.4.0-" +function replaceXRanges (ranges) { + return ranges.split(/\s+/) + .map(replaceXRange) + .join(" ") +} + +function replaceXRange (version) { + return version.trim().replace(expressions.parseXRange, + function (v, gtlt, M, m, p, t) { + var anyX = !M || M.toLowerCase() === "x" || M === "*" + || !m || m.toLowerCase() === "x" || m === "*" + || !p || p.toLowerCase() === "x" || p === "*" + , ret = v + + if (gtlt && anyX) { + // just replace x'es with zeroes + ;(!M || M === "*" || M.toLowerCase() === "x") && (M = 0) + ;(!m || m === "*" || m.toLowerCase() === "x") && (m = 0) + ;(!p || p === "*" || p.toLowerCase() === "x") && (p = 0) + ret = gtlt + M+"."+m+"."+p+"-" + } else if (!M || M === "*" || M.toLowerCase() === "x") { + ret = "*" // allow any + } else if (!m || m === "*" || m.toLowerCase() === "x") { + // append "-" onto the version, otherwise + // "1.x.x" matches "2.0.0beta", since the tag + // *lowers* the version value + ret = ">="+M+".0.0- <"+(+M+1)+".0.0-" + } else if (!p || p === "*" || p.toLowerCase() === "x") { + ret = ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-" + } + //console.error("parseXRange", [].slice.call(arguments), ret) + return ret + }) +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceSpermies (version) { + return version.trim().replace(expressions.parseSpermy, + function (v, gtlt, M, m, p, t) { + if (gtlt) throw new Error( + "Using '"+gtlt+"' with ~ makes no sense. Don't do it.") + + if (!M || M.toLowerCase() === "x") { + return "" + } + // ~1 == >=1.0.0- <2.0.0- + if (!m || m.toLowerCase() === "x") { + return ">="+M+".0.0- <"+(+M+1)+".0.0-" + } + // ~1.2 == >=1.2.0- <1.3.0- + if (!p || p.toLowerCase() === "x") { + return ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-" + } + // ~1.2.3 == >=1.2.3- <1.3.0- + t = t || "-" + return ">="+M+"."+m+"."+p+t+" <"+M+"."+(+m+1)+".0-" + }) +} + +function validRange (range) { + range = replaceStars(range) + var c = toComparators(range) + return (c.length === 0) + ? null + : c.map(function (c) { return c.join(" ") }).join("||") +} + +// returns the highest satisfying version in the list, or undefined +function maxSatisfying (versions, range) { + return versions + .filter(function (v) { return satisfies(v, range) }) + .sort(compare) + .pop() +} +function satisfies (version, range) { + version = valid(version) + if (!version) return false + range = toComparators(range) + for (var i = 0, l = range.length ; i < l ; i ++) { + var ok = false + for (var j = 0, ll = range[i].length ; j < ll ; j ++) { + var r = range[i][j] + , gtlt = r.charAt(0) === ">" ? gt + : r.charAt(0) === "<" ? lt + : false + , eq = r.charAt(!!gtlt) === "=" + , sub = (!!eq) + (!!gtlt) + if (!gtlt) eq = true + r = r.substr(sub) + r = (r === "") ? r : valid(r) + ok = (r === "") || (eq && r === version) || (gtlt && gtlt(version, r)) + if (!ok) break + } + if (ok) return true + } + return false +} + +// return v1 > v2 ? 1 : -1 +function compare (v1, v2) { + var g = gt(v1, v2) + return g === null ? 0 : g ? 1 : -1 +} + +function rcompare (v1, v2) { + return compare(v2, v1) +} + +function lt (v1, v2) { return gt(v2, v1) } +function gte (v1, v2) { return !lt(v1, v2) } +function lte (v1, v2) { return !gt(v1, v2) } +function eq (v1, v2) { return gt(v1, v2) === null } +function neq (v1, v2) { return gt(v1, v2) !== null } +function cmp (v1, c, v2) { + switch (c) { + case ">": return gt(v1, v2) + case "<": return lt(v1, v2) + case ">=": return gte(v1, v2) + case "<=": return lte(v1, v2) + case "==": return eq(v1, v2) + case "!=": return neq(v1, v2) + case "===": return v1 === v2 + case "!==": return v1 !== v2 + default: throw new Error("Y U NO USE VALID COMPARATOR!? "+c) + } +} + +// return v1 > v2 +function num (v) { + return v === undefined ? -1 : parseInt((v||"0").replace(/[^0-9]+/g, ''), 10) +} +function gt (v1, v2) { + v1 = exports.parse(v1) + v2 = exports.parse(v2) + if (!v1 || !v2) return false + + for (var i = 1; i < 5; i ++) { + v1[i] = num(v1[i]) + v2[i] = num(v2[i]) + if (v1[i] > v2[i]) return true + else if (v1[i] !== v2[i]) return false + } + // no tag is > than any tag, or use lexicographical order. + var tag1 = v1[5] || "" + , tag2 = v2[5] || "" + + // kludge: null means they were equal. falsey, and detectable. + // embarrassingly overclever, though, I know. + return tag1 === tag2 ? null + : !tag1 ? true + : !tag2 ? false + : tag1 > tag2 +} + +function inc (version, release) { + version = exports.parse(version) + if (!version) return null + + var parsedIndexLookup = + { 'major': 1 + , 'minor': 2 + , 'patch': 3 + , 'build': 4 } + var incIndex = parsedIndexLookup[release] + if (incIndex === undefined) return null + + var current = num(version[incIndex]) + version[incIndex] = current === -1 ? 1 : current + 1 + + for (var i = incIndex + 1; i < 5; i ++) { + if (num(version[i]) !== -1) version[i] = "0" + } + + if (version[4]) version[4] = "-" + version[4] + version[5] = "" + + return stringify(version) +} +})(typeof exports === "object" ? exports : semver = {}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/test.js new file mode 100644 index 0000000..65ff8a9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/semver/test.js @@ -0,0 +1,405 @@ +var tap = require("tap") + , test = tap.test + , semver = require("./semver.js") + , eq = semver.eq + , gt = semver.gt + , lt = semver.lt + , neq = semver.neq + , cmp = semver.cmp + , gte = semver.gte + , lte = semver.lte + , satisfies = semver.satisfies + , validRange = semver.validRange + , inc = semver.inc + , replaceStars = semver.replaceStars + , toComparators = semver.toComparators + +tap.plan(8) + +test("\ncomparison tests", function (t) { +; [ ["0.0.0", "0.0.0foo"] + , ["0.0.1", "0.0.0"] + , ["1.0.0", "0.9.9"] + , ["0.10.0", "0.9.0"] + , ["0.99.0", "0.10.0"] + , ["2.0.0", "1.2.3"] + , ["v0.0.0", "0.0.0foo"] + , ["v0.0.1", "0.0.0"] + , ["v1.0.0", "0.9.9"] + , ["v0.10.0", "0.9.0"] + , ["v0.99.0", "0.10.0"] + , ["v2.0.0", "1.2.3"] + , ["0.0.0", "v0.0.0foo"] + , ["0.0.1", "v0.0.0"] + , ["1.0.0", "v0.9.9"] + , ["0.10.0", "v0.9.0"] + , ["0.99.0", "v0.10.0"] + , ["2.0.0", "v1.2.3"] + , ["1.2.3", "1.2.3-asdf"] + , ["1.2.3-4", "1.2.3"] + , ["1.2.3-4-foo", "1.2.3"] + , ["1.2.3-5", "1.2.3-5-foo"] + , ["1.2.3-5", "1.2.3-4"] + , ["1.2.3-5-foo", "1.2.3-5-Foo"] + ].forEach(function (v) { + var v0 = v[0] + , v1 = v[1] + t.ok(gt(v0, v1), "gt('"+v0+"', '"+v1+"')") + t.ok(lt(v1, v0), "lt('"+v1+"', '"+v0+"')") + t.ok(!gt(v1, v0), "!gt('"+v1+"', '"+v0+"')") + t.ok(!lt(v0, v1), "!lt('"+v0+"', '"+v1+"')") + t.ok(eq(v0, v0), "eq('"+v0+"', '"+v0+"')") + t.ok(eq(v1, v1), "eq('"+v1+"', '"+v1+"')") + t.ok(neq(v0, v1), "neq('"+v0+"', '"+v1+"')") + t.ok(cmp(v1, "==", v1), "cmp('"+v1+"' == '"+v1+"')") + t.ok(cmp(v0, ">=", v1), "cmp('"+v0+"' >= '"+v1+"')") + t.ok(cmp(v1, "<=", v0), "cmp('"+v1+"' <= '"+v0+"')") + t.ok(cmp(v0, "!=", v1), "cmp('"+v0+"' != '"+v1+"')") + }) + t.end() +}) + +test("\nequality tests", function (t) { +; [ ["1.2.3", "v1.2.3"] + , ["1.2.3", "=1.2.3"] + , ["1.2.3", "v 1.2.3"] + , ["1.2.3", "= 1.2.3"] + , ["1.2.3", " v1.2.3"] + , ["1.2.3", " =1.2.3"] + , ["1.2.3", " v 1.2.3"] + , ["1.2.3", " = 1.2.3"] + , ["1.2.3-0", "v1.2.3-0"] + , ["1.2.3-0", "=1.2.3-0"] + , ["1.2.3-0", "v 1.2.3-0"] + , ["1.2.3-0", "= 1.2.3-0"] + , ["1.2.3-0", " v1.2.3-0"] + , ["1.2.3-0", " =1.2.3-0"] + , ["1.2.3-0", " v 1.2.3-0"] + , ["1.2.3-0", " = 1.2.3-0"] + , ["1.2.3-01", "v1.2.3-1"] + , ["1.2.3-01", "=1.2.3-1"] + , ["1.2.3-01", "v 1.2.3-1"] + , ["1.2.3-01", "= 1.2.3-1"] + , ["1.2.3-01", " v1.2.3-1"] + , ["1.2.3-01", " =1.2.3-1"] + , ["1.2.3-01", " v 1.2.3-1"] + , ["1.2.3-01", " = 1.2.3-1"] + , ["1.2.3beta", "v1.2.3beta"] + , ["1.2.3beta", "=1.2.3beta"] + , ["1.2.3beta", "v 1.2.3beta"] + , ["1.2.3beta", "= 1.2.3beta"] + , ["1.2.3beta", " v1.2.3beta"] + , ["1.2.3beta", " =1.2.3beta"] + , ["1.2.3beta", " v 1.2.3beta"] + , ["1.2.3beta", " = 1.2.3beta"] + ].forEach(function (v) { + var v0 = v[0] + , v1 = v[1] + t.ok(eq(v0, v1), "eq('"+v0+"', '"+v1+"')") + t.ok(!neq(v0, v1), "!neq('"+v0+"', '"+v1+"')") + t.ok(cmp(v0, "==", v1), "cmp("+v0+"=="+v1+")") + t.ok(!cmp(v0, "!=", v1), "!cmp("+v0+"!="+v1+")") + t.ok(!cmp(v0, "===", v1), "!cmp("+v0+"==="+v1+")") + t.ok(cmp(v0, "!==", v1), "cmp("+v0+"!=="+v1+")") + t.ok(!gt(v0, v1), "!gt('"+v0+"', '"+v1+"')") + t.ok(gte(v0, v1), "gte('"+v0+"', '"+v1+"')") + t.ok(!lt(v0, v1), "!lt('"+v0+"', '"+v1+"')") + t.ok(lte(v0, v1), "lte('"+v0+"', '"+v1+"')") + }) + t.end() +}) + + +test("\nrange tests", function (t) { +; [ ["1.0.0 - 2.0.0", "1.2.3"] + , ["1.0.0", "1.0.0"] + , [">=*", "0.2.4"] + , ["", "1.0.0"] + , ["*", "1.2.3"] + , ["*", "v1.2.3-foo"] + , [">=1.0.0", "1.0.0"] + , [">=1.0.0", "1.0.1"] + , [">=1.0.0", "1.1.0"] + , [">1.0.0", "1.0.1"] + , [">1.0.0", "1.1.0"] + , ["<=2.0.0", "2.0.0"] + , ["<=2.0.0", "1.9999.9999"] + , ["<=2.0.0", "0.2.9"] + , ["<2.0.0", "1.9999.9999"] + , ["<2.0.0", "0.2.9"] + , [">= 1.0.0", "1.0.0"] + , [">= 1.0.0", "1.0.1"] + , [">= 1.0.0", "1.1.0"] + , ["> 1.0.0", "1.0.1"] + , ["> 1.0.0", "1.1.0"] + , ["<= 2.0.0", "2.0.0"] + , ["<= 2.0.0", "1.9999.9999"] + , ["<= 2.0.0", "0.2.9"] + , ["< 2.0.0", "1.9999.9999"] + , ["<\t2.0.0", "0.2.9"] + , [">=0.1.97", "v0.1.97"] + , [">=0.1.97", "0.1.97"] + , ["0.1.20 || 1.2.4", "1.2.4"] + , [">=0.2.3 || <0.0.1", "0.0.0"] + , [">=0.2.3 || <0.0.1", "0.2.3"] + , [">=0.2.3 || <0.0.1", "0.2.4"] + , ["||", "1.3.4"] + , ["2.x.x", "2.1.3"] + , ["1.2.x", "1.2.3"] + , ["1.2.x || 2.x", "2.1.3"] + , ["1.2.x || 2.x", "1.2.3"] + , ["x", "1.2.3"] + , ["2.*.*", "2.1.3"] + , ["1.2.*", "1.2.3"] + , ["1.2.* || 2.*", "2.1.3"] + , ["1.2.* || 2.*", "1.2.3"] + , ["*", "1.2.3"] + , ["2", "2.1.2"] + , ["2.3", "2.3.1"] + , ["~2.4", "2.4.0"] // >=2.4.0 <2.5.0 + , ["~2.4", "2.4.5"] + , ["~>3.2.1", "3.2.2"] // >=3.2.1 <3.3.0 + , ["~1", "1.2.3"] // >=1.0.0 <2.0.0 + , ["~>1", "1.2.3"] + , ["~> 1", "1.2.3"] + , ["~1.0", "1.0.2"] // >=1.0.0 <1.1.0 + , ["~ 1.0", "1.0.2"] + , [">=1", "1.0.0"] + , [">= 1", "1.0.0"] + , ["<1.2", "1.1.1"] + , ["< 1.2", "1.1.1"] + , ["1", "1.0.0beta"] + , ["~v0.5.4-pre", "0.5.5"] + , ["~v0.5.4-pre", "0.5.4"] + , ["=0.7.x", "0.7.2"] + , [">=0.7.x", "0.7.2"] + , ["=0.7.x", "0.7.0-asdf"] + , [">=0.7.x", "0.7.0-asdf"] + , ["<=0.7.x", "0.6.2"] + ].forEach(function (v) { + t.ok(satisfies(v[1], v[0]), v[0]+" satisfied by "+v[1]) + }) + t.end() +}) + +test("\nnegative range tests", function (t) { +; [ ["1.0.0 - 2.0.0", "2.2.3"] + , ["1.0.0", "1.0.1"] + , [">=1.0.0", "0.0.0"] + , [">=1.0.0", "0.0.1"] + , [">=1.0.0", "0.1.0"] + , [">1.0.0", "0.0.1"] + , [">1.0.0", "0.1.0"] + , ["<=2.0.0", "3.0.0"] + , ["<=2.0.0", "2.9999.9999"] + , ["<=2.0.0", "2.2.9"] + , ["<2.0.0", "2.9999.9999"] + , ["<2.0.0", "2.2.9"] + , [">=0.1.97", "v0.1.93"] + , [">=0.1.97", "0.1.93"] + , ["0.1.20 || 1.2.4", "1.2.3"] + , [">=0.2.3 || <0.0.1", "0.0.3"] + , [">=0.2.3 || <0.0.1", "0.2.2"] + , ["2.x.x", "1.1.3"] + , ["2.x.x", "3.1.3"] + , ["1.2.x", "1.3.3"] + , ["1.2.x || 2.x", "3.1.3"] + , ["1.2.x || 2.x", "1.1.3"] + , ["2.*.*", "1.1.3"] + , ["2.*.*", "3.1.3"] + , ["1.2.*", "1.3.3"] + , ["1.2.* || 2.*", "3.1.3"] + , ["1.2.* || 2.*", "1.1.3"] + , ["2", "1.1.2"] + , ["2.3", "2.4.1"] + , ["~2.4", "2.5.0"] // >=2.4.0 <2.5.0 + , ["~2.4", "2.3.9"] + , ["~>3.2.1", "3.3.2"] // >=3.2.1 <3.3.0 + , ["~>3.2.1", "3.2.0"] // >=3.2.1 <3.3.0 + , ["~1", "0.2.3"] // >=1.0.0 <2.0.0 + , ["~>1", "2.2.3"] + , ["~1.0", "1.1.0"] // >=1.0.0 <1.1.0 + , ["<1", "1.0.0"] + , [">=1.2", "1.1.1"] + , ["1", "2.0.0beta"] + , ["~v0.5.4-beta", "0.5.4-alpha"] + , ["<1", "1.0.0beta"] + , ["< 1", "1.0.0beta"] + , ["=0.7.x", "0.8.2"] + , [">=0.7.x", "0.6.2"] + , ["<=0.7.x", "0.7.2"] + ].forEach(function (v) { + t.ok(!satisfies(v[1], v[0]), v[0]+" not satisfied by "+v[1]) + }) + t.end() +}) + +test("\nincrement versions test", function (t) { +; [ [ "1.2.3", "major", "2.0.0" ] + , [ "1.2.3", "minor", "1.3.0" ] + , [ "1.2.3", "patch", "1.2.4" ] + , [ "1.2.3", "build", "1.2.3-1" ] + , [ "1.2.3-4", "build", "1.2.3-5" ] + , [ "1.2.3tag", "major", "2.0.0" ] + , [ "1.2.3-tag", "major", "2.0.0" ] + , [ "1.2.3tag", "build", "1.2.3-1" ] + , [ "1.2.3-tag", "build", "1.2.3-1" ] + , [ "1.2.3-4-tag", "build", "1.2.3-5" ] + , [ "1.2.3-4tag", "build", "1.2.3-5" ] + , [ "1.2.3", "fake", null ] + , [ "fake", "major", null ] + ].forEach(function (v) { + t.equal(inc(v[0], v[1]), v[2], "inc("+v[0]+", "+v[1]+") === "+v[2]) + }) + + t.end() +}) + +test("\nreplace stars test", function (t) { +; [ [ "", "" ] + , [ "*", "" ] + , [ "> *", "" ] + , [ "<*", "" ] + , [ " >= *", "" ] + , [ "* || 1.2.3", " || 1.2.3" ] + ].forEach(function (v) { + t.equal(replaceStars(v[0]), v[1], "replaceStars("+v[0]+") === "+v[1]) + }) + + t.end() +}) + +test("\nvalid range test", function (t) { +; [ ["1.0.0 - 2.0.0", ">=1.0.0 <=2.0.0"] + , ["1.0.0", "1.0.0"] + , [">=*", ""] + , ["", ""] + , ["*", ""] + , ["*", ""] + , [">=1.0.0", ">=1.0.0"] + , [">1.0.0", ">1.0.0"] + , ["<=2.0.0", "<=2.0.0"] + , ["1", ">=1.0.0- <2.0.0-"] + , ["<=2.0.0", "<=2.0.0"] + , ["<=2.0.0", "<=2.0.0"] + , ["<2.0.0", "<2.0.0"] + , ["<2.0.0", "<2.0.0"] + , [">= 1.0.0", ">=1.0.0"] + , [">= 1.0.0", ">=1.0.0"] + , [">= 1.0.0", ">=1.0.0"] + , ["> 1.0.0", ">1.0.0"] + , ["> 1.0.0", ">1.0.0"] + , ["<= 2.0.0", "<=2.0.0"] + , ["<= 2.0.0", "<=2.0.0"] + , ["<= 2.0.0", "<=2.0.0"] + , ["< 2.0.0", "<2.0.0"] + , ["< 2.0.0", "<2.0.0"] + , [">=0.1.97", ">=0.1.97"] + , [">=0.1.97", ">=0.1.97"] + , ["0.1.20 || 1.2.4", "0.1.20||1.2.4"] + , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] + , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] + , [">=0.2.3 || <0.0.1", ">=0.2.3||<0.0.1"] + , ["||", "||"] + , ["2.x.x", ">=2.0.0- <3.0.0-"] + , ["1.2.x", ">=1.2.0- <1.3.0-"] + , ["1.2.x || 2.x", ">=1.2.0- <1.3.0-||>=2.0.0- <3.0.0-"] + , ["1.2.x || 2.x", ">=1.2.0- <1.3.0-||>=2.0.0- <3.0.0-"] + , ["x", ""] + , ["2.*.*", null] + , ["1.2.*", null] + , ["1.2.* || 2.*", null] + , ["1.2.* || 2.*", null] + , ["*", ""] + , ["2", ">=2.0.0- <3.0.0-"] + , ["2.3", ">=2.3.0- <2.4.0-"] + , ["~2.4", ">=2.4.0- <2.5.0-"] + , ["~2.4", ">=2.4.0- <2.5.0-"] + , ["~>3.2.1", ">=3.2.1- <3.3.0-"] + , ["~1", ">=1.0.0- <2.0.0-"] + , ["~>1", ">=1.0.0- <2.0.0-"] + , ["~> 1", ">=1.0.0- <2.0.0-"] + , ["~1.0", ">=1.0.0- <1.1.0-"] + , ["~ 1.0", ">=1.0.0- <1.1.0-"] + , ["<1", "<1.0.0-"] + , ["< 1", "<1.0.0-"] + , [">=1", ">=1.0.0-"] + , [">= 1", ">=1.0.0-"] + , ["<1.2", "<1.2.0-"] + , ["< 1.2", "<1.2.0-"] + , ["1", ">=1.0.0- <2.0.0-"] + ].forEach(function (v) { + t.equal(validRange(v[0]), v[1], "validRange("+v[0]+") === "+v[1]) + }) + + t.end() +}) + +test("\ncomparators test", function (t) { +; [ ["1.0.0 - 2.0.0", [[">=1.0.0", "<=2.0.0"]] ] + , ["1.0.0", [["1.0.0"]] ] + , [">=*", [[">=0.0.0-"]] ] + , ["", [[""]]] + , ["*", [[""]] ] + , ["*", [[""]] ] + , [">=1.0.0", [[">=1.0.0"]] ] + , [">=1.0.0", [[">=1.0.0"]] ] + , [">=1.0.0", [[">=1.0.0"]] ] + , [">1.0.0", [[">1.0.0"]] ] + , [">1.0.0", [[">1.0.0"]] ] + , ["<=2.0.0", [["<=2.0.0"]] ] + , ["1", [[">=1.0.0-", "<2.0.0-"]] ] + , ["<=2.0.0", [["<=2.0.0"]] ] + , ["<=2.0.0", [["<=2.0.0"]] ] + , ["<2.0.0", [["<2.0.0"]] ] + , ["<2.0.0", [["<2.0.0"]] ] + , [">= 1.0.0", [[">=1.0.0"]] ] + , [">= 1.0.0", [[">=1.0.0"]] ] + , [">= 1.0.0", [[">=1.0.0"]] ] + , ["> 1.0.0", [[">1.0.0"]] ] + , ["> 1.0.0", [[">1.0.0"]] ] + , ["<= 2.0.0", [["<=2.0.0"]] ] + , ["<= 2.0.0", [["<=2.0.0"]] ] + , ["<= 2.0.0", [["<=2.0.0"]] ] + , ["< 2.0.0", [["<2.0.0"]] ] + , ["<\t2.0.0", [["<2.0.0"]] ] + , [">=0.1.97", [[">=0.1.97"]] ] + , [">=0.1.97", [[">=0.1.97"]] ] + , ["0.1.20 || 1.2.4", [["0.1.20"], ["1.2.4"]] ] + , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] + , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] + , [">=0.2.3 || <0.0.1", [[">=0.2.3"], ["<0.0.1"]] ] + , ["||", [[""], [""]] ] + , ["2.x.x", [[">=2.0.0-", "<3.0.0-"]] ] + , ["1.2.x", [[">=1.2.0-", "<1.3.0-"]] ] + , ["1.2.x || 2.x", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] + , ["1.2.x || 2.x", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] + , ["x", [[""]] ] + , ["2.*.*", [[">=2.0.0-", "<3.0.0-"]] ] + , ["1.2.*", [[">=1.2.0-", "<1.3.0-"]] ] + , ["1.2.* || 2.*", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] + , ["1.2.* || 2.*", [[">=1.2.0-", "<1.3.0-"], [">=2.0.0-", "<3.0.0-"]] ] + , ["*", [[""]] ] + , ["2", [[">=2.0.0-", "<3.0.0-"]] ] + , ["2.3", [[">=2.3.0-", "<2.4.0-"]] ] + , ["~2.4", [[">=2.4.0-", "<2.5.0-"]] ] + , ["~2.4", [[">=2.4.0-", "<2.5.0-"]] ] + , ["~>3.2.1", [[">=3.2.1-", "<3.3.0-"]] ] + , ["~1", [[">=1.0.0-", "<2.0.0-"]] ] + , ["~>1", [[">=1.0.0-", "<2.0.0-"]] ] + , ["~> 1", [[">=1.0.0-", "<2.0.0-"]] ] + , ["~1.0", [[">=1.0.0-", "<1.1.0-"]] ] + , ["~ 1.0", [[">=1.0.0-", "<1.1.0-"]] ] + , ["<1", [["<1.0.0-"]] ] + , ["< 1", [["<1.0.0-"]] ] + , [">=1", [[">=1.0.0-"]] ] + , [">= 1", [[">=1.0.0-"]] ] + , ["<1.2", [["<1.2.0-"]] ] + , ["< 1.2", [["<1.2.0-"]] ] + , ["1", [[">=1.0.0-", "<2.0.0-"]] ] + ].forEach(function (v) { + t.equivalent(toComparators(v[0]), v[1], "toComparators("+v[0]+") === "+JSON.stringify(v[1])) + }) + + t.end() +}) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.npmignore new file mode 100644 index 0000000..3b3a32f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.npmignore @@ -0,0 +1,22 @@ +tmp +node_modules +*._ +*.tmp +.monitor +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.vi +*~ +.DS_Store +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 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/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/Makefile new file mode 100644 index 0000000..98957d6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/Makefile @@ -0,0 +1,11 @@ +TESTS = test/*.test.js + +test: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter spec \ + $(TESTS) + +clean: + rm -f examples/tmp/* + +.PHONY: test clean diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/Readme.md new file mode 100644 index 0000000..858510f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/Readme.md @@ -0,0 +1,82 @@ +[![Build Status](https://secure.travis-ci.org/vesln/temporary.png)](http://travis-ci.org/vesln/temporary) + +# temporary - The lord of tmp. + +## Intro + +Temporary provides an easy way to create temporary files and directories. +It will create a temporary file/directory with a unique name. + +## Features + +- Generates unique name. +- Auto-discovers tmp dir. + +## Installation + + $ npm install temporary + +## Usage + + var Tempfile = require('temporary/file'); + var Tempdir = require('temporary/dir'); + var file = new Tempfile; + var dir = new Tempdir; + + console.log(file.path); // path. + console.log(dir.path); // path. + + file.unlink(); + dir.rmdir(); + +## Methods + +### File + +- File.readFile +- File.readFileSync +- File.writeFile +- File.writeFileSync +- File.open +- File.openSync +- File.close +- File.closeSync +- File.unlink +- File.unlinkSync + +### Dir + +- Dir.rmdir +- Dir.rmdirSync + +## Tests + + $ make test + +## Contribution + +Bug fixes and features are welcomed. + +## License + +MIT License + +Copyright (C) 2012 Veselin Todorov + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/dir.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/dir.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/dir.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/dir.js new file mode 100644 index 0000000..5182b83 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/dir.js @@ -0,0 +1,18 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +var Tempdir = require('../lib/dir'); +var dir = new Tempdir('foo') // name - optional + +console.log(dir.path); // path. + +/** + * You can also use: + * + * dir.rmdir + * dir.rmdirSync + */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/file.js new file mode 100644 index 0000000..6a3fe31 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/examples/file.js @@ -0,0 +1,26 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +var Tempfile = require('../lib/file'); +var file = new Tempfile('foo') // name - optional + +console.log(file.path); // file path. + +/** + * You can also use: + * + * file.readFile + * file.readFileSync + * file.writeFile + * file.writeFileSync + * file.open + * file.openSync + * file.close + * file.closeSync + * file.unlink + * file.unlinkSync + */ \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/file.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/index.js new file mode 100644 index 0000000..b1ec2b7 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/index.js @@ -0,0 +1,26 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('package')(module); + +/** + * Version. + */ +module.exports.version = package.version; + +/** + * Exporting the temp file + */ +module.exports.File = require('./file'); + +/** + * Exporting the temp directory. + */ +module.exports.Dir = require('./dir'); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/base.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/base.js new file mode 100644 index 0000000..a3e95c8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/base.js @@ -0,0 +1,80 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); + +/** + * Base constructor. + * + * @param {String|null} name + */ +function Base(name) { + this.init(name); +}; + +/** + * Initializes the class. + * + * @param {String|null} name + */ +Base.prototype.init = function(name) { + var filename = generator.build(name); + this.create(filename); + this.path = filename; +}; + +/** + * Converts the arguments object to array and + * append `this.path` as first element. + * + * @returns {Array} + */ +Base.prototype.prepareArgs = function(args) { + args = Array.prototype.slice.call(args); + args.unshift(this.path); + return args; +}; + +/** + * Renames the dir/file. + * + * @param {String} name + * @param {Function} cb Callback. + */ +Base.prototype.rename = function(name, cb) { + var self = this; + var args = arguments; + var tmp = path.normalize(path.dirname(self.path) + '/' + name); + + fs.rename(this.path, tmp, function(err) { + self.path = tmp; + if (args.length === 2) cb(err); + }); +}; + +/** + * Renames the dir/file sync. + * + * @param {String} name + */ +Base.prototype.renameSync = function(name) { + var tmp = path.normalize(path.dirname(this.path) + '/' + name); + var result = fs.renameSync(this.path, tmp); + this.path = tmp; + return result; +}; + +/** + * Exporting the lib. + */ +module.exports = Base; 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 new file mode 100644 index 0000000..c09b46d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/detector.js @@ -0,0 +1,44 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Detection stolen from NPM (https://github.com/isaacs/npm/) + * + * Copyright 2009, 2010, 2011 Isaac Z. Schlueter (the "Author") + * MIT License (https://github.com/isaacs/npm/blob/master/LICENSE) + */ + +/** + * Detector namespace. + * + * @type {Object} + */ +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() { + 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/lib/dir.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/dir.js new file mode 100644 index 0000000..73acecc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/dir.js @@ -0,0 +1,57 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); +var Base = require('./base'); + +/** + * Dir constructor. + * + * @param {String|null} name + */ +function Dir(name) { + this.init(name); +}; + +/** + * Dir extends from tmp. + */ +Dir.prototype.__proto__ = Base.prototype; + +/** + * Creates new file. + * + * @param {String} dirname + */ +Dir.prototype.create = function(dirname) { + return fs.mkdirSync(path.normalize(dirname), 0777); +}; + +/** + * Asynchronous dir. + */ +Dir.prototype.rmdir = function() { + fs.rmdir.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous rmdir. + */ +Dir.prototype.rmdirSync = function() { + return fs.rmdirSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Exporting the lib. + */ +module.exports = Dir; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/file.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/file.js new file mode 100644 index 0000000..49de026 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/file.js @@ -0,0 +1,113 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); +var Base = require('./base'); + +/** + * File constructor. + * + * @param {String|null} name + */ +function File(name) { + this.init(name); +}; + +/** + * File extends from tmp. + */ +File.prototype.__proto__ = Base.prototype; + +/** + * Creates new file. + * + * @param {String} filename + */ +File.prototype.create = function(filename) { + return fs.writeFileSync(path.normalize(filename), ''); +}; + +/** + * Asynchronously reads the entire contents of a file. + */ +File.prototype.readFile = function() { + fs.readFile.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous read. + */ +File.prototype.readFileSync = function() { + return fs.readFileSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronously writes data to a file. + */ +File.prototype.writeFile = function() { + fs.writeFile.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous writes data to a file. + */ +File.prototype.writeFileSync = function() { + return fs.writeFileSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronous file open. + */ +File.prototype.open = function() { + fs.open.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous open. + */ +File.prototype.openSync = function() { + return fs.openSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronous close. + */ +File.prototype.close = function() { + fs.close.apply(fs, Array.prototype.slice.call(arguments)); +}; + +/** + * Synchronous close. + */ +File.prototype.closeSync = function() { + return fs.closeSync.apply(fs, Array.prototype.slice.call(arguments)); +}; + +/** + * Asynchronous unlink. + */ +File.prototype.unlink = function() { + fs.unlink.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous unlink. + */ +File.prototype.unlinkSync = function() { + return fs.unlinkSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Exporting the lib. + */ +module.exports = File; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/generator.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/generator.js new file mode 100644 index 0000000..a68f0ba --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/lib/generator.js @@ -0,0 +1,48 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var detector = require('./detector'); +var existsSync = fs.existsSync || path.existsSync; + +/** + * Generator namespace. + * + * @type {Object} + */ +var generator = module.exports; + +/** + * Generates random name. + * + * @returns {String} + */ +generator.name = function() { + var id = null; + var tmp = detector.tmp(); + do { + id = Date.now() + Math.random(); + } while(existsSync(tmp + '/' + id)); + + return id + ''; +}; + +/** + * Buld a full name. (tmp dir + name). + * + * @param {String} name + * @returns {String} + */ +generator.build = function(name) { + var filename = detector.tmp(); + if (name) filename += name + '.'; + return filename + this.name(); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.npmignore new file mode 100644 index 0000000..3b3a32f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.npmignore @@ -0,0 +1,22 @@ +tmp +node_modules +*._ +*.tmp +.monitor +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.vi +*~ +.DS_Store +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.travis.yml new file mode 100644 index 0000000..b8e1f17 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/History.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/History.md new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Makefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Makefile new file mode 100644 index 0000000..277485c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Makefile @@ -0,0 +1,12 @@ +TESTS = $(shell find test -iname \*.test.js) + +test: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + $(TESTS) + +clean: + rm -f examples/tmp/* + +.PHONY: test clean \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Readme.md b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Readme.md new file mode 100644 index 0000000..c531965 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/Readme.md @@ -0,0 +1,54 @@ +[![Build Status](https://secure.travis-ci.org/vesln/package.png)](http://travis-ci.org/vesln/package) + +# package - Easy package.json exports. + +## Intro + +This module provides an easy and simple way to export package.json data. + +## Installation + + $ npm install package + +## Usage + + var package = require('package')(module); // contains package.json data. + var yourAwesomeModule = {}; + yourAwesomeModule.version = package.version; + +## Tests + + $ make test + +## Contribution + +Bug fixes and features are welcomed. + +## Other similar modules + +- pkginfo (https://github.com/indexzero/node-pkginfo) by indexzero. +- JSON.parse + fs.readFile + +## License + +MIT License + +Copyright (C) 2012 Veselin Todorov + +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. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/custom_path.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/custom_path.js new file mode 100644 index 0000000..a03c0cc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/custom_path.js @@ -0,0 +1,14 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ + +var package = require('../')(__dirname + '/..'); // parent dir. + +console.log(package); // This will contain the package.json data. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/module.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/module.js new file mode 100644 index 0000000..c479069 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/examples/module.js @@ -0,0 +1,14 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ + +var package = require('../')(module); + +console.log(package); // This will contain the package.json data. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/lib/package.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/lib/package.js new file mode 100644 index 0000000..348db0c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/lib/package.js @@ -0,0 +1,64 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var exists = fs.existsSync || path.existsSync; + +/** + * Package. + * + * @param {String|null} location + * @returns {Object} package.json data + */ +var package = function(location) { + if (location === Object(location)) { + location = package.discover(location); + } + return package.read(path.normalize(location + '/package.json')); +}; + +/** + * Reads and parses a package.json file. + * + * @param {String} file + * @returns {Object} package.json data + */ +package.read = function(file) { + var data = fs.readFileSync(file, 'utf8'); + return JSON.parse(data); +}; + +/** + * Makes an atempt to find package.json file. + * + * @returns {Object} package.json data + */ +package.discover = function(module) { + var location = path.dirname(module.filename); + var found = null; + + while (!found) { + if (exists(location + '/package.json')) { + found = location; + } else if (location !== '/') { + location = path.dirname(location); + } else { + throw new Error('package.json can not be located'); + } + } + + return found; +}; + +/** + * Exporting the lib. + */ +module.exports = package; 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 new file mode 100644 index 0000000..3df7344 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/package.json @@ -0,0 +1,32 @@ +{ + "name": "package", + "version": "1.0.1", + "description": "Easy package.json exports.", + "keywords": [ + "package.json" + ], + "author": { + "name": "Veselin Todorov", + "email": "hi@vesln.com" + }, + "devDependencies": { + "mocha": "0.3.3", + "should": "0.3.2" + }, + "repository": { + "type": "git", + "url": "http://github.com/vesln/package.git" + }, + "homepage": "http://github.com/vesln/package", + "scripts": { + "test": "make test" + }, + "main": "./lib/package", + "engines": { + "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/node_modules/package/test/index.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/index.test.js new file mode 100644 index 0000000..c43364b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/index.test.js @@ -0,0 +1,42 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('../'); + +describe('package', function() { + describe('read', function() { + it('should read and parse .json file', function() { + var result = package.read(__dirname + '/support/package.json'); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); + }); + + it('should read and parse given .json file', function() { + var result = package(__dirname + '/support'); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); + + it('should autodiscover, read and parse package.json', function() { + var result = package(module); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js new file mode 100644 index 0000000..99c012e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js @@ -0,0 +1,22 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('../../../'); + +describe('nested package json', function() { + it('should autodiscover, read and parse package.json', function() { + var result = package(module); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/package.json new file mode 100644 index 0000000..ed5e671 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-package-json-file" + , "version": "0.0.1" + , "private": true +} \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/support/package.json b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/support/package.json new file mode 100644 index 0000000..ed5e671 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/node_modules/package/test/support/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-package-json-file" + , "version": "0.0.1" + , "private": true +} \ No newline at end of file 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 new file mode 100644 index 0000000..ccf3ac5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/package.json @@ -0,0 +1,39 @@ +{ + "name": "temporary", + "version": "0.0.5", + "description": "The lord of tmp.", + "keywords": [ + "tmp", + "temp", + "tempfile", + "tempdirectory" + ], + "author": { + "name": "Veselin Todorov", + "email": "hi@vesln.com" + }, + "dependencies": { + "package": ">= 1.0.0 < 1.2.0" + }, + "devDependencies": { + "mocha": "1.2.x", + "chai": "*", + "sinon": "1.2.0" + }, + "repository": { + "type": "git", + "url": "http://github.com/vesln/temporary.git" + }, + "homepage": "http://github.com/vesln/temporary", + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "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.", + "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/temporary/test/base.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/base.test.js new file mode 100644 index 0000000..2fdea28 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/base.test.js @@ -0,0 +1,57 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var path = require('path'); +var fs = require('fs'); +var existsSync = fs.existsSync || path.existsSync; + +var Base = require('../lib/base'); +var generator = require('../lib/generator'); +var should = require('chai').should(); + +Base.prototype.create = function() {}; + +describe('Base', function() { + describe('rename', function() { + it('should rename the directory', function(done) { + var tmp = new Base; + tmp.path = generator.build(); + fs.mkdirSync(path.normalize(tmp.path), 0777); + existsSync(tmp.path).should.be.ok; + tmp.rename('foo', function(err) { + existsSync(tmp.path).should.be.ok; + done(); + }); + }); + }); + + describe('renameSync', function() { + it('should rename the directory', function() { + var tmp = new Base('foo'); + tmp.path = generator.build(); + fs.mkdirSync(path.normalize(tmp.path), 0777); + var oldPath = tmp.path; + existsSync(tmp.path).should.be.ok; + tmp.renameSync('foo3'); + existsSync(tmp.path).should.be.ok; + path.should.not.eql(oldPath); + }); + }); + + describe('prepareArgs', function() { + it('should convert object to array and append path as first element', function() { + var tmp = new Base('foo'); + var args = { 0: 'foo' }; + args.length = 1; + tmp.path = generator.build(); + tmp.prepareArgs(args).should.eql([tmp.path, 'foo']); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/detector.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/detector.test.js new file mode 100644 index 0000000..ed48366 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/detector.test.js @@ -0,0 +1,24 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var detector = require('../lib/detector'); +var should = require('chai').should(); + +describe('detector', function() { + describe('tmp', function() { + it('should return the tmp dir of the system', function() { + var tmp = process.env.TMPDIR + || process.env.TMP + || process.env.TEMP + || (process.platform === "win32" ? "c:\\windows\\temp\\" : "/tmp/"); + detector.tmp().should.eql(tmp); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/dir.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/dir.test.js new file mode 100644 index 0000000..8875a88 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/dir.test.js @@ -0,0 +1,44 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var existsSync = fs.existsSync || path.existsSync; + +var Tempdir = require('../lib/dir'); +var sinon = require('sinon'); +var should = require('chai').should(); + +describe('Tempdir', function() { + it('should create file', function() { + var tmp = new Tempdir('foo'); + existsSync(tmp.path).should.be.ok; + }); + + describe('rmdir', function() { + it('should remove the directory', function() { + var tmp = new Tempdir('foo'); + sinon.spy(fs, 'rmdir'); + tmp.rmdir(); + fs.rmdir.getCall(0).args[0].should.eql(tmp.path); + fs.rmdir.restore(); + }); + }); + + describe('rmdirSync', function() { + it('should remove the directory', function() { + var tmp = new Tempdir('foo'); + sinon.spy(fs, 'rmdirSync'); + tmp.rmdirSync(); + fs.rmdirSync.getCall(0).args[0].should.eql(tmp.path); + fs.rmdirSync.restore(); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/file.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/file.test.js new file mode 100644 index 0000000..9927e31 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/file.test.js @@ -0,0 +1,126 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var path = require('path'); +var fs = require('fs'); +var existsSync = fs.existsSync || path.existsSync; + +var Tempfile = require('../lib/file'); +var sinon = require('sinon'); +var should = require('chai').should(); + +describe('Tempfile', function() { + it('should create file', function() { + var tmp = new Tempfile('foo'); + existsSync(tmp.path).should.be.ok; + }); + + describe('readFile', function() { + it('should call fs.readfile', function() { + sinon.spy(fs, 'readFile'); + var tmp = new Tempfile; + tmp.readFile(); + fs.readFile.getCall(0).args[0].should.eql(tmp.path); + fs.readFile.restore(); + }); + }); + + describe('readFileSync', function() { + it('should call fs.readfileSync', function() { + sinon.spy(fs, 'readFileSync'); + var tmp = new Tempfile; + tmp.readFileSync(); + fs.readFileSync.getCall(0).args[0].should.eql(tmp.path); + fs.readFileSync.restore(); + }); + }); + + describe('writeFile', function() { + it('should call fs.readfile', function() { + sinon.spy(fs, 'writeFile'); + var tmp = new Tempfile; + tmp.writeFile(); + fs.writeFile.getCall(0).args[0].should.eql(tmp.path); + fs.writeFile.restore(); + }); + }); + + describe('writeFileSync', function() { + it('should call fs.writeFileSync', function() { + sinon.spy(fs, 'writeFileSync'); + var tmp = new Tempfile; + tmp.writeFileSync(); + fs.writeFileSync.getCall(0).args[0].should.eql(tmp.path); + fs.writeFileSync.restore(); + }); + }); + + describe('open', function() { + it('should call fs.open', function() { + sinon.spy(fs, 'open'); + var tmp = new Tempfile; + tmp.open('r'); + fs.open.getCall(0).args[0].should.eql(tmp.path); + fs.open.restore(); + }); + }); + + describe('openSync', function() { + it('should call fs.openSync', function() { + sinon.spy(fs, 'openSync'); + var tmp = new Tempfile; + tmp.openSync('r'); + fs.openSync.getCall(0).args[0].should.eql(tmp.path); + fs.openSync.restore(); + }); + }); + + describe('close', function() { + it('should call fs.close', function() { + sinon.spy(fs, 'close'); + var tmp = new Tempfile; + var fd = tmp.openSync('r'); + tmp.close(fd); + fs.close.getCall(0).args[0].should.eql(fd); + fs.close.restore(); + }); + }); + + describe('closeSync', function() { + it('should call fs.closeSync', function() { + sinon.spy(fs, 'closeSync'); + var tmp = new Tempfile; + var fd = tmp.openSync('r'); + tmp.closeSync(fd); + fs.closeSync.getCall(0).args[0].should.eql(fd); + fs.closeSync.restore(); + }); + }); + + describe('unlink', function() { + it('should call fs.unlink', function() { + sinon.spy(fs, 'unlink'); + var tmp = new Tempfile; + tmp.unlink(); + fs.unlink.getCall(0).args[0].should.eql(tmp.path); + fs.unlink.restore(); + }); + }); + + describe('unlinkSync', function() { + it('should call fs.readfileSync', function() { + sinon.spy(fs, 'unlinkSync'); + var tmp = new Tempfile; + tmp.unlinkSync(); + fs.unlinkSync.getCall(0).args[0].should.eql(tmp.path); + fs.unlinkSync.restore(); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/generator.test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/generator.test.js new file mode 100644 index 0000000..2483a91 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/temporary/test/generator.test.js @@ -0,0 +1,29 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var generator = require('../lib/generator'); +var detector = require('../lib/detector'); +var should = require('chai').should(); + +describe('generator', function() { + describe('name', function() { + it('should unique generate name', function() { + generator.name().should.be.ok; + }); + }); + + describe('build', function() { + it('should build full names', function() { + var tmp = detector.tmp(); + generator.build().should.match(new RegExp("^" + tmp)); + generator.build('foo').should.match(new RegExp("^" + tmp + 'foo.')); + }); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..83c3dac --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/.npmignore @@ -0,0 +1,6 @@ +.DS_Store +.tmp*~ +*.local.* +.pinf-* +node_modules/ +npm-debug.log 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 new file mode 100644 index 0000000..abefdf1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.html @@ -0,0 +1,1012 @@ + + + + +UglifyJS – a JavaScript parser/compressor/beautifier + + + + + + + + + + + + + +
    + +
    + +
    +

    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 +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the exports.* lines from UglifyJS sources). +

    +

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

    +

    +( See cl-uglify-js if you're looking for the Common Lisp version of +UglifyJS. ) +

    +

    +The second part of this package, implemented in process.js, inspects and +manipulates the AST generated by the parser to provide the following: +

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

    2.1 Unsafe transformations

    +
    + + +

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

    + +
    + +
    +

    2.1.1 Calls involving the global Array constructor

    +
    + + +

    +The following transformations occur: +

    + + + +
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +Array(a, b, c)         => [a,b,c]
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
    +
    + + +

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

    +

    +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a function or var declaration. Therefore, in the +following cases UglifyJS doesn't touch calls or instantiations of Array: +

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

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

    +
    + + +
    +
    + +
    + +
    +

    2.2 Install (NPM)

    +
    + + +

    +UglifyJS is now available through NPM — npm install uglify-js should do +the job. +

    +
    + +
    + +
    +

    2.3 Install latest code from GitHub

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

    2.4 Usage

    +
    + + +

    +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: +

    + + + +
    uglifyjs [ options... ] [ filename ]
    +
    + + +

    +filename should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. +

    +

    +Supported options: +

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

    2.4.1 API

    +
    + + +

    +To use the library from JavaScript, you'd do the following (example for +NodeJS): +

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

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

    +

    +Some of these functions take optional arguments. Here's a description: +

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

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

      +

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

      +

      + Here's an example of what it does: +

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

    2.4.2 Beautifier shortcoming – no more comments

    +
    + + +

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

    +

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

    +
    + +
    + +
    +

    2.4.3 Use as a code pre-processor

    +
    + + +

    +The --define option can be used, particularly when combined with the +constant folding logic, as a form of pre-processor to enable or remove +particular constructions, such as might be used for instrumenting +development code, or to produce variations aimed at a specific +platform. +

    +

    +The code below illustrates the way this can be done, and how the +symbol replacement is performed. +

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

    +When the above code is normally executed, the undeclared global +variable DEVMODE will be assigned the value true (see CLAUSE1) +and so the init() function (CLAUSE2) will write messages to the +console log when executed, but in CLAUSE3 a locally declared +variable will mask access to the DEVMODE global symbol. +

    +

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

    +

    +And more so, the constant-folding features of UglifyJS will recognise +that the if condition of CLAUSE1 is thus always false, and so will +remove the test and body of CLAUSE1 altogether (including the +otherwise slightly problematical statement false = true; which it +will have formed by replacing DEVMODE in the body). Similarly, +within CLAUSE2 both calls to console.log() will be removed +altogether. +

    +

    +In this way you can mimic, to a limited degree, the functionality of +the C/C++ pre-processor to enable or completely remove blocks +depending on how certain symbols are defined - perhaps using UglifyJS +to generate different versions of source aimed at different +environments +

    +

    +It is recommmended (but not made mandatory) that symbols designed for +this purpose are given names consisting of UPPER_CASE_LETTERS to +distinguish them from other (normal) symbols and avoid the sort of +clash that CLAUSE3 above illustrates. +

    +
    +
    + +
    + +
    +

    2.5 Compression – how good is it?

    +
    + + +

    +Here are updated statistics. (I also updated my Google Closure and YUI +installations). +

    +

    +We're still a lot better than YUI in terms of compression, though slightly +slower. We're still a lot faster than Closure, and compression after gzip +is comparable. +

    + + ++ + + + + + + + + + +
    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
    + + +
    + +
    + +
    +

    2.6 Bugs?

    +
    + + +

    +Unfortunately, for the time being there is no automated test suite. But I +ran the compressor manually on non-trivial code, and then I tested that the +generated code works as expected. A few hundred times. +

    +

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

    +

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

    +
    + +
    + +
    +

    2.7 Links

    +
    + + + + + +
    + +
    + +
    +

    2.8 License

    +
    + + +

    +UglifyJS is released under the BSD license: +

    + + + +
    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
    +Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions
    +are met:
    +
    +    * Redistributions of source code must retain the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer.
    +
    +    * Redistributions in binary form must reproduce the above
    +      copyright notice, this list of conditions and the following
    +      disclaimer in the documentation and/or other materials
    +      provided with the distribution.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
    +
    + + +
    +

    Footnotes:

    +
    +

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

    +
    +
    + +
    +
    +
    + +
    +

    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 new file mode 100644 index 0000000..2588088 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/README.org @@ -0,0 +1,593 @@ +#+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier +#+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier +#+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript +#+STYLE: +#+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 +parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it +should work on any JavaScript platform supporting the CommonJS module system +(and if your platform of choice doesn't support CommonJS, you can easily +implement it, or discard the =exports.*= lines from UglifyJS sources). + +The tokenizer/parser generates an abstract syntax tree from JS code. You +can then traverse the AST to learn more about the code, or do various +manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a +port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn +Haverbeke]]. + +( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of +UglifyJS. ) + +The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and +manipulates the AST generated by the parser to provide the following: + +- ability to re-generate JavaScript code from the AST. Optionally + indented---you can use this if you want to “beautify” a program that has + been compressed, so that you can inspect the source. But you can also run + our code generator to print out an AST without any whitespace, so you + achieve compression as well. + +- shorten variable names (usually to single characters). Our mangler will + analyze the code and generate proper variable names, depending on scope + and usage, and is smart enough to deal with globals defined elsewhere, or + with =eval()= calls or =with{}= statements. In short, if =eval()= or + =with{}= are used in some scope, then all variables in that scope and any + variables in the parent scopes will remain unmangled, and any references + to such variables remain unmangled as well. + +- various small optimizations that may lead to faster code but certainly + lead to smaller code. Where possible, we do the following: + + - foo["bar"] ==> foo.bar + + - remove block brackets ={}= + + - join consecutive var declarations: + var a = 10; var b = 20; ==> var a=10,b=20; + + - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the + replacement if the result occupies less bytes; for example 1/3 would + translate to 0.333333333333, so in this case we don't replace it. + + - consecutive statements in blocks are merged into a sequence; in many + cases, this leaves blocks with a single statement, so then we can remove + the block brackets. + + - various optimizations for IF statements: + + - if (foo) bar(); else baz(); ==> foo?bar():baz(); + - if (!foo) bar(); else baz(); ==> foo?baz():bar(); + - if (foo) bar(); ==> foo&&bar(); + - if (!foo) bar(); ==> foo||bar(); + - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); + - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()} + + - remove some unreachable code and warn about it (code that follows a + =return=, =throw=, =break= or =continue= statement, except + function/variable declarations). + + - act a limited version of a pre-processor (c.f. the pre-processor of + C/C++) to allow you to safely replace selected global symbols with + specified values. When combined with the optimisations above this can + make UglifyJS operate slightly more like a compilation process, in + that when certain symbols are replaced by constant values, entire code + blocks may be optimised away as unreachable. + +** <> + +The following transformations can in theory break code, although they're +probably safe in most practical cases. To enable them you need to pass the +=--unsafe= flag. + +*** Calls involving the global Array constructor + +The following transformations occur: + +#+BEGIN_SRC js +new Array(1, 2, 3, 4) => [1,2,3,4] +Array(a, b, c) => [a,b,c] +new Array(5) => Array(5) +new Array(a) => Array(a) +#+END_SRC + +These are all safe if the Array name isn't redefined. JavaScript does allow +one to globally redefine Array (and pretty much everything, in fact) but I +personally don't see why would anyone do that. + +UglifyJS does handle the case where Array is redefined locally, or even +globally but with a =function= or =var= declaration. Therefore, in the +following cases UglifyJS *doesn't touch* calls or instantiations of Array: + +#+BEGIN_SRC js +// case 1. globally declared variable + var Array; + new Array(1, 2, 3); + Array(a, b); + + // or (can be declared later) + new Array(1, 2, 3); + var Array; + + // or (can be a function) + new Array(1, 2, 3); + function Array() { ... } + +// case 2. declared in a function + (function(){ + a = new Array(1, 2, 3); + b = Array(5, 6); + var Array; + })(); + + // or + (function(Array){ + return Array(5, 6, 7); + })(); + + // or + (function(){ + return new Array(1, 2, 3, 4); + function Array() { ... } + })(); + + // etc. +#+END_SRC + +*** =obj.toString()= ==> =obj+“”= + +** Install (NPM) + +UglifyJS is now available through NPM --- =npm install uglify-js= should do +the job. + +** Install latest code from GitHub + +#+BEGIN_SRC sh +## clone the repository +mkdir -p /where/you/wanna/put/it +cd /where/you/wanna/put/it +git clone git://github.com/mishoo/UglifyJS.git + +## make the module available to Node +mkdir -p ~/.node_libraries/ +cd ~/.node_libraries/ +ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js + +## and if you want the CLI script too: +mkdir -p ~/bin +cd ~/bin +ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs + # (then add ~/bin to your $PATH if it's not there already) +#+END_SRC + +** Usage + +There is a command-line tool that exposes the functionality of this library +for your shell-scripting needs: + +#+BEGIN_SRC sh +uglifyjs [ options... ] [ filename ] +#+END_SRC + +=filename= should be the last argument and should name the file from which +to read the JavaScript code. If you don't specify it, it will read code +from STDIN. + +Supported options: + +- =-b= or =--beautify= --- output indented code; when passed, additional + options control the beautifier: + + - =-i N= or =--indent N= --- indentation level (number of spaces) + + - =-q= or =--quote-keys= --- quote keys in literal objects (by default, + only keys that cannot be identifier names will be quotes). + +- =-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 + output Unicode characters instead. (the output is always encoded in UTF8, + but if you pass this option you'll only get ASCII). + +- =-nm= or =--no-mangle= --- don't mangle names. + +- =-nmf= or =--no-mangle-functions= -- in case you want to mangle variable + names, but not touch function names. + +- =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various + optimizations that result in smaller, less readable code). + +- =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too + (by default we don't do this). + +- =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass + =--no-squeeze=) it will reduce consecutive statements in blocks into a + sequence. For example, "a = 10; b = 20; foo();" will be written as + "a=10,b=20,foo();". In various occasions, this allows us to discard the + block brackets (since the block becomes a single statement). This is ON + by default because it seems safe and saves a few hundred bytes on some + libs that I tested it on, but pass =--no-seqs= to disable it. + +- =--no-dead-code= --- by default, UglifyJS will remove code that is + obviously unreachable (code that follows a =return=, =throw=, =break= or + =continue= statement and is not a function/variable declaration). Pass + this option to disable this optimization. + +- =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial + comment tokens in the generated code (assumed to be copyright information + etc.). If you pass this it will discard it. + +- =-o filename= or =--output filename= --- put the result in =filename=. If + this isn't given, the result goes to standard output (or see next one). + +- =--overwrite= --- if the code is read from a file (not from STDIN) and you + pass =--overwrite= then the output will be written in the same file. + +- =--ast= --- pass this if you want to get the Abstract Syntax Tree instead + of JavaScript as output. Useful for debugging or learning more about the + internals. + +- =-v= or =--verbose= --- output some notes on STDERR (for now just how long + each operation takes). + +- =-d SYMBOL[=VALUE]= or =--define SYMBOL[=VALUE]= --- will replace + all instances of the specified symbol where used as an identifier + (except where symbol has properly declared by a var declaration or + use as function parameter or similar) with the specified value. This + argument may be specified multiple times to define multiple + symbols - if no value is specified the symbol will be replaced with + the value =true=, or you can specify a numeric value (such as + =1024=), a quoted string value (such as ="object"= or + ='https://github.com'=), or the name of another symbol or keyword + (such as =null= or =document=). + This allows you, for example, to assign meaningful names to key + constant values but discard the symbolic names in the uglified + version for brevity/efficiency, or when used wth care, allows + UglifyJS to operate as a form of *conditional compilation* + whereby defining appropriate values may, by dint of the constant + folding and dead code removal features above, remove entire + superfluous code blocks (e.g. completely remove instrumentation or + trace code for production use). + Where string values are being defined, the handling of quotes are + likely to be subject to the specifics of your command shell + environment, so you may need to experiment with quoting styles + depending on your platform, or you may find the option + =--define-from-module= more suitable for use. + +- =-define-from-module SOMEMODULE= --- will load the named module (as + per the NodeJS =require()= function) and iterate all the exported + properties of the module defining them as symbol names to be defined + (as if by the =--define= option) per the name of each property + (i.e. without the module name prefix) and given the value of the + property. This is a much easier way to handle and document groups of + symbols to be defined rather than a large number of =--define= + options. + +- =--unsafe= --- enable other additional optimizations that are known to be + unsafe in some contrived situations, but could still be generally useful. + For now only these: + + - foo.toString() ==> foo+"" + - new Array(x,...) ==> [x,...] + - new Array(x) ==> Array(x) + +- =--max-line-len= (default 32K characters) --- add a newline after around + 32K characters. I've seen both FF and Chrome croak when all the code was + on a single line of around 670K. Pass --max-line-len 0 to disable this + safety feature. + +- =--reserved-names= --- some libraries rely on certain names to be used, as + pointed out in issue #92 and #81, so this option allow you to exclude such + names from the mangler. For example, to keep names =require= and =$super= + intact you'd specify --reserved-names "require,$super". + +- =--inline-script= -- when you want to include the output literally in an + HTML =\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/beautify.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/beautify.js new file mode 100755 index 0000000..f19369e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/beautify.js @@ -0,0 +1,28 @@ +#! /usr/bin/env node + +global.sys = require("sys"); +var fs = require("fs"); + +var jsp = require("../lib/parse-js"); +var pro = require("../lib/process"); + +var filename = process.argv[2]; +fs.readFile(filename, "utf8", function(err, text){ + try { + var ast = time_it("parse", function(){ return jsp.parse(text); }); + ast = time_it("mangle", function(){ return pro.ast_mangle(ast); }); + ast = time_it("squeeze", function(){ return pro.ast_squeeze(ast); }); + var gen = time_it("generate", function(){ return pro.gen_code(ast, false); }); + sys.puts(gen); + } catch(ex) { + sys.debug(ex.stack); + sys.debug(sys.inspect(ex)); + sys.debug(JSON.stringify(ex)); + } +}); + +function time_it(name, 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/test/testconsolidator.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/testconsolidator.js new file mode 100755 index 0000000..0803012 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/testconsolidator.js @@ -0,0 +1,1391 @@ +#! /usr/bin/env node +global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + +'use strict'; +/*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, + latedef:true, newcap:true, noarge:true, noempty:true, nonew:true, + onevar:true, plusplus:true, regexp:true, undef:true, strict:true, + sub:false, trailing:true */ + +var _, + /** + * NodeJS module for unit testing. + * @namespace + * @type {!TAssert} + * @see http://nodejs.org/docs/v0.6.10/api/all.html#assert + */ + oAssert = (/** @type {!TAssert} */ require('assert')), + /** + * Consolidates null, Boolean, and String values found inside an + * AST. The object under test. + * @namespace + * @type {!TConsolidator} + */ + oConsolidator = (/** @type {!TConsolidator} */ require('../lib/consolidator')), + /** + * The parser of ECMA-262 found in UglifyJS. + * @namespace + * @type {!TParser} + */ + oParser = (/** @type {!TParser} */ require('../lib/parse-js')), + /** + * The processor of ASTs + * found in UglifyJS. + * @namespace + * @type {!TProcessor} + */ + oProcessor = (/** @type {!TProcessor} */ require('../lib/process')), + /** + * An instance of an object that allows the traversal of an AST. + * @type {!TWalker} + */ + oWalker, + /** + * A collection of functions for the removal of the scope information + * during the traversal of an AST. + * @namespace + * @type {!Object.} + */ + oWalkersPurifiers = { + /**#nocode+*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + /** + * Deletes the scope information from the branch of the abstract + * syntax tree representing the encountered function declaration. + * @param {string} sIdentifier The identifier of the function. + * @param {!Array.} aFormalParameterList Formal parameters. + * @param {!TSyntacticCodeUnit} oFunctionBody Function code. + */ + 'defun': function( + sIdentifier, + aFormalParameterList, + oFunctionBody) { + delete oFunctionBody.scope; + }, + /** + * Deletes the scope information from the branch of the abstract + * syntax tree representing the encountered function expression. + * @param {?string} sIdentifier The optional identifier of the + * function. + * @param {!Array.} aFormalParameterList Formal parameters. + * @param {!TSyntacticCodeUnit} oFunctionBody Function code. + */ + 'function': function( + sIdentifier, + aFormalParameterList, + oFunctionBody) { + delete oFunctionBody.scope; + } + /**#nocode-*/ // JsDoc Toolkit 2.4.0 hides some of the keys. + }, + /** + * Initiates the traversal of a source element. + * @param {!TWalker} oWalker An instance of an object that allows the + * traversal of an abstract syntax tree. + * @param {!TSyntacticCodeUnit} oSourceElement A source element from + * which the traversal should commence. + * @return {function(): !TSyntacticCodeUnit} A function that is able to + * initiate the traversal from a given source element. + */ + cContext = function(oWalker, oSourceElement) { + /** + * @return {!TSyntacticCodeUnit} A function that is able to + * initiate the traversal from a given source element. + */ + var fLambda = function() { + return oWalker.walk(oSourceElement); + }; + + return fLambda; + }, + /** + * A record consisting of configuration for the code generation phase. + * @type {!Object} + */ + oCodeGenerationOptions = { + beautify: true + }, + /** + * A boolean to track whether all tests have passed. + * @type {boolean} + */ + bTestsPassed = true, + /** + * Tests whether consolidation of an ECMAScript program yields expected + * results. + * @param {{ + * sTitle: string, + * sInput: string, + * sOutput: string + * }} oUnitTest A record consisting of data about a unit test: its + * name, an ECMAScript program, and, if consolidation is to take + * place, the resulting ECMAScript program. + */ + cAssert = function(oUnitTest) { + var _, + /** + * An array-like object representing the AST obtained after consolidation. + * @type {!TSyntacticCodeUnit} + */ + oSyntacticCodeUnitActual = + oConsolidator.ast_consolidate(oParser.parse(oUnitTest.sInput)), + /** + * An array-like object representing the expected AST. + * @type {!TSyntacticCodeUnit} + */ + oSyntacticCodeUnitExpected = oParser.parse( + oUnitTest.hasOwnProperty('sOutput') ? + oUnitTest.sOutput : oUnitTest.sInput); + + delete oSyntacticCodeUnitActual.scope; + oWalker = oProcessor.ast_walker(); + oWalker.with_walkers( + oWalkersPurifiers, + cContext(oWalker, oSyntacticCodeUnitActual)); + try { + oAssert.deepEqual( + oSyntacticCodeUnitActual, + oSyntacticCodeUnitExpected); + } catch (oException) { + console.error( + '########## A unit test has failed.\n' + + oUnitTest.sTitle + '\n' + + '##### actual code (' + + oProcessor.gen_code(oSyntacticCodeUnitActual).length + + ' bytes)\n' + + oProcessor.gen_code( + oSyntacticCodeUnitActual, + oCodeGenerationOptions) + '\n' + + '##### expected code (' + + oProcessor.gen_code(oSyntacticCodeUnitExpected).length + + ' bytes)\n' + + oProcessor.gen_code( + oSyntacticCodeUnitExpected, + oCodeGenerationOptions)); + bTestsPassed = false; + } + }; + +[ + // 7.6.1 Reserved Words. + { + sTitle: + 'Omission of keywords while choosing an identifier name.', + sInput: + '(function() {' + + ' var a, b, c, d, e, f, g, h, i, j, k, l, m,' + + ' n, o, p, q, r, s, t, u, v, w, x, y, z,' + + ' A, B, C, D, E, F, G, H, I, J, K, L, M,' + + ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' + + ' $, _,' + + ' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' + + ' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' + + ' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' + + ' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' + + ' a$, a_,' + + ' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' + + ' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' + + ' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' + + ' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' + + ' b$, b_,' + + ' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' + + ' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' + + ' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' + + ' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' + + ' c$, c_,' + + ' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' + + ' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' + + ' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' + + ' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' + + ' d$, d_;' + + ' void ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' + + ' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];' + + '}());', + sOutput: + '(function() {' + + ' var eb =' + + ' "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",' + + ' a, b, c, d, e, f, g, h, i, j, k, l, m,' + + ' n, o, p, q, r, s, t, u, v, w, x, y, z,' + + ' A, B, C, D, E, F, G, H, I, J, K, L, M,' + + ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' + + ' $, _,' + + ' aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am,' + + ' an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az,' + + ' aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,' + + ' aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,' + + ' a$, a_,' + + ' ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm,' + + ' bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz,' + + ' bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM,' + + ' bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ,' + + ' b$, b_,' + + ' ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm,' + + ' cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz,' + + ' cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM,' + + ' cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ,' + + ' c$, c_,' + + ' da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm,' + + ' dn, dq, dr, ds, dt, du, dv, dw, dx, dy, dz,' + + ' dA, dB, dC, dD, dE, dF, dG, dH, dI, dJ, dK, dL, dM,' + + ' dN, dO, dP, dQ, dR, dS, dT, dU, dV, dW, dX, dY, dZ,' + + ' d$, d_;' + + ' void [eb, eb];' + + '}());' + }, + // 7.8.1 Null Literals. + { + sTitle: + 'Evaluation with regard to the null value.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' var foo;' + + ' void [null, null, null];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [null, null];' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' var a = null, foo;' + + ' void [a, a, a];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [null, null];' + + '}());' + }, + // 7.8.2 Boolean Literals. + { + sTitle: + 'Evaluation with regard to the false value.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' var foo;' + + ' void [false, false, false];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [false, false];' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' var a = false, foo;' + + ' void [a, a, a];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [false, false];' + + '}());' + }, + { + sTitle: + 'Evaluation with regard to the true value.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' var foo;' + + ' void [true, true, true];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [true, true];' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' var a = true, foo;' + + ' void [a, a, a];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void [true, true];' + + '}());' + }, + // 7.8.4 String Literals. + { + sTitle: + 'Evaluation with regard to the String value of a string literal.', + sInput: + '(function() {' + + ' var foo;' + + ' void ["abcd", "abcd", "abc", "abc"];' + + '}());', + sOutput: + '(function() {' + + ' var a = "abcd", foo;' + + ' void [a, a, "abc", "abc"];' + + '}());' + }, + // 7.8.5 Regular Expression Literals. + { + sTitle: + 'Preservation of the pattern of a regular expression literal.', + sInput: + 'void [/abcdefghijklmnopqrstuvwxyz/, /abcdefghijklmnopqrstuvwxyz/];' + }, + { + sTitle: + 'Preservation of the flags of a regular expression literal.', + sInput: + 'void [/(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' + + ' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim,' + + ' /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim, /(?:)/gim];' + }, + // 10.2 Lexical Environments. + { + sTitle: + 'Preservation of identifier names in the same scope.', + sInput: + '/*jshint shadow:true */' + + 'var a;' + + 'function b(i) {' + + '}' + + 'for (var c; 0 === Math.random(););' + + 'for (var d in {});' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + 'void [b(a), b(c), b(d)];' + + 'void [typeof e];' + + 'i: for (; 0 === Math.random();) {' + + ' if (42 === (new Date()).getMinutes()) {' + + ' continue i;' + + ' } else {' + + ' break i;' + + ' }' + + '}' + + 'try {' + + '} catch (f) {' + + '} finally {' + + '}' + + '(function g(h) {' + + '}());' + + 'void [{' + + ' i: 42,' + + ' "j": 42,' + + ' \'k\': 42' + + '}];' + + 'void ["abcdefghijklmnopqrstuvwxyz"];', + sOutput: + '/*jshint shadow:true */' + + 'var a;' + + 'function b(i) {' + + '}' + + 'for (var c; 0 === Math.random(););' + + 'for (var d in {});' + + '(function() {' + + ' var i = "abcdefghijklmnopqrstuvwxyz";' + + ' void [i];' + + ' void [b(a), b(c), b(d)];' + + ' void [typeof e];' + + ' i: for (; 0 === Math.random();) {' + + ' if (42 === (new Date()).getMinutes()) {' + + ' continue i;' + + ' } else {' + + ' break i;' + + ' }' + + ' }' + + ' try {' + + ' } catch (f) {' + + ' } finally {' + + ' }' + + ' (function g(h) {' + + ' }());' + + ' void [{' + + ' i: 42,' + + ' "j": 42,' + + ' \'k\': 42' + + ' }];' + + ' void [i];' + + '}());' + }, + { + sTitle: + 'Preservation of identifier names in nested function code.', + sInput: + '(function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' (function() {' + + ' var a;' + + ' for (var b; 0 === Math.random(););' + + ' for (var c in {});' + + ' void [typeof d];' + + ' h: for (; 0 === Math.random();) {' + + ' if (42 === (new Date()).getMinutes()) {' + + ' continue h;' + + ' } else {' + + ' break h;' + + ' }' + + ' }' + + ' try {' + + ' } catch (e) {' + + ' } finally {' + + ' }' + + ' (function f(g) {' + + ' }());' + + ' void [{' + + ' h: 42,' + + ' "i": 42,' + + ' \'j\': 42' + + ' }];' + + ' }());' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '(function() {' + + ' var h = "abcdefghijklmnopqrstuvwxyz";' + + ' void [h];' + + ' (function() {' + + ' var a;' + + ' for (var b; 0 === Math.random(););' + + ' for (var c in {});' + + ' void [typeof d];' + + ' h: for (; 0 === Math.random();) {' + + ' if (42 === (new Date()).getMinutes()) {' + + ' continue h;' + + ' } else {' + + ' break h;' + + ' }' + + ' }' + + ' try {' + + ' } catch (e) {' + + ' } finally {' + + ' }' + + ' (function f(g) {' + + ' }());' + + ' void [{' + + ' h: 42,' + + ' "i": 42,' + + ' \'j\': 42' + + ' }];' + + ' }());' + + ' void [h];' + + '}());' + }, + { + sTitle: + 'Consolidation of a closure with other source elements.', + sInput: + '(function(foo) {' + + '}("abcdefghijklmnopqrstuvwxyz"));' + + 'void ["abcdefghijklmnopqrstuvwxyz"];', + sOutput: + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' (function(foo) {' + + ' })(a);' + + ' void [a];' + + '}());' + }, + { + sTitle: + 'Consolidation of function code instead of a sole closure.', + sInput: + '(function(foo, bar) {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));', + sOutput: + '(function(foo, bar) {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"));' + }, + // 11.1.5 Object Initialiser. + { + sTitle: + 'Preservation of property names of an object initialiser.', + sInput: + 'var foo = {' + + ' abcdefghijklmnopqrstuvwxyz: 42,' + + ' "zyxwvutsrqponmlkjihgfedcba": 42,' + + ' \'mlkjihgfedcbanopqrstuvwxyz\': 42' + + '};' + + 'void [' + + ' foo.abcdefghijklmnopqrstuvwxyz,' + + ' "zyxwvutsrqponmlkjihgfedcba",' + + ' \'mlkjihgfedcbanopqrstuvwxyz\'' + + '];' + }, + { + sTitle: + 'Evaluation with regard to String values derived from identifier ' + + 'names used as property accessors.', + sInput: + '(function() {' + + ' var foo;' + + ' void [' + + ' Math.abcdefghij,' + + ' Math.abcdefghij,' + + ' Math.abcdefghi,' + + ' Math.abcdefghi' + + ' ];' + + '}());', + sOutput: + '(function() {' + + ' var a = "abcdefghij", foo;' + + ' void [' + + ' Math[a],' + + ' Math[a],' + + ' Math.abcdefghi,' + + ' Math.abcdefghi' + + ' ];' + + '}());' + }, + // 11.2.1 Property Accessors. + { + sTitle: + 'Preservation of identifiers in the nonterminal MemberExpression.', + sInput: + 'void [' + + ' Math.E,' + + ' Math.LN10,' + + ' Math.LN2,' + + ' Math.LOG2E,' + + ' Math.LOG10E,' + + ' Math.PI,' + + ' Math.SQRT1_2,' + + ' Math.SQRT2,' + + ' Math.abs,' + + ' Math.acos' + + '];' + }, + // 12.2 Variable Statement. + { + sTitle: + 'Preservation of the identifier of a variable that is being ' + + 'declared in a variable statement.', + sInput: + '(function() {' + + ' var abcdefghijklmnopqrstuvwxyz;' + + ' void [abcdefghijklmnopqrstuvwxyz];' + + '}());' + }, + { + sTitle: + 'Exclusion of a variable statement in global code.', + sInput: + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + 'var foo = "abcdefghijklmnopqrstuvwxyz",' + + ' bar = "abcdefghijklmnopqrstuvwxyz";' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + { + sTitle: + 'Exclusion of a variable statement in function code that ' + + 'contains a with statement.', + sInput: + '(function() {' + + ' with ({});' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' var foo;' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());' + }, + { + sTitle: + 'Exclusion of a variable statement in function code that ' + + 'contains a direct call to the eval function.', + sInput: + '/*jshint evil:true */' + + 'void [' + + ' function() {' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' var foo;' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' }' + + '];' + }, + { + sTitle: + 'Consolidation within a variable statement in global code.', + sInput: + 'var foo = function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '};', + sOutput: + 'var foo = function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '};' + }, + { + sTitle: + 'Consolidation within a variable statement excluded in function ' + + 'code due to the presence of a with statement.', + sInput: + '(function() {' + + ' with ({});' + + ' var foo = function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' };' + + '}());', + sOutput: + '(function() {' + + ' with ({});' + + ' var foo = function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' };' + + '}());' + }, + { + sTitle: + 'Consolidation within a variable statement excluded in function ' + + 'code due to the presence of a direct call to the eval function.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' eval("");' + + ' var foo = function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' };' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' eval("");' + + ' var foo = function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' };' + + '}());' + }, + { + sTitle: + 'Inclusion of a variable statement in function code that ' + + 'contains no with statement and no direct call to the eval ' + + 'function.', + sInput: + '(function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' var foo;' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a];' + + ' var foo;' + + ' void [a];' + + '}());' + }, + { + sTitle: + 'Ignorance with regard to a variable statement in global code.', + sInput: + 'var foo = "abcdefghijklmnopqrstuvwxyz";' + + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];', + sOutput: + 'var foo = "abcdefghijklmnopqrstuvwxyz";' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + // 12.4 Expression Statement. + { + sTitle: + 'Preservation of identifiers in an expression statement.', + sInput: + 'void [typeof abcdefghijklmnopqrstuvwxyz,' + + ' typeof abcdefghijklmnopqrstuvwxyz];' + }, + // 12.6.3 The {@code for} Statement. + { + sTitle: + 'Preservation of identifiers in the variable declaration list of ' + + 'a for statement.', + sInput: + 'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););' + + 'for (var abcdefghijklmnopqrstuvwxyz; 0 === Math.random(););' + }, + // 12.6.4 The {@code for-in} Statement. + { + sTitle: + 'Preservation of identifiers in the variable declaration list of ' + + 'a for-in statement.', + sInput: + 'for (var abcdefghijklmnopqrstuvwxyz in {});' + + 'for (var abcdefghijklmnopqrstuvwxyz in {});' + }, + // 12.7 The {@code continue} Statement. + { + sTitle: + 'Preservation of the identifier in a continue statement.', + sInput: + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' + + ' continue abcdefghijklmnopqrstuvwxyz;' + + '}' + + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' + + ' continue abcdefghijklmnopqrstuvwxyz;' + + '}' + }, + // 12.8 The {@code break} Statement. + { + sTitle: + 'Preservation of the identifier in a break statement.', + sInput: + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' + + ' break abcdefghijklmnopqrstuvwxyz;' + + '}' + + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random();) {' + + ' break abcdefghijklmnopqrstuvwxyz;' + + '}' + }, + // 12.9 The {@code return} Statement. + { + sTitle: + 'Exclusion of a return statement in function code that contains ' + + 'a with statement.', + sInput: + '(function() {' + + ' with ({});' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' if (0 === Math.random()) {' + + ' return;' + + ' } else {' + + ' }' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());' + }, + { + sTitle: + 'Exclusion of a return statement in function code that contains ' + + 'a direct call to the eval function.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' if (0 === Math.random()) {' + + ' return;' + + ' } else {' + + ' }' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());' + }, + { + sTitle: + 'Consolidation within a return statement excluded in function ' + + 'code due to the presence of a with statement.', + sInput: + '(function() {' + + ' with ({});' + + ' return function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' };' + + '}());', + sOutput: + '(function() {' + + ' with ({});' + + ' return function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' };' + + '}());' + }, + { + sTitle: + 'Consolidation within a return statement excluded in function ' + + 'code due to the presence of a direct call to the eval function.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' eval("");' + + ' return function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' };' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' eval("");' + + ' return function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' };' + + '}());' + }, + { + sTitle: + 'Inclusion of a return statement in function code that contains ' + + 'no with statement and no direct call to the eval function.', + sInput: + '(function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + ' if (0 === Math.random()) {' + + ' return;' + + ' } else {' + + ' }' + + ' void ["abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a];' + + ' if (0 === Math.random()) {' + + ' return;' + + ' } else {' + + ' }' + + ' void [a];' + + '}());' + }, + // 12.10 The {@code with} Statement. + { + sTitle: + 'Preservation of the statement in a with statement.', + sInput: + 'with ({}) {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}' + }, + { + sTitle: + 'Exclusion of a with statement in the same syntactic code unit.', + sInput: + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + 'with ({' + + ' foo: "abcdefghijklmnopqrstuvwxyz",' + + ' bar: "abcdefghijklmnopqrstuvwxyz"' + + '}) {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + { + sTitle: + 'Exclusion of a with statement in nested function code.', + sInput: + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + '(function() {' + + ' with ({' + + ' foo: "abcdefghijklmnopqrstuvwxyz",' + + ' bar: "abcdefghijklmnopqrstuvwxyz"' + + ' }) {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' }' + + '}());' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + // 12.12 Labelled Statements. + { + sTitle: + 'Preservation of the label of a labelled statement.', + sInput: + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););' + + 'abcdefghijklmnopqrstuvwxyz: for (; 0 === Math.random(););' + }, + // 12.14 The {@code try} Statement. + { + sTitle: + 'Preservation of the identifier in the catch clause of a try' + + 'statement.', + sInput: + 'try {' + + '} catch (abcdefghijklmnopqrstuvwxyz) {' + + '} finally {' + + '}' + + 'try {' + + '} catch (abcdefghijklmnopqrstuvwxyz) {' + + '} finally {' + + '}' + }, + // 13 Function Definition. + { + sTitle: + 'Preservation of the identifier of a function declaration.', + sInput: + 'function abcdefghijklmnopqrstuvwxyz() {' + + '}' + + 'void [abcdefghijklmnopqrstuvwxyz];' + }, + { + sTitle: + 'Preservation of the identifier of a function expression.', + sInput: + 'void [' + + ' function abcdefghijklmnopqrstuvwxyz() {' + + ' },' + + ' function abcdefghijklmnopqrstuvwxyz() {' + + ' }' + + '];' + }, + { + sTitle: + 'Preservation of a formal parameter of a function declaration.', + sInput: + 'function foo(abcdefghijklmnopqrstuvwxyz) {' + + '}' + + 'function bar(abcdefghijklmnopqrstuvwxyz) {' + + '}' + }, + { + sTitle: + 'Preservation of a formal parameter in a function expression.', + sInput: + 'void [' + + ' function(abcdefghijklmnopqrstuvwxyz) {' + + ' },' + + ' function(abcdefghijklmnopqrstuvwxyz) {' + + ' }' + + '];' + }, + { + sTitle: + 'Exclusion of a function declaration.', + sInput: + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + 'function foo() {' + + '}' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + { + sTitle: + 'Consolidation within a function declaration.', + sInput: + 'function foo() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}', + sOutput: + 'function foo() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}' + }, + // 14 Program. + { + sTitle: + 'Preservation of a program without source elements.', + sInput: + '' + }, + // 14.1 Directive Prologues and the Use Strict Directive. + { + sTitle: + 'Preservation of a Directive Prologue in global code.', + sInput: + '"abcdefghijklmnopqrstuvwxyz";' + + '\'zyxwvutsrqponmlkjihgfedcba\';' + }, + { + sTitle: + 'Preservation of a Directive Prologue in a function declaration.', + sInput: + 'function foo() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' \'zyxwvutsrqponmlkjihgfedcba\';' + + '}' + }, + { + sTitle: + 'Preservation of a Directive Prologue in a function expression.', + sInput: + 'void [' + + ' function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' \'zyxwvutsrqponmlkjihgfedcba\';' + + ' }' + + '];' + }, + { + sTitle: + 'Ignorance with regard to a Directive Prologue in global code.', + sInput: + '"abcdefghijklmnopqrstuvwxyz";' + + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];', + sOutput: + '"abcdefghijklmnopqrstuvwxyz";' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + { + sTitle: + 'Ignorance with regard to a Directive Prologue in a function' + + 'declaration.', + sInput: + 'function foo() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}', + sOutput: + 'function foo() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}' + }, + { + sTitle: + 'Ignorance with regard to a Directive Prologue in a function' + + 'expression.', + sInput: + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + // 15.1 The Global Object. + { + sTitle: + 'Preservation of a property of the global object.', + sInput: + 'void [undefined, undefined, undefined, undefined, undefined];' + }, + // 15.1.2.1.1 Direct Call to Eval. + { + sTitle: + 'Exclusion of a direct call to the eval function in the same ' + + 'syntactic code unit.', + sInput: + '/*jshint evil:true */' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + 'eval("");' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + { + sTitle: + 'Exclusion of a direct call to the eval function in nested ' + + 'function code.', + sInput: + '/*jshint evil:true */' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + + '(function() {' + + ' eval("");' + + '}());' + + 'void ["abcdefghijklmnopqrstuvwxyz"];' + }, + { + sTitle: + 'Consolidation within a direct call to the eval function.', + sInput: + '/*jshint evil:true */' + + 'eval(function() {' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '/*jshint evil:true */' + + 'eval(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + // Consolidation proper. + { + sTitle: + 'No consolidation if it does not result in a reduction of the ' + + 'number of source characters.', + sInput: + '(function() {' + + ' var foo;' + + ' void ["ab", "ab", "abc", "abc"];' + + '}());' + }, + { + sTitle: + 'Identification of a range of source elements at the beginning ' + + 'of global code.', + sInput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + 'eval("");', + sOutput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + + 'eval("");' + }, + { + sTitle: + 'Identification of a range of source elements in the middle of ' + + 'global code.', + sInput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + 'eval("");' + + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + 'eval("");', + sOutput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + 'eval("");' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + + 'eval("");' + }, + { + sTitle: + 'Identification of a range of source elements at the end of ' + + 'global code.', + sInput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + 'eval("");' + + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];', + sOutput: + '/*jshint evil:true */' + + '"abcdefghijklmnopqrstuvwxyz";' + + 'eval("");' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + { + sTitle: + 'Identification of a range of source elements at the beginning ' + + 'of function code.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' eval("");' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' (function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' }());' + + ' eval("");' + + '}());' + }, + { + sTitle: + 'Identification of a range of source elements in the middle of ' + + 'function code.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + ' eval("");' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' eval("");' + + ' (function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' }());' + + ' eval("");' + + '}());' + }, + { + sTitle: + 'Identification of a range of source elements at the end of ' + + 'function code.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' "abcdefghijklmnopqrstuvwxyz";' + + ' eval("");' + + ' (function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + ' }());' + + '}());' + }, + { + sTitle: + 'Evaluation with regard to String values of String literals and ' + + 'String values derived from identifier names used as property' + + 'accessors.', + sInput: + '(function() {' + + ' var foo;' + + ' void ["abcdefg", Math.abcdefg, "abcdef", Math.abcdef];' + + '}());', + sOutput: + '(function() {' + + ' var a = "abcdefg", foo;' + + ' void [a, Math[a], "abcdef", Math.abcdef];' + + '}());' + }, + { + sTitle: + 'Evaluation with regard to the necessity of adding a variable ' + + 'statement.', + sInput: + '/*jshint evil:true */' + + '(function() {' + + ' void ["abcdefgh", "abcdefgh"];' + + '}());' + + 'eval("");' + + '(function() {' + + ' void ["abcdefg", "abcdefg"];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var foo;' + + ' void ["abcd", "abcd"];' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' var a = "abcdefgh";' + + ' void [a, a];' + + '}());' + + 'eval("");' + + '(function() {' + + ' void ["abcdefg", "abcdefg"];' + + '}());' + + 'eval("");' + + '(function() {' + + ' var a = "abcd", foo;' + + ' void [a, a];' + + '}());' + }, + { + sTitle: + 'Evaluation with regard to the necessity of enclosing source ' + + 'elements.', + sInput: + '/*jshint evil:true */' + + 'void ["abcdefghijklmnopqrstuvwxy", "abcdefghijklmnopqrstuvwxy"];' + + 'eval("");' + + 'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' + + 'eval("");' + + '(function() {' + + ' void ["abcdefgh", "abcdefgh"];' + + '}());' + + '(function() {' + + ' void ["abcdefghijklmnopqrstuvwxy",' + + ' "abcdefghijklmnopqrstuvwxy"];' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwx",' + + ' "abcdefghijklmnopqrstuvwx"];' + + ' eval("");' + + ' (function() {' + + ' void ["abcdefgh", "abcdefgh"];' + + ' }());' + + '}());', + sOutput: + '/*jshint evil:true */' + + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxy";' + + ' void [a, a];' + + '}());' + + 'eval("");' + + 'void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' + + 'eval("");' + + '(function() {' + + ' var a = "abcdefgh";' + + ' void [a, a];' + + '}());' + + '(function() {' + + ' (function() {' + + ' var a = "abcdefghijklmnopqrstuvwxy";' + + ' void [a, a];' + + ' }());' + + ' eval("");' + + ' void ["abcdefghijklmnopqrstuvwx", "abcdefghijklmnopqrstuvwx"];' + + ' eval("");' + + ' (function() {' + + ' var a = "abcdefgh";' + + ' void [a, a];' + + ' }());' + + '}());' + }, + { + sTitle: + 'Employment of a closure while consolidating in global code.', + sInput: + 'void ["abcdefghijklmnopqrstuvwxyz",' + + ' "abcdefghijklmnopqrstuvwxyz"];', + sOutput: + '(function() {' + + ' var a = "abcdefghijklmnopqrstuvwxyz";' + + ' void [a, a];' + + '}());' + }, + { + sTitle: + 'Assignment of a shorter identifier to a value whose ' + + 'consolidation results in a greater reduction of the number of ' + + 'source characters.', + sInput: + '(function() {' + + ' var b, c, d, e, f, g, h, i, j, k, l, m,' + + ' n, o, p, q, r, s, t, u, v, w, x, y, z,' + + ' A, B, C, D, E, F, G, H, I, J, K, L, M,' + + ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' + + ' $, _;' + + ' void ["abcde", "abcde", "edcba", "edcba", "edcba"];' + + '}());', + sOutput: + '(function() {' + + ' var a = "edcba",' + + ' b, c, d, e, f, g, h, i, j, k, l, m,' + + ' n, o, p, q, r, s, t, u, v, w, x, y, z,' + + ' A, B, C, D, E, F, G, H, I, J, K, L, M,' + + ' N, O, P, Q, R, S, T, U, V, W, X, Y, Z,' + + ' $, _;' + + ' void ["abcde", "abcde", a, a, a];' + + '}());' + } +].forEach(cAssert); + +process.exit(bTestsPassed ? 0 : 1); + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/testparser.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/testparser.js new file mode 100755 index 0000000..a0f9f28 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/testparser.js @@ -0,0 +1,409 @@ +#! /usr/bin/env node +global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + +var parseJS = require("../lib/parse-js"); +var sys = require("util"); + +// write debug in a very straightforward manner +var debug = function(){ + sys.log(Array.prototype.slice.call(arguments).join(', ')); +}; + +var testsPassed = true; + +ParserTestSuite(function(i, input, desc){ + try { + parseJS.parse(input); + debug("ok " + i + ": " + desc); + } catch(e){ + debug("FAIL " + i + " " + desc + " (" + e + ")"); + testsPassed = false; + } +}); + +process.exit(testsPassed ? 0 : 1); + +function ParserTestSuite(callback){ + var inps = [ + ["var abc;", "Regular variable statement w/o assignment"], + ["var abc = 5;", "Regular variable statement with assignment"], + ["/* */;", "Multiline comment"], + ['/** **/;', 'Double star multiline comment'], + ["var f = function(){;};", "Function expression in var assignment"], + ['hi; // moo\n;', 'single line comment'], + ['var varwithfunction;', 'Dont match keywords as substrings'], // difference between `var withsomevar` and `"str"` (local search and lits) + ['a + b;', 'addition'], + ["'a';", 'single string literal'], + ["'a\\n';", 'single string literal with escaped return'], + ['"a";', 'double string literal'], + ['"a\\n";', 'double string literal with escaped return'], + ['"var";', 'string is a keyword'], + ['"variable";', 'string starts with a keyword'], + ['"somevariable";', 'string contains a keyword'], + ['"somevar";', 'string ends with a keyword'], + ['500;', 'int literal'], + ['500.;', 'float literal w/o decimals'], + ['500.432;', 'float literal with decimals'], + ['.432432;', 'float literal w/o int'], + ['(a,b,c);', 'parens and comma'], + ['[1,2,abc];', 'array literal'], + ['var o = {a:1};', 'object literal unquoted key'], + ['var o = {"b":2};', 'object literal quoted key'], // opening curly may not be at the start of a statement... + ['var o = {c:c};', 'object literal keyname is identifier'], + ['var o = {a:1,"b":2,c:c};', 'object literal combinations'], + ['var x;\nvar y;', 'two lines'], + ['var x;\nfunction n(){; }', 'function def'], + ['var x;\nfunction n(abc){; }', 'function def with arg'], + ['var x;\nfunction n(abc, def){ ;}', 'function def with args'], + ['function n(){ "hello"; }', 'function def with body'], + ['/a/;', 'regex literal'], + ['/a/b;', 'regex literal with flag'], + ['/a/ / /b/;', 'regex div regex'], + ['a/b/c;', 'triple division looks like regex'], + ['+function(){/regex/;};', 'regex at start of function body'], + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=86 + // http://code.google.com/p/es-lab/source/browse/trunk/tests/parser/parsertests.js?r=430 + + // first tests for the lexer, should also parse as program (when you append a semi) + + // comments + ['//foo!@#^&$1234\nbar;', 'single line comment'], + ['/* abcd!@#@$* { } && null*/;', 'single line multi line comment'], + ['/*foo\nbar*/;','multi line comment'], + ['/*x*x*/;','multi line comment with *'], + ['/**/;','empty comment'], + // identifiers + ["x;",'1 identifier'], + ["_x;",'2 identifier'], + ["xyz;",'3 identifier'], + ["$x;",'4 identifier'], + ["x$;",'5 identifier'], + ["_;",'6 identifier'], + ["x5;",'7 identifier'], + ["x_y;",'8 identifier'], + ["x+5;",'9 identifier'], + ["xyz123;",'10 identifier'], + ["x1y1z1;",'11 identifier'], + ["foo\\u00D8bar;",'12 identifier unicode escape'], + //["foo�bar;",'13 identifier unicode embedded (might fail)'], + // numbers + ["5;", '1 number'], + ["5.5;", '2 number'], + ["0;", '3 number'], + ["0.0;", '4 number'], + ["0.001;", '5 number'], + ["1.e2;", '6 number'], + ["1.e-2;", '7 number'], + ["1.E2;", '8 number'], + ["1.E-2;", '9 number'], + [".5;", '10 number'], + [".5e3;", '11 number'], + [".5e-3;", '12 number'], + ["0.5e3;", '13 number'], + ["55;", '14 number'], + ["123;", '15 number'], + ["55.55;", '16 number'], + ["55.55e10;", '17 number'], + ["123.456;", '18 number'], + ["1+e;", '20 number'], + ["0x01;", '22 number'], + ["0XCAFE;", '23 number'], + ["0x12345678;", '24 number'], + ["0x1234ABCD;", '25 number'], + ["0x0001;", '26 number'], + // strings + ["\"foo\";", '1 string'], + ["\'foo\';", '2 string'], + ["\"x\";", '3 string'], + ["\'\';", '4 string'], + ["\"foo\\tbar\";", '5 string'], + ["\"!@#$%^&*()_+{}[]\";", '6 string'], + ["\"/*test*/\";", '7 string'], + ["\"//test\";", '8 string'], + ["\"\\\\\";", '9 string'], + ["\"\\u0001\";", '10 string'], + ["\"\\uFEFF\";", '11 string'], + ["\"\\u10002\";", '12 string'], + ["\"\\x55\";", '13 string'], + ["\"\\x55a\";", '14 string'], + ["\"a\\\\nb\";", '15 string'], + ['";"', '16 string: semi in a string'], + ['"a\\\nb";', '17 string: line terminator escape'], + // literals + ["null;", "null"], + ["true;", "true"], + ["false;", "false"], + // regex + ["/a/;", "1 regex"], + ["/abc/;", "2 regex"], + ["/abc[a-z]*def/g;", "3 regex"], + ["/\\b/;", "4 regex"], + ["/[a-zA-Z]/;", "5 regex"], + + // program tests (for as far as they havent been covered above) + + // regexp + ["/foo(.*)/g;", "another regexp"], + // arrays + ["[];", "1 array"], + ["[ ];", "2 array"], + ["[1];", "3 array"], + ["[1,2];", "4 array"], + ["[1,2,,];", "5 array"], + ["[1,2,3];", "6 array"], + ["[1,2,3,,,];", "7 array"], + // objects + ["{};", "1 object"], + ["({x:5});", "2 object"], + ["({x:5,y:6});", "3 object"], + ["({x:5,});", "4 object"], + ["({if:5});", "5 object"], + ["({ get x() {42;} });", "6 object"], + ["({ set y(a) {1;} });", "7 object"], + // member expression + ["o.m;", "1 member expression"], + ["o['m'];", "2 member expression"], + ["o['n']['m'];", "3 member expression"], + ["o.n.m;", "4 member expression"], + ["o.if;", "5 member expression"], + // call and invoke expressions + ["f();", "1 call/invoke expression"], + ["f(x);", "2 call/invoke expression"], + ["f(x,y);", "3 call/invoke expression"], + ["o.m();", "4 call/invoke expression"], + ["o['m'];", "5 call/invoke expression"], + ["o.m(x);", "6 call/invoke expression"], + ["o['m'](x);", "7 call/invoke expression"], + ["o.m(x,y);", "8 call/invoke expression"], + ["o['m'](x,y);", "9 call/invoke expression"], + ["f(x)(y);", "10 call/invoke expression"], + ["f().x;", "11 call/invoke expression"], + + // eval + ["eval('x');", "1 eval"], + ["(eval)('x');", "2 eval"], + ["(1,eval)('x');", "3 eval"], + ["eval(x,y);", "4 eval"], + // new expression + ["new f();", "1 new expression"], + ["new o;", "2 new expression"], + ["new o.m;", "3 new expression"], + ["new o.m(x);", "4 new expression"], + ["new o.m(x,y);", "5 new expression"], + // prefix/postfix + ["++x;", "1 pre/postfix"], + ["x++;", "2 pre/postfix"], + ["--x;", "3 pre/postfix"], + ["x--;", "4 pre/postfix"], + ["x ++;", "5 pre/postfix"], + ["x /* comment */ ++;", "6 pre/postfix"], + ["++ /* comment */ x;", "7 pre/postfix"], + // unary operators + ["delete x;", "1 unary operator"], + ["void x;", "2 unary operator"], + ["+ x;", "3 unary operator"], + ["-x;", "4 unary operator"], + ["~x;", "5 unary operator"], + ["!x;", "6 unary operator"], + // meh + ["new Date++;", "new date ++"], + ["+x++;", " + x ++"], + // expression expressions + ["1 * 2;", "1 expression expressions"], + ["1 / 2;", "2 expression expressions"], + ["1 % 2;", "3 expression expressions"], + ["1 + 2;", "4 expression expressions"], + ["1 - 2;", "5 expression expressions"], + ["1 << 2;", "6 expression expressions"], + ["1 >>> 2;", "7 expression expressions"], + ["1 >> 2;", "8 expression expressions"], + ["1 * 2 + 3;", "9 expression expressions"], + ["(1+2)*3;", "10 expression expressions"], + ["1*(2+3);", "11 expression expressions"], + ["xy;", "13 expression expressions"], + ["x<=y;", "14 expression expressions"], + ["x>=y;", "15 expression expressions"], + ["x instanceof y;", "16 expression expressions"], + ["x in y;", "17 expression expressions"], + ["x&y;", "18 expression expressions"], + ["x^y;", "19 expression expressions"], + ["x|y;", "20 expression expressions"], + ["x+y>>= y;", "1 assignment"], + ["x <<= y;", "2 assignment"], + ["x = y;", "3 assignment"], + ["x += y;", "4 assignment"], + ["x /= y;", "5 assignment"], + // comma + ["x, y;", "comma"], + // block + ["{};", "1 block"], + ["{x;};", "2 block"], + ["{x;y;};", "3 block"], + // vars + ["var x;", "1 var"], + ["var x,y;", "2 var"], + ["var x=1,y=2;", "3 var"], + ["var x,y=2;", "4 var"], + // empty + [";", "1 empty"], + ["\n;", "2 empty"], + // expression statement + ["x;", "1 expression statement"], + ["5;", "2 expression statement"], + ["1+2;", "3 expression statement"], + // if + ["if (c) x; else y;", "1 if statement"], + ["if (c) x;", "2 if statement"], + ["if (c) {} else {};", "3 if statement"], + ["if (c1) if (c2) s1; else s2;", "4 if statement"], + // while + ["do s; while (e);", "1 while statement"], + ["do { s; } while (e);", "2 while statement"], + ["while (e) s;", "3 while statement"], + ["while (e) { s; };", "4 while statement"], + // for + ["for (;;) ;", "1 for statement"], + ["for (;c;x++) x;", "2 for statement"], + ["for (i;i> 1; +var c = 8 >>> 1; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue34.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue34.js new file mode 100644 index 0000000..022f7a3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue34.js @@ -0,0 +1,3 @@ +var a = {}; +a["this"] = 1; +a["that"] = 2; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue349.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue349.js new file mode 100644 index 0000000..71241f6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue349.js @@ -0,0 +1,25 @@ +(function () { + var cake + if (noFreeCakes) return /* I would + insert something + there, but I'm sort + of lazy so whatever. + */ cake = new FreeCake() + return cake +})() + +(function () { + var cake + if (noFreeCakes) return /* I would insert something there, */ /* + but I'm sort of lazy so + */ /* whatever. */ cake = new FreeCake() + return cake +})() + +(function () { + var cake + if (noFreeCakes) return // I would insert something there, but I'm sort of lazy so whatever. + cake = new FreeCake() + return cake +})() + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue353.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue353.js new file mode 100644 index 0000000..11ec116 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue353.js @@ -0,0 +1,4 @@ +function test() { + debugger; + return; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue372.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue372.js new file mode 100644 index 0000000..3791ce8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue372.js @@ -0,0 +1,32 @@ +"use strict"; +"use strict"; + +function a() { + void "a"; + function b() { + "use strict"; + void "b"; + function c() { + "use strict"; + void "c"; + } + function d() { + "salmon"; + void "d"; + } + } + function e() { + "salmon"; + void "e"; + function f() { + "use strict"; + "salmon"; + void "f"; + for (var i = 0; i < 10; i++) var g = function() { + "use strict"; + "salmon"; + void "g"; + }(); + } + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue4.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue4.js new file mode 100644 index 0000000..0b76103 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue4.js @@ -0,0 +1,3 @@ +var a = 2e3; +var b = 2e-3; +var c = 2e-5; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue48.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue48.js new file mode 100644 index 0000000..031e85b --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue48.js @@ -0,0 +1 @@ +var s, i; s = ''; i = 0; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue50.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue50.js new file mode 100644 index 0000000..060f9df --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue50.js @@ -0,0 +1,9 @@ +function bar(a) { + try { + foo(); + } catch(e) { + alert("Exception caught (foo not defined)"); + } + alert(a); // 10 in FF, "[object Error]" in IE +} +bar(10); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue53.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue53.js new file mode 100644 index 0000000..4f8b32f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue53.js @@ -0,0 +1 @@ +x = (y, z) diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue54.1.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue54.1.js new file mode 100644 index 0000000..967052e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue54.1.js @@ -0,0 +1,3 @@ +foo.toString(); +a.toString(16); +b.toString.call(c); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue68.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue68.js new file mode 100644 index 0000000..14054d0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue68.js @@ -0,0 +1,5 @@ +function f() { + if (a) return; + g(); + function g(){} +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue69.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue69.js new file mode 100644 index 0000000..d25ecd6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue69.js @@ -0,0 +1 @@ +[(a,b)] diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue9.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue9.js new file mode 100644 index 0000000..6158861 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issue9.js @@ -0,0 +1,4 @@ +var a = { + a: 1, + b: 2, // <-- trailing comma +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issues222_324.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issues222_324.js new file mode 100644 index 0000000..58b0d3c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/issues222_324.js @@ -0,0 +1,82 @@ +!function() { + 'use strict'; + + var 七, // issue #222 + $1, // issue #222 + ლ_ಠ益ಠ_ლ; // issue #324 +}; + +!function() { + 'use strict'; + + // test if Unicode canonical equivalence is ignored + var \u006E\u0303, + \u00F1; +}; + +!function() { + 'use strict'; + + var \uFF38, // X Lu (third to last) + \uFF58, // x Ll (third to last) + \u1FBC, // ᾼ Lt (third to last) + \uFF70, // ー Lm (third to last) + \u4DB3, // 䶳 Lo (third to last within a range) + \u97CA, // 韊 Lo (third to last within a range) + \uD7A1, // 힡 Lo (third to last within a range) + \uFFDA, // ᅳ Lo (third to last) + \uA6ED, // ꛭ Nl (third to last) + \u0024, // $ + \u005F, // _ + \u0024\uFF38, // X Lu (third to last) + \u0024\uFF58, // x Ll (third to last) + \u0024\u1FBC, // ᾼ Lt (third to last) + \u0024\uFF70, // ー Lm (third to last) + \u0024\u4DB3, // 䶳 Lo (third to last within a range) + \u0024\u97CA, // 韊 Lo (third to last within a range) + \u0024\uD7A1, // 힡 Lo (third to last within a range) + \u0024\uFFDA, // ᅳ Lo (third to last) + \u0024\uA6ED, // ꛭ Nl (third to last) + \u0024\uFE24, // ︤ Mn (third to last) + \u0024\uABE9, // ꯩ Mc (third to last) + \u0024\uFF17, // 7 Nd (third to last) + \u0024\uFE4E, // ﹎ Pc (third to last) + \u0024\u200C, // ZERO WIDTH NON-JOINER + \u0024\u200D, // ZERO WIDTH JOINER + \u0024\u0024, // $ + \u0024\u005F; // _ +}; + +!function() { + 'use strict'; + + var X, + x, + ᾼ, + ー, + 䶳, + 韊, + 힡, + ᅳ, + ꛭ, + $, + _, + $X, + $x, + $ᾼ, + $ー, + $䶳, + $韊, + $힡, + $ᅳ, + $ꛭ, + $︤, + $ꯩ, + $7, + $﹎, + $‌, + $‍, + $$, + $_; +}; + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/mangle.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/mangle.js new file mode 100644 index 0000000..c271a26 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/mangle.js @@ -0,0 +1,5 @@ +(function() { + var x = function fun(a, fun, b) { + return fun; + }; +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/null_string.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/null_string.js new file mode 100644 index 0000000..a675b1c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/null_string.js @@ -0,0 +1 @@ +var nullString = "\0" \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/strict-equals.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/strict-equals.js new file mode 100644 index 0000000..b631f4c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/strict-equals.js @@ -0,0 +1,3 @@ +typeof a === 'string' +b + "" !== c + "" +d < e === f < g diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/var.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/var.js new file mode 100644 index 0000000..609a35d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/var.js @@ -0,0 +1,3 @@ +// var declarations after each other should be combined +var a = 1; +var b = 2; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/whitespace.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/whitespace.js new file mode 100644 index 0000000..6a15c46 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/whitespace.js @@ -0,0 +1,21 @@ +function id(a) { + // Form-Feed + // Vertical Tab + // No-Break Space + ᠎// Mongolian Vowel Separator +  // En quad +  // Em quad +  // En space +  // Em space +  // Three-Per-Em Space +  // Four-Per-Em Space +  // Six-Per-Em Space +  // Figure Space +  // Punctuation Space +  // Thin Space +  // Hair Space +  // Narrow No-Break Space +  // Medium Mathematical Space +  // Ideographic Space + return a; +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/with.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/with.js new file mode 100644 index 0000000..de266ed --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/compress/test/with.js @@ -0,0 +1,2 @@ +with({}) { +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/scripts.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/scripts.js new file mode 100644 index 0000000..564abd3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/test/unit/scripts.js @@ -0,0 +1,57 @@ +global.DIGITS_OVERRIDE_FOR_TESTING = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + +var fs = require('fs'), + uglify = require('../../uglify-js'), + jsp = uglify.parser, + nodeunit = require('nodeunit'), + path = require('path'), + pro = uglify.uglify; + +var Script = process.binding('evals').Script; + +var scriptsPath = __dirname; + +function compress(code) { + var ast = jsp.parse(code); + ast = pro.ast_mangle(ast, { mangle: true }); + ast = pro.ast_squeeze(ast, { no_warnings: true }); + ast = pro.ast_squeeze_more(ast); + return pro.gen_code(ast); +}; + +var testDir = path.join(scriptsPath, "compress", "test"); +var expectedDir = path.join(scriptsPath, "compress", "expected"); + +function getTester(script) { + return function(test) { + var testPath = path.join(testDir, script); + var expectedPath = path.join(expectedDir, script); + var content = fs.readFileSync(testPath, 'utf-8'); + var outputCompress = compress(content); + + // Check if the noncompressdata is larger or same size as the compressed data + test.ok(content.length >= outputCompress.length); + + // Check that a recompress gives the same result + var outputReCompress = compress(content); + test.equal(outputCompress, outputReCompress); + + // Check if the compressed output is what is expected + var expected = fs.readFileSync(expectedPath, 'utf-8'); + test.equal(outputCompress, expected.replace(/(\r?\n)+$/, "")); + + test.done(); + }; +}; + +var tests = {}; + +var scripts = fs.readdirSync(testDir); +for (var i in scripts) { + var script = scripts[i]; + if (/\.js$/.test(script)) { + tests[script] = getTester(script); + } +} + +module.exports = nodeunit.testCase(tests); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/hoist.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/hoist.js new file mode 100644 index 0000000..4bf2b94 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/hoist.js @@ -0,0 +1,33 @@ +function foo(arg1, arg2, arg3, arg4, arg5, arg6) { + var a = 5; + { + var d = 10, mak = 20, buz = 30; + var q = buz * 2; + } + if (moo) { + var a, b, c; + } + for (var arg1 = 0, d = 20; arg1 < 10; ++arg1) + console.log(arg3); + for (var i in mak) {} + for (j in d) {} + var d; + + function test() { + + }; + + //test(); + + (function moo(first, second){ + console.log(first); + })(1); + + (function moo(first, second){ + console.log(moo()); + })(1); +} + + +var foo; +var bar; diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/instrument.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/instrument.js new file mode 100644 index 0000000..c6a9d79 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/instrument.js @@ -0,0 +1,97 @@ +// sample on how to use the parser and walker API to instrument some code + +var jsp = require("uglify-js").parser; +var pro = require("uglify-js").uglify; + +function instrument(code) { + var ast = jsp.parse(code, false, true); // true for the third arg specifies that we want + // to have start/end tokens embedded in the + // statements + var w = pro.ast_walker(); + + // we're gonna need this to push elements that we're currently looking at, to avoid + // endless recursion. + var analyzing = []; + function do_stat() { + var ret; + if (this[0].start && analyzing.indexOf(this) < 0) { + // without the `analyzing' hack, w.walk(this) would re-enter here leading + // to infinite recursion + analyzing.push(this); + ret = [ "splice", // XXX: "block" is safer + [ [ "stat", + [ "call", [ "name", "trace" ], + [ [ "string", this[0].toString() ], + [ "num", this[0].start.line ], + [ "num", this[0].start.col ], + [ "num", this[0].end.line ], + [ "num", this[0].end.col ]]]], + w.walk(this) ]]; + analyzing.pop(this); + } + return ret; + }; + var new_ast = w.with_walkers({ + "stat" : do_stat, + "label" : do_stat, + "break" : do_stat, + "continue" : do_stat, + "debugger" : do_stat, + "var" : do_stat, + "const" : do_stat, + "return" : do_stat, + "throw" : do_stat, + "try" : do_stat, + "defun" : do_stat, + "if" : do_stat, + "while" : do_stat, + "do" : do_stat, + "for" : do_stat, + "for-in" : do_stat, + "switch" : do_stat, + "with" : do_stat + }, function(){ + return w.walk(ast); + }); + return pro.gen_code(new_ast, { beautify: true }); +} + + + + +////// test code follows. + +var code = instrument(test.toString()); +console.log(code); + +function test() { + // simple stats + a = 5; + c += a + b; + "foo"; + + // var + var foo = 5; + const bar = 6, baz = 7; + + // switch block. note we can't track case lines the same way. + switch ("foo") { + case "foo": + return 1; + case "bar": + return 2; + } + + // for/for in + for (var i = 0; i < 5; ++i) { + console.log("Hello " + i); + } + for (var i in [ 1, 2, 3]) { + console.log(i); + } + + // note however that the following is broken. I guess we + // should add the block brackets in this case... + for (var i = 0; i < 5; ++i) + console.log("foo"); +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/test.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/test.js new file mode 100755 index 0000000..f295fba --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/tmp/test.js @@ -0,0 +1,30 @@ +#! /usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var fs = require("fs"); +var uglify = require("uglify-js"), // symlink ~/.node_libraries/uglify-js.js to ../uglify-js.js + jsp = uglify.parser, + pro = uglify.uglify; + +var code = fs.readFileSync("hoist.js", "utf8"); +var ast = jsp.parse(code); + +ast = pro.ast_lift_variables(ast); + +var w = pro.ast_walker(); +ast = w.with_walkers({ + "function": function() { + var node = w.dive(this); // walk depth first + console.log(pro.gen_code(node, { beautify: true })); + return node; + }, + "name": function(name) { + return [ this[0], "X" ]; + } +}, function(){ + return w.walk(ast); +}); + +console.log(pro.gen_code(ast, { + beautify: true +})); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/uglify-js.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/uglify-js.js new file mode 100644 index 0000000..6e14a63 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/uglify-js/uglify-js.js @@ -0,0 +1,18 @@ +//convienence function(src, [options]); +function uglify(orig_code, options){ + options || (options = {}); + var jsp = uglify.parser; + var pro = uglify.uglify; + + var ast = jsp.parse(orig_code, options.strict_semicolons); // parse code and get the initial AST + ast = pro.ast_mangle(ast, options.mangle_options); // get a new AST with mangled names + ast = pro.ast_squeeze(ast, options.squeeze_options); // get an AST with compression optimizations + var final_code = pro.gen_code(ast, options.gen_options); // compressed code here + return final_code; +}; + +uglify.parser = require("./lib/parse-js"); +uglify.uglify = require("./lib/process"); +uglify.consolidator = require("./lib/consolidator"); + +module.exports = uglify diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/.travis.yml b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/.travis.yml new file mode 100644 index 0000000..ab27b29 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/.travis.yml @@ -0,0 +1,8 @@ +language: ruby +rvm: + - 1.9.3 + +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - sleep 2 \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile new file mode 100644 index 0000000..f024827 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile @@ -0,0 +1,5 @@ +source :rubygems + +gem 'serve' +gem 'uglifier' +gem 'rake' \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile.lock b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile.lock new file mode 100644 index 0000000..6b49945 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Gemfile.lock @@ -0,0 +1,34 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (3.2.1) + i18n (~> 0.6) + multi_json (~> 1.0) + execjs (1.3.0) + multi_json (~> 1.0) + i18n (0.6.0) + multi_json (1.1.0) + rack (1.4.1) + rack-test (0.6.1) + rack (>= 1.0) + rake (0.9.2.2) + serve (1.5.1) + activesupport (~> 3.0) + i18n + rack (~> 1.2) + rack-test (~> 0.5) + tilt (~> 1.3) + tzinfo + tilt (1.3.3) + tzinfo (0.3.31) + uglifier (1.2.3) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + +PLATFORMS + ruby + +DEPENDENCIES + rake + serve + uglifier diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/README.markdown b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/README.markdown new file mode 100644 index 0000000..d744a57 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/README.markdown @@ -0,0 +1,663 @@ +# Underscore.string [![Build Status](https://secure.travis-ci.org/epeli/underscore.string.png?branch=master)](http://travis-ci.org/epeli/underscore.string) # + + + +Javascript lacks complete string manipulation operations. +This an attempt to fill that gap. List of build-in methods can be found +for example from [Dive Into JavaScript][d]. + +[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object + + +As name states this an extension for [Underscore.js][u], but it can be used +independently from **_s**-global variable. But with Underscore.js you can +use Object-Oriented style and chaining: + +[u]: http://documentcloud.github.com/underscore/ + +```javascript +_(" epeli ").chain().trim().capitalize().value() +=> "Epeli" +``` + +## Download ## + + * [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb* + * [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb* + + +## Node.js installation ## + +**npm package** + + npm install underscore.string + +**Standalone usage**: + +```javascript +var _s = require('underscore.string'); +``` + +**Integrate with Underscore.js**: + +```javascript +var _ = require('underscore'); + +// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains) +_.str = require('underscore.string'); + +// Mix in non-conflict functions to Underscore namespace if you want +_.mixin(_.str.exports()); + +// All functions, include conflict, will be available through _.str object +_.str.include('Underscore.string', 'string'); // => true +``` + +## String Functions ## + +For availability of functions in this way you need to mix in Underscore.string functions: + +```javascript +_.mixin(_.string.exports()); +``` + +otherwise functions from examples will be available through _.string or _.str objects: + +```javascript +_.str.capitalize('epeli') +=> "Epeli" +``` + +**capitalize** _.capitalize(string) + +Converts first letter of the string to uppercase and the rest of the string to lower case. + +```javascript +_.capitalize("foo Bar") +=> "Foo bar" +``` + +**chop** _.chop(string, step) + +```javascript +_.chop('whitespace', 3) +=> ['whi','tes','pac','e'] +``` + +**clean** _.clean(str) + +Compress some whitespaces to one. + +```javascript +_.clean(" foo bar ") +=> 'foo bar' +``` + +**chars** _.chars(str) + +```javascript +_.chars('Hello') +=> ['H','e','l','l','o'] +``` + +**includes** _.includes(string, substring) + +Tests if string contains a substring. + +```javascript +_.includes("foobar", "ob") +=> true +``` + +**include** available only through _.str object, because Underscore has function with the same name. + +```javascript +_.str.include("foobar", "ob") +=> true +``` + +**includes** function was removed + +But you can create it in this way, for compatibility with previous versions: + +```javascript +_.includes = _.str.include +``` + +**count** _.count(string, substring) + +```javascript +_('Hello world').count('l') +=> 3 +``` + +**escapeHTML** _.escapeHTML(string) + +Converts HTML special characters to their entity equivalents. + +```javascript +_('
    Blah blah blah
    ').escapeHTML(); +=> '<div>Blah blah blah</div>' +``` + +**unescapeHTML** _.unescapeHTML(string) + +Converts entity characters to HTML equivalents. + +```javascript +_('<div>Blah blah blah</div>').unescapeHTML(); +=> '
    Blah blah blah
    ' +``` + +**insert** _.insert(string, index, substing) + +```javascript +_('Hello ').insert(6, 'world') +=> 'Hello world' +``` + +**isBlank** _.isBlank(string) + +```javascript +_('').isBlank(); // => true +_('\n').isBlank(); // => true +_(' ').isBlank(); // => true +_('a').isBlank(); // => false +``` + +**join** _.join(separator, *strings) + +Joins strings together with given separator + +```javascript +_.join(" ", "foo", "bar") +=> "foo bar" +``` + +**lines** _.lines(str) + +```javascript +_.lines("Hello\nWorld") +=> ["Hello", "World"] +``` + +**reverse** available only through _.str object, because Underscore has function with the same name. + +Return reversed string: + +```javascript +_.str.reverse("foobar") +=> 'raboof' +``` + +**splice** _.splice(string, index, howmany, substring) + +Like a array splice. + +```javascript +_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli') +=> 'https://edtsech@bitbucket.org/epeli/underscore.strings' +``` + +**startsWith** _.startsWith(string, starts) + +This method checks whether string starts with starts. + +```javascript +_("image.gif").startsWith("image") +=> true +``` + +**endsWith** _.endsWith(string, ends) + +This method checks whether string ends with ends. + +```javascript +_("image.gif").endsWith("gif") +=> true +``` + +**succ** _.succ(str) + +Returns the successor to str. + +```javascript +_('a').succ() +=> 'b' + +_('A').succ() +=> 'B' +``` + +**supplant** + +Supplant function was removed, use Underscore.js [template function][p]. + +[p]: http://documentcloud.github.com/underscore/#template + +**strip** alias for *trim* + +**lstrip** alias for *ltrim* + +**rstrip** alias for *rtrim* + +**titleize** _.titleize(string) + +```javascript +_('my name is epeli').titleize() +=> 'My Name Is Epeli' +``` + +**camelize** _.camelize(string) + +Converts underscored or dasherized string to a camelized one + +```javascript +_('-moz-transform').camelize() +=> 'MozTransform' +``` + +**classify** _.classify(string) + +Converts string to camelized class name + +```javascript +_('some_class_name').classify() +=> 'SomeClassName' +``` + +**underscored** _.underscored(string) + +Converts a camelized or dasherized string into an underscored one + +```javascript +_('MozTransform').underscored() +=> 'moz_transform' +``` + +**dasherize** _.dasherize(string) + +Converts a underscored or camelized string into an dasherized one + +```javascript +_('MozTransform').dasherize() +=> '-moz-transform' +``` + +**humanize** _.humanize(string) + +Converts an underscored, camelized, or dasherized string into a humanized one. +Also removes beginning and ending whitespace, and removes the postfix '_id'. + +```javascript +_(' capitalize dash-CamelCase_underscore trim ').humanize() +=> 'Capitalize dash camel case underscore trim' +``` + +**trim** _.trim(string, [characters]) + +trims defined characters from begining and ending of the string. +Defaults to whitespace characters. + +```javascript +_.trim(" foobar ") +=> "foobar" + +_.trim("_-foobar-_", "_-") +=> "foobar" +``` + + +**ltrim** _.ltrim(string, [characters]) + +Left trim. Similar to trim, but only for left side. + + +**rtrim** _.rtrim(string, [characters]) + +Right trim. Similar to trim, but only for right side. + +**truncate** _.truncate(string, length, truncateString) + +```javascript +_('Hello world').truncate(5) +=> 'Hello...' + +_('Hello').truncate(10) +=> 'Hello' +``` + +**prune** _.prune(string, length, pruneString) + +Elegant version of truncate. +Makes sure the pruned string does not exceed the original length. +Avoid half-chopped words when truncating. + +```javascript +_('Hello, world').prune(5) +=> 'Hello...' + +_('Hello, world').prune(8) +=> 'Hello...' + +_('Hello, world').prune(5, ' (read a lot more)') +=> 'Hello, world' (as adding "(read a lot more)" would be longer than the original string) + +_('Hello, cruel world').prune(15) +=> 'Hello, cruel...' + +_('Hello').prune(10) +=> 'Hello' +``` + +**words** _.words(str, delimiter=" ") + +Split string by delimiter (String or RegExp), ' ' by default. + +```javascript +_.words("I love you") +=> ["I","love","you"] + +_.words("I_love_you", "_") +=> ["I","love","you"] + +_.words("I-love-you", /-/) +=> ["I","love","you"] +``` + +**sprintf** _.sprintf(string format, *arguments) + +C like string formatting. +Credits goes to [Alexandru Marasteanu][o]. +For more detailed documentation, see the [original page][o]. + +[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript + +```javascript +_.sprintf("%.1f", 1.17) +"1.2" +``` + +**pad** _.pad(str, length, [padStr, type]) + +pads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`" "`). `padStr` is truncated to a single character if necessary. + +```javascript +_.pad("1", 8) +-> " 1"; + +_.pad("1", 8, '0') +-> "00000001"; + +_.pad("1", 8, '0', 'right') +-> "10000000"; + +_.pad("1", 8, '0', 'both') +-> "00001000"; + +_.pad("1", 8, 'bleepblorp', 'both') +-> "bbbb1bbb"; +``` + +**lpad** _.lpad(str, length, [padStr]) + +left-pad a string. Alias for `pad(str, length, padStr, 'left')` + +```javascript +_.lpad("1", 8, '0') +-> "00000001"; +``` + +**rpad** _.rpad(str, length, [padStr]) + +right-pad a string. Alias for `pad(str, length, padStr, 'right')` + +```javascript +_.rpad("1", 8, '0') +-> "10000000"; +``` + +**lrpad** _.lrpad(str, length, [padStr]) + +left/right-pad a string. Alias for `pad(str, length, padStr, 'both')` + +```javascript +_.lrpad("1", 8, '0') +-> "00001000"; +``` + +**center** alias for **lrpad** + +**ljust** alias for *rpad* + +**rjust** alias for *lpad* + +**toNumber** _.toNumber(string, [decimals]) + +Parse string to number. Returns NaN if string can't be parsed to number. + +```javascript +_('2.556').toNumber() +=> 3 + +_('2.556').toNumber(1) +=> 2.6 +``` + +**strRight** _.strRight(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRight('_') +=> "is_a_test_string"; +``` + +**strRightBack** _.strRightBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strRightBack('_') +=> "string"; +``` + +**strLeft** _.strLeft(string, pattern) + +Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeft('_') +=> "This"; +``` + +**strLeftBack** _.strLeftBack(string, pattern) + +Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found. + +```javascript +_('This_is_a_test_string').strLeftBack('_') +=> "This_is_a_test"; +``` + +**stripTags** + +Removes all html tags from string. + +```javascript +_('a link').stripTags() +=> 'a link' + +_('a link').stripTags() +=> 'a linkalert("hello world!")' +``` + +**toSentence** _.toSentence(array, [delimiter, lastDelimiter]) + +Join an array into a human readable sentence. + +```javascript +_.toSentence(['jQuery', 'Mootools', 'Prototype']) +=> 'jQuery, Mootools and Prototype'; + +_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ') +=> 'jQuery, Mootools unt Prototype'; +``` + +**repeat** _.repeat(string, count, [separator]) + +Repeats a string count times. + +```javascript +_.repeat("foo", 3) +=> 'foofoofoo'; + +_.repeat("foo", 3, "bar") +=> 'foobarfoobarfoo' +``` + +**slugify** _.slugify(string) + +Transform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash. + +```javascript +_.slugify("Un éléphant à l'orée du bois") +=> 'un-elephant-a-loree-du-bois'; +``` + +***Caution: this function is charset dependent*** + +## Roadmap ## + +Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. + +## Changelog ## + +### 2.0.0 ### + +* Added prune, humanize functions +* Added _.string (_.str) namespace for Underscore.string library +* Removed includes function + +#### Problems + +We lose two things for `include` and `reverse` methods from `_.string`: + +* Calls like `_('foobar').include('bar')` aren't available; +* Chaining isn't available too. + +But if you need this functionality you can create aliases for conflict functions which will be convenient for you: + +```javascript +_.mixin({ + includeString: _.str.include, + reverseString: _.str.reverse +}) + +// Now wrapper calls and chaining are available. +_('foobar').chain().reverseString().includeString('rab').value() +``` + +#### Standalone Usage + +If you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias +But of course you can just reassign `_` variable with `_.string` + +```javascript +_ = _.string +``` +### 2.1.1### + +* Fixed words method bug +* Added classify method + +### 2.1.0 ### + +* AMD support +* Added toSentence method +* Added slugify method +* Lots of speed optimizations + +### 2.0.0 ### + +For upgrading to this version you need to mix in Underscore.string library to Underscore object: + +```javascript +_.mixin(_.string.exports()); +``` + +and all non-conflict Underscore.string functions will be available through Underscore object. +Also function `includes` has been removed, you should replace this function by `_.str.include` +or create alias `_.includes = _.str.include` and all your code will work fine. + +### 1.1.6 ### + +* Fixed reverse and truncate +* Added isBlank, stripTags, inlude(alias for includes) +* Added uglifier compression + +### 1.1.5 ### + +* Added strRight, strRightBack, strLeft, strLeftBack + +### 1.1.4 ### + +* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust +* Integration with Underscore 1.1.6 + +### 1.1.3 ### + +* Added methods: underscored, camelize, dasherize +* Support newer version of npm + +### 1.1.2 ### + +* Created functions: lines, chars, words functions + +### 1.0.2 ### + +* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible) +* Removed 'reverse' function, because this function override underscore.js 'reverse' + +## Contribute ## + +* Fork & pull request. Don't forget about tests. +* If you planning add some feature please create issue before. + +Otherwise changes will be rejected. + +## Contributors list ## + +* Esa-Matti Suuronen (), +* Edward Tsech , +* Sasha Koss (), +* Vladimir Dronnikov , +* Pete Kruckenberg (), +* Paul Chavard (), +* Ed Finkler () +* Pavel Pravosud +* Anton Lindqvist () + +## Licence ## + +The MIT License + +Copyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Rakefile b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Rakefile new file mode 100644 index 0000000..9fecdfe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/Rakefile @@ -0,0 +1,27 @@ +# encoding: utf-8 +task default: :test + +desc 'Use UglifyJS to compress Underscore.string' +task :build do + require 'uglifier' + source = File.read('lib/underscore.string.js') + compressed = Uglifier.compile(source, copyright: false) + File.open('dist/underscore.string.min.js', 'w'){ |f| f.write compressed } + compression_rate = compressed.length.to_f/source.length + puts "compressed dist/underscore.string.min.js: #{compressed.length}/#{source.length} #{(compression_rate * 100).round}%" +end + + +desc 'Run tests' +task :test do + system %{bundle exec serve 2>/dev/null &} + sleep 2 + + puts "Running underscore.string test suite." + result1 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test.html"} + + puts "Running Underscore test suite." + result2 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test_underscore/test.html"} + + exit(result1 && result2 ? 0 : 1) +end \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js new file mode 100644 index 0000000..5538694 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/dist/underscore.string.min.js @@ -0,0 +1 @@ +(function(a){"use strict";var b=String.prototype.trim,c=String.prototype.trimRight,d=String.prototype.trimLeft,e=function(a){return a*1||0},f=function(a,b,c){a+="",b=~~b;for(var d=[];b>0;d[--b]=a);return d.join(c==null?"":c)},g=function(a){return Array.prototype.slice.call(a)},h=function(a){return a!=null?"["+j.escapeRegExp(""+a)+"]":"\\s"},i=function(){function a(a){return Object.prototype.toString.call(a).slice(8,-1).toLowerCase()}var b=f,c=function(){return c.cache.hasOwnProperty(arguments[0])||(c.cache[arguments[0]]=c.parse(arguments[0])),c.format.call(null,c.cache[arguments[0]],arguments)};return c.format=function(c,d){var e=1,f=c.length,g="",h,j=[],k,l,m,n,o,p;for(k=0;k=0?"+"+h:h,o=m[4]?m[4]=="0"?"0":m[4].charAt(1):" ",p=m[6]-String(h).length,n=m[6]?b(o,p):"",j.push(m[5]?h+n:n+h)}}return j.join("")},c.cache={},c.parse=function(a){var b=a,c=[],d=[],e=0;while(b){if((c=/^[^\x25]+/.exec(b))!==null)d.push(c[0]);else if((c=/^\x25{2}/.exec(b))!==null)d.push("%");else{if((c=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(b))===null)throw new Error("[_.sprintf] huh?");if(c[2]){e|=1;var f=[],g=c[2],h=[];if((h=/^([a-z_][a-z_\d]*)/i.exec(g))===null)throw new Error("[_.sprintf] huh?");f.push(h[1]);while((g=g.substring(h[0].length))!=="")if((h=/^\.([a-z_][a-z_\d]*)/i.exec(g))!==null)f.push(h[1]);else{if((h=/^\[(\d+)\]/.exec(g))===null)throw new Error("[_.sprintf] huh?");f.push(h[1])}c[2]=f}else e|=2;if(e===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");d.push(c)}b=b.substring(c[0].length)}return d},c}(),j={VERSION:"2.1.1",isBlank:function(a){return/^\s*$/.test(a)},stripTags:function(a){return(""+a).replace(/<\/?[^>]+>/ig,"")},capitalize:function(a){return a+="",a.charAt(0).toUpperCase()+a.substring(1).toLowerCase()},chop:function(a,b){a+="",b=~~b||a.length;var c=[];for(var d=0;d/g,">").replace(/"/g,""").replace(/'/g,"'")},unescapeHTML:function(a){return(""+a).replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")},escapeRegExp:function(a){return a.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1")},insert:function(a,b,c){var d=(""+a).split("");return d.splice(~~b,0,""+c),d.join("")},include:function(a,b){return(""+a).indexOf(b)!==-1},join:function(a){var b=g(arguments);return b.join(b.shift())},lines:function(a){return(""+a).split("\n")},reverse:function(a){return Array.prototype.reverse.apply(String(a).split("")).join("")},splice:function(a,b,c,d){var e=(""+a).split("");return e.splice(~~b,~~c,d),e.join("")},startsWith:function(a,b){return a+="",b+="",a.length>=b.length&&a.substring(0,b.length)===b},endsWith:function(a,b){return a+="",b+="",a.length>=b.length&&a.substring(a.length-b.length)===b},succ:function(a){a+="";var b=a.split("");return b.splice(a.length-1,1,String.fromCharCode(a.charCodeAt(a.length-1)+1)),b.join("")},titleize:function(a){return(""+a).replace(/\b./g,function(a){return a.toUpperCase()})},camelize:function(a){return j.trim(a).replace(/(\-|_|\s)+(.)?/g,function(a,b,c){return c?c.toUpperCase():""})},underscored:function(a){return j.trim(a).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(a){return j.trim(a).replace(/[_\s]+/g,"-").replace(/([A-Z])/g,"-$1").replace(/-+/g,"-").toLowerCase()},classify:function(a){return j.titleize(a.replace(/_/g," ")).replace(/\s/g,"")},humanize:function(a){return j.capitalize(this.underscored(a).replace(/_id$/,"").replace(/_/g," "))},trim:function(a,c){return a+="",!c&&b?b.call(a):(c=h(c),a.replace(new RegExp("^"+c+"+|"+c+"+$","g"),""))},ltrim:function(a,b){return!b&&d?d.call(a):(b=h(b),(""+a).replace(new RegExp("^"+b+"+","g"),""))},rtrim:function(a,b){return!b&&c?c.call(a):(b=h(b),(""+a).replace(new RegExp(b+"+$","g"),""))},truncate:function(a,b,c){return a+="",c=c||"...",b=~~b,a.length>b?a.slice(0,b)+c:a},prune:function(a,b,c){a+="",b=~~b,c=c!=null?""+c:"...";var d,e,f=a.replace(/\W/g,function(a){return a.toUpperCase()!==a.toLowerCase()?"A":" "});return e=f.charAt(b),d=f.slice(0,b),e&&e.match(/\S/)&&(d=d.replace(/\s\S+$/,"")),d=j.rtrim(d),(d+c).length>a.length?a:a.substring(0,d.length)+c},words:function(a,b){return j.trim(a,b).split(b||/\s+/)},pad:function(a,b,c,d){a+="";var e="",g=0;b=~~b,c?c.length>1&&(c=c.charAt(0)):c=" ";switch(d){case"right":g=b-a.length,e=f(c,g),a+=e;break;case"both":g=b-a.length,e={left:f(c,Math.ceil(g/2)),right:f(c,Math.floor(g/2))},a=e.left+a+e.right;break;default:g=b-a.length,e=f(c,g),a=e+a}return a},lpad:function(a,b,c){return j.pad(a,b,c)},rpad:function(a,b,c){return j.pad(a,b,c,"right")},lrpad:function(a,b,c){return j.pad(a,b,c,"both")},sprintf:i,vsprintf:function(a,b){return b.unshift(a),i.apply(null,b)},toNumber:function(a,b){var c=e(e(a).toFixed(~~b));return c===0&&""+a!="0"?Number.NaN:c},strRight:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.indexOf(b):-1;return c!=-1?a.slice(c+b.length,a.length):a},strRightBack:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.lastIndexOf(b):-1;return c!=-1?a.slice(c+b.length,a.length):a},strLeft:function(a,b){a+="",b=b!=null?""+b:b;var c=b?a.indexOf(b):-1;return c!=-1?a.slice(0,c):a},strLeftBack:function(a,b){a+="",b=b!=null?""+b:b;var c=a.lastIndexOf(b);return c!=-1?a.slice(0,c):a},toSentence:function(a,b,c){b||(b=", "),c||(c=" and ");var d=a.length,e="";for(var f=0;f +// Underscore.strings is freely distributable under the terms of the MIT license. +// Documentation: https://github.com/epeli/underscore.string +// Some code is borrowed from MooTools and Alexandru Marasteanu. + +// Version 2.1.1 + +(function(root){ + 'use strict'; + + // Defining helper functions. + + var nativeTrim = String.prototype.trim; + var nativeTrimRight = String.prototype.trimRight; + var nativeTrimLeft = String.prototype.trimLeft; + + var parseNumber = function(source) { return source * 1 || 0; }; + + var strRepeat = function(str, qty, separator){ + // ~~var — is the fastest available way to convert anything to Integer in javascript. + // We'll use it extensively in this lib. + str += ''; qty = ~~qty; + for (var repeat = []; qty > 0; repeat[--qty] = str) {} + return repeat.join(separator == null ? '' : separator); + }; + + var slice = function(a){ + return Array.prototype.slice.call(a); + }; + + var defaultToWhiteSpace = function(characters){ + if (characters != null) { + return '[' + _s.escapeRegExp(''+characters) + ']'; + } + return '\\s'; + }; + + // sprintf() for JavaScript 0.7-beta1 + // http://www.diveintojavascript.com/projects/javascript-sprintf + // + // Copyright (c) Alexandru Marasteanu + // All rights reserved. + + var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + + var str_repeat = strRepeat; + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw new Error('[_.sprintf] huh?'); + } + } + } + else { + throw new Error('[_.sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw new Error('[_.sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; + })(); + + + + // Defining underscore.string + + var _s = { + + VERSION: '2.1.1', + + isBlank: function(str){ + return (/^\s*$/).test(str); + }, + + stripTags: function(str){ + return (''+str).replace(/<\/?[^>]+>/ig, ''); + }, + + capitalize : function(str) { + str += ''; + return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase(); + }, + + chop: function(str, step){ + str = str+''; + step = ~~step || str.length; + var arr = []; + for (var i = 0; i < str.length;) { + arr.push(str.slice(i,i + step)); + i = i + step; + } + return arr; + }, + + clean: function(str){ + return _s.strip((''+str).replace(/\s+/g, ' ')); + }, + + count: function(str, substr){ + str += ''; substr += ''; + return str.split(substr).length - 1; + }, + + chars: function(str) { + return (''+str).split(''); + }, + + escapeHTML: function(str) { + return (''+str).replace(/&/g,'&').replace(//g,'>') + .replace(/"/g, '"').replace(/'/g, "'"); + }, + + unescapeHTML: function(str) { + return (''+str).replace(/</g, '<').replace(/>/g, '>') + .replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&'); + }, + + escapeRegExp: function(str){ + // From MooTools core 1.2.4 + return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + insert: function(str, i, substr){ + var arr = (''+str).split(''); + arr.splice(~~i, 0, ''+substr); + return arr.join(''); + }, + + include: function(str, needle){ + return (''+str).indexOf(needle) !== -1; + }, + + join: function(sep) { + var args = slice(arguments); + return args.join(args.shift()); + }, + + lines: function(str) { + return (''+str).split("\n"); + }, + + reverse: function(str){ + return Array.prototype.reverse.apply(String(str).split('')).join(''); + }, + + splice: function(str, i, howmany, substr){ + var arr = (''+str).split(''); + arr.splice(~~i, ~~howmany, substr); + return arr.join(''); + }, + + startsWith: function(str, starts){ + str += ''; starts += ''; + return str.length >= starts.length && str.substring(0, starts.length) === starts; + }, + + endsWith: function(str, ends){ + str += ''; ends += ''; + return str.length >= ends.length && str.substring(str.length - ends.length) === ends; + }, + + succ: function(str){ + str += ''; + var arr = str.split(''); + arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1)); + return arr.join(''); + }, + + titleize: function(str){ + return (''+str).replace(/\b./g, function(ch){ return ch.toUpperCase(); }); + }, + + camelize: function(str){ + return _s.trim(str).replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) { + return chr ? chr.toUpperCase() : ''; + }); + }, + + underscored: function(str){ + return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); + }, + + dasherize: function(str){ + return _s.trim(str).replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase(); + }, + + classify: function(str){ + return _s.titleize(str.replace(/_/g, ' ')).replace(/\s/g, '') + }, + + humanize: function(str){ + return _s.capitalize(this.underscored(str).replace(/_id$/,'').replace(/_/g, ' ')); + }, + + trim: function(str, characters){ + str += ''; + if (!characters && nativeTrim) { + return nativeTrim.call(str); + } + characters = defaultToWhiteSpace(characters); + return str.replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), ''); + }, + + ltrim: function(str, characters){ + if (!characters && nativeTrimLeft) { + return nativeTrimLeft.call(str); + } + characters = defaultToWhiteSpace(characters); + return (''+str).replace(new RegExp('\^' + characters + '+', 'g'), ''); + }, + + rtrim: function(str, characters){ + if (!characters && nativeTrimRight) { + return nativeTrimRight.call(str); + } + characters = defaultToWhiteSpace(characters); + return (''+str).replace(new RegExp(characters + '+$', 'g'), ''); + }, + + truncate: function(str, length, truncateStr){ + str += ''; truncateStr = truncateStr || '...'; + length = ~~length; + return str.length > length ? str.slice(0, length) + truncateStr : str; + }, + + /** + * _s.prune: a more elegant version of truncate + * prune extra chars, never leaving a half-chopped word. + * @author github.com/sergiokas + */ + prune: function(str, length, pruneStr){ + str += ''; length = ~~length; + pruneStr = pruneStr != null ? ''+pruneStr : '...'; + + var pruned, borderChar, template = str.replace(/\W/g, function(ch){ + return (ch.toUpperCase() !== ch.toLowerCase()) ? 'A' : ' '; + }); + + borderChar = template.charAt(length); + + pruned = template.slice(0, length); + + // Check if we're in the middle of a word + if (borderChar && borderChar.match(/\S/)) + pruned = pruned.replace(/\s\S+$/, ''); + + pruned = _s.rtrim(pruned); + + return (pruned+pruneStr).length > str.length ? str : str.substring(0, pruned.length)+pruneStr; + }, + + words: function(str, delimiter) { + return _s.trim(str, delimiter).split(delimiter || /\s+/); + }, + + pad: function(str, length, padStr, type) { + str += ''; + + var padding = '', padlen = 0; + + length = ~~length; + + if (!padStr) { + padStr = ' '; + } else if (padStr.length > 1) { + padStr = padStr.charAt(0); + } + + switch(type) { + case 'right': + padlen = (length - str.length); + padding = strRepeat(padStr, padlen); + str = str+padding; + break; + case 'both': + padlen = (length - str.length); + padding = { + 'left' : strRepeat(padStr, Math.ceil(padlen/2)), + 'right': strRepeat(padStr, Math.floor(padlen/2)) + }; + str = padding.left+str+padding.right; + break; + default: // 'left' + padlen = (length - str.length); + padding = strRepeat(padStr, padlen);; + str = padding+str; + } + return str; + }, + + lpad: function(str, length, padStr) { + return _s.pad(str, length, padStr); + }, + + rpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'right'); + }, + + lrpad: function(str, length, padStr) { + return _s.pad(str, length, padStr, 'both'); + }, + + sprintf: sprintf, + + vsprintf: function(fmt, argv){ + argv.unshift(fmt); + return sprintf.apply(null, argv); + }, + + toNumber: function(str, decimals) { + var num = parseNumber(parseNumber(str).toFixed(~~decimals)); + return num === 0 && ''+str !== '0' ? Number.NaN : num; + }, + + strRight: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = (!sep) ? -1 : str.indexOf(sep); + return (pos != -1) ? str.slice(pos+sep.length, str.length) : str; + }, + + strRightBack: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = (!sep) ? -1 : str.lastIndexOf(sep); + return (pos != -1) ? str.slice(pos+sep.length, str.length) : str; + }, + + strLeft: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = (!sep) ? -1 : str.indexOf(sep); + return (pos != -1) ? str.slice(0, pos) : str; + }, + + strLeftBack: function(str, sep){ + str += ''; sep = sep != null ? ''+sep : sep; + var pos = str.lastIndexOf(sep); + return (pos != -1) ? str.slice(0, pos) : str; + }, + + toSentence: function(array, separator, lastSeparator) { + separator || (separator = ', '); + lastSeparator || (lastSeparator = ' and '); + var length = array.length, str = ''; + + for (var i = 0; i < length; i++) { + str += array[i]; + if (i === (length - 2)) { str += lastSeparator; } + else if (i < (length - 1)) { str += separator; } + } + + return str; + }, + + slugify: function(str) { + var from = "ąàáäâãćęèéëêìíïîłńòóöôõùúüûñçżź·/_:;", + to = "aaaaaaceeeeeiiiilnooooouuuunczz", + regex = new RegExp(defaultToWhiteSpace(from), 'g'); + + str = (''+str).toLowerCase(); + + str = str.replace(regex, function(ch){ + var index = from.indexOf(ch); + return to.charAt(index) || '-'; + }); + + return _s.trim(str.replace(/[^\w\s-]/g, '').replace(/[-\s]+/g, '-'), '-'); + }, + + exports: function() { + var result = {}; + + for (var prop in this) { + if (!this.hasOwnProperty(prop) || prop == 'include' || prop == 'contains' || prop == 'reverse') continue; + result[prop] = this[prop]; + } + + return result; + }, + + repeat: strRepeat + + }; + + // Aliases + + _s.strip = _s.trim; + _s.lstrip = _s.ltrim; + _s.rstrip = _s.rtrim; + _s.center = _s.lrpad; + _s.rjust = _s.lpad; + _s.ljust = _s.rpad; + _s.contains = _s.include; + + // CommonJS module is defined + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + // Export module + module.exports = _s; + } + exports._s = _s; + + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore.string', function() { + return _s; + }); + + // Integrate with Underscore.js + } else if (typeof root._ !== 'undefined') { + // root._.mixin(_s); + root._.string = _s; + root._.str = root._.string; + + // Or define it + } else { + root._ = { + string: _s, + str: _s + }; + } + +}(this || window)); 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 new file mode 100644 index 0000000..af696ca --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/package.json @@ -0,0 +1,72 @@ +{ + "name": "underscore.string", + "version": "2.1.1", + "description": "String manipulation extensions for Underscore.js javascript library.", + "homepage": "http://epeli.github.com/underscore.string/", + "contributors": [ + { + "name": "Esa-Matti Suuronen", + "email": "esa-matti@suuronen.org", + "url": "http://esa-matti.suuronen.org/" + }, + { + "name": "Edward Tsech", + "email": "edtsech@gmail.com" + }, + { + "name": "Sasha Koss", + "email": "kossnocorp@gmail.com", + "url": "http://koss.nocorp.me/" + }, + { + "name": "Vladimir Dronnikov", + "email": "dronnikov@gmail.com" + }, + { + "name": "Pete Kruckenberg", + "email": "https://github.com/kruckenb", + "url": "" + }, + { + "name": "Paul Chavard", + "email": "paul@chavard.net", + "url": "" + }, + { + "name": "Ed Finkler", + "email": "coj@funkatron.com", + "url": "" + }, + { + "name": "Pavel Pravosud", + "email": "rwz@duckroll.ru" + } + ], + "keywords": [ + "underscore", + "string" + ], + "main": "./lib/underscore.string", + "directories": { + "lib": "./lib" + }, + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/epeli/underscore.string.git" + }, + "bugs": { + "url": "https://github.com/epeli/underscore.string/issues" + }, + "licenses": [ + { + "type": "MIT" + } + ], + "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.string/test/run-qunit.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/run-qunit.js new file mode 100644 index 0000000..326658e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/run-qunit.js @@ -0,0 +1,44 @@ +function waitFor(test, complete, timeout) { + var result, start = new Date().getTime() + setInterval(function interval() { + if ((new Date().getTime() - start < timeout) && !result) { + result = test() + } else { + if (!result) { + phantom.exit(1) + } else { + complete() + clearInterval(interval) + } + } + }, 100) +} + + +var page = new WebPage() + +page.onConsoleMessage = function(msg) { + console.log(msg) +} + +page.open(phantom.args[0], function(status) { + waitFor(function() { + return page.evaluate(function(){ + var el = document.getElementById('qunit-testresult') + return el && el.innerText.match('completed') + }) + }, function() { + var failures = page.evaluate(function() { + var el = document.getElementById('qunit-testresult'), + fails = document.getElementsByClassName('fail') + + for (var i = 0; i < fails.length; i++) + console.log(fails[i].innerText) + + console.log(el.innerText) + + return parseInt(el.getElementsByClassName('failed')[0].innerHTML) + }) + phantom.exit(failures > 0 ? 1 : 0) + }, 10000) +}) \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/speed.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/speed.js new file mode 100644 index 0000000..4346414 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/speed.js @@ -0,0 +1,138 @@ +(function() { + + JSLitmus.test('trimNoNative', function() { + return _.trim(" foobar ", " "); + }); + + JSLitmus.test('trim', function() { + return _.trim(" foobar "); + }); + + JSLitmus.test('trim object-oriented', function() { + return _(" foobar ").trim(); + }); + + JSLitmus.test('trim jQuery', function() { + return jQuery.trim(" foobar "); + }); + + JSLitmus.test('ltrimp', function() { + return _.ltrim(" foobar ", " "); + }); + + JSLitmus.test('rtrimp', function() { + return _.rtrim(" foobar ", " "); + }); + + JSLitmus.test('startsWith', function() { + return _.startsWith("foobar", "foo"); + }); + + JSLitmus.test('endsWith', function() { + return _.endsWith("foobar", "xx"); + }); + + JSLitmus.test('chop', function(){ + return _('whitespace').chop(2); + }); + + JSLitmus.test('count', function(){ + return _('Hello worls').count('l'); + }); + + JSLitmus.test('insert', function() { + return _('Hello ').insert(6, 'world'); + }); + + JSLitmus.test('splice', function() { + return _('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'); + }); + + JSLitmus.test('succ', function(){ + var let = 'a', alphabet = []; + + for (var i=0; i < 26; i++) { + alphabet.push(let); + let = _(let).succ(); + } + + return alphabet; + }); + + JSLitmus.test('titleize', function(){ + return _('the titleize string method').titleize(); + }); + + JSLitmus.test('truncate', function(){ + return _('Hello world').truncate(5); + }); + + JSLitmus.test('prune', function(){ + return _('Hello world').prune(5); + }); + + JSLitmus.test('isBlank', function(){ + return _('').isBlank(); + }); + + JSLitmus.test('escapeHTML', function(){ + _('
    Blah blah blah
    ').escapeHTML(); + }); + + JSLitmus.test('unescapeHTML', function(){ + _('<div>Blah blah blah</div>').unescapeHTML(); + }); + + JSLitmus.test('reverse', function(){ + _('Hello World').reverse(); + }); + + JSLitmus.test('pad default', function(){ + _('foo').pad(12); + }); + + JSLitmus.test('pad hash left', function(){ + _('foo').pad(12, '#'); + }); + + JSLitmus.test('pad hash right', function(){ + _('foo').pad(12, '#', 'right'); + }); + + JSLitmus.test('pad hash both', function(){ + _('foo').pad(12, '#', 'both'); + }); + + JSLitmus.test('pad hash both longPad', function(){ + _('foo').pad(12, 'f00f00f00', 'both'); + }); + + JSLitmus.test('toNumber', function(){ + _('10.232323').toNumber(2); + }); + + JSLitmus.test('strRight', function(){ + _('aaa_bbb_ccc').strRight('_'); + }); + + JSLitmus.test('strRightBack', function(){ + _('aaa_bbb_ccc').strRightBack('_'); + }); + + JSLitmus.test('strLeft', function(){ + _('aaa_bbb_ccc').strLeft('_'); + }); + + JSLitmus.test('strLeftBack', function(){ + _('aaa_bbb_ccc').strLeftBack('_'); + }); + + JSLitmus.test('join', function(){ + _('separator').join(1, 2, 3, 4, 5, 6, 7, 8, 'foo', 'bar', 'lol', 'wut'); + }); + + JSLitmus.test('slugify', function(){ + _("Un éléphant à l'orée du bois").slugify(); + }); + +})(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/strings.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/strings.js new file mode 100644 index 0000000..c9df79e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/strings.js @@ -0,0 +1,409 @@ +$(document).ready(function() { + + // Include Underscore.string methods to Underscore namespace + _.mixin(_.str.exports()); + + module("String extensions"); + + test("Strings: trim", function() { + equals(_.trim(123), "123", "Non string"); + equals(_(" foo").trim(), "foo"); + equals(_("foo ").trim(), "foo"); + equals(_(" foo ").trim(), "foo"); + equals(_(" foo ").trim(), "foo"); + equals(_(" foo ", " ").trim(), "foo", "Manually set whitespace"); + + equals(_("ffoo").trim("f"), "oo"); + equals(_("ooff").trim("f"), "oo"); + equals(_("ffooff").trim("f"), "oo"); + + + equals(_("_-foobar-_").trim("_-"), "foobar"); + + equals(_("http://foo/").trim("/"), "http://foo"); + equals(_("c:\\").trim('\\'), "c:"); + + equals(_(123).trim(), '123'); + equals(_(123).trim(3), '12'); + }); + + test("Strings: ltrim", function() { + equals(_(" foo").ltrim(), "foo"); + equals(_(" foo").ltrim(), "foo"); + equals(_("foo ").ltrim(), "foo "); + equals(_(" foo ").ltrim(), "foo "); + + + equals(_("ffoo").ltrim("f"), "oo"); + equals(_("ooff").ltrim("f"), "ooff"); + equals(_("ffooff").ltrim("f"), "ooff"); + + equals(_("_-foobar-_").ltrim("_-"), "foobar-_"); + + equals(_(123).ltrim(1), '23'); + }); + + test("Strings: rtrim", function() { + equals(_("http://foo/").rtrim("/"), "http://foo", 'clean trailing slash'); + equals(_(" foo").rtrim(), " foo"); + equals(_("foo ").rtrim(), "foo"); + equals(_("foo ").rtrim(), "foo"); + equals(_("foo bar ").rtrim(), "foo bar"); + equals(_(" foo ").rtrim(), " foo"); + + equals(_("ffoo").rtrim("f"), "ffoo"); + equals(_("ooff").rtrim("f"), "oo"); + equals(_("ffooff").rtrim("f"), "ffoo"); + + equals(_("_-foobar-_").rtrim("_-"), "_-foobar"); + + equals(_(123).rtrim(3), '12'); + }); + + test("Strings: capitalize", function() { + equals(_("fabio").capitalize(), "Fabio", 'First letter is upper case'); + equals(_.capitalize("fabio"), "Fabio", 'First letter is upper case'); + equals(_(123).capitalize(), "123", "Non string"); + }); + + test("Strings: join", function() { + equals(_.join("", "foo", "bar"), "foobar", 'basic join'); + equals(_.join("", 1, "foo", 2), "1foo2", 'join numbers and strings'); + equals(_.join(" ","foo", "bar"), "foo bar", 'join with spaces'); + equals(_.join("1", "2", "2"), "212", 'join number strings'); + equals(_.join(1, 2, 2), "212", 'join numbers'); + equals(_(" ").join("foo", "bar"), "foo bar", 'join object oriented'); + }); + + test("Strings: reverse", function() { + equals(_.str.reverse("foo"), "oof" ); + equals(_.str.reverse("foobar"), "raboof" ); + equals(_.str.reverse("foo bar"), "rab oof" ); + equals(_.str.reverse("saippuakauppias"), "saippuakauppias" ); + equals(_.str.reverse(123), "321", "Non string"); + equals(_.str.reverse(123.45), "54.321", "Non string"); + }); + + test("Strings: clean", function() { + equals(_(" foo bar ").clean(), "foo bar"); + equals(_(123).clean(), "123"); + }); + + test("Strings: sprintf", function() { + // Should be very tested function already. Thanks to + // http://www.diveintojavascript.com/projects/sprintf-for-javascript + equals(_.sprintf("Hello %s", "me"), "Hello me", 'basic'); + equals(_("Hello %s").sprintf("me"), "Hello me", 'object'); + equals(_("hello %s").chain().sprintf("me").capitalize().value(), "Hello me", 'Chaining works'); + equals(_.sprintf("%.1f", 1.22222), "1.2", 'round'); + equals(_.sprintf("%.1f", 1.17), "1.2", 'round 2'); + equals(_.sprintf("%(id)d - %(name)s", {id: 824, name: "Hello World"}), "824 - Hello World", 'Named replacements work'); + equals(_.sprintf("%(args[0].id)d - %(args[1].name)s", {args: [{id: 824}, {name: "Hello World"}]}), "824 - Hello World", 'Named replacements with arrays work'); + }); + + + test("Strings: vsprintf", function() { + equals(_.vsprintf("Hello %s", ["me"]), "Hello me", 'basic'); + equals(_("Hello %s").vsprintf(["me"]), "Hello me", 'object'); + equals(_("hello %s").chain().vsprintf(["me"]).capitalize().value(), "Hello me", 'Chaining works'); + equals(_.vsprintf("%.1f", [1.22222]), "1.2", 'round'); + equals(_.vsprintf("%.1f", [1.17]), "1.2", 'round 2'); + equals(_.vsprintf("%(id)d - %(name)s", [{id: 824, name: "Hello World"}]), "824 - Hello World", 'Named replacement works'); + equals(_.vsprintf("%(args[0].id)d - %(args[1].name)s", [{args: [{id: 824}, {name: "Hello World"}]}]), "824 - Hello World", 'Named replacement with arrays works'); + }); + + test("Strings: startsWith", function() { + ok(_("foobar").startsWith("foo"), 'foobar starts with foo'); + ok(!_("oobar").startsWith("foo"), 'oobar does not start with foo'); + ok(_(12345).startsWith(123), '12345 starts with 123'); + ok(!_(2345).startsWith(123), '2345 does not start with 123'); + }); + + test("Strings: endsWith", function() { + ok(_("foobar").endsWith("bar"), 'foobar ends with bar'); + ok(_.endsWith("foobar", "bar"), 'foobar ends with bar'); + ok(_.endsWith("00018-0000062.Plone.sdh264.1a7264e6912a91aa4a81b64dc5517df7b8875994.mp4", "mp4"), 'endsWith .mp4'); + ok(!_("fooba").endsWith("bar"), 'fooba does not end with bar'); + ok(_.endsWith(12345, 45), '12345 ends with 45'); + ok(!_.endsWith(12345, 6), '12345 does not end with 6'); + }); + + test("Strings: include", function() { + ok(_.str.include("foobar", "bar"), 'foobar includes bar'); + ok(!_.str.include("foobar", "buzz"), 'foobar does not includes buzz'); + ok(_.str.include(12345, 34), '12345 includes 34'); + ok(!_.str.contains(12345, 6), '12345 does not includes 6'); + }); + + test('String: chop', function(){ + ok(_('whitespace').chop(2).length === 5, "output ['wh','it','es','pa','ce']"); + ok(_('whitespace').chop(3).length === 4, "output ['whi','tes','pac','e']"); + ok(_('whitespace').chop()[0].length === 10, "output ['whitespace']"); + ok(_(12345).chop(1).length === 5, "output ['1','2','3','4','5']"); + }); + + test('String: count', function(){ + equals(_('Hello world').count('l'), 3); + equals(_('Hello world').count('Hello'), 1); + equals(_('Hello world').count('foo'), 0); + equals(_('x.xx....x.x').count('x'), 5); + equals(_(12345).count(1), 1); + equals(_(11345).count(1), 2); + }); + + test('String: insert', function(){ + equals(_('Hello ').insert(6, 'Jessy'), 'Hello Jessy'); + equals(_('Hello ').insert(100, 'Jessy'), 'Hello Jessy'); + equals(_(12345).insert(6, 'Jessy'), '12345Jessy'); + }); + + test('String: splice', function(){ + equals(_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'), + 'https://edtsech@bitbucket.org/epeli/underscore.strings'); + equals(_.splice(12345, 1, 2, 321), '132145', 'Non strings'); + }); + + test('String: succ', function(){ + equals(_('a').succ(), 'b'); + equals(_('A').succ(), 'B'); + equals(_('+').succ(), ','); + equals(_(1).succ(), '2'); + }); + + test('String: titleize', function(){ + equals(_('the titleize string method').titleize(), 'The Titleize String Method'); + equals(_('the titleize string method').titleize(), 'The Titleize String Method'); + equals(_(123).titleize(), '123'); + }); + + test('String: camelize', function(){ + equals(_('the_camelize_string_method').camelize(), 'theCamelizeStringMethod'); + equals(_('-the-camelize-string-method').camelize(), 'TheCamelizeStringMethod'); + equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_(' the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod'); + equals(_(123).camelize(), '123'); + }); + + test('String: underscored', function(){ + equals(_('the-underscored-string-method').underscored(), 'the_underscored_string_method'); + equals(_('theUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equals(_('TheUnderscoredStringMethod').underscored(), 'the_underscored_string_method'); + equals(_(' the underscored string method').underscored(), 'the_underscored_string_method'); + equals(_(123).underscored(), '123'); + }); + + test('String: dasherize', function(){ + equals(_('the_dasherize_string_method').dasherize(), 'the-dasherize-string-method'); + equals(_('TheDasherizeStringMethod').dasherize(), '-the-dasherize-string-method'); + equals(_('thisIsATest').dasherize(), 'this-is-a-test'); + equals(_('this Is A Test').dasherize(), 'this-is-a-test'); + equals(_('thisIsATest123').dasherize(), 'this-is-a-test123'); + equals(_('123thisIsATest').dasherize(), '123this-is-a-test'); + equals(_('the dasherize string method').dasherize(), 'the-dasherize-string-method'); + equals(_('the dasherize string method ').dasherize(), 'the-dasherize-string-method'); + equals(_('téléphone').dasherize(), 'téléphone'); + equals(_('foo$bar').dasherize(), 'foo$bar'); + equals(_(123).dasherize(), '123'); + }); + + test('String: classify', function(){ + equals(_('some_class_name').classify(), 'SomeClassName'); + }); + + test('String: humanize', function(){ + equals(_('the_humanize_string_method').humanize(), 'The humanize string method'); + equals(_('ThehumanizeStringMethod').humanize(), 'Thehumanize string method'); + equals(_('the humanize string method').humanize(), 'The humanize string method'); + equals(_('the humanize_id string method_id').humanize(), 'The humanize id string method'); + equals(_('the humanize string method ').humanize(), 'The humanize string method'); + equals(_(' capitalize dash-CamelCase_underscore trim ').humanize(), 'Capitalize dash camel case underscore trim'); + equals(_(123).humanize(), '123'); + }); + + test('String: truncate', function(){ + equals(_('Hello world').truncate(6, 'read more'), 'Hello read more'); + equals(_('Hello world').truncate(5), 'Hello...'); + equals(_('Hello').truncate(10), 'Hello'); + equals(_(1234567890).truncate(5), '12345...'); + }); + + test('String: prune', function(){ + equals(_('Hello, cruel world').prune(6, ' read more'), 'Hello read more'); + equals(_('Hello, world').prune(5, 'read a lot more'), 'Hello, world'); + equals(_('Hello, world').prune(5), 'Hello...'); + equals(_('Hello, world').prune(8), 'Hello...'); + equals(_('Hello, cruel world').prune(15), 'Hello, cruel...'); + equals(_('Hello world').prune(22), 'Hello world'); + equals(_('Привет, жестокий мир').prune(6, ' read more'), 'Привет read more'); + equals(_('Привет, мир').prune(6, 'read a lot more'), 'Привет, мир'); + equals(_('Привет, мир').prune(6), 'Привет...'); + equals(_('Привет, мир').prune(8), 'Привет...'); + equals(_('Привет, жестокий мир').prune(16), 'Привет, жестокий...'); + equals(_('Привет, мир').prune(22), 'Привет, мир'); + equals(_(123).prune(10), '123'); + equals(_(123).prune(1,1), '11'); + }); + + test('String: isBlank', function(){ + ok(_('').isBlank()); + ok(_(' ').isBlank()); + ok(_('\n').isBlank()); + ok(!_('a').isBlank()); + ok(!_('0').isBlank()); + ok(!_(0).isBlank()); + }); + + test('String: escapeHTML', function(){ + equals(_('
    Blah & "blah" & \'blah\'
    ').escapeHTML(), + '<div>Blah & "blah" & 'blah'</div>'); + equals(_('<').escapeHTML(), '&lt;'); + equals(_(5).escapeHTML(), '5'); + // equals(_(undefined).escapeHTML(), ''); + }); + + test('String: unescapeHTML', function(){ + equals(_('<div>Blah & "blah" & 'blah'</div>').unescapeHTML(), + '
    Blah & "blah" & \'blah\'
    '); + equals(_('&lt;').unescapeHTML(), '<'); + equals(_(5).unescapeHTML(), '5'); + // equals(_(undefined).unescapeHTML(), ''); + }); + + test('String: words', function() { + equals(_("I love you!").words().length, 3); + equals(_(" I love you! ").words().length, 3); + equals(_("I_love_you!").words('_').length, 3); + equals(_("I-love-you!").words(/-/).length, 3); + equals(_(123).words().length, 1); + }); + + test('String: chars', function() { + equals(_("Hello").chars().length, 5); + equals(_(123).chars().length, 3); + }); + + test('String: lines', function() { + equals(_("Hello\nWorld").lines().length, 2); + equals(_("Hello World").lines().length, 1); + equals(_(123).lines().length, 1); + }); + + test('String: pad', function() { + equals(_("1").pad(8), ' 1'); + equals(_(1).pad(8), ' 1'); + equals(_("1").pad(8, '0'), '00000001'); + equals(_("1").pad(8, '0', 'left'), '00000001'); + equals(_("1").pad(8, '0', 'right'), '10000000'); + equals(_("1").pad(8, '0', 'both'), '00001000'); + equals(_("foo").pad(8, '0', 'both'), '000foo00'); + equals(_("foo").pad(7, '0', 'both'), '00foo00'); + equals(_("foo").pad(7, '!@$%dofjrofj', 'both'), '!!foo!!'); + }); + + test('String: lpad', function() { + equals(_("1").lpad(8), ' 1'); + equals(_(1).lpad(8), ' 1'); + equals(_("1").lpad(8, '0'), '00000001'); + equals(_("1").lpad(8, '0', 'left'), '00000001'); + }); + + test('String: rpad', function() { + equals(_("1").rpad(8), '1 '); + equals(_(1).lpad(8), ' 1'); + equals(_("1").rpad(8, '0'), '10000000'); + equals(_("foo").rpad(8, '0'), 'foo00000'); + equals(_("foo").rpad(7, '0'), 'foo0000'); + }); + + test('String: lrpad', function() { + equals(_("1").lrpad(8), ' 1 '); + equals(_(1).lrpad(8), ' 1 '); + equals(_("1").lrpad(8, '0'), '00001000'); + equals(_("foo").lrpad(8, '0'), '000foo00'); + equals(_("foo").lrpad(7, '0'), '00foo00'); + equals(_("foo").lrpad(7, '!@$%dofjrofj'), '!!foo!!'); + }); + + test('String: toNumber', function() { + deepEqual(_("not a number").toNumber(), Number.NaN); + equals(_(0).toNumber(), 0); + equals(_("0").toNumber(), 0); + equals(_("2.345").toNumber(), 2); + equals(_("2.345").toNumber(NaN), 2); + equals(_("2.345").toNumber(2), 2.35); + equals(_("2.344").toNumber(2), 2.34); + equals(_("2").toNumber(2), 2.00); + equals(_(2).toNumber(2), 2.00); + equals(_(-2).toNumber(), -2); + equals(_("-2").toNumber(), -2); + }); + + test('String: strRight', function() { + equals(_("This_is_a_test_string").strRight("_"), "is_a_test_string"); + equals(_("This_is_a_test_string").strRight("string"), ""); + equals(_("This_is_a_test_string").strRight(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRight(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRight("-"), "This_is_a_test_string"); + equals(_(12345).strRight(2), "345"); + }); + + test('String: strRightBack', function() { + equals(_("This_is_a_test_string").strRightBack("_"), "string"); + equals(_("This_is_a_test_string").strRightBack("string"), ""); + equals(_("This_is_a_test_string").strRightBack(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRightBack(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strRightBack("-"), "This_is_a_test_string"); + equals(_(12345).strRightBack(2), "345"); + }); + + test('String: strLeft', function() { + equals(_("This_is_a_test_string").strLeft("_"), "This"); + equals(_("This_is_a_test_string").strLeft("This"), ""); + equals(_("This_is_a_test_string").strLeft(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeft(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeft("-"), "This_is_a_test_string"); + equals(_(123454321).strLeft(3), "12"); + }); + + test('String: strLeftBack', function() { + equals(_("This_is_a_test_string").strLeftBack("_"), "This_is_a_test"); + equals(_("This_is_a_test_string").strLeftBack("This"), ""); + equals(_("This_is_a_test_string").strLeftBack(), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeftBack(""), "This_is_a_test_string"); + equals(_("This_is_a_test_string").strLeftBack("-"), "This_is_a_test_string"); + equals(_(123454321).strLeftBack(3), "123454"); + }); + + test('Strings: stripTags', function() { + equals(_('a link').stripTags(), 'a link'); + equals(_('a link + + + + + + + + +

    Underscore.string Test Suite

    +

    +

    +
      +
      +

      Underscore.string Speed Suite

      + +
      + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html new file mode 100644 index 0000000..9854c17 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_standalone.html @@ -0,0 +1,18 @@ + + + + Underscore.strings Test Suite + + + + + + + + +

      Underscore.string Test Suite

      +

      +

      +
        + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js new file mode 100644 index 0000000..b3b1ce1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/arrays.js @@ -0,0 +1,166 @@ +$(document).ready(function() { + + module("Arrays"); + + test("arrays: first", function() { + equals(_.first([1,2,3]), 1, 'can pull out the first element of an array'); + equals(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); + equals(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first'); + equals(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first'); + equals(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first'); + var result = (function(){ return _.first(arguments); })(4, 3, 2, 1); + equals(result, 4, 'works on an arguments object.'); + result = _.map([[1,2,3],[1,2,3]], _.first); + equals(result.join(','), '1,1', 'works well with _.map'); + }); + + test("arrays: rest", function() { + var numbers = [1, 2, 3, 4]; + equals(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()'); + equals(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)'); + equals(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index'); + var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4); + equals(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.rest); + equals(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map'); + }); + + test("arrays: initial", function() { + equals(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()'); + equals(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index'); + var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4); + equals(result.join(", "), "1, 2, 3", 'initial works on arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.initial); + equals(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map'); + }); + + test("arrays: last", function() { + equals(_.last([1,2,3]), 3, 'can pull out the last element of an array'); + equals(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last'); + equals(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last'); + equals(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last'); + var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4); + equals(result, 4, 'works on an arguments object'); + result = _.map([[1,2,3],[1,2,3]], _.last); + equals(result.join(','), '3,3', 'works well with _.map'); + }); + + test("arrays: compact", function() { + equals(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); + var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3); + equals(result, 3, 'works on an arguments object'); + }); + + test("arrays: flatten", function() { + if (window.JSON) { + var list = [1, [2], [3, [[[4]]]]]; + equals(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays'); + equals(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays'); + var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); + equals(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object'); + } + }); + + test("arrays: without", function() { + var list = [1, 2, 1, 0, 3, 1, 4]; + equals(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object'); + var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4); + equals(result.join(', '), '2, 3, 4', 'works on an arguments object'); + + var list = [{one : 1}, {two : 2}]; + ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.'); + ok(_.without(list, list[0]).length == 1, 'ditto.'); + }); + + test("arrays: uniq", function() { + var list = [1, 2, 1, 3, 1, 4]; + equals(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array'); + + var list = [1, 1, 1, 2, 2, 3]; + equals(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster'); + + var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}]; + var iterator = function(value) { return value.name; }; + equals(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator'); + + var iterator = function(value) { return value +1; }; + var list = [1, 2, 2, 3, 4, 4]; + equals(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array'); + + var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4); + equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); + }); + + test("arrays: intersection", function() { + var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; + equals(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); + equals(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection'); + var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); + equals(result.join(''), 'moe', 'works on an arguments object'); + }); + + test("arrays: union", function() { + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); + equals(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); + + var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); + equals(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays'); + }); + + test("arrays: difference", function() { + var result = _.difference([1, 2, 3], [2, 30, 40]); + equals(result.join(' '), '1 3', 'takes the difference of two arrays'); + + var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); + equals(result.join(' '), '3 4', 'takes the difference of three arrays'); + }); + + test('arrays: zip', function() { + var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; + var stooges = _.zip(names, ages, leaders); + equals(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths'); + }); + + test("arrays: indexOf", function() { + var numbers = [1, 2, 3]; + numbers.indexOf = null; + equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function'); + var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3); + equals(result, 1, 'works on an arguments object'); + equals(_.indexOf(null, 2), -1, 'handles nulls properly'); + + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.indexOf(numbers, num, true); + equals(index, -1, '35 is not in the list'); + + numbers = [10, 20, 30, 40, 50]; num = 40; + index = _.indexOf(numbers, num, true); + equals(index, 3, '40 is in the list'); + + numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; + index = _.indexOf(numbers, num, true); + equals(index, 1, '40 is in the list'); + }); + + test("arrays: lastIndexOf", function() { + var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; + numbers.lastIndexOf = null; + equals(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); + equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); + var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0); + equals(result, 5, 'works on an arguments object'); + equals(_.indexOf(null, 2), -1, 'handles nulls properly'); + }); + + test("arrays: range", function() { + equals(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array'); + equals(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); + equals(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); + equals(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array'); + equals(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); + equals(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); + equals(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); + equals(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs'); + }); + +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js new file mode 100644 index 0000000..0e3d5f3 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/chaining.js @@ -0,0 +1,59 @@ +$(document).ready(function() { + + module("Chaining"); + + test("chaining: map/flatten/reduce", function() { + var lyrics = [ + "I'm a lumberjack and I'm okay", + "I sleep all night and I work all day", + "He's a lumberjack and he's okay", + "He sleeps all night and he works all day" + ]; + var counts = _(lyrics).chain() + .map(function(line) { return line.split(''); }) + .flatten() + .reduce(function(hash, l) { + hash[l] = hash[l] || 0; + hash[l]++; + return hash; + }, {}).value(); + ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); + }); + + test("chaining: select/reject/sortBy", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _(numbers).chain().select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("chaining: select/reject/sortBy in functional style", function() { + var numbers = [1,2,3,4,5,6,7,8,9,10]; + numbers = _.chain(numbers).select(function(n) { + return n % 2 == 0; + }).reject(function(n) { + return n % 4 == 0; + }).sortBy(function(n) { + return -n; + }).value(); + equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); + }); + + test("chaining: reverse/concat/unshift/pop/map", function() { + var numbers = [1,2,3,4,5]; + numbers = _(numbers).chain() + .reverse() + .concat([5, 5, 5]) + .unshift(17) + .pop() + .map(function(n){ return n * 2; }) + .value(); + equals(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); + }); + +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js new file mode 100644 index 0000000..cff9763 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/collections.js @@ -0,0 +1,270 @@ +$(document).ready(function() { + + module("Collections"); + + test("collections: each", function() { + _.each([1, 2, 3], function(num, i) { + equals(num, i + 1, 'each iterators provide value and iteration count'); + }); + + var answers = []; + _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5}); + equals(answers.join(', '), '5, 10, 15', 'context object property accessed'); + + answers = []; + _.forEach([1, 2, 3], function(num){ answers.push(num); }); + equals(answers.join(', '), '1, 2, 3', 'aliased as "forEach"'); + + answers = []; + var obj = {one : 1, two : 2, three : 3}; + obj.constructor.prototype.four = 4; + _.each(obj, function(value, key){ answers.push(key); }); + equals(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); + delete obj.constructor.prototype.four; + + answer = null; + _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); + ok(answer, 'can reference the original collection from inside the iterator'); + + answers = 0; + _.each(null, function(){ ++answers; }); + equals(answers, 0, 'handles a null properly'); + }); + + test('collections: map', function() { + var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'doubled numbers'); + + doubled = _.collect([1, 2, 3], function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'aliased as "collect"'); + + var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3}); + equals(tripled.join(', '), '3, 6, 9', 'tripled numbers with context'); + + var doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); + equals(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers'); + + var ids = _.map($('div.underscore-test').children(), function(n){ return n.id; }); + ok(_.include(ids, 'qunit-header'), 'can use collection methods on NodeLists'); + + var ids = _.map(document.images, function(n){ return n.id; }); + ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); + + var ifnull = _.map(null, function(){}); + ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly'); + + var length = _.map(Array(2), function(v) { return v; }).length; + equals(length, 2, "can preserve a sparse array's length"); + }); + + test('collections: reduce', function() { + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'can sum up an array'); + + var context = {multiplier : 3}; + sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context); + equals(sum, 18, 'can reduce with a context object'); + + sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'aliased as "inject"'); + + sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); + equals(sum, 6, 'OO-style reduce'); + + var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }); + equals(sum, 6, 'default initial value'); + + var ifnull; + try { + _.reduce(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + equals(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + + var sparseArray = []; + sparseArray[0] = 20; + sparseArray[2] = -5; + equals(_.reduce(sparseArray, function(a, b){ return a - b; }), 25, 'initially-sparse arrays with no memo'); + }); + + test('collections: reduceRight', function() { + var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equals(list, 'bazbarfoo', 'can perform right folds'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); + equals(list, 'bazbarfoo', 'aliased as "foldr"'); + + var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }); + equals(list, 'bazbarfoo', 'default initial value'); + + var ifnull; + try { + _.reduceRight(null, function(){}); + } catch (ex) { + ifnull = ex; + } + ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + + ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); + + equals(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); + raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); + + var sparseArray = []; + sparseArray[0] = 20; + sparseArray[2] = -5; + equals(_.reduceRight(sparseArray, function(a, b){ return a - b; }), -25, 'initially-sparse arrays with no memo'); + }); + + test('collections: detect', function() { + var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; }); + equals(result, 2, 'found the first "2" and broke the loop'); + }); + + test('collections: select', function() { + var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(evens.join(', '), '2, 4, 6', 'selected each even number'); + + evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(evens.join(', '), '2, 4, 6', 'aliased as "filter"'); + }); + + test('collections: reject', function() { + var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); + equals(odds.join(', '), '1, 3, 5', 'rejected each even number'); + }); + + test('collections: all', function() { + ok(_.all([], _.identity), 'the empty set'); + ok(_.all([true, true, true], _.identity), 'all true values'); + ok(!_.all([true, false, true], _.identity), 'one false value'); + ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers'); + ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number'); + ok(_.every([true, true, true], _.identity), 'aliased as "every"'); + }); + + test('collections: any', function() { + var nativeSome = Array.prototype.some; + Array.prototype.some = null; + ok(!_.any([]), 'the empty set'); + ok(!_.any([false, false, false]), 'all false values'); + ok(_.any([false, false, true]), 'one true value'); + ok(_.any([null, 0, 'yes', false]), 'a string'); + ok(!_.any([null, 0, '', false]), 'falsy values'); + ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers'); + ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number'); + ok(_.some([false, false, true]), 'aliased as "some"'); + Array.prototype.some = nativeSome; + }); + + test('collections: include', function() { + ok(_.include([1,2,3], 2), 'two is in the array'); + ok(!_.include([1,3,9], 2), 'two is not in the array'); + ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values'); + ok(_([1,2,3]).include(2), 'OO-style include'); + }); + + test('collections: invoke', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, 'sort'); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + test('collections: invoke w/ function reference', function() { + var list = [[5, 1, 7], [3, 2, 1]]; + var result = _.invoke(list, Array.prototype.sort); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + }); + + // Relevant when using ClojureScript + test('collections: invoke when strings have a call method', function() { + String.prototype.call = function(){return 42;} + var list = [[5, 1, 7], [3, 2, 1]]; + var s = "foo"; + equals(s.call(), 42, "call function exists"); + var result = _.invoke(list, 'sort'); + equals(result[0].join(', '), '1, 5, 7', 'first array sorted'); + equals(result[1].join(', '), '1, 2, 3', 'second array sorted'); + delete String.prototype.call; + equals(s.call, undefined, "call function removed"); + }); + + test('collections: pluck', function() { + var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; + equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); + }); + + test('collections: max', function() { + equals(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); + + var neg = _.max([1, 2, 3], function(num){ return -num; }); + equals(neg, 1, 'can perform a computation-based max'); + + equals(-Infinity, _.max({}), 'Maximum value of an empty object'); + equals(-Infinity, _.max([]), 'Maximum value of an empty array'); + }); + + test('collections: min', function() { + equals(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); + + var neg = _.min([1, 2, 3], function(num){ return -num; }); + equals(neg, 3, 'can perform a computation-based min'); + + equals(Infinity, _.min({}), 'Minimum value of an empty object'); + equals(Infinity, _.min([]), 'Minimum value of an empty array'); + }); + + test('collections: sortBy', function() { + var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; + people = _.sortBy(people, function(person){ return person.age; }); + equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age'); + }); + + test('collections: groupBy', function() { + var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); + ok('0' in parity && '1' in parity, 'created a group for each value'); + equals(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group'); + + var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; + var grouped = _.groupBy(list, 'length'); + equals(grouped['3'].join(' '), 'one two six ten'); + equals(grouped['4'].join(' '), 'four five nine'); + equals(grouped['5'].join(' '), 'three seven eight'); + }); + + test('collections: sortedIndex', function() { + var numbers = [10, 20, 30, 40, 50], num = 35; + var index = _.sortedIndex(numbers, num); + equals(index, 3, '35 should be inserted at index 3'); + }); + + test('collections: shuffle', function() { + var numbers = _.range(10); + var shuffled = _.shuffle(numbers).sort(); + notStrictEqual(numbers, shuffled, 'original object is unmodified'); + equals(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle'); + }); + + test('collections: toArray', function() { + ok(!_.isArray(arguments), 'arguments object is not an array'); + ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); + var a = [1,2,3]; + ok(_.toArray(a) !== a, 'array is cloned'); + equals(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements'); + + var numbers = _.toArray({one : 1, two : 2, three : 3}); + equals(numbers.join(', '), '1, 2, 3', 'object flattened into array'); + }); + + test('collections: size', function() { + equals(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); + }); + +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js new file mode 100644 index 0000000..78721af --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/functions.js @@ -0,0 +1,198 @@ +$(document).ready(function() { + + module("Functions"); + + test("functions: bind", function() { + var context = {name : 'moe'}; + var func = function(arg) { return "name: " + (this.name || arg); }; + var bound = _.bind(func, context); + equals(bound(), 'name: moe', 'can bind a function to a context'); + + bound = _(func).bind(context); + equals(bound(), 'name: moe', 'can do OO-style binding'); + + bound = _.bind(func, null, 'curly'); + equals(bound(), 'name: curly', 'can bind without specifying a context'); + + func = function(salutation, name) { return salutation + ': ' + name; }; + func = _.bind(func, this, 'hello'); + equals(func('moe'), 'hello: moe', 'the function was partially applied in advance'); + + var func = _.bind(func, this, 'curly'); + equals(func(), 'hello: curly', 'the function was completely applied in advance'); + + var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; + func = _.bind(func, this, 'hello', 'moe', 'curly'); + equals(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); + + func = function(context, message) { equals(this, context, message); }; + _.bind(func, 0, 0, 'can bind a function to `0`')(); + _.bind(func, '', '', 'can bind a function to an empty string')(); + _.bind(func, false, false, 'can bind a function to `false`')(); + + // These tests are only meaningful when using a browser without a native bind function + // To test this with a modern browser, set underscore's nativeBind to undefined + var F = function () { return this; }; + var Boundf = _.bind(F, {hello: "moe curly"}); + equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5"); + equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); + }); + + test("functions: bindAll", function() { + var curly = {name : 'curly'}, moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + curly.getName = moe.getName; + _.bindAll(moe, 'getName', 'sayHi'); + curly.sayHi = moe.sayHi; + equals(curly.getName(), 'name: curly', 'unbound function is bound to current object'); + equals(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); + + curly = {name : 'curly'}; + moe = { + name : 'moe', + getName : function() { return 'name: ' + this.name; }, + sayHi : function() { return 'hi: ' + this.name; } + }; + _.bindAll(moe); + curly.sayHi = moe.sayHi; + equals(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object'); + }); + + test("functions: memoize", function() { + var fib = function(n) { + return n < 2 ? n : fib(n - 1) + fib(n - 2); + }; + var fastFib = _.memoize(fib); + equals(fib(10), 55, 'a memoized version of fibonacci produces identical results'); + equals(fastFib(10), 55, 'a memoized version of fibonacci produces identical results'); + + var o = function(str) { + return str; + }; + var fastO = _.memoize(o); + equals(o('toString'), 'toString', 'checks hasOwnProperty'); + equals(fastO('toString'), 'toString', 'checks hasOwnProperty'); + }); + + asyncTest("functions: delay", 2, function() { + var delayed = false; + _.delay(function(){ delayed = true; }, 100); + setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50); + setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150); + }); + + asyncTest("functions: defer", 1, function() { + var deferred = false; + _.defer(function(bool){ deferred = bool; }, true); + _.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50); + }); + + asyncTest("functions: throttle", 2, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); throttledIncr(); + setTimeout(throttledIncr, 70); + setTimeout(throttledIncr, 120); + setTimeout(throttledIncr, 140); + setTimeout(throttledIncr, 190); + setTimeout(throttledIncr, 220); + setTimeout(throttledIncr, 240); + _.delay(function(){ ok(counter == 1, "incr was called immediately"); }, 30); + _.delay(function(){ ok(counter == 4, "incr was throttled"); start(); }, 400); + }); + + asyncTest("functions: throttle arguments", 2, function() { + var value = 0; + var update = function(val){ value = val; }; + var throttledUpdate = _.throttle(update, 100); + throttledUpdate(1); throttledUpdate(2); throttledUpdate(3); + setTimeout(function(){ throttledUpdate(4); }, 120); + setTimeout(function(){ throttledUpdate(5); }, 140); + setTimeout(function(){ throttledUpdate(6); }, 250); + _.delay(function(){ equals(value, 1, "updated to latest value"); }, 40); + _.delay(function(){ equals(value, 6, "updated to latest value"); start(); }, 400); + }); + + asyncTest("functions: throttle once", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); + _.delay(function(){ ok(counter == 1, "incr was called once"); start(); }, 220); + }); + + asyncTest("functions: throttle twice", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var throttledIncr = _.throttle(incr, 100); + throttledIncr(); throttledIncr(); + _.delay(function(){ ok(counter == 2, "incr was called twice"); start(); }, 220); + }); + + asyncTest("functions: debounce", 1, function() { + var counter = 0; + var incr = function(){ counter++; }; + var debouncedIncr = _.debounce(incr, 50); + debouncedIncr(); debouncedIncr(); debouncedIncr(); + setTimeout(debouncedIncr, 30); + setTimeout(debouncedIncr, 60); + setTimeout(debouncedIncr, 90); + setTimeout(debouncedIncr, 120); + setTimeout(debouncedIncr, 150); + _.delay(function(){ ok(counter == 1, "incr was debounced"); start(); }, 220); + }); + + test("functions: once", function() { + var num = 0; + var increment = _.once(function(){ num++; }); + increment(); + increment(); + equals(num, 1); + }); + + test("functions: wrap", function() { + var greet = function(name){ return "hi: " + name; }; + var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); + equals(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function'); + + var inner = function(){ return "Hello "; }; + var obj = {name : "Moe"}; + obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); + equals(obj.hi(), "Hello Moe"); + + var noop = function(){}; + var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); }); + var ret = wrapped(['whats', 'your'], 'vector', 'victor'); + same(ret, [noop, ['whats', 'your'], 'vector', 'victor']); + }); + + test("functions: compose", function() { + var greet = function(name){ return "hi: " + name; }; + var exclaim = function(sentence){ return sentence + '!'; }; + var composed = _.compose(exclaim, greet); + equals(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); + + composed = _.compose(greet, exclaim); + equals(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); + }); + + test("functions: after", function() { + var testAfter = function(afterAmount, timesCalled) { + var afterCalled = 0; + var after = _.after(afterAmount, function() { + afterCalled++; + }); + while (timesCalled--) after(); + return afterCalled; + }; + + equals(testAfter(5, 5), 1, "after(N) should fire after being called N times"); + equals(testAfter(5, 4), 0, "after(N) should not fire unless called N times"); + equals(testAfter(0, 0), 1, "after(0) should fire immediately"); + }); + +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js new file mode 100644 index 0000000..0105d60 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/objects.js @@ -0,0 +1,535 @@ +$(document).ready(function() { + + module("Objects"); + + test("objects: keys", function() { + var exception = /object/; + equals(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); + // the test above is not safe because it relies on for-in enumeration order + var a = []; a[1] = 0; + equals(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95'); + raises(function() { _.keys(null); }, exception, 'throws an error for `null` values'); + raises(function() { _.keys(void 0); }, exception, 'throws an error for `undefined` values'); + raises(function() { _.keys(1); }, exception, 'throws an error for number primitives'); + raises(function() { _.keys('a'); }, exception, 'throws an error for string primitives'); + raises(function() { _.keys(true); }, exception, 'throws an error for boolean primitives'); + }); + + test("objects: values", function() { + equals(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object'); + }); + + test("objects: functions", function() { + var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; + ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); + + var Animal = function(){}; + Animal.prototype.run = function(){}; + equals(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype'); + }); + + test("objects: extend", function() { + var result; + equals(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another'); + equals(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination'); + equals(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden'); + result = _.extend({x:'x'}, {a:'a'}, {b:'b'}); + ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects'); + result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'}); + ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); + result = _.extend({}, {a: void 0, b: null}); + equals(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); + }); + + test("objects: defaults", function() { + var result; + var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"}; + + _.defaults(options, {zero: 1, one: 10, twenty: 20}); + equals(options.zero, 0, 'value exists'); + equals(options.one, 1, 'value exists'); + equals(options.twenty, 20, 'default applied'); + + _.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"}); + equals(options.empty, "", 'value exists'); + ok(_.isNaN(options.nan), "NaN isn't overridden"); + equals(options.word, "word", 'new value is added, first one wins'); + }); + + test("objects: clone", function() { + var moe = {name : 'moe', lucky : [13, 27, 34]}; + var clone = _.clone(moe); + equals(clone.name, 'moe', 'the clone as the attributes of the original'); + + clone.name = 'curly'; + ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original'); + + clone.lucky.push(101); + equals(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); + + equals(_.clone(undefined), void 0, 'non objects should not be changed by clone'); + equals(_.clone(1), 1, 'non objects should not be changed by clone'); + equals(_.clone(null), null, 'non objects should not be changed by clone'); + }); + + test("objects: isEqual", function() { + function First() { + this.value = 1; + } + First.prototype.value = 1; + function Second() { + this.value = 1; + } + Second.prototype.value = 2; + + // Basic equality and identity comparisons. + ok(_.isEqual(null, null), "`null` is equal to `null`"); + ok(_.isEqual(), "`undefined` is equal to `undefined`"); + + ok(!_.isEqual(0, -0), "`0` is not equal to `-0`"); + ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`"); + ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`"); + ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`"); + + // String object and primitive comparisons. + ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal"); + ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal"); + ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal"); + ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives"); + + ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal"); + ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal"); + ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal"); + + // Number object and primitive comparisons. + ok(_.isEqual(75, 75), "Identical number primitives are equal"); + ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal"); + ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives"); + ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal"); + ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`"); + + ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal"); + ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal"); + + // Comparisons involving `NaN`. + ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`"); + ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`"); + ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`"); + ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`"); + + // Boolean object and primitive comparisons. + ok(_.isEqual(true, true), "Identical boolean primitives are equal"); + ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal"); + ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal"); + ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans"); + ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal"); + + // Common type coercions. + ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`"); + ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal"); + ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal"); + ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values"); + ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal"); + ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal"); + ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal"); + ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal"); + ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal"); + + // Dates. + ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal"); + ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal"); + ok(!_.isEqual(new Date(2009, 11, 13), { + getTime: function(){ + return 12606876e5; + } + }), "Date objects and objects with a `getTime` method are not equal"); + ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal"); + + // Functions. + ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal"); + + // RegExps. + ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal"); + ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal"); + ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal"); + ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps"); + ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal"); + + // Empty arrays, array-like objects, and object literals. + ok(_.isEqual({}, {}), "Empty object literals are equal"); + ok(_.isEqual([], []), "Empty array literals are equal"); + ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal"); + ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal."); + ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects"); + + ok(!_.isEqual({}, []), "Object literals and array literals are not equal"); + ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays"); + + // Arrays with primitive and object values. + ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal"); + ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal"); + + // Multi-dimensional arrays. + var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; + ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared"); + + // Overwrite the methods defined in ES 5.1 section 15.4.4. + a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; + b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; + + // Array elements and properties. + ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal"); + a.push("White Rocks"); + ok(!_.isEqual(a, b), "Arrays of different lengths are not equal"); + a.push("East Boulder"); + b.push("Gunbarrel Ranch", "Teller Farm"); + ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal"); + + // Sparse arrays. + ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal"); + ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty"); + + // According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined` + // elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined` + // values are equivalent. + if (0 in [undefined]) { + ok(!_.isEqual(Array(3), [undefined, undefined, undefined]), "Sparse and dense arrays are not equal"); + ok(!_.isEqual([undefined, undefined, undefined], Array(3)), "Commutative equality is implemented for sparse and dense arrays"); + } + + // Simple objects. + ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal"); + ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal"); + ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal"); + ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal"); + ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects"); + ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent"); + + // `A` contains nested objects and arrays. + a = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + + // `B` contains equivalent nested objects and arrays. + b = { + name: new String("Moe Howard"), + age: new Number(77), + stooge: true, + hobbies: ["acting"], + film: { + name: "Sing a Song of Six Pants", + release: new Date(1947, 9, 30), + stars: [new String("Larry Fine"), "Shemp Howard"], + minutes: new Number(16), + seconds: 54 + } + }; + ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared"); + + // Instances. + ok(_.isEqual(new First, new First), "Object instances are equal"); + ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal"); + ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal"); + ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined"); + + // Circular Arrays. + (a = []).push(a); + (b = []).push(b); + ok(_.isEqual(a, b), "Arrays containing circular references are equal"); + a.push(new String("Larry")); + b.push(new String("Larry")); + ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal"); + a.push("Shemp"); + b.push("Curly"); + ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal"); + + // Circular Objects. + a = {abc: null}; + b = {abc: null}; + a.abc = a; + b.abc = b; + ok(_.isEqual(a, b), "Objects containing circular references are equal"); + a.def = 75; + b.def = 75; + ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal"); + a.def = new Number(75); + b.def = new Number(63); + ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal"); + + // Cyclic Structures. + a = [{abc: null}]; + b = [{abc: null}]; + (a[0].abc = a).push(a); + (b[0].abc = b).push(b); + ok(_.isEqual(a, b), "Cyclic structures are equal"); + a[0].def = "Larry"; + b[0].def = "Larry"; + ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal"); + a[0].def = new String("Larry"); + b[0].def = new String("Curly"); + ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal"); + + // Complex Circular References. + a = {foo: {b: {foo: {c: {foo: null}}}}}; + b = {foo: {b: {foo: {c: {foo: null}}}}}; + a.foo.b.foo.c.foo = a; + b.foo.b.foo.c.foo = b; + ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal"); + + // Chaining. + ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); + equals(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained'); + + // Custom `isEqual` methods. + var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}}; + var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}}; + + ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods'); + ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods'); + ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal'); + ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods'); + + // Custom `isEqual` methods - comparing different types + LocalizedString = (function() { + function LocalizedString(id) { this.id = id; this.string = (this.id===10)? 'Bonjour': ''; } + LocalizedString.prototype.isEqual = function(that) { + if (_.isString(that)) return this.string == that; + else if (that instanceof LocalizedString) return this.id == that.id; + return false; + }; + return LocalizedString; + })(); + var localized_string1 = new LocalizedString(10), localized_string2 = new LocalizedString(10), localized_string3 = new LocalizedString(11); + ok(_.isEqual(localized_string1, localized_string2), 'comparing same typed instances with same ids'); + ok(!_.isEqual(localized_string1, localized_string3), 'comparing same typed instances with different ids'); + ok(_.isEqual(localized_string1, 'Bonjour'), 'comparing different typed instances with same values'); + ok(_.isEqual('Bonjour', localized_string1), 'comparing different typed instances with same values'); + ok(!_.isEqual('Bonjour', localized_string3), 'comparing two localized strings with different ids'); + ok(!_.isEqual(localized_string1, 'Au revoir'), 'comparing different typed instances with different values'); + ok(!_.isEqual('Au revoir', localized_string1), 'comparing different typed instances with different values'); + + // Custom `isEqual` methods - comparing with serialized data + Date.prototype.toJSON = function() { + return { + _type:'Date', + year:this.getUTCFullYear(), + month:this.getUTCMonth(), + day:this.getUTCDate(), + hours:this.getUTCHours(), + minutes:this.getUTCMinutes(), + seconds:this.getUTCSeconds() + }; + }; + Date.prototype.isEqual = function(that) { + var this_date_components = this.toJSON(); + var that_date_components = (that instanceof Date) ? that.toJSON() : that; + delete this_date_components['_type']; delete that_date_components['_type'] + return _.isEqual(this_date_components, that_date_components); + }; + + var date = new Date(); + var date_json = { + _type:'Date', + year:date.getUTCFullYear(), + month:date.getUTCMonth(), + day:date.getUTCDate(), + hours:date.getUTCHours(), + minutes:date.getUTCMinutes(), + seconds:date.getUTCSeconds() + }; + + ok(_.isEqual(date_json, date), 'serialized date matches date'); + ok(_.isEqual(date, date_json), 'date matches serialized date'); + }); + + test("objects: isEmpty", function() { + ok(!_([1]).isEmpty(), '[1] is not empty'); + ok(_.isEmpty([]), '[] is empty'); + ok(!_.isEmpty({one : 1}), '{one : 1} is not empty'); + ok(_.isEmpty({}), '{} is empty'); + ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); + ok(_.isEmpty(null), 'null is empty'); + ok(_.isEmpty(), 'undefined is empty'); + ok(_.isEmpty(''), 'the empty string is empty'); + ok(!_.isEmpty('moe'), 'but other strings are not'); + + var obj = {one : 1}; + delete obj.one; + ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); + }); + + // Setup remote variables for iFrame tests. + var iframe = document.createElement('iframe'); + jQuery(iframe).appendTo(document.body); + var iDoc = iframe.contentDocument || iframe.contentWindow.document; + iDoc.write( + "" + ); + iDoc.close(); + + test("objects: isElement", function() { + ok(!_.isElement('div'), 'strings are not dom elements'); + ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); + ok(_.isElement(iElement), 'even from another frame'); + }); + + test("objects: isArguments", function() { + var args = (function(){ return arguments; })(1, 2, 3); + ok(!_.isArguments('string'), 'a string is not an arguments object'); + ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); + ok(_.isArguments(args), 'but the arguments object is an arguments object'); + ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); + ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.'); + ok(_.isArguments(iArguments), 'even from another frame'); + }); + + test("objects: isObject", function() { + ok(_.isObject(arguments), 'the arguments object is object'); + ok(_.isObject([1, 2, 3]), 'and arrays'); + ok(_.isObject($('html')[0]), 'and DOM element'); + ok(_.isObject(iElement), 'even from another frame'); + ok(_.isObject(function () {}), 'and functions'); + ok(_.isObject(iFunction), 'even from another frame'); + ok(!_.isObject(null), 'but not null'); + ok(!_.isObject(undefined), 'and not undefined'); + ok(!_.isObject('string'), 'and not string'); + ok(!_.isObject(12), 'and not number'); + ok(!_.isObject(true), 'and not boolean'); + ok(_.isObject(new String('string')), 'but new String()'); + }); + + test("objects: isArray", function() { + ok(!_.isArray(arguments), 'the arguments object is not an array'); + ok(_.isArray([1, 2, 3]), 'but arrays are'); + ok(_.isArray(iArray), 'even from another frame'); + }); + + test("objects: isString", function() { + ok(!_.isString(document.body), 'the document body is not a string'); + ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); + ok(_.isString(iString), 'even from another frame'); + }); + + test("objects: isNumber", function() { + ok(!_.isNumber('string'), 'a string is not a number'); + ok(!_.isNumber(arguments), 'the arguments object is not a number'); + ok(!_.isNumber(undefined), 'undefined is not a number'); + ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); + ok(_.isNumber(NaN), 'NaN *is* a number'); + ok(_.isNumber(Infinity), 'Infinity is a number'); + ok(_.isNumber(iNumber), 'even from another frame'); + ok(!_.isNumber('1'), 'numeric strings are not numbers'); + }); + + test("objects: isBoolean", function() { + ok(!_.isBoolean(2), 'a number is not a boolean'); + ok(!_.isBoolean("string"), 'a string is not a boolean'); + ok(!_.isBoolean("false"), 'the string "false" is not a boolean'); + ok(!_.isBoolean("true"), 'the string "true" is not a boolean'); + ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); + ok(!_.isBoolean(undefined), 'undefined is not a boolean'); + ok(!_.isBoolean(NaN), 'NaN is not a boolean'); + ok(!_.isBoolean(null), 'null is not a boolean'); + ok(_.isBoolean(true), 'but true is'); + ok(_.isBoolean(false), 'and so is false'); + ok(_.isBoolean(iBoolean), 'even from another frame'); + }); + + test("objects: isFunction", function() { + ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); + ok(!_.isFunction('moe'), 'strings are not functions'); + ok(_.isFunction(_.isFunction), 'but functions are'); + ok(_.isFunction(iFunction), 'even from another frame'); + }); + + test("objects: isDate", function() { + ok(!_.isDate(100), 'numbers are not dates'); + ok(!_.isDate({}), 'objects are not dates'); + ok(_.isDate(new Date()), 'but dates are'); + ok(_.isDate(iDate), 'even from another frame'); + }); + + test("objects: isRegExp", function() { + ok(!_.isRegExp(_.identity), 'functions are not RegExps'); + ok(_.isRegExp(/identity/), 'but RegExps are'); + ok(_.isRegExp(iRegExp), 'even from another frame'); + }); + + test("objects: isNaN", function() { + ok(!_.isNaN(undefined), 'undefined is not NaN'); + ok(!_.isNaN(null), 'null is not NaN'); + ok(!_.isNaN(0), '0 is not NaN'); + ok(_.isNaN(NaN), 'but NaN is'); + ok(_.isNaN(iNaN), 'even from another frame'); + }); + + test("objects: isNull", function() { + ok(!_.isNull(undefined), 'undefined is not null'); + ok(!_.isNull(NaN), 'NaN is not null'); + ok(_.isNull(null), 'but null is'); + ok(_.isNull(iNull), 'even from another frame'); + }); + + test("objects: isUndefined", function() { + ok(!_.isUndefined(1), 'numbers are defined'); + ok(!_.isUndefined(null), 'null is defined'); + ok(!_.isUndefined(false), 'false is defined'); + ok(!_.isUndefined(NaN), 'NaN is defined'); + ok(_.isUndefined(), 'nothing is undefined'); + ok(_.isUndefined(undefined), 'undefined is undefined'); + ok(_.isUndefined(iUndefined), 'even from another frame'); + }); + + if (window.ActiveXObject) { + test("objects: IE host objects", function() { + var xml = new ActiveXObject("Msxml2.DOMDocument.3.0"); + ok(!_.isNumber(xml)); + ok(!_.isBoolean(xml)); + ok(!_.isNaN(xml)); + ok(!_.isFunction(xml)); + ok(!_.isNull(xml)); + ok(!_.isUndefined(xml)); + }); + } + + test("objects: tap", function() { + var intercepted = null; + var interceptor = function(obj) { intercepted = obj; }; + var returned = _.tap(1, interceptor); + equals(intercepted, 1, "passes tapped object to interceptor"); + equals(returned, 1, "returns tapped object"); + + returned = _([1,2,3]).chain(). + map(function(n){ return n * 2; }). + max(). + tap(interceptor). + value(); + ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); + }); +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js new file mode 100644 index 0000000..86663a2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/speed.js @@ -0,0 +1,70 @@ +(function() { + + var numbers = []; + for (var i=0; i<1000; i++) numbers.push(i); + var objects = _.map(numbers, function(n){ return {num : n}; }); + var randomized = _.sortBy(numbers, function(){ return Math.random(); }); + + JSLitmus.test('_.each()', function() { + var timesTwo = []; + _.each(numbers, function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('_(list).each()', function() { + var timesTwo = []; + _(numbers).each(function(num){ timesTwo.push(num * 2); }); + return timesTwo; + }); + + JSLitmus.test('jQuery.each()', function() { + var timesTwo = []; + jQuery.each(numbers, function(){ timesTwo.push(this * 2); }); + return timesTwo; + }); + + JSLitmus.test('_.map()', function() { + return _.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('jQuery.map()', function() { + return jQuery.map(objects, function(obj){ return obj.num; }); + }); + + JSLitmus.test('_.pluck()', function() { + return _.pluck(objects, 'num'); + }); + + JSLitmus.test('_.uniq()', function() { + return _.uniq(randomized); + }); + + JSLitmus.test('_.uniq() (sorted)', function() { + return _.uniq(numbers, true); + }); + + JSLitmus.test('_.sortBy()', function() { + return _.sortBy(numbers, function(num){ return -num; }); + }); + + JSLitmus.test('_.isEqual()', function() { + return _.isEqual(numbers, randomized); + }); + + JSLitmus.test('_.keys()', function() { + return _.keys(objects); + }); + + JSLitmus.test('_.values()', function() { + return _.values(objects); + }); + + JSLitmus.test('_.intersect()', function() { + return _.intersect(numbers, randomized); + }); + + JSLitmus.test('_.range()', function() { + return _.range(1000); + }); + +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js new file mode 100644 index 0000000..68c39dc --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp.js @@ -0,0 +1,27 @@ +(function() { + + var func = function(){}; + var date = new Date(); + var str = "a string"; + var numbers = []; + for (var i=0; i<1000; i++) numbers.push(i); + var objects = _.map(numbers, function(n){ return {num : n}; }); + var randomized = _.sortBy(numbers, function(){ return Math.random(); }); + + JSLitmus.test('_.isNumber', function() { + return _.isNumber(1000) + }); + + JSLitmus.test('_.newIsNumber', function() { + return _.newIsNumber(1000) + }); + + JSLitmus.test('_.isNumber(NaN)', function() { + return _.isNumber(NaN) + }); + + JSLitmus.test('_.newIsNumber(NaN)', function() { + return _.newIsNumber(NaN) + }); + +})(); \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html new file mode 100644 index 0000000..bd34f9d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/temp_tests.html @@ -0,0 +1,19 @@ + + + + Underscore Temporary Tests + + + + + + + +

        Underscore Temporary Tests

        +

        + A page for temporary speed tests, used for developing faster implementations + of existing Underscore methods. +

        +
        + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html new file mode 100644 index 0000000..77f2f3a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/test.html @@ -0,0 +1,43 @@ + + + + Underscore Test Suite + + + + + + + + + + + + + + + +
        +

        Underscore Test Suite

        +

        +

        +
          +
          +

          Underscore Speed Suite

          +

          + A representative sample of the functions are benchmarked here, to provide + a sense of how fast they might run in different browsers. + Each iteration runs on an array of 1000 elements.

          + For example, the 'intersect' test measures the number of times you can + find the intersection of two thousand-element arrays in one second. +

          +
          + + +
          + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js new file mode 100644 index 0000000..7bc5cb4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore.string/test/test_underscore/utility.js @@ -0,0 +1,155 @@ +$(document).ready(function() { + + module("Utility"); + + test("utility: noConflict", function() { + var underscore = _.noConflict(); + ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state."); + var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]); + equals(intersection.join(', '), '1, 2', 'but the intersection function still works'); + window._ = underscore; + }); + + test("utility: identity", function() { + var moe = {name : 'moe'}; + equals(_.identity(moe), moe, 'moe is the same as his identity'); + }); + + test("utility: uniqueId", function() { + var ids = [], i = 0; + while(i++ < 100) ids.push(_.uniqueId()); + equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); + }); + + test("utility: times", function() { + var vals = []; + _.times(3, function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); + // + vals = []; + _(3).times(function (i) { vals.push(i); }); + ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); + }); + + test("utility: mixin", function() { + _.mixin({ + myReverse: function(string) { + return string.split('').reverse().join(''); + } + }); + equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); + equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); + }); + + test("utility: _.escape", function() { + equals(_.escape("Curly & Moe"), "Curly & Moe"); + equals(_.escape("Curly & Moe"), "Curly &amp; Moe"); + }); + + test("utility: template", function() { + var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); + var result = basicTemplate({thing : 'This'}); + equals(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); + + var sansSemicolonTemplate = _.template("A <% this %> B"); + equals(sansSemicolonTemplate(), "A B"); + + var backslashTemplate = _.template("<%= thing %> is \\ridanculous"); + equals(backslashTemplate({thing: 'This'}), "This is \\ridanculous"); + + var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); + equals(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); + + var fancyTemplate = _.template("
            <% \ + for (key in people) { \ + %>
          • <%= people[key] %>
          • <% } %>
          "); + result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); + equals(result, "
          • Moe
          • Larry
          • Curly
          ", 'can run arbitrary javascript in templates'); + + var escapedCharsInJavascriptTemplate = _.template("
            <% _.each(numbers.split('\\n'), function(item) { %>
          • <%= item %>
          • <% }) %>
          "); + result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); + equals(result, "
          • one
          • two
          • three
          • four
          ", 'Can use escaped characters (e.g. \\n) in Javascript'); + + var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
          \">
          <% }); %>"); + result = namespaceCollisionTemplate({ + pageCount: 3, + thumbnails: { + 1: "p1-thumbnail.gif", + 2: "p2-thumbnail.gif", + 3: "p3-thumbnail.gif" + } + }); + equals(result, "3 p3-thumbnail.gif
          "); + + var noInterpolateTemplate = _.template("

          Just some text. Hey, I know this is silly but it aids consistency.

          "); + result = noInterpolateTemplate(); + equals(result, "

          Just some text. Hey, I know this is silly but it aids consistency.

          "); + + var quoteTemplate = _.template("It's its, not it's"); + equals(quoteTemplate({}), "It's its, not it's"); + + var quoteInStatementAndBody = _.template("<%\ + if(foo == 'bar'){ \ + %>Statement quotes and 'quotes'.<% } %>"); + equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'."); + + var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); + equals(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); + + var template = _.template("<%- value %>"); + var result = template({value: " + + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/index.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); 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 new file mode 100644 index 0000000..f2e3a0e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/package.json @@ -0,0 +1,27 @@ +{ + "name": "underscore", + "description": "JavaScript's functional programming helper library.", + "homepage": "http://documentcloud.github.com/underscore/", + "keywords": [ + "util", + "functional", + "server", + "client", + "browser" + ], + "author": { + "name": "Jeremy Ashkenas", + "email": "jeremy@documentcloud.org" + }, + "contributors": [], + "repository": { + "type": "git", + "url": "git://github.com/documentcloud/underscore.git" + }, + "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/node_modules/underscore/raw/underscore.psd b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/raw/underscore.psd new file mode 100644 index 0000000..73ad2d7 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/raw/underscore.psd differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore-min.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..122914e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore-min.js @@ -0,0 +1,31 @@ +// Underscore.js 1.2.4 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, +h)&&!f--)break;g=!f}}d.pop();return g}var s=this,G=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,H=k.unshift,l=p.toString,m=p.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,q=k.indexOf,D=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&define.amd? +define("underscore",function(){return b}):s._=b;b.VERSION="1.2.4";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(w&&a.forEach===w)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&& +(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e; +if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a, +function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a, +b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c= +e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e= +0;e= +0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!== +void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)== +"[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"}; +b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}; +b.mixin=function(a){j(b.functions(a),function(c){J(c,b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/;b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||u,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate|| +u,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||u,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ").replace(/\\\\/g,"\\")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var v=function(a,c){return c?b(a).chain(): +a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}}); +n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore.js b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore.js new file mode 100644 index 0000000..c8cd1fd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/node_modules/underscore/underscore.js @@ -0,0 +1,995 @@ +// Underscore.js 1.2.4 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var slice = ArrayProto.slice, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js** and **"CommonJS"**, with + // backwards-compatibility for the old `require()` API. If we're not in + // CommonJS, add `_` to the global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else if (typeof define === 'function' && define.amd) { + // Register as a named module with AMD. + define('underscore', function() { + return _; + }); + } else { + // Exported as a string, for Closure Compiler "advanced" mode. + root['_'] = _; + } + + // Current version. + _.VERSION = '1.2.4'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (hasOwnProperty.call(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + if (obj.length === +obj.length) results.length = obj.length; + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (_.isFunction(method) ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = _.flatten(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func].concat(slice.call(arguments, 0)); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (source[prop] !== void 0) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (hasOwnProperty.call(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (hasOwnProperty.call(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType == 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && hasOwnProperty.call(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return obj !== obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /.^/; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape || noMatch, function(match, code) { + return "',_.escape(" + code.replace(/\\'/g, "'") + "),'"; + }) + .replace(c.interpolate || noMatch, function(match, code) { + return "'," + code.replace(/\\'/g, "'") + ",'"; + }) + .replace(c.evaluate || noMatch, function(match, code) { + return "');" + code.replace(/\\'/g, "'") + .replace(/[\r\n\t]/g, ' ') + .replace(/\\\\/g, '\\') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // The OOP Wrapper + // --------------- + + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + var wrapped = this._wrapped; + method.apply(wrapped, arguments); + var length = wrapped.length; + if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0]; + return result(wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/node_modules/grunt-coffee/node_modules/grunt/package.json b/node_modules/grunt-coffee/node_modules/grunt/package.json new file mode 100644 index 0000000..2056124 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/package.json @@ -0,0 +1,75 @@ +{ + "name": "grunt", + "description": "A task-based command line build tool for JavaScript projects.", + "version": "0.3.17", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "homepage": "http://github.com/gruntjs/grunt", + "repository": { + "type": "git", + "url": "git://github.com/gruntjs/grunt.git" + }, + "bugs": { + "url": "http://github.com/gruntjs/grunt/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT" + } + ], + "main": "lib/grunt", + "bin": { + "grunt": "bin/grunt" + }, + "scripts": { + "test": "grunt test" + }, + "engines": { + "node": ">= 0.6.0" + }, + "preferGlobal": true, + "keywords": [ + "async", + "cli", + "minify", + "uglify", + "build", + "underscore", + "unit", + "test", + "qunit", + "nodeunit", + "server", + "init", + "scaffold", + "make", + "jake", + "tool" + ], + "dependencies": { + "async": "~0.1.18", + "colors": "~0.6.0", + "connect": "~2.4.4", + "dateformat": "1.0.2-1.2.3", + "glob-whatev": "~0.1.4", + "hooker": "~0.2.3", + "jshint": "~0.9.1", + "nodeunit": "~0.7.4", + "nopt": "~1.0.10", + "prompt": "~0.1.12", + "semver": "~1.0.13", + "uglify-js": "~1.3.3", + "underscore": "~1.2.4", + "underscore.string": "~2.1.1", + "temporary": "~0.0.4", + "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](/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 new file mode 100644 index 0000000..edd562e --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/concat.js @@ -0,0 +1,43 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('concat', 'Concatenate files.', function() { + var files = grunt.file.expandFiles(this.file.src); + // Concat specified files. + var src = grunt.helper('concat', files, {separator: this.data.separator}); + grunt.file.write(this.file.dest, src); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message. + grunt.log.writeln('File "' + this.file.dest + '" created.'); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + // Concat source files and/or directives. + grunt.registerHelper('concat', function(files, options) { + options = grunt.utils._.defaults(options || {}, { + separator: grunt.utils.linefeed + }); + return files ? files.map(function(filepath) { + return grunt.task.directive(filepath, grunt.file.read); + }).join(grunt.utils.normalizelf(options.separator)) : ''; + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js new file mode 100644 index 0000000..f21684c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init.js @@ -0,0 +1,617 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Nodejs libs. + var fs = require('fs'); + var path = require('path'); + + // External libs. + var semver = require('semver'); + + var prompt = require('prompt'); + prompt.message = '[' + '?'.green + ']'; + prompt.delimiter = ' '; + + // ========================================================================== + // TASKS + // ========================================================================== + + // An array of all available license files. + function availableLicenses() { + return grunt.task.expandFiles('init/licenses/*').map(function(obj) { + return path.basename(String(obj)).replace(/^LICENSE-/, ''); + }); + } + + grunt.registerInitTask('init', 'Generate project scaffolding from a predefined template.', function() { + // Extra arguments will be applied to the template file. + var args = grunt.utils.toArray(arguments); + // Template name. + var name = args.shift(); + // Default to last-specified grunt.npmTasks plugin name if template name + // was omitted. Note that specifying just a : after init like "grunt init:" + // will allow all available templates to be listed. + if (name == null) { + name = grunt._npmTasks[grunt._npmTasks.length - 1]; + } + // Valid init templates (.js files). + var templates = {}; + grunt.task.expandFiles('init/*.js').forEach(function(fileobj) { + // Add template (plus its path) to the templates object. + templates[path.basename(fileobj.abs, '.js')] = require(fileobj.abs); + }); + var initTemplate = templates[name]; + + // Give the user a little help. + grunt.log.writelns( + 'This task will create one or more files in the current directory, ' + + 'based on the environment and the answers to a few questions. ' + + 'Note that answering "?" to any question will show question-specific ' + + 'help and answering "none" to most questions will leave its value blank.' + ); + + // Abort if a valid template was not specified. + if (!initTemplate) { + grunt.log.writeln().write('Loading' + (name ? ' "' + name + '"' : '') + ' init template...').error(); + grunt.log.errorlns('A valid template name must be specified, eg. "grunt ' + + 'init:commonjs". The currently-available init templates are: '); + Object.keys(templates).forEach(function(name) { + var description = templates[name].description || '(no description)'; + grunt.log.errorlns(name.cyan + ' - ' + description); + }); + return false; + } + + // Abort if matching files or directories were found (to avoid accidentally + // nuking them). + if (initTemplate.warnOn && grunt.file.expand(initTemplate.warnOn).length > 0) { + grunt.log.writeln(); + grunt.warn('Existing files may be overwritten!'); + } + + // This task is asynchronous. + var taskDone = this.async(); + + var pathPrefix = 'init/' + name + '/root/'; + + // Useful init sub-task-specific utilities. + var init = { + // Expose any user-specified default init values. + defaults: grunt.task.readDefaults('init/defaults.json'), + // Expose rename rules for this template. + renames: grunt.task.readDefaults('init', name, 'rename.json'), + // Return an object containing files to copy with their absolute source path + // and relative destination path, renamed (or omitted) according to rules in + // rename.json (if it exists). + filesToCopy: function(props) { + var files = {}; + // Iterate over all source files. + grunt.task.expandFiles({dot: true}, pathPrefix + '**').forEach(function(obj) { + // Get the path relative to the template root. + var relpath = obj.rel.slice(pathPrefix.length); + var rule = init.renames[relpath]; + // Omit files that have an empty / false rule value. + if (!rule && relpath in init.renames) { return; } + // Create a property for this file. + files[rule ? grunt.template.process(rule, props, 'init') : relpath] = obj.rel; + }); + return files; + }, + // Search init template paths for filename. + srcpath: function(arg1) { + if (arg1 == null) { return null; } + var args = ['init', name, 'root'].concat(grunt.utils.toArray(arguments)); + return grunt.task.getFile.apply(grunt.file, args); + }, + // Determine absolute destination file path. + destpath: path.join.bind(path, process.cwd()), + // Given some number of licenses, add properly-named license files to the + // files object. + addLicenseFiles: function(files, licenses) { + var available = availableLicenses(); + licenses.forEach(function(license) { + var fileobj = grunt.task.expandFiles('init/licenses/LICENSE-' + license)[0]; + files['LICENSE-' + license] = fileobj ? fileobj.rel : null; + }); + }, + // Given an absolute or relative source path, and an optional relative + // destination path, copy a file, optionally processing it through the + // passed callback. + copy: function(srcpath, destpath, options) { + // Destpath is optional. + if (typeof destpath !== 'string') { + options = destpath; + destpath = srcpath; + } + // Ensure srcpath is absolute. + if (!grunt.file.isPathAbsolute(srcpath)) { + srcpath = init.srcpath(srcpath); + } + // Use placeholder file if no src exists. + if (!srcpath) { + srcpath = grunt.task.getFile('init/misc/placeholder'); + } + grunt.verbose.or.write('Writing ' + destpath + '...'); + try { + grunt.file.copy(srcpath, init.destpath(destpath), options); + grunt.verbose.or.ok(); + } catch(e) { + grunt.verbose.or.error().error(e); + throw e; + } + }, + // Iterate over all files in the passed object, copying the source file to + // the destination, processing the contents. + copyAndProcess: function(files, props, options) { + options = grunt.utils._.defaults(options || {}, { + process: function(contents) { + return grunt.template.process(contents, props, 'init'); + } + }); + Object.keys(files).forEach(function(destpath) { + var o = Object.create(options); + var srcpath = files[destpath]; + // If srcpath is relative, match it against options.noProcess if + // necessary, then make srcpath absolute. + var relpath; + if (srcpath && !grunt.file.isPathAbsolute(srcpath)) { + if (o.noProcess) { + relpath = srcpath.slice(pathPrefix.length); + o.noProcess = grunt.file.isMatch(o.noProcess, relpath); + } + srcpath = grunt.task.getFile(srcpath); + } + // Copy! + init.copy(srcpath, destpath, o); + }); + }, + // Save a package.json file in the destination directory. The callback + // can be used to post-process properties to add/remove/whatever. + writePackageJSON: function(filename, props, callback) { + var pkg = {}; + // Basic values. + ['name', 'title', 'description', 'version', 'homepage'].forEach(function(prop) { + if (prop in props) { pkg[prop] = props[prop]; } + }); + // Author. + var hasAuthor = Object.keys(props).some(function(prop) { + return (/^author_/).test(prop); + }); + if (hasAuthor) { + pkg.author = {}; + ['name', 'email', 'url'].forEach(function(prop) { + if (props['author_' + prop]) { + pkg.author[prop] = props['author_' + prop]; + } + }); + } + // Other stuff. + if ('repository' in props) { pkg.repository = {type: 'git', url: props.repository}; } + if ('bugs' in props) { pkg.bugs = {url: props.bugs}; } + if (props.licenses) { + pkg.licenses = props.licenses.map(function(license) { + return {type: license, url: props.homepage + '/blob/master/LICENSE-' + license}; + }); + } + + // Node/npm-specific (?) + if (props.main) { pkg.main = props.main; } + if (props.bin) { pkg.bin = props.bin; } + if (props.node_version) { pkg.engines = {node: props.node_version}; } + if (props.npm_test) { + pkg.scripts = {test: props.npm_test}; + if (props.npm_test.split(' ')[0] === 'grunt') { + if (!props.devDependencies) { props.devDependencies = {}; } + props.devDependencies.grunt = '~' + grunt.version; + } + } + + if (props.dependencies) { pkg.dependencies = props.dependencies; } + if (props.devDependencies) { pkg.devDependencies = props.devDependencies; } + if (props.keywords) { pkg.keywords = props.keywords; } + + // Allow final tweaks to the pkg object. + if (callback) { pkg = callback(pkg, props); } + + // Write file. + grunt.file.write(init.destpath(filename), JSON.stringify(pkg, null, 2)); + } + }; + + // Make args available as flags. + init.flags = {}; + args.forEach(function(flag) { init.flags[flag] = true; }); + + // Show any template-specific notes. + if (initTemplate.notes) { + grunt.log.subhead('"' + name + '" template notes:').writelns(initTemplate.notes); + } + + // Execute template code, passing in the init object, done function, and any + // other arguments specified after the init:name:???. + initTemplate.template.apply(this, [grunt, init, function() { + // Fail task if errors were logged. + if (grunt.task.current.errorCount) { taskDone(false); } + // Otherwise, print a success message. + grunt.log.writeln().writeln('Initialized from template "' + name + '".'); + // All done! + taskDone(); + }].concat(args)); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + // Prompt user to override default values passed in obj. + grunt.registerHelper('prompt', function(defaults, options, done) { + // If defaults are omitted, shuffle arguments a bit. + if (grunt.utils.kindOf(defaults) === 'array') { + done = options; + options = defaults; + defaults = {}; + } + + // Keep track of any "sanitize" functions for later use. + var sanitize = {}; + options.forEach(function(option) { + if (option.sanitize) { + sanitize[option.name] = option.sanitize; + } + }); + + // Add one final "are you sure?" prompt. + if (options.length > 0) { + options.push({ + message: 'Do you need to make any changes to the above before continuing?'.green, + name: 'ANSWERS_VALID', + default: 'y/N' + }); + } + + // Ask user for input. This is in an IIFE because it has to execute at least + // once, and might be repeated. + (function ask() { + grunt.log.subhead('Please answer the following:'); + var result = grunt.utils._.clone(defaults); + // Loop over each prompt option. + grunt.utils.async.forEachSeries(options, function(option, done) { + var defaultValue; + grunt.utils.async.forEachSeries(['default', 'altDefault'], function(prop, next) { + if (typeof option[prop] === 'function') { + // If the value is a function, execute that function, using the + // value passed into the return callback as the new default value. + option[prop](defaultValue, result, function(err, value) { + defaultValue = String(value); + next(); + }); + } else { + // Otherwise, if the value actually exists, use it. + if (prop in option) { + defaultValue = option[prop]; + } + next(); + } + }, function() { + // Handle errors (there should never be errors). + option.default = defaultValue; + delete option.altDefault; + // Wrap validator so that answering '?' always fails. + var validator = option.validator; + option.validator = function(line, next) { + if (line === '?') { + return next(false); + } else if (validator) { + if (validator.test) { + return next(validator.test(line)); + } else if (typeof validator === 'function') { + return validator.length < 2 ? next(validator(line)) : validator(line, next); + } + } + next(true); + }; + // Actually get user input. + prompt.start(); + prompt.getInput(option, function(err, line) { + if (err) { return done(err); } + option.validator = validator; + result[option.name] = line; + done(); + }); + }); + }, function(err) { + // After all prompt questions have been answered... + if (/n/i.test(result.ANSWERS_VALID)) { + // User accepted all answers. Suspend prompt. + prompt.pause(); + // Clean up. + delete result.ANSWERS_VALID; + // Iterate over all results. + grunt.utils.async.forEachSeries(Object.keys(result), function(name, next) { + // If this value needs to be sanitized, process it now. + if (sanitize[name]) { + sanitize[name](result[name], result, function(err, value) { + if (err) { + result[name] = err; + } else if (arguments.length === 2) { + result[name] = value === 'none' ? '' : value; + } + next(); + }); + } else { + if (result[name] === 'none') { result[name] = ''; } + next(); + } + }, function(err) { + // Done! + grunt.log.writeln(); + done(err, result); + }); + } else { + // Otherwise update the default value for each user prompt option... + options.slice(0, -1).forEach(function(option) { + option.default = result[option.name]; + }); + // ...and start over again. + ask(); + } + }); + }()); + }); + + // Built-in prompt options for the prompt_for helper. + // These generally follow the node "prompt" module convention, except: + // * The "default" value can be a function which is executed at run-time. + // * An optional "sanitize" function has been added to post-process data. + var prompts = { + name: { + message: 'Project name', + default: function(value, data, done) { + var types = ['javascript', 'js']; + if (data.type) { types.push(data.type); } + var type = '(?:' + types.join('|') + ')'; + // This regexp matches: + // leading type- type. type_ + // trailing -type .type _type and/or -js .js _js + var re = new RegExp('^' + type + '[\\-\\._]?|(?:[\\-\\._]?' + type + ')?(?:[\\-\\._]?js)?$', 'ig'); + // Strip the above stuff from the current dirname. + var name = path.basename(process.cwd()).replace(re, ''); + // Remove anything not a letter, number, dash, dot or underscore. + name = name.replace(/[^\w\-\.]/g, ''); + done(null, name); + }, + validator: /^[\w\-\.]+$/, + warning: 'Must be only letters, numbers, dashes, dots or underscores.', + sanitize: function(value, data, done) { + // An additional value, safe to use as a JavaScript identifier. + data.js_safe_name = value.replace(/[\W_]+/g, '_').replace(/^(\d)/, '_$1'); + // If no value is passed to `done`, the original property isn't modified. + done(); + } + }, + title: { + message: 'Project title', + default: function(value, data, done) { + var title = data.name || ''; + title = title.replace(/[\W_]+/g, ' '); + title = title.replace(/\w+/g, function(word) { + return word[0].toUpperCase() + word.slice(1).toLowerCase(); + }); + done(null, title); + }, + warning: 'May consist of any characters.' + }, + description: { + message: 'Description', + default: 'The best project ever.', + warning: 'May consist of any characters.' + }, + version: { + message: 'Version', + default: function(value, data, done) { + // Get a valid semver tag from `git describe --tags` if possible. + grunt.utils.spawn({ + cmd: 'git', + args: ['describe', '--tags'], + fallback: '' + }, function(err, result, code) { + result = result.split('-')[0]; + done(null, semver.valid(result) || '0.1.0'); + }); + }, + validator: semver.valid, + warning: 'Must be a valid semantic version (semver.org).' + }, + repository: { + message: 'Project git repository', + default: function(value, data, done) { + // Change any git@...:... uri to git://.../... format. + grunt.helper('git_origin', function(err, result) { + if (err) { + // Attempt to guess at the repo name. Maybe we'll get lucky! + result = 'git://github.com/' + (process.env.USER || process.env.USERNAME || '???') + '/' + + data.name + '.git'; + } else { + result = result.replace(/^git@([^:]+):/, 'git://$1/'); + } + done(null, result); + }); + }, + sanitize: function(value, data, done) { + // An additional computed "git_user" property. + var repo = grunt.helper('github_web_url', data.repository); + var parts; + 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. + grunt.utils.spawn({ + cmd: 'git', + args: ['config', '--get', 'github.user'], + fallback: '' + }, function(err, result, code) { + data.git_user = result || process.env.USER || process.env.USERNAME || '???'; + data.git_repo = path.basename(process.cwd()); + done(); + }); + } + }, + warning: 'Should be a public git:// URI.' + }, + homepage: { + message: 'Project homepage', + // If GitHub is the origin, the (potential) homepage is easy to figure out. + default: function(value, data, done) { + done(null, grunt.helper('github_web_url', data.repository) || 'none'); + }, + warning: 'Should be a public URL.' + }, + bugs: { + message: 'Project issues tracker', + // If GitHub is the origin, the issues tracker is easy to figure out. + default: function(value, data, done) { + done(null, grunt.helper('github_web_url', data.repository, 'issues') || 'none'); + }, + warning: 'Should be a public URL.' + }, + licenses: { + message: 'Licenses', + default: 'MIT', + validator: /^[\w\-]+(?:\s+[\w\-]+)*$/, + warning: 'Must be zero or more space-separated licenses. Built-in ' + + 'licenses are: ' + availableLicenses().join(' ') + ', but you may ' + + 'specify any number of custom licenses.', + // Split the string on spaces. + sanitize: function(value, data, done) { done(value.split(/\s+/)); } + }, + author_name: { + message: 'Author name', + default: function(value, data, done) { + // Attempt to pull the data from the user's git config. + grunt.utils.spawn({ + cmd: 'git', + args: ['config', '--get', 'user.name'], + fallback: 'none' + }, done); + }, + warning: 'May consist of any characters.' + }, + author_email: { + message: 'Author email', + default: function(value, data, done) { + // Attempt to pull the data from the user's git config. + grunt.utils.spawn({ + cmd: 'git', + args: ['config', '--get', 'user.email'], + fallback: 'none' + }, done); + }, + warning: 'Should be a valid email address.' + }, + author_url: { + message: 'Author url', + default: 'none', + warning: 'Should be a public URL.' + }, + jquery_version: { + message: 'Required jQuery version', + default: '*', + warning: 'Must be a valid semantic version range descriptor.' + }, + node_version: { + message: 'What versions of node does it run on?', + // TODO: pull from grunt's package.json + default: '>= 0.6.0', + warning: 'Must be a valid semantic version range descriptor.' + }, + main: { + message: 'Main module/entry point', + default: function(value, data, done) { + done(null, 'lib/' + data.name); + }, + warning: 'Must be a path relative to the project root.' + }, + bin: { + message: 'CLI script', + default: function(value, data, done) { + done(null, 'bin/' + data.name); + }, + warning: 'Must be a path relative to the project root.' + }, + npm_test: { + message: 'Npm test command', + default: 'grunt test', + warning: 'Must be an executable command.' + }, + grunt_version: { + message: 'What versions of grunt does it require?', + default: '~' + grunt.version, + warning: 'Must be a valid semantic version range descriptor.' + } + }; + + // Expose prompts object so that prompt_for prompts can be added or modified. + grunt.registerHelper('prompt_for_obj', function() { + return prompts; + }); + + // Commonly-used prompt options with meaningful default values. + grunt.registerHelper('prompt_for', function(name, altDefault) { + // Clone the option so the original options object doesn't get modified. + var option = grunt.utils._.clone(prompts[name]); + option.name = name; + + var defaults = grunt.task.readDefaults('init/defaults.json'); + if (name in defaults) { + // A user default was specified for this option, so use its value. + option.default = defaults[name]; + } else if (arguments.length === 2) { + // An alternate default was specified, so use it. + option.altDefault = altDefault; + } + return option; + }); + + // Get the git origin url from the current repo (if possible). + grunt.registerHelper('git_origin', function(done) { + grunt.utils.spawn({ + cmd: 'git', + args: ['remote', '-v'] + }, function(err, result, code) { + var re = /^origin\s/; + var lines; + if (!err) { + lines = result.split('\n').filter(re.test, re); + if (lines.length > 0) { + done(null, lines[0].split(/\s/)[1]); + return; + } + } + done(true, 'none'); + }); + }); + + // Generate a GitHub web URL from a GitHub repo URI. + var githubWebUrlRe = /^.+(?:@|:\/\/)(github.com)[:\/](.+?)(?:\.git|\/)?$/; + grunt.registerHelper('github_web_url', function(uri, suffix) { + var matches = githubWebUrlRe.exec(uri); + if (!matches) { return null; } + var url = 'https://' + matches[1] + '/' + matches[2]; + if (suffix) { + url += '/' + suffix.replace(/^\//, ''); + } + return url; + }); + +}; 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 new file mode 100644 index 0000000..7863dd4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs.js @@ -0,0 +1,56 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Basic template description. +exports.description = 'Create a commonjs module, including Nodeunit unit tests.'; + +// Template-specific notes to be displayed before question prompts. +exports.notes = ''; + +// Any existing file or directory matching this wildcard will cause a warning. +exports.warnOn = '*'; + +// The actual init template. +exports.template = function(grunt, init, done) { + + grunt.helper('prompt', {}, [ + // Prompt for these values. + grunt.helper('prompt_for', 'name'), + grunt.helper('prompt_for', 'description'), + grunt.helper('prompt_for', 'version'), + grunt.helper('prompt_for', 'repository'), + grunt.helper('prompt_for', 'homepage'), + grunt.helper('prompt_for', 'bugs'), + grunt.helper('prompt_for', 'licenses'), + grunt.helper('prompt_for', 'author_name'), + grunt.helper('prompt_for', 'author_email'), + grunt.helper('prompt_for', 'author_url'), + grunt.helper('prompt_for', 'node_version', '*'), + grunt.helper('prompt_for', 'main'), + grunt.helper('prompt_for', 'npm_test') + ], function(err, props) { + props.keywords = []; + + // Files to copy (and process). + var files = init.filesToCopy(props); + + // Add properly-named license files. + init.addLicenseFiles(files, props.licenses); + + // Actually copy (and process) files. + init.copyAndProcess(files, props); + + // Generate package.json file. + init.writePackageJSON('package.json', props); + + // All done! + done(); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/rename.json b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/rename.json new file mode 100644 index 0000000..69305ee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/rename.json @@ -0,0 +1,4 @@ +{ + "lib/name.js": "lib/{%= name %}.js", + "test/name_test.js": "test/{%= name %}_test.js" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/.npmignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/.npmignore @@ -0,0 +1 @@ +/node_modules/ 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 new file mode 100644 index 0000000..01dfdb2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/README.md @@ -0,0 +1,57 @@ +# {%= name %} + +{%= description %} + +## Getting Started +### On the server +Install the module with: `npm install {%= name %}` + +```javascript +var {%= js_safe_name %} = require('{%= name %}'); +{%= js_safe_name %}.awesome(); // "awesome" +``` + +### In the browser +Download the [production version][min] or the [development version][max]. + +[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: + +```html + + +``` + +In your code, you can attach {%= name %}'s methods to any object. + +```html + + + +``` + +## Documentation +_(Coming soon)_ + +## Examples +_(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](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!_ + +## Release History +_(Nothing yet)_ + +## License +Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} +Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/grunt.js new file mode 100644 index 0000000..344790f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/grunt.js @@ -0,0 +1,59 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + concat: { + dist: { + src: ['', '.js>'], + dest: 'dist/<%= pkg.name %>.js' + } + }, + min: { + dist: { + src: ['', ''], + dest: 'dist/<%= pkg.name %>.min.js' + } + }, + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'lint test' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true + }, + globals: { + exports: true, + module: false + } + }, + uglify: {} + }); + + // Default task. + grunt.registerTask('default', 'lint test concat min'); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/lib/name.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/lib/name.js new file mode 100644 index 0000000..dadc70f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/lib/name.js @@ -0,0 +1,15 @@ +/* + * {%= name %} + * {%= homepage %} + * + * Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} + * Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. + */ + +(function(exports) { + + exports.awesome = function() { + return 'awesome'; + }; + +}(typeof exports === 'object' && exports || this)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/test/name_test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/test/name_test.js new file mode 100644 index 0000000..aaec812 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/commonjs/root/test/name_test.js @@ -0,0 +1,35 @@ +/*global require:true */ +var {%= js_safe_name %} = require('../lib/{%= name %}.js'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports['awesome'] = { + setUp: function(done) { + // setup here + done(); + }, + 'no args': function(test) { + test.expect(1); + // tests here + test.equal({%= js_safe_name %}.awesome(), 'awesome', 'should be awesome.'); + test.done(); + } +}; 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 new file mode 100644 index 0000000..007b267 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile.js @@ -0,0 +1,80 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Basic template description. +exports.description = 'Create a basic grunt.js gruntfile.'; + +// Template-specific notes to be displayed before question prompts. +exports.notes = 'This template tries to guess file and directory paths, but ' + + 'you will most likely need to edit the generated grunt.js file before ' + + 'running grunt. _If you run grunt after generating grunt.js, and grunt ' + + 'exits with errors, edit the grunt.js file!_'; + +// Any existing file or directory matching this wildcard will cause a warning. +exports.warnOn = 'grunt.js'; + +// The actual init template. +exports.template = function(grunt, init, done) { + + grunt.helper('prompt', {}, [ + // Prompt for these values. + { + name: 'dom', + message: 'Is the DOM involved in ANY way?', + default: 'Y/n', + warning: 'Yes: QUnit unit tests + JSHint "browser" globals. No: Nodeunit unit tests.' + }, + { + name: 'min_concat', + message: 'Will files be concatenated or minified?', + default: 'Y/n', + warning: 'Yes: min + concat tasks. No: nothing to see here.' + }, + { + name: 'package_json', + message: 'Will you have a package.json file?', + default: 'Y/n', + warning: 'This changes how filenames are determined and banners are generated.' + } + ], function(err, props) { + props.dom = /y/i.test(props.dom); + props.min_concat = /y/i.test(props.min_concat); + props.package_json = /y/i.test(props.package_json); + props.test_task = props.dom ? 'qunit' : 'test'; + props.file_name = props.package_json ? '<%= pkg.name %>' : 'FILE_NAME'; + + // Find the first `preferred` item existing in `arr`. + function prefer(arr, preferred) { + for (var i = 0; i < preferred.length; i++) { + if (arr.indexOf(preferred[i]) !== -1) { + return preferred[i]; + } + } + return preferred[0]; + } + + // Guess at some directories, if they exist. + var dirs = grunt.file.expandDirs('*').map(function(d) { return d.slice(0, -1); }); + props.lib_dir = prefer(dirs, ['lib', 'src']); + props.test_dir = prefer(dirs, ['test', 'tests', 'unit', 'spec']); + + // Maybe this should be extended to support more libraries. Patches welcome! + props.jquery = grunt.file.expandFiles('**/jquery*.js').length > 0; + + // Files to copy (and process). + var files = init.filesToCopy(props); + + // Actually copy (and process) files. + init.copyAndProcess(files, props); + + // All done! + done(); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile/root/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile/root/grunt.js new file mode 100644 index 0000000..fda2e91 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntfile/root/grunt.js @@ -0,0 +1,71 @@ +/*global module:false*/ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({{% if (min_concat) { if (package_json) { %} + pkg: '', + meta: { + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + },{% } else { %} + meta: { + version: '0.1.0', + banner: '/*! PROJECT_NAME - v<%= meta.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '* http://PROJECT_WEBSITE/\n' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> ' + + 'YOUR_NAME; Licensed MIT */' + },{% } } %} + lint: { + files: ['grunt.js', '{%= lib_dir %}/**/*.js', '{%= test_dir %}/**/*.js'] + },{% if (dom) { %} + qunit: { + files: ['{%= test_dir %}/**/*.html'] + },{% } else { %} + test: { + files: ['{%= test_dir %}/**/*.js'] + },{% } %}{% if (min_concat) { %} + concat: { + dist: { + src: ['', ''], + dest: 'dist/{%= file_name %}.js' + } + }, + min: { + dist: { + src: ['', ''], + dest: 'dist/{%= file_name %}.min.js' + } + },{% } %} + watch: { + files: '', + tasks: 'lint {%= test_task %}' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true{% if (dom) { %}, + browser: true{% } %} + }, + globals: {{% if (jquery) { %} + jQuery: true + {% } %}} + }{% if (min_concat) { %}, + uglify: {}{% } %} + }); + + // Default task. + grunt.registerTask('default', 'lint {%= test_task %}{%= min_concat ? " concat min" : "" %}'); + +}; 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 new file mode 100644 index 0000000..b7ec6a4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin.js @@ -0,0 +1,66 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Basic template description. +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/gruntjs/grunt/blob/master/docs/plugins.md'; + +// Any existing file or directory matching this wildcard will cause a warning. +exports.warnOn = '*'; + +// The actual init template. +exports.template = function(grunt, init, done) { + + grunt.helper('prompt', {type: 'grunt'}, [ + // Prompt for these values. + grunt.helper('prompt_for', 'name', function(value, data, done) { + // Prepend "grunt-" to default name if not already there. + data.short_name = value; + value = data.full_name = 'grunt-' + value; + // if (!/^grunt-/.test(value)) { value = 'grunt-' + value; } + done(null, value); + }), + grunt.helper('prompt_for', 'description', 'The best sample grunt tasks ever.'), + grunt.helper('prompt_for', 'version'), + grunt.helper('prompt_for', 'repository'), + grunt.helper('prompt_for', 'homepage'), + grunt.helper('prompt_for', 'bugs'), + grunt.helper('prompt_for', 'licenses'), + grunt.helper('prompt_for', 'author_name'), + grunt.helper('prompt_for', 'author_email'), + grunt.helper('prompt_for', 'author_url'), + grunt.helper('prompt_for', 'grunt_version'), + grunt.helper('prompt_for', 'node_version', '*') + ], function(err, props) { + // Set a few grunt-plugin-specific properties. + props.main = 'grunt.js'; + props.npm_test = 'grunt test'; + props.bin = 'bin/' + props.name; + props.keywords = ['gruntplugin']; + + // Files to copy (and process). + var files = init.filesToCopy(props); + + // Add properly-named license files. + init.addLicenseFiles(files, props.licenses); + + // Actually copy (and process) files. + init.copyAndProcess(files, props); + + // Generate package.json file. + init.writePackageJSON('package.json', props); + + // All done! + done(); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/rename.json b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/rename.json new file mode 100644 index 0000000..181cfaa --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/rename.json @@ -0,0 +1,5 @@ +{ + "bin/name": "bin/{%= full_name %}", + "tasks/name.js": "tasks/{%= short_name %}.js", + "test/name_test.js": "test/{%= short_name %}_test.js" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/.npmignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/.npmignore @@ -0,0 +1 @@ +/node_modules/ 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 new file mode 100644 index 0000000..b0aba01 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/README.md @@ -0,0 +1,28 @@ +# {%= full_name %} + +{%= description %} + +## Getting Started +Install this grunt plugin next to your project's [grunt.js gruntfile][getting_started] with: `npm install {%= full_name %}` + +Then add this line to your project's `grunt.js` gruntfile: + +```javascript +grunt.loadNpmTasks('{%= full_name %}'); +``` + +[grunt]: http://gruntjs.com/ +[getting_started]: https://github.com/gruntjs/grunt/blob/master/docs/getting_started.md + +## Documentation +_(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][grunt]. + +## Release History +_(Nothing yet)_ + +## License +Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} +Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/bin/name b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/bin/name new file mode 100755 index 0000000..07a6c9f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/bin/name @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('grunt').npmTasks('{%= full_name %}').cli(); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/grunt.js new file mode 100644 index 0000000..008da40 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/grunt.js @@ -0,0 +1,40 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'tasks/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'default' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + node: true, + es5: true + }, + globals: {} + } + }); + + // Load local tasks. + grunt.loadTasks('tasks'); + + // Default task. + grunt.registerTask('default', 'lint test'); + +}; 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 new file mode 100644 index 0000000..9c0f861 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/tasks/name.js @@ -0,0 +1,30 @@ +/* + * {%= full_name %} + * {%= homepage %} + * + * Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} + * Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. + */ + +module.exports = function(grunt) { + + // Please see the grunt documentation for more information regarding task and + // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerTask('{%= short_name %}', 'Your task description goes here.', function() { + grunt.log.write(grunt.helper('{%= short_name %}')); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + grunt.registerHelper('{%= short_name %}', function() { + return '{%= short_name %}!!!'; + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/test/name_test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/test/name_test.js new file mode 100644 index 0000000..122b358 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/gruntplugin/root/test/name_test.js @@ -0,0 +1,34 @@ +var grunt = require('grunt'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports['{%= short_name %}'] = { + setUp: function(done) { + // setup here + done(); + }, + 'helper': function(test) { + test.expect(1); + // tests here + test.equal(grunt.helper('{%= short_name %}'), '{%= short_name %}!!!', 'should return the correct value.'); + test.done(); + } +}; 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 new file mode 100644 index 0000000..410da68 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery.js @@ -0,0 +1,77 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Basic template description. +exports.description = 'Create a jQuery plugin, including QUnit unit tests.'; + +// Template-specific notes to be displayed before question prompts. +exports.notes = '_Project name_ should not contain "jquery" or "js" and ' + + 'should be a unique ID not already in use at plugins.jquery.com. _Project ' + + 'title_ should be a human-readable title, and doesn\'t need to contain ' + + '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/manifest.md'; + +// Any existing file or directory matching this wildcard will cause a warning. +exports.warnOn = '*'; + +// The actual init template. +exports.template = function(grunt, init, done) { + + grunt.helper('prompt', {type: 'jquery'}, [ + // Prompt for these values. + grunt.helper('prompt_for', 'name'), + grunt.helper('prompt_for', 'title', function(value, data, done) { + // Fix jQuery capitalization. + value = value.replace(/jquery/gi, 'jQuery'); + done(null, value); + }), + grunt.helper('prompt_for', 'description', 'The best jQuery plugin ever.'), + grunt.helper('prompt_for', 'version'), + grunt.helper('prompt_for', 'repository'), + grunt.helper('prompt_for', 'homepage'), + grunt.helper('prompt_for', 'bugs'), + grunt.helper('prompt_for', 'licenses', 'MIT'), + grunt.helper('prompt_for', 'author_name'), + grunt.helper('prompt_for', 'author_email'), + grunt.helper('prompt_for', 'author_url'), + grunt.helper('prompt_for', 'jquery_version') + ], function(err, props) { + // A few additional properties. + props.jqueryjson = props.name + '.jquery.json'; + props.dependencies = {jquery: props.jquery_version || '>= 1'}; + props.keywords = []; + + // Files to copy (and process). + var files = init.filesToCopy(props); + + // Add properly-named license files. + init.addLicenseFiles(files, props.licenses); + + // Actually copy (and process) files. + init.copyAndProcess(files, props, {noProcess: 'libs/**'}); + + // Generate package.json file, used by npm and grunt. + init.writePackageJSON('package.json', { + name: 'jquery-plugin', + version: '0.0.0-ignored', + npm_test: 'grunt qunit', + // TODO: pull from grunt's package.json + node_version: '>= 0.6.0', + }); + + // Generate jquery.json file. + init.writePackageJSON(props.jqueryjson, props); + + // All done! + done(); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/rename.json b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/rename.json new file mode 100644 index 0000000..28ca1e5 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/rename.json @@ -0,0 +1,5 @@ +{ + "src/name.js": "src/{%= name %}.js", + "test/name_test.js": "test/{%= name %}_test.js", + "test/name.html": "test/{%= name %}.html" +} 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 new file mode 100644 index 0000000..2b5c59a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/README.md @@ -0,0 +1,30 @@ +# {%= title || name %} + +{%= description %} + +## Getting Started +Download the [production version][min] or the [development version][max]. + +[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: + +```html + + + +``` + +## Documentation +_(Coming soon)_ + +## Examples +_(Coming soon)_ + +## Release History +_(Nothing yet)_ diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/grunt.js new file mode 100644 index 0000000..87d6f18 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/grunt.js @@ -0,0 +1,60 @@ +/*global module:false*/ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: '', + meta: { + banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' + }, + concat: { + dist: { + src: ['', '.js>'], + dest: 'dist/<%= pkg.name %>.js' + } + }, + min: { + dist: { + src: ['', ''], + dest: 'dist/<%= pkg.name %>.min.js' + } + }, + qunit: { + files: ['test/**/*.html'] + }, + lint: { + files: ['grunt.js', 'src/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'lint qunit' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + browser: true + }, + globals: { + jQuery: true + } + }, + uglify: {} + }); + + // Default task. + grunt.registerTask('default', 'lint qunit concat min'); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery-loader.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery-loader.js new file mode 100644 index 0000000..e7356a1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery-loader.js @@ -0,0 +1,14 @@ +(function() { + // Get any jquery=___ param from the query string. + var jqversion = location.search.match(/[?&]jquery=(.*?)(?=&|$)/); + var path; + if (jqversion) { + // A version was specified, load that version from code.jquery.com. + path = 'http://code.jquery.com/jquery-' + jqversion[1] + '.js'; + } else { + // No version was specified, load the local version. + path = '../libs/jquery/jquery.js'; + } + // This is the only time I'll ever use document.write, I promise! + document.write(''); +}()); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery/jquery.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery/jquery.js new file mode 100644 index 0000000..3774ff9 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/libs/jquery/jquery.js @@ -0,0 +1,9404 @@ +/*! + * jQuery JavaScript Library v1.7.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: Wed Mar 21 12:46:34 2012 -0700 + */ +(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 + // Prioritize #id over to avoid XSS via location.hash (#9521) + 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+$/, + + // 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]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // 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.7.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.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +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.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // 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"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( 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; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + 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 new Error( 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 + parseXML: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + var xml, tmp; + try { + 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 ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + 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 ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).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' + // 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, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && 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, fn, key, value, chainable, emptyGet, pass ) { + var exec, + bulk = key == null, + i = 0, + length = elems.length; + + // Sets many values + if ( key && typeof key === "object" ) { + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + } + chainable = 1; + + // Sets one value + } else if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = pass === undefined && jQuery.isFunction( value ); + + if ( bulk ) { + // Bulk operations only iterate when executing function values + if ( exec ) { + exec = fn; + fn = function( elem, key, value ) { + return exec.call( jQuery( elem ), value ); + }; + + // Otherwise they run against the entire set + } else { + fn.call( elems, value ); + fn = null; + } + } + + if ( fn ) { + for (; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + } + + chainable = 1; + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + 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; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + fired = true; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, 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, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ 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 ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // 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", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + pixelMargin: true + }; + + // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead + jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); + + // 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 its 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"); + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/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; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, + paddingMarginBorderVisibility, paddingMarginBorder, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + paddingMarginBorder = "padding:0;margin:0;border:"; + positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; + paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; + style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; + html = "
          " + + "" + + "
          "; + + container = document.createElement("div"); + container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // 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) + div.innerHTML = "
          t
          "; + tds = div.getElementsByTagName( "td" ); + 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 ); + + // 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 ( window.getComputedStyle ) { + div.innerHTML = ""; + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + if ( typeof div.style.zoom !== "undefined" ) { + // 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.innerHTML = ""; + div.style.width = div.style.padding = "1px"; + div.style.border = 0; + div.style.overflow = "hidden"; + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = "block"; + div.style.overflow = "visible"; + div.innerHTML = "
          "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + } + + div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + if ( window.getComputedStyle ) { + div.style.marginTop = "1%"; + support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; + } + + if ( typeof container.style.zoom !== "undefined" ) { + container.style.zoom = 1; + } + + body.removeChild( container ); + marginDiv = div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([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 privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // 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[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // 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 || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && 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[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // 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 ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + 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[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // 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 + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + 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[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = 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 parts, part, attr, name, l, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attr = elem.attributes; + for ( l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split( ".", 2 ); + parts[1] = parts[1] ? "." + parts[1] : ""; + part = parts[1] + "!"; + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + data = this.triggerHandler( "getData" + part, [ parts[0] ] ); + + // Try to fetch any internally stored data first + if ( data === undefined && elem ) { + data = jQuery.data( elem, key ); + data = dataAttr( elem, key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } + + parts[1] = value; + this.each(function() { + var self = jQuery( this ); + + self.triggerHandler( "setData" + part, parts ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + part, parts ); + }); + }, null, value, arguments.length > 1, null, false ); + }, + + 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" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? +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; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + 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 ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // 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 ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _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 ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // 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) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // 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" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + 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( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + 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.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise( object ); + } +}); + + + + +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, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + 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 + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + 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; + } + + 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.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // 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, i, max, option, + 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 + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + 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 + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } 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, value ) { + var propName, attrNames, name, l, isBool, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + isBool = rboolean.test( name ); + + // See #9699 for explanation of this approach (setting first, then removal) + // Do not do this for boolean attributes (see #10870) + if ( !isBool ) { + jQuery.attr( elem, name, "" ); + } + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( isBool && propName 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; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.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 ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + 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 )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + 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; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + 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 ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true, + coords: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // 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; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// 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; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// 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 rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + 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.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: selector && quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // 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 to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever 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, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], 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 ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + 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.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + 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 ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === 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. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + special = jQuery.event.special[ event.type ] || {}, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers that should run if there are delegated events + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + + // Don't process events on disabled elements (#6911, #8165) + if ( cur.disabled !== true ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + 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; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // 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. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +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 instanceof jQuery.Event) ) { + 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 ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.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 +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// 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, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { // && selector != null + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + 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 ); + } +}); + +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 contextmenu").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.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * 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, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/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, seed ); + + } 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, seed ); + } + } + + } 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, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + 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, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + 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 ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + 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 new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +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 || 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 first, last, + doneName, parent, cache, + count, diff, + 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; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + 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 && 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 = Sizzle.attr ? + Sizzle.attr( elem, name ) : + 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 && Sizzle.attr ? + result != null : + 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) ); +} +// Expose origPOS +// "global" as in regardless of relation to brackets/parens +Expr.match.globalPOS = origPOS; + +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; + }; +} + +// 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[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = 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[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = 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, seed ) { + 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, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +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.globalPOS, + // 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" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], 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 ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // 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 ); + + 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, slice.call( arguments ).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; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /]", "i"), + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*", "" ], + legend: [ 1, "
          ", "
          " ], + thead: [ 1, "", "
          " ], + tr: [ 2, "", "
          " ], + td: [ 3, "", "
          " ], + col: [ 2, "", "
          " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + + + + + +

          {%= title || name %} Test Suite

          +

          +
          +

          +
            +
            + lame test markup + normal test markup + awesome test markup +
            + + diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/test/name_test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/test/name_test.js new file mode 100644 index 0000000..129db8c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/jquery/root/test/name_test.js @@ -0,0 +1,57 @@ +/*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/ +/*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/ +/*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/ +(function($) { + + /* + ======== A Handy Little QUnit Reference ======== + http://docs.jquery.com/QUnit + + Test methods: + expect(numAssertions) + stop(increment) + start(decrement) + Test assertions: + ok(value, [message]) + equal(actual, expected, [message]) + notEqual(actual, expected, [message]) + deepEqual(actual, expected, [message]) + notDeepEqual(actual, expected, [message]) + strictEqual(actual, expected, [message]) + notStrictEqual(actual, expected, [message]) + raises(block, [expected], [message]) + */ + + module('jQuery#awesome', { + setup: function() { + this.elems = $('#qunit-fixture').children(); + } + }); + + test('is chainable', 1, function() { + // Not a bad test to run on collection methods. + strictEqual(this.elems.awesome(), this.elems, 'should be chaninable'); + }); + + test('is awesome', 1, function() { + strictEqual(this.elems.awesome().text(), 'awesomeawesomeawesome', 'should be thoroughly awesome'); + }); + + module('jQuery.awesome'); + + test('is awesome', 1, function() { + strictEqual($.awesome(), 'awesome', 'should be thoroughly awesome'); + }); + + module(':awesome selector', { + setup: function() { + this.elems = $('#qunit-fixture').children(); + } + }); + + test('is awesome', 1, function() { + // Use deepEqual & .get() when comparing jQuery objects. + deepEqual(this.elems.filter(':awesome').get(), this.elems.last().get(), 'knows awesome when it sees it'); + }); + +}(jQuery)); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-GPL b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-GPL new file mode 100644 index 0000000..11dddd0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-GPL @@ -0,0 +1,278 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-MIT b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-MIT new file mode 100644 index 0000000..1922cc2 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/licenses/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} + +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/tasks/init/misc/placeholder b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/misc/placeholder new file mode 100644 index 0000000..4923c07 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/misc/placeholder @@ -0,0 +1 @@ +What is this I don’t even \ No newline at end of file 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 new file mode 100644 index 0000000..bee75b4 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node.js @@ -0,0 +1,57 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +// Basic template description. +exports.description = 'Create a Node.js module, including Nodeunit unit tests.'; + +// Template-specific notes to be displayed before question prompts. +exports.notes = '_Project name_ shouldn\'t contain "node" or "js" and should ' + + 'be a unique ID not already in use at search.npmjs.org.'; + +// Any existing file or directory matching this wildcard will cause a warning. +exports.warnOn = '*'; + +// The actual init template. +exports.template = function(grunt, init, done) { + + grunt.helper('prompt', {type: 'node'}, [ + // Prompt for these values. + grunt.helper('prompt_for', 'name'), + grunt.helper('prompt_for', 'description'), + grunt.helper('prompt_for', 'version'), + grunt.helper('prompt_for', 'repository'), + grunt.helper('prompt_for', 'homepage'), + grunt.helper('prompt_for', 'bugs'), + grunt.helper('prompt_for', 'licenses'), + grunt.helper('prompt_for', 'author_name'), + grunt.helper('prompt_for', 'author_email'), + grunt.helper('prompt_for', 'author_url'), + grunt.helper('prompt_for', 'node_version'), + grunt.helper('prompt_for', 'main'), + grunt.helper('prompt_for', 'npm_test') + ], function(err, props) { + props.keywords = []; + + // Files to copy (and process). + var files = init.filesToCopy(props); + + // Add properly-named license files. + init.addLicenseFiles(files, props.licenses); + + // Actually copy (and process) files. + init.copyAndProcess(files, props); + + // Generate package.json file. + init.writePackageJSON('package.json', props); + + // All done! + done(); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/rename.json b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/rename.json new file mode 100644 index 0000000..69305ee --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/rename.json @@ -0,0 +1,4 @@ +{ + "lib/name.js": "lib/{%= name %}.js", + "test/name_test.js": "test/{%= name %}_test.js" +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/.npmignore b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/.npmignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/.npmignore @@ -0,0 +1 @@ +/node_modules/ 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 new file mode 100644 index 0000000..bb67667 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/README.md @@ -0,0 +1,27 @@ +# {%= name %} + +{%= description %} + +## Getting Started +Install the module with: `npm install {%= name %}` + +```javascript +var {%= js_safe_name %} = require('{%= name %}'); +{%= js_safe_name %}.awesome(); // "awesome" +``` + +## Documentation +_(Coming soon)_ + +## Examples +_(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/gruntjs/grunt). + +## Release History +_(Nothing yet)_ + +## License +Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} +Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/grunt.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/grunt.js new file mode 100644 index 0000000..e0c2cbb --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/grunt.js @@ -0,0 +1,39 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: '', + test: { + files: ['test/**/*.js'] + }, + lint: { + files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] + }, + watch: { + files: '', + tasks: 'default' + }, + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + node: true + }, + globals: { + exports: true + } + } + }); + + // Default task. + grunt.registerTask('default', 'lint test'); + +}; \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/lib/name.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/lib/name.js new file mode 100644 index 0000000..0213883 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/lib/name.js @@ -0,0 +1,11 @@ +/* + * {%= name %} + * {%= homepage %} + * + * Copyright (c) {%= grunt.template.today('yyyy') %} {%= author_name %} + * Licensed under the {%= licenses.join(', ') %} license{%= licenses.length === 1 ? '' : 's' %}. + */ + +exports.awesome = function() { + return 'awesome'; +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/test/name_test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/test/name_test.js new file mode 100644 index 0000000..252490f --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/init/node/root/test/name_test.js @@ -0,0 +1,34 @@ +var {%= js_safe_name %} = require('../lib/{%= name %}.js'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports['awesome'] = { + setUp: function(done) { + // setup here + done(); + }, + 'no args': function(test) { + test.expect(1); + // tests here + test.equal({%= js_safe_name %}.awesome(), 'awesome', 'should be awesome.'); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js new file mode 100644 index 0000000..dfbfeb8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/lint.js @@ -0,0 +1,151 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // External libs. + var jshint = require('jshint').JSHINT; + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('lint', 'Validate files with JSHint.', function() { + // Get flags and globals, allowing target-specific options and globals to + // override the default options and globals. + var options, globals, tmp; + + tmp = grunt.config(['jshint', this.target, 'options']); + if (typeof tmp === 'object') { + grunt.verbose.writeln('Using "' + this.target + '" JSHint options.'); + options = tmp; + } else { + grunt.verbose.writeln('Using master JSHint options.'); + options = grunt.config('jshint.options'); + } + grunt.verbose.writeflags(options, 'Options'); + + tmp = grunt.config(['jshint', this.target, 'globals']); + if (typeof tmp === 'object') { + grunt.verbose.writeln('Using "' + this.target + '" JSHint globals.'); + globals = tmp; + } else { + grunt.verbose.writeln('Using master JSHint globals.'); + globals = grunt.config('jshint.globals'); + } + grunt.verbose.writeflags(globals, 'Globals'); + + // Lint specified files. + grunt.file.expandFiles(this.file.src).forEach(function(filepath) { + grunt.helper('lint', grunt.file.read(filepath), options, globals, filepath); + }); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message. + grunt.log.writeln('Lint free.'); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + // No idea why JSHint treats tabs as options.indent # characters wide, but it + // does. See issue: https://github.com/jshint/jshint/issues/430 + function getTabStr(options) { + // Do something that's going to error. + jshint('\tx', options || {}); + // If an error occurred, figure out what character JSHint reported and + // subtract one. + var character = jshint.errors && jshint.errors[0] && jshint.errors[0].character - 1; + // If character is actually a number, use it. Otherwise use 1. + var tabsize = isNaN(character) ? 1 : character; + // If tabsize > 1, return something that should be safe to use as a + // placeholder. \uFFFF repeated 2+ times. + return tabsize > 1 && grunt.utils.repeat(tabsize, '\uFFFF'); + } + + var tabregex = /\t/g; + + // Lint source code with JSHint. + grunt.registerHelper('lint', function(src, options, globals, extraMsg) { + // JSHint sometimes modifies objects you pass in, so clone them. + options = grunt.utils._.clone(options); + globals = grunt.utils._.clone(globals); + // Enable/disable debugging if option explicitly set. + if (grunt.option('debug') !== undefined) { + options.devel = options.debug = grunt.option('debug'); + // Tweak a few things. + if (grunt.option('debug')) { + options.maxerr = Infinity; + } + } + var msg = 'Linting' + (extraMsg ? ' ' + extraMsg : '') + '...'; + grunt.verbose.write(msg); + // Tab size as reported by JSHint. + var tabstr = getTabStr(options); + var placeholderregex = new RegExp(tabstr, 'g'); + // Lint. + var result = jshint(src, options || {}, globals || {}); + // Attempt to work around JSHint erroneously reporting bugs. + // if (!result) { + // // Filter out errors that shouldn't be reported. + // jshint.errors = jshint.errors.filter(function(o) { + // return o && o.something === 'something'; + // }); + // // If no errors are left, JSHint actually succeeded. + // result = jshint.errors.length === 0; + // } + if (result) { + // Success! + grunt.verbose.ok(); + } else { + // Something went wrong. + grunt.verbose.or.write(msg); + grunt.log.error(); + // Iterate over all errors. + jshint.errors.forEach(function(e) { + // Sometimes there's no error object. + if (!e) { return; } + var pos; + var evidence = e.evidence; + var character = e.character; + if (evidence) { + // Manually increment errorcount since we're not using grunt.log.error(). + grunt.fail.errorcount++; + // Descriptive code error. + pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + character).yellow + ']'.red; + grunt.log.writeln(pos + ' ' + e.reason.yellow); + // If necessary, eplace each tab char with something that can be + // swapped out later. + if (tabstr) { + evidence = evidence.replace(tabregex, tabstr); + } + if (character > evidence.length) { + // End of line. + evidence = evidence + ' '.inverse.red; + } else { + // Middle of line. + evidence = evidence.slice(0, character - 1) + evidence[character - 1].inverse.red + + evidence.slice(character); + } + // Replace tab placeholder (or tabs) but with a 2-space soft tab. + evidence = evidence.replace(tabstr ? placeholderregex : tabregex, ' '); + grunt.log.writeln(evidence); + } else { + // Generic "Whoops, too many errors" error. + grunt.log.error(e.reason); + } + }); + grunt.log.writeln(); + } + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js new file mode 100644 index 0000000..536e406 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/min.js @@ -0,0 +1,92 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // External libs. + var uglifyjs = require('uglify-js'); + var gzip = require('gzip-js'); + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('min', 'Minify files with UglifyJS.', function() { + var files = grunt.file.expandFiles(this.file.src); + // Get banner, if specified. It would be nice if UglifyJS supported ignoring + // all comments matching a certain pattern, like /*!...*/, but it doesn't. + var banner = grunt.task.directive(files[0], function() { return null; }); + if (banner === null) { + banner = ''; + } else { + files.shift(); + } + // Concat specified files. This should really be a single, pre-built (and + // linted) file, but it supports any number of files. + var max = grunt.helper('concat', files, {separator: this.data.separator}); + + // Concat banner + minified source. + var min = banner + grunt.helper('uglify', max, grunt.config('uglify')); + grunt.file.write(this.file.dest, min); + + // Fail task if errors were logged. + if (this.errorCount) { return false; } + + // Otherwise, print a success message.... + grunt.log.writeln('File "' + this.file.dest + '" created.'); + // ...and report some size information. + grunt.helper('min_max_info', min, max); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + // Minify with UglifyJS. + // From https://github.com/mishoo/UglifyJS + grunt.registerHelper('uglify', function(src, options) { + if (!options) { options = {}; } + var jsp = uglifyjs.parser; + var pro = uglifyjs.uglify; + var ast, pos; + var msg = 'Minifying with UglifyJS...'; + grunt.verbose.write(msg); + try { + ast = jsp.parse(src); + ast = pro.ast_mangle(ast, options.mangle || {}); + ast = pro.ast_squeeze(ast, options.squeeze || {}); + src = pro.gen_code(ast, options.codegen || {}); + // Success! + grunt.verbose.ok(); + // UglifyJS adds a trailing semicolon only when run as a binary. + // So we manually add the trailing semicolon when using it as a module. + // https://github.com/mishoo/UglifyJS/issues/126 + return src + ';'; + } catch(e) { + // Something went wrong. + grunt.verbose.or.write(msg); + pos = '['.red + ('L' + e.line).yellow + ':'.red + ('C' + e.col).yellow + ']'.red; + grunt.log.error().writeln(pos + ' ' + (e.message + ' (position: ' + e.pos + ')').yellow); + grunt.warn('UglifyJS found errors.', 10); + } + }); + + // Return gzipped source. + grunt.registerHelper('gzip', function(src) { + return src ? gzip.zip(src, {}) : ''; + }); + + // Output some size info about a file. + grunt.registerHelper('min_max_info', function(min, max) { + var gzipSize = String(grunt.helper('gzip', min).length); + grunt.log.writeln('Uncompressed size: ' + String(max.length).green + ' bytes.'); + grunt.log.writeln('Compressed size: ' + gzipSize.green + ' bytes gzipped (' + String(min.length).green + ' bytes minified).'); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js new file mode 100644 index 0000000..e6265cd --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/misc.js @@ -0,0 +1,85 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // ========================================================================== + // HELPERS + // ========================================================================== + + // Get a config property. Most useful as a directive like . + grunt.registerHelper('config', grunt.config); + + // Read a JSON file. Most useful as a directive like . + var jsons = {}; + grunt.registerHelper('json', function(filepath) { + // Don't re-fetch if being called as a directive and JSON is already cached. + if (!this.directive || !(filepath in jsons)) { + jsons[filepath] = grunt.file.readJSON(filepath); + } + return jsons[filepath]; + }); + + // Return the given source coude with any leading banner comment stripped. + grunt.registerHelper('strip_banner', function(src, options) { + if (!options) { options = {}; } + var m = []; + if (options.line) { + // Strip // ... leading banners. + m.push('(?:.*\\/\\/.*\\n)*\\s*'); + } + if (options.block) { + // Strips all /* ... */ block comment banners. + m.push('\\/\\*[\\s\\S]*?\\*\\/'); + } else { + // Strips only /* ... */ block comment banners, excluding /*! ... */. + m.push('\\/\\*[^!][\\s\\S]*?\\*\\/'); + } + var re = new RegExp('^\\s*(?:' + m.join('|') + ')\\s*', ''); + return src.replace(re, ''); + }); + + // Get a source file's contents with any leading banner comment stripped. If + // used as a directive, get options from the flags object. + grunt.registerHelper('file_strip_banner', function(filepath, opts) { + var src = grunt.file.read(filepath); + return grunt.helper('strip_banner', src, this.directive ? this.flags : opts); + }); + + // Process a file as a template. + grunt.registerHelper('file_template', function(filepath) { + var src = grunt.file.read(filepath); + return grunt.template.process(src); + }); + + // Generate banner from template. + grunt.registerHelper('banner', function(prop) { + if (!prop) { prop = 'meta.banner'; } + var banner; + var tmpl = grunt.config(prop); + if (tmpl) { + // Now, log. + grunt.verbose.write('Generating banner...'); + try { + // Compile and run template, using config object as the data source. + banner = grunt.template.process(tmpl) + grunt.utils.linefeed; + grunt.verbose.ok(); + } catch(e) { + banner = ''; + grunt.verbose.error(); + grunt.warn(e, 11); + } + } else { + grunt.warn('No "' + prop + '" banner template defined.', 11); + banner = ''; + } + return banner; + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js new file mode 100644 index 0000000..851afd8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit.js @@ -0,0 +1,258 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Nodejs libs. + var fs = require('fs'); + var path = require('path'); + + // External libs. + var Tempfile = require('temporary/lib/file'); + + // Keep track of the last-started module, test and status. + var currentModule, currentTest, status; + // Keep track of the last-started test(s). + var unfinished = {}; + + // Allow an error message to retain its color when split across multiple lines. + function formatMessage(str) { + return String(str).split('\n').map(function(s) { return s.magenta; }).join('\n'); + } + + // Keep track of failed assertions for pretty-printing. + var failedAssertions = []; + function logFailedAssertions() { + var assertion; + // Print each assertion error. + while (assertion = failedAssertions.shift()) { + grunt.verbose.or.error(assertion.testName); + grunt.log.error('Message: ' + formatMessage(assertion.message)); + if (assertion.actual !== assertion.expected) { + grunt.log.error('Actual: ' + formatMessage(assertion.actual)); + grunt.log.error('Expected: ' + formatMessage(assertion.expected)); + } + if (assertion.source) { + grunt.log.error(assertion.source.replace(/ {4}(at)/g, ' $1')); + } + grunt.log.writeln(); + } + } + + // Handle methods passed from PhantomJS, including QUnit hooks. + var phantomHandlers = { + // QUnit hooks. + moduleStart: function(name) { + unfinished[name] = true; + currentModule = name; + }, + moduleDone: function(name, failed, passed, total) { + delete unfinished[name]; + }, + log: function(result, actual, expected, message, source) { + if (!result) { + failedAssertions.push({ + actual: actual, expected: expected, message: message, source: source, + testName: currentTest + }); + } + }, + testStart: function(name) { + currentTest = (currentModule ? currentModule + ' - ' : '') + name; + grunt.verbose.write(currentTest + '...'); + }, + testDone: function(name, failed, passed, total) { + // Log errors if necessary, otherwise success. + if (failed > 0) { + // list assertions + if (grunt.option('verbose')) { + grunt.log.error(); + logFailedAssertions(); + } else { + grunt.log.write('F'.red); + } + } else { + grunt.verbose.ok().or.write('.'); + } + }, + done: function(failed, passed, total, duration) { + status.failed += failed; + status.passed += passed; + status.total += total; + status.duration += duration; + // Print assertion errors here, if verbose mode is disabled. + if (!grunt.option('verbose')) { + if (failed > 0) { + grunt.log.writeln(); + logFailedAssertions(); + } else { + grunt.log.ok(); + } + } + }, + // Error handlers. + done_fail: function(url) { + grunt.verbose.write('Running PhantomJS...').or.write('...'); + grunt.log.error(); + grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90); + }, + done_timeout: function() { + grunt.log.writeln(); + grunt.warn('PhantomJS timed out, possibly due to a missing QUnit start() call.', 90); + }, + // console.log pass-through. + console: console.log.bind(console), + // Debugging messages. + debug: grunt.log.debug.bind(grunt.log, 'phantomjs') + }; + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('qunit', 'Run QUnit unit tests in a headless PhantomJS instance.', function() { + // Get files as URLs. + var urls = grunt.file.expandFileURLs(this.file.src); + + // This task is asynchronous. + var done = this.async(); + + // Reset status. + status = {failed: 0, passed: 0, total: 0, duration: 0}; + + // Process each filepath in-order. + grunt.utils.async.forEachSeries(urls, function(url, next) { + var basename = path.basename(url); + grunt.verbose.subhead('Testing ' + basename).or.write('Testing ' + basename); + + // Create temporary file to be used for grunt-phantom communication. + var tempfile = new Tempfile(); + // Timeout ID. + var id; + // The number of tempfile lines already read. + var n = 0; + + // Reset current module. + currentModule = null; + + // Clean up. + function cleanup() { + clearTimeout(id); + tempfile.unlink(); + } + + // It's simple. As QUnit tests, assertions and modules begin and complete, + // the results are written as JSON to a temporary file. This polling loop + // checks that file for new lines, and for each one parses its JSON and + // executes the corresponding method with the specified arguments. + (function loopy() { + // Disable logging temporarily. + grunt.log.muted = true; + // Read the file, splitting lines on \n, and removing a trailing line. + var lines = grunt.file.read(tempfile.path).split('\n').slice(0, -1); + // Re-enable logging. + grunt.log.muted = false; + // Iterate over all lines that haven't already been processed. + var done = lines.slice(n).some(function(line) { + // Get args and method. + var args = JSON.parse(line); + var method = args.shift(); + // Execute method if it exists. + if (phantomHandlers[method]) { + phantomHandlers[method].apply(null, args); + } + // If the method name started with test, return true. Because the + // Array#some method was used, this not only sets "done" to true, + // but stops further iteration from occurring. + return (/^done/).test(method); + }); + + if (done) { + // All done. + cleanup(); + next(); + } else { + // Update n so previously processed lines are ignored. + n = lines.length; + // Check back in a little bit. + id = setTimeout(loopy, 100); + } + }()); + + // Launch PhantomJS. + 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. + tempfile.path, + // The QUnit helper file to be injected. + grunt.task.getFile('qunit/qunit.js'), + // URL to the QUnit .html test file to run. + url + ], + done: function(err) { + if (err) { + cleanup(); + done(); + } + }, + }); + }, function(err) { + // All tests have been run. + + // Log results. + if (status.failed > 0) { + grunt.warn(status.failed + '/' + status.total + ' assertions failed (' + + status.duration + 'ms)', Math.min(99, 90 + status.failed)); + } else { + grunt.verbose.writeln(); + grunt.log.ok(status.total + ' assertions passed (' + status.duration + 'ms)'); + } + + // All done! + done(); + }); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + grunt.registerHelper('phantomjs', function(options) { + return grunt.utils.spawn({ + cmd: 'phantomjs', + args: options.args + }, function(err, result, code) { + if (!err) { return options.done(null); } + // Something went horribly wrong. + grunt.verbose.or.writeln(); + grunt.log.write('Running PhantomJS...').error(); + if (code === 127) { + grunt.log.errorlns( + 'In order for this task to work properly, PhantomJS 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. ' + + 'See the grunt FAQ for PhantomJS installation instructions: ' + + 'https://github.com/gruntjs/grunt/blob/master/docs/faq.md' + ); + grunt.warn('PhantomJS not found.', options.code); + } else { + result.split('\n').forEach(grunt.log.error, grunt.log); + grunt.warn('PhantomJS exited unexpectedly with exit code ' + code + '.', options.code); + } + options.done(code); + }); + }); + +}; 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 new file mode 100644 index 0000000..ab4cdc8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.js @@ -0,0 +1,91 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +/*global phantom:true*/ + +var fs = require('fs'); + +// The temporary file used for communications. +var tmpfile = phantom.args[0]; +// The QUnit helper file to be injected. +var qunit = phantom.args[1]; +// The QUnit .html test file to run. +var url = phantom.args[2]; + +// Keep track of the last time a QUnit message was sent. +var last = new Date(); + +// Messages are sent to the parent by appending them to the tempfile. +function sendMessage(args) { + last = new Date(); + fs.write(tmpfile, JSON.stringify(args) + '\n', 'a'); + // Exit when all done. + if (/^done/.test(args[0])) { + phantom.exit(); + } +} + +// Send a debugging message. +function sendDebugMessage() { + sendMessage(['debug'].concat([].slice.call(arguments))); +} + +// Abort if QUnit doesn't do anything for a while. +setInterval(function() { + if (new Date() - last > 5000) { + sendMessage(['done_timeout']); + } +}, 1000); + +// Create a new page. +var page = require('webpage').create(); + +// QUnit sends its messages via alert(jsonstring); +page.onAlert = function(args) { + sendMessage(JSON.parse(args)); +}; + +// Keep track if QUnit has been injected already. +var injected; + +// Additional message sending +page.onConsoleMessage = function(message) { + sendMessage(['console', message]); +}; +page.onResourceRequested = function(request) { + if (/\/qunit\.js$/.test(request.url)) { + // Reset injected to false, if for some reason a redirect occurred and + // the test page (including qunit.js) had to be re-requested. + injected = false; + } + sendDebugMessage('onResourceRequested', request.url); +}; +page.onResourceReceived = function(request) { + if (request.stage === 'end') { + sendDebugMessage('onResourceReceived', request.url); + } +}; + +page.open(url, function(status) { + // Only execute this code if QUnit has not yet been injected. + if (injected) { return; } + injected = true; + // The window has loaded. + if (status !== 'success') { + // File loading failure. + sendMessage(['done_fail', url]); + } else { + // Inject QUnit helper file. + sendDebugMessage('inject', qunit); + page.injectJs(qunit); + // Because injection happens after window load, "begin" must be sent + // manually. + sendMessage(['begin']); + } +}); diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.json b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/phantom.json @@ -0,0 +1 @@ +{} \ No newline at end of file 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 new file mode 100644 index 0000000..f775426 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/qunit/qunit.js @@ -0,0 +1,55 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +/*global QUnit:true, alert:true*/ + +// Don't re-order tests. +QUnit.config.reorder = false; +// Run tests serially, not in parallel. +QUnit.config.autorun = false; + +// Send messages to the parent zombie.js process via alert! Good times!! +function sendMessage() { + var args = [].slice.call(arguments); + alert(JSON.stringify(args)); +} + +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. + var actual = QUnit.jsDump.parse(obj.actual); + var expected = QUnit.jsDump.parse(obj.expected); + // Send it. + sendMessage('log', obj.result, actual, expected, obj.message, obj.source); +}); + +QUnit.testStart(function(obj) { + sendMessage('testStart', obj.name); +}); + +QUnit.testDone(function(obj) { + sendMessage('testDone', obj.name, obj.failed, obj.passed, obj.total); +}); + +QUnit.moduleStart(function(obj) { + sendMessage('moduleStart', obj.name); +}); + +QUnit.moduleDone(function(obj) { + sendMessage('moduleDone', obj.name, obj.failed, obj.passed, obj.total); +}); + +QUnit.begin(function() { + sendMessage('begin'); +}); + +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 new file mode 100644 index 0000000..450e8de --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/server.js @@ -0,0 +1,46 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Nodejs libs. + var path = require('path'); + + // External libs. + var connect = require('connect'); + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerTask('server', 'Start a static web server.', function() { + // Get values from config, or use defaults. + var port = grunt.config('server.port') || 8000; + var base = path.resolve(grunt.config('server.base') || '.'); + + var middleware = [ + // Serve static files. + connect.static(base), + // Make empty directories browsable. (overkill?) + connect.directory(base) + ]; + + // If --debug was specified, enable logging. + if (grunt.option('debug')) { + connect.logger.format('grunt', ('[D] server :method :url :status ' + + ':res[content-length] - :response-time ms').magenta); + middleware.unshift(connect.logger('grunt')); + } + + // Start server. + grunt.log.writeln('Starting static web server on port ' + port + '.'); + connect.apply(null, middleware).listen(port); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js new file mode 100644 index 0000000..048665a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/test.js @@ -0,0 +1,160 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Nodejs libs. + var path = require('path'); + + // External libs. + var nodeunit = require('nodeunit'); + var nodeunitUtils = require('nodeunit/lib/utils'); + + // ========================================================================== + // CUSTOM NODEUNIT REPORTER + // ========================================================================== + + // Keep track of the last-started module. + var currentModule; + // Keep track of the last-started test(s). + var unfinished = {}; + + // If Nodeunit explodes because a test was missing test.done(), handle it. + process.on('exit', function() { + var len = Object.keys(unfinished).length; + // If there are unfinished tests, tell the user why Nodeunit killed grunt. + if (len > 0) { + grunt.log.muted = false; + grunt.verbose.error().or.writeln('F'.red); + grunt.log.error('Incomplete tests/setups/teardowns:'); + Object.keys(unfinished).forEach(grunt.log.error, grunt.log); + grunt.fatal('A test was missing test.done(), so nodeunit exploded. Sorry!', + Math.min(99, 90 + len)); + } + }); + + // Keep track of failed assertions for pretty-printing. + var failedAssertions = []; + function logFailedAssertions() { + var assertion, stack; + // Print each assertion error + stack. + while (assertion = failedAssertions.shift()) { + nodeunitUtils.betterErrors(assertion); + grunt.verbose.or.error(assertion.testName); + if (assertion.error.name === 'AssertionError' && assertion.message) { + grunt.log.error('AssertionMessage: ' + assertion.message.magenta); + } + stack = assertion.error.stack.replace(/ {4}(at)/g, ' $1'); + stack = stack.replace(/:(.*?\n)/, '$1'.magenta); + grunt.log.error(stack + '\n').writeln(); + } + } + + // Define our own Nodeunit reporter. + nodeunit.reporters.grunt = { + info: 'Grunt reporter', + run: function(files, options, callback) { + var opts = { + // No idea. + testspec: undefined, + // Executed when the first test in a file is run. If no tests exist in + // the file, this doesn't execute. + moduleStart: function(name) { + // Keep track of this so that moduleDone output can be suppressed in + // cases where a test file contains no tests. + currentModule = name; + grunt.verbose.subhead('Testing ' + name).or.write('Testing ' + name); + }, + // Executed after a file is done being processed. This executes whether + // tests exist in the file or not. + moduleDone: function(name) { + // Abort if no tests actually ran. + if (name !== currentModule) { return; } + // Print assertion errors here, if verbose mode is disabled. + if (!grunt.option('verbose')) { + if (failedAssertions.length > 0) { + grunt.log.writeln(); + logFailedAssertions(); + } else { + grunt.log.ok(); + } + } + }, + // Executed before each test is run. + testStart: function(name) { + // Keep track of the current test, in case test.done() was omitted + // and Nodeunit explodes. + unfinished[name] = name; + grunt.verbose.write(name + '...'); + // Mute output, in cases where a function being tested logs through + // grunt (for testing grunt internals). + grunt.log.muted = true; + }, + // Executed after each test and all its assertions are run. + testDone: function(name, assertions) { + delete unfinished[name]; + // Un-mute output. + grunt.log.muted = false; + // Log errors if necessary, otherwise success. + if (assertions.failures()) { + assertions.forEach(function(ass) { + if (ass.failed()) { + ass.testName = name; + failedAssertions.push(ass); + } + }); + if (grunt.option('verbose')) { + grunt.log.error(); + logFailedAssertions(); + } else { + grunt.log.write('F'.red); + } + } else { + grunt.verbose.ok().or.write('.'); + } + }, + // Executed when everything is all done. + done: function (assertions) { + if (assertions.failures()) { + grunt.warn(assertions.failures() + '/' + assertions.length + + ' assertions failed (' + assertions.duration + 'ms)', + Math.min(99, 90 + assertions.failures())); + } else { + grunt.verbose.writeln(); + grunt.log.ok(assertions.length + ' assertions passed (' + + assertions.duration + 'ms)'); + } + // Tell the task manager we're all done. + callback(); // callback(assertions.failures() === 0); + } + }; + + // Nodeunit needs absolute paths. + var paths = files.map(function(filepath) { + return path.resolve(filepath); + }); + nodeunit.runFiles(paths, opts); + } + }; + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('test', 'Run unit tests with nodeunit.', function() { + // File paths. + var filepaths = grunt.file.expandFiles(this.file.src); + // Clear all tests' cached require data, in case this task is run inside a + // "watch" task loop. + grunt.file.clearRequireCache(filepaths); + // Run test(s)... asynchronously! + nodeunit.reporters.grunt.run(filepaths, {}, this.async()); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js b/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js new file mode 100644 index 0000000..98e61b1 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/tasks/watch.js @@ -0,0 +1,168 @@ +/* + * grunt + * http://gruntjs.com/ + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT + */ + +module.exports = function(grunt) { + + // Nodejs libs. + var fs = require('fs'); + var path = require('path'); + // In Nodejs 0.8.0, existsSync moved from path -> fs. + var existsSync = fs.existsSync || path.existsSync; + + // ========================================================================== + // TASKS + // ========================================================================== + + // Keep track of last modified times of files, in case files are reported to + // have changed incorrectly. + var mtimes = {}; + + grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) { + this.requiresConfig('watch'); + // Build an array of files/tasks objects. + var watch = grunt.config('watch'); + var targets = target ? [target] : Object.keys(watch).filter(function(key) { + return typeof watch[key] !== 'string' && !Array.isArray(watch[key]); + }); + targets = targets.map(function(target) { + // Fail if any required config properties have been omitted. + target = ['watch', target]; + this.requiresConfig(target.concat('files'), target.concat('tasks')); + return grunt.config(target); + }, this); + + // Allow "basic" non-target format. + if (typeof watch.files === 'string' || Array.isArray(watch.files)) { + targets.push({files: watch.files, tasks: watch.tasks}); + } + + grunt.log.write('Waiting...'); + + // This task is asynchronous. + var taskDone = this.async(); + // Get a list of files to be watched. + var patterns = grunt.utils._.chain(targets).pluck('files').flatten().uniq().value(); + var getFiles = grunt.file.expandFiles.bind(grunt.file, patterns); + // The tasks to be run. + var tasks = []; //grunt.config(tasksProp); + // This task's name + optional args, in string format. + var nameArgs = this.nameArgs; + // An ID by which the setInterval can be canceled. + var intervalId; + // Files that are being watched. + var watchedFiles = {}; + // File changes to be logged. + var changedFiles = {}; + + // Define an alternate fail "warn" behavior. + grunt.fail.warnAlternate = function() { + grunt.task.clearQueue({untilMarker: true}).run(nameArgs); + }; + + // Cleanup when files have changed. This is debounced to handle situations + // where editors save multiple files "simultaneously" and should wait until + // all the files are saved. + var done = grunt.utils._.debounce(function() { + // Clear the files-added setInterval. + clearInterval(intervalId); + // Ok! + grunt.log.ok(); + var fileArray = Object.keys(changedFiles); + fileArray.forEach(function(filepath) { + // Log which file has changed, and how. + grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.'); + // Clear the modified file's cached require data. + grunt.file.clearRequireCache(filepath); + }); + // Unwatch all watched files. + Object.keys(watchedFiles).forEach(unWatchFile); + // For each specified target, test to see if any files matching that + // target's file patterns were modified. + targets.forEach(function(target) { + var files = grunt.file.expandFiles(target.files); + var intersection = grunt.utils._.intersection(fileArray, files); + // Enqueue specified tasks if a matching file was found. + if (intersection.length > 0 && target.tasks) { + grunt.task.run(target.tasks).mark(); + } + }); + // Enqueue the watch task, so that it loops. + grunt.task.run(nameArgs); + // Continue task queue. + taskDone(); + }, 250); + + // Handle file changes. + function fileChanged(status, filepath) { + // If file was deleted and then re-added, consider it changed. + if (changedFiles[filepath] === 'deleted' && status === 'added') { + status = 'changed'; + } + // Keep track of changed status for later. + changedFiles[filepath] = status; + // Execute debounced done function. + done(); + } + + // Watch a file. + function watchFile(filepath) { + if (!watchedFiles[filepath]) { + // Watch this file for changes. This probably won't scale to hundreds of + // files.. but I bet someone will try it! + watchedFiles[filepath] = fs.watch(filepath, function(event) { + var mtime; + // Has the file been deleted? + var deleted = !existsSync(filepath); + if (deleted) { + // If file was deleted, stop watching file. + unWatchFile(filepath); + // Remove from mtimes. + delete mtimes[filepath]; + } else { + // Get last modified time of file. + mtime = +fs.statSync(filepath).mtime; + // If same as stored mtime, the file hasn't changed. + if (mtime === mtimes[filepath]) { return; } + // Otherwise it has, store mtime for later use. + mtimes[filepath] = mtime; + } + // Call "change" for this file, setting status appropriately (rename -> + // renamed, change -> changed). + fileChanged(deleted ? 'deleted' : event + 'd', filepath); + }); + } + } + + // Unwatch a file. + function unWatchFile(filepath) { + if (watchedFiles[filepath]) { + // Close watcher. + watchedFiles[filepath].close(); + // Remove from watched files. + delete watchedFiles[filepath]; + } + } + + // Watch all currently existing files for changes. + getFiles().forEach(watchFile); + + // Watch for files to be added. + intervalId = setInterval(function() { + // Files that have been added since last interval execution. + var added = grunt.utils._.difference(getFiles(), Object.keys(watchedFiles)); + added.forEach(function(filepath) { + // This file has been added. + fileChanged('added', filepath); + // Watch this file. + watchFile(filepath); + }); + }, 200); + }); + +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/a.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/a.js new file mode 100644 index 0000000..f688910 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/a.js @@ -0,0 +1 @@ +var a = 1; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/b.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/b.js new file mode 100644 index 0000000..a2f3122 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/b.js @@ -0,0 +1 @@ +var b = 2; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner.js new file mode 100644 index 0000000..61cf35d --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner.js @@ -0,0 +1,11 @@ + +/* THIS + * IS + * A + * SAMPLE + * BANNER! + */ + +// Comment + +/* Comment */ diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner2.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner2.js new file mode 100644 index 0000000..f8ff08c --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner2.js @@ -0,0 +1,7 @@ + +/*! SAMPLE + * BANNER */ + +// Comment + +/* Comment */ diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner3.js b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner3.js new file mode 100644 index 0000000..ef55520 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/banner3.js @@ -0,0 +1,10 @@ + +// This is +// A sample +// Banner + +// But this is not + +/* And neither + * is this + */ 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/fixtures/octocat.png b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/octocat.png new file mode 100644 index 0000000..0b68cf0 Binary files /dev/null and b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/octocat.png differ diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/template.txt b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/template.txt new file mode 100644 index 0000000..99342d6 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/template.txt @@ -0,0 +1 @@ +Version: <%= grunt.version %>, today: <%= grunt.template.today("yyyy-mm-dd") %>. \ No newline at end of file diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/test.json b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/test.json new file mode 100644 index 0000000..098e7b8 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/fixtures/test.json @@ -0,0 +1,4 @@ +{ + "foo": "bar", + "baz": [1, 2, 3] +} diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/grunt/file_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/file_test.js new file mode 100644 index 0000000..2d8a608 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/file_test.js @@ -0,0 +1,67 @@ +var grunt = require('../../lib/grunt'); + +var fs = require('fs'); +var path = require('path'); + +// test helper +// +// compare - to effectively compare Buffers, we would need something like +// bnoordhuis/buffertools, but I'd rather not add a new dependency for the sake +// of testing. +// +// So we're relying on comparisons between the `hex` of buffers to do that, +// seems to be reliant enough to cover our test needs with file copy. +function compare(actual, expected, encoding) { + encoding = encoding || 'hex'; + return fs.readFileSync(actual, encoding) === fs.readFileSync(expected, encoding); +} + +exports['file'] = { + 'isPathAbsolute': function(test) { + test.expect(2); + test.ok(grunt.file.isPathAbsolute(path.resolve('test/fixtures/a.js')), 'should return true'); + test.equal(grunt.file.isPathAbsolute('test/fixtures/a.js'), false, 'should return false'); + test.done(); + }, + 'read': function(test) { + test.expect(2); + test.strictEqual(grunt.file.read('test/fixtures/a.js'), fs.readFileSync('test/fixtures/a.js', 'utf8')); + test.strictEqual(grunt.file.read('test/fixtures/octocat.png'), fs.readFileSync('test/fixtures/octocat.png', 'utf8')); + test.done(); + }, + 'write': function(test) { + test.expect(4); + var content = 'var a = "foobar";'; + grunt.file.write('test/fixtures/test_write.js', content); + test.strictEqual(fs.readFileSync('test/fixtures/test_write.js', 'utf8'), content); + test.strictEqual(grunt.file.read('test/fixtures/test_write.js'), content); + + var octocat = fs.readFileSync('test/fixtures/octocat.png'); + grunt.file.write('test/fixtures/test_write.png', octocat); + test.strictEqual(fs.readFileSync('test/fixtures/test_write.png', 'utf8'), fs.readFileSync('test/fixtures/octocat.png', 'utf8')); + test.ok(compare('test/fixtures/test_write.png', 'test/fixtures/octocat.png'), 'both buffers should match'); + + ['test/fixtures/test_write.js', 'test/fixtures/test_write.png'].forEach(fs.unlinkSync); + test.done(); + }, + 'copy': function(test) { + test.expect(6); + grunt.file.copy('test/fixtures/a.js', 'test/fixtures/test_copy.js'); + test.strictEqual(fs.readFileSync('test/fixtures/test_copy.js', 'utf8'), fs.readFileSync('test/fixtures/a.js', 'utf8')); + + var tmpltest = '// should src be a string and template process be all good.'; + grunt.file.copy('test/fixtures/a.js', 'test/fixtures/test_copy.js', {process: function(src) { + test.equal(Buffer.isBuffer(src), false); + test.equal(typeof src, 'string'); + return grunt.template.process(src + '<%= tmpltest %>', {tmpltest: tmpltest}); + }}); + test.strictEqual(fs.readFileSync('test/fixtures/test_copy.js', 'utf8'), grunt.utils.normalizelf(fs.readFileSync('test/fixtures/a.js', 'utf8')) + tmpltest); + + grunt.file.copy('test/fixtures/octocat.png', 'test/fixtures/test_copy.png'); + test.strictEqual(fs.readFileSync('test/fixtures/test_copy.png', 'utf8'), fs.readFileSync('test/fixtures/octocat.png', 'utf8')); + test.ok(compare('test/fixtures/test_copy.png', 'test/fixtures/octocat.png'), 'both buffers should match'); + + ['test/fixtures/test_copy.js', 'test/fixtures/test_copy.png'].forEach(fs.unlinkSync); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/grunt/template_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/template_test.js new file mode 100644 index 0000000..f119a66 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/template_test.js @@ -0,0 +1,20 @@ +var grunt = require('../../lib/grunt'); + +exports['template'] = { + 'process': function(test) { + test.expect(4); + var obj = { + foo: 'c', + bar: 'b<%= foo %>d', + baz: 'a<%= bar %>e' + }; + + test.equal(grunt.template.process('<%= foo %>', obj), 'c', 'should retrieve value.'); + test.equal(grunt.template.process('<%= bar %>', obj), 'bcd', 'should recurse.'); + test.equal(grunt.template.process('<%= baz %>', obj), 'abcde', 'should recurse.'); + + obj.foo = '<% oops %'; + test.equal(grunt.template.process('<%= baz %>', obj), 'ab<% oops %de', 'should not explode.'); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/grunt/utils_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/utils_test.js new file mode 100644 index 0000000..52b6f66 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/grunt/utils_test.js @@ -0,0 +1,22 @@ +var grunt = require('../../lib/grunt'); + +exports['utils'] = { + 'linefeed': function(test) { + test.expect(1); + if (process.platform === 'win32') { + test.equal(grunt.utils.linefeed, '\r\n', 'linefeed should be operating-system appropriate.'); + } else { + test.equal(grunt.utils.linefeed, '\n', 'linefeed should be operating-system appropriate.'); + } + test.done(); + }, + 'normalizelf': function(test) { + test.expect(1); + if (process.platform === 'win32') { + test.equal(grunt.utils.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\r\nbar\r\nbaz\r\n\r\nqux\r\n\r\nquux', 'linefeeds should be normalized'); + } else { + test.equal(grunt.utils.normalizelf('foo\nbar\r\nbaz\r\n\r\nqux\n\nquux'), 'foo\nbar\nbaz\n\nqux\n\nquux', 'linefeeds should be normalized'); + } + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/tasks/concat_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/concat_test.js new file mode 100644 index 0000000..afba24a --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/concat_test.js @@ -0,0 +1,21 @@ +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({}); +} + +exports['concat'] = function(test) { + test.expect(1); + grunt.registerHelper('test_helper', function(a, b) { return a + b; }); + var files = [ + 'test/fixtures/a.js', + '', + 'test/fixtures/b.js' + ]; + var lf = grunt.utils.linefeed; + test.equal(grunt.helper('concat', files), 'var a = 1;\n' + lf + 'xy' + lf + 'var b = 2;\n', 'It should concatenate files and directives.'); + test.done(); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/tasks/init_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/init_test.js new file mode 100644 index 0000000..891c9e0 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/init_test.js @@ -0,0 +1,44 @@ +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({}); +} + +exports['github_web_url'] = { + 'no args': function(test) { + test.expect(1); + test.equal(grunt.helper('github_web_url'), null, 'It should return null.'); + test.done(); + }, + 'nonsensical args': function(test) { + test.expect(3); + test.equal(grunt.helper('github_web_url', ''), null, 'It should return null.'); + test.equal(grunt.helper('github_web_url', 'omgfoo'), null, 'It should return null.'); + test.equal(grunt.helper('github_web_url', 'http://benalman.com/'), null, 'It should return null.'); + test.done(); + }, + 'no suffix': function(test) { + test.expect(5); + test.equal(grunt.helper('github_web_url', 'git@github.com:cowboy/grunt.git'), 'https://github.com/cowboy/grunt', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'https://cowboy@github.com/cowboy/grunt.git'), 'https://github.com/cowboy/grunt', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'git://github.com/cowboy/grunt.git'), 'https://github.com/cowboy/grunt', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite'), 'https://github.com/paulirish/newsite', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite/'), 'https://github.com/paulirish/newsite', 'It should convert the URI.'); + test.done(); + }, + 'suffix': function(test) { + test.expect(7); + test.equal(grunt.helper('github_web_url', 'git@github.com:cowboy/grunt.git', 'issues'), 'https://github.com/cowboy/grunt/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'https://cowboy@github.com/cowboy/grunt.git', 'issues'), 'https://github.com/cowboy/grunt/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'git://github.com/cowboy/grunt.git', 'issues'), 'https://github.com/cowboy/grunt/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite', 'issues'), 'https://github.com/paulirish/newsite/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite/', 'issues'), 'https://github.com/paulirish/newsite/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite', '/issues'), 'https://github.com/paulirish/newsite/issues', 'It should convert the URI.'); + test.equal(grunt.helper('github_web_url', 'http://github.com/paulirish/newsite/', '/issues'), 'https://github.com/paulirish/newsite/issues', 'It should convert the URI.'); + test.done(); + } +}; + 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/node_modules/grunt/test/tasks/misc_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/misc_test.js new file mode 100644 index 0000000..e14e1ca --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/tasks/misc_test.js @@ -0,0 +1,91 @@ +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({}); +} + +exports['config'] = function(test) { + test.expect(2); + test.deepEqual(grunt.helper('config'), grunt.config(), 'It should just pass through to config.'); + test.deepEqual(grunt.helper('config', 'meta'), grunt.config('meta'), 'It should just pass through to config.'); + test.done(); +}; + +exports['json'] = function(test) { + test.expect(2); + var obj = grunt.helper('json', 'test/fixtures/test.json'); + test.equal(obj.foo, 'bar', 'JSON properties should be available as-defined.'); + test.deepEqual(obj.baz, [1, 2, 3], 'JSON properties should be available as-defined.'); + test.done(); +}; + +exports['strip_banner'] = function(test) { + test.expect(7); + var src = grunt.file.read('test/fixtures/banner.js'); + test.equal(grunt.helper('strip_banner', src), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + test.equal(grunt.helper('strip_banner', src, {block: true}), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + src = grunt.file.read('test/fixtures/banner2.js'); + test.equal(grunt.helper('strip_banner', src), '\n/*! SAMPLE\n * BANNER */\n\n// Comment\n\n/* Comment */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('strip_banner', src, {block: true}), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + src = grunt.file.read('test/fixtures/banner3.js'); + test.equal(grunt.helper('strip_banner', src), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('strip_banner', src, {block: true}), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('strip_banner', src, {line: true}), '// But this is not\n\n/* And neither\n * is this\n */\n', 'It should strip the top banner.'); + test.done(); +}; + +exports['file_strip_banner'] = function(test) { + test.expect(14); + var filepath = 'test/fixtures/banner.js'; + test.equal(grunt.helper('file_strip_banner', filepath), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + test.equal(grunt.helper('file_strip_banner', filepath, {block: true}), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + filepath = 'test/fixtures/banner2.js'; + test.equal(grunt.helper('file_strip_banner', filepath), '\n/*! SAMPLE\n * BANNER */\n\n// Comment\n\n/* Comment */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('file_strip_banner', filepath, {block: true}), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + filepath = 'test/fixtures/banner3.js'; + test.equal(grunt.helper('file_strip_banner', filepath), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('file_strip_banner', filepath, {block: true}), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.helper('file_strip_banner', filepath, {line: true}), '// But this is not\n\n/* And neither\n * is this\n */\n', 'It should strip the top banner.'); + + test.equal(grunt.task.directive(''), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + test.equal(grunt.task.directive(''), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + test.equal(grunt.task.directive(''), '\n/*! SAMPLE\n * BANNER */\n\n// Comment\n\n/* Comment */\n', 'It should not strip the top banner.'); + test.equal(grunt.task.directive(''), '// Comment\n\n/* Comment */\n', 'It should strip the top banner.'); + test.equal(grunt.task.directive(''), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.task.directive(''), '\n// This is\n// A sample\n// Banner\n\n// But this is not\n\n/* And neither\n * is this\n */\n', 'It should not strip the top banner.'); + test.equal(grunt.task.directive(''), '// But this is not\n\n/* And neither\n * is this\n */\n', 'It should strip the top banner.'); + test.done(); +}; + +exports['file_template'] = function(test) { + test.expect(2); + var expected = 'Version: ' + grunt.version + ', today: ' + grunt.template.today('yyyy-mm-dd') + '.'; + test.equal(grunt.helper('file_template', 'test/fixtures/template.txt'), expected, 'It should return the parsed template.'); + test.equal(grunt.task.directive(''), expected, 'It should return the parsed template.'); + test.done(); +}; + +exports['banner'] = function(test) { + test.expect(5); + grunt.config('test_config', {a: 'aaaaa', b: 'bbbbb', c: [1, 2, 3], d: [{a: 1}, {a: 2}, {a: 3}]}); + + grunt.config('meta.banner', 'foo\n<%= test_config.a %>\nbar'); + test.equal(grunt.helper('banner'), grunt.utils.normalizelf('foo\naaaaa\nbar\n'), 'It should use the default banner.'); + + grunt.config('test_config.banner', '<%= test_config.b %>'); + test.equal(grunt.helper('banner', 'test_config.banner'), grunt.utils.normalizelf('bbbbb\n'), 'It should use the requested banner.'); + + grunt.config('test_config.banner', '<%= test_config.c.join(", ") %>'); + test.equal(grunt.helper('banner', 'test_config.banner'), grunt.utils.normalizelf('1, 2, 3\n'), 'It should join arrays.'); + + grunt.config('test_config.banner', '<%= _.pluck(test_config.d, "a").join(", ") %>'); + test.equal(grunt.helper('banner', 'test_config.banner'), grunt.utils.normalizelf('1, 2, 3\n'), 'It should join arrays.'); + + grunt.config('test_config.banner', '<%= grunt.template.today("yyyy-mm-dd") %>'); + test.equal(grunt.helper('banner', 'test_config.banner'), grunt.utils.normalizelf(grunt.template.today('yyyy-mm-dd') + '\n'), 'It should parse the current date correctly.'); + + test.done(); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/util/namespace_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/util/namespace_test.js new file mode 100644 index 0000000..dc04594 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/util/namespace_test.js @@ -0,0 +1,49 @@ +var namespace = require('../../lib/util/namespace.js'); + +exports.get = { + 'no create': function(test) { + var obj = {a: {b: {c: 1, d: '', e: null, f: undefined, 'g.h.i': 2}}}; + test.strictEqual(namespace.get(obj, 'a'), obj.a, 'should get immediate properties.'); + test.strictEqual(namespace.get(obj, 'a.b'), obj.a.b, 'should get nested properties.'); + test.strictEqual(namespace.get(obj, 'a.x'), undefined, 'should return undefined for nonexistent properties.'); + test.strictEqual(namespace.get(obj, 'a.b.c'), 1, 'should return values.'); + test.strictEqual(namespace.get(obj, 'a.b.d'), '', 'should return values.'); + test.strictEqual(namespace.get(obj, 'a.b.e'), null, 'should return values.'); + test.strictEqual(namespace.get(obj, 'a.b.f'), undefined, 'should return values.'); + test.strictEqual(namespace.get(obj, 'a.b.g\\.h\\.i'), 2, 'literal backslash should escape period in property name.'); + test.done(); + }, + 'create': function(test) { + var obj = {a: 1}; + test.strictEqual(namespace.get(obj, 'a', true), obj.a, 'should just return existing properties.'); + test.strictEqual(namespace.get(obj, 'b', true), obj.b, 'should create immediate properties.'); + test.strictEqual(namespace.get(obj, 'c.d.e', true), obj.c.d.e, 'should create nested properties.'); + test.done(); + } +}; + +exports.set = function(test) { + var obj = {}; + test.strictEqual(namespace.set(obj, 'a', 1), 1, 'should return immediate property value.'); + test.strictEqual(obj.a, 1, 'should set property value.'); + test.strictEqual(namespace.set(obj, 'b.c.d', 1), 1, 'should return nested property value.'); + test.strictEqual(obj.b.c.d, 1, 'should set property value.'); + test.strictEqual(namespace.set(obj, 'e\\.f\\.g', 1), 1, 'literal backslash should escape period in property name.'); + test.strictEqual(obj['e.f.g'], 1, 'should set property value.'); + test.done(); +}; + +exports.exists = function(test) { + var obj = {a: {b: {c: 1, d: '', e: null, f: undefined, 'g.h.i': 2}}}; + test.ok(namespace.exists(obj, 'a'), 'immediate property should exist.'); + test.ok(namespace.exists(obj, 'a.b'), 'nested property should exist.'); + test.ok(namespace.exists(obj, 'a.b.c'), 'nested property should exist.'); + test.ok(namespace.exists(obj, 'a.b.d'), 'nested property should exist.'); + test.ok(namespace.exists(obj, 'a.b.e'), 'nested property should exist.'); + test.ok(namespace.exists(obj, 'a.b.f'), 'nested property should exist.'); + test.ok(namespace.exists(obj, 'a.b.g\\.h\\.i'), 'literal backslash should escape period in property name.'); + test.equal(namespace.exists(obj, 'x'), false, 'nonexistent property should not exist.'); + test.equal(namespace.exists(obj, 'a.x'), false, 'nonexistent property should not exist.'); + test.equal(namespace.exists(obj, 'a.b.x'), false, 'nonexistent property should not exist.'); + test.done(); +}; diff --git a/node_modules/grunt-coffee/node_modules/grunt/test/util/task_test.js b/node_modules/grunt-coffee/node_modules/grunt/test/util/task_test.js new file mode 100644 index 0000000..afe9e16 --- /dev/null +++ b/node_modules/grunt-coffee/node_modules/grunt/test/util/task_test.js @@ -0,0 +1,444 @@ +// Test helpers. +function delay(fn) { setTimeout(fn, 10); } + +var result = (function() { + var arr; + var push = function() { [].push.apply(arr, arguments); }; + return { + reset: function() { arr = []; }, + push: push, + pushTaskname: function() { push(this.name); }, + get: function() { return arr; }, + getJoined: function() { return arr.join(''); } + }; +}()); + +var requireTask = require.bind(this, '../../lib/util/task.js'); + +exports['new Task'] = { + 'create': function(test) { + test.expect(1); + var tasklib = requireTask(); + test.ok(tasklib.create() instanceof tasklib.Task, 'It should return a Task instance.'); + test.done(); + } +}; + +exports['Helpers'] = { + setUp: function(done) { + this.task = requireTask().create(); + this.fn = function(a, b) { return a + b; }; + this.task.registerHelper('add', this.fn); + done(); + }, + 'Task#registerHelper': function(test) { + test.expect(1); + var task = this.task; + test.ok('add' in task._helpers, 'It should register the passed helper.'); + test.done(); + }, + 'Task#helper': function(test) { + test.expect(4); + var task = this.task; + test.strictEqual(task.helper('add', 1, 2), 3, 'It should receive arguments and return a value.'); + test.throws(function() { task.helper('nonexistent'); }, 'Attempting to execute unregistered handlers should throw an exception.'); + task.options({ + error: result.pushTaskname + }); + result.reset(); + test.doesNotThrow(function() { task.helper('nonexistent'); }, 'It should not throw an exception because an error handler is defined.'); + test.deepEqual(result.get(), [null], 'Non-nested tasks have a null name.'); + test.done(); + }, + 'Task#renameHelper': function(test) { + test.expect(4); + var task = this.task; + task.renameHelper('add', 'newadd'); + test.ok('newadd' in task._helpers, 'It should rename the specified helper.'); + test.equal('add' in task._helpers, false, 'It should remove the previous helper.'); + test.doesNotThrow(function() { task.helper('newadd'); }, 'It should be accessible by its new name.'); + test.throws(function() { task.helper('add'); }, 'It should not be accessible by its previous name.'); + test.done(); + } +}; + +exports['Directives'] = { + setUp: function(done) { + this.task = requireTask().create(); + this.task.registerHelper('add', function(a, b) { return Number(a) + Number(b); }); + done(); + }, + 'Task#getDirectiveParts': function(test) { + test.expect(8); + var task = this.task; + test.deepEqual(task.getDirectiveParts(''), ['add'], 'It should split a directive into parts.'); + test.deepEqual(task.getDirectiveParts(''), ['add', '1'], 'It should split a directive into parts.'); + test.deepEqual(task.getDirectiveParts(''), ['add', '1', '2'], 'It should split a directive into parts.'); + test.deepEqual(task.getDirectiveParts(''), null, 'It should return null if the directive does not match an existing helper.'); + test.deepEqual(task.getDirectiveParts(''), null, 'It should return null if the directive does not match an existing helper.'); + test.deepEqual(task.getDirectiveParts('x'), null, 'It should return null otherwise.'); + test.deepEqual(task.getDirectiveParts('x'), null, 'It should return null otherwise.'); + test.deepEqual(task.getDirectiveParts('<--arrow!'), null, 'It should return null otherwise.'); + test.done(); + }, + 'Task#directive': function(test) { + test.expect(13); + var task = this.task; + var fn = function(val) { return '_' + val + '_'; }; + test.equal(task.directive('foo'), 'foo', 'If a directive is not passed, it should return the passed value.'); + test.equal(task.directive('foo', fn), '_foo_', 'If a directive is not passed, the value should be passed through the specified callback.'); + test.equal(task.directive(''), '', 'If a directive is passed but not found, it should return the passed value.'); + test.equal(task.directive('', fn), '__', 'If a directive is passed but not found, the value should be passed through the specified callback.'); + test.equal(task.directive(''), 3, 'If a directive is passed and found, it should call the directive with arguments.'); + + task.registerHelper('call_as_helper', function(a, b) { + test.ok(!this.directive, 'should not indicate the helper was called as a directive'); + test.deepEqual(this.args, [1, 2], 'Should be an array of args.'); + test.deepEqual(this.flags, {'1': true, '2': true}, 'Should be a map of flags.'); + return a + b; + }); + test.equal(task.helper('call_as_helper', 1, 2), 3, 'Should receive the proper arguments (and return the proper result).'); + + task.registerHelper('call_as_directive', function(a, b) { + test.ok(this.directive, 'should indicate the helper was called as a directive'); + test.deepEqual(this.args, ['1', '2'], 'Should be an array of args.'); + test.deepEqual(this.flags, {'1': true, '2': true}, 'Should be a map of flags.'); + return Number(a) + Number(b); + }); + test.equal(task.directive(''), 3, 'Should receive the proper arguments (and return the proper result).'); + test.done(); + } +}; + +exports['Tasks'] = { + setUp: function(done) { + result.reset(); + this.task = requireTask().create(); + var task = this.task; + task.registerTask('nothing', 'Do nothing.', function() {}); + done(); + }, + 'Task#registerTask': function(test) { + test.expect(1); + var task = this.task; + test.ok('nothing' in task._tasks, 'It should register the passed task.'); + test.done(); + }, + 'Task#registerTask (alias)': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name onto result.', result.pushTaskname); + task.registerTask('b', 'Push task name onto result.', result.pushTaskname); + task.registerTask('c', 'Push task name onto result.', result.pushTaskname); + task.registerTask('x', 'a b c'); + task.registerTask('y', ['a', 'b', 'c']); + task.registerTask('z', 'a b nonexistent c'); + task.options({ + error: function(e) { + result.push('!' + this.name); + }, + done: function() { + test.strictEqual(result.getJoined(), 'abcabc!z', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('x y z').start(); + }, + 'Task#isTaskAlias': function(test) { + test.expect(2); + var task = this.task; + task.registerTask('a', 'nothing', function() {}); + task.registerTask('b', 'nothing', function() {}); + task.registerTask('c', 'a b'); + test.strictEqual(task.isTaskAlias('a'), false, 'It should not be an alias.'); + test.strictEqual(task.isTaskAlias('c'), true, 'It should be an alias.'); + test.done(); + }, + 'Task#renameTask': function(test) { + test.expect(4); + var task = this.task; + task.renameTask('nothing', 'newnothing'); + test.ok('newnothing' in task._tasks, 'It should rename the specified task.'); + test.equal('nothing' in task._tasks, false, 'It should remove the previous task.'); + test.doesNotThrow(function() { task.run('newnothing'); }, 'It should be accessible by its new name.'); + test.throws(function() { task.run('nothing'); }, 'It should not be accessible by its previous name and throw an exception.'); + test.done(); + }, + 'Task#run (exception handling)': function(test) { + test.expect(4); + var task = this.task; + test.doesNotThrow(function() { task.run('nothing'); }, 'Registered tasks should be runnable.'); + test.throws(function() { task.run('nonexistent'); }, 'Attempting to run unregistered tasks should throw an exception.'); + task.options({ + error: result.pushTaskname + }); + test.doesNotThrow(function() { task.run('nonexistent'); }, 'It should not throw an exception because an error handler is defined.'); + test.deepEqual(result.get(), [null], 'Non-nested tasks have a null name.'); + test.done(); + }, + 'Task#run (nested, exception handling)': function(test) { + test.expect(2); + var task = this.task; + task.registerTask('yay', 'Run a registered task.', function() { + test.doesNotThrow(function() { task.run('nothing'); }, 'Registered tasks should be runnable.'); + }); + task.registerTask('nay', 'Attempt to run an unregistered task.', function() { + test.throws(function() { task.run('nonexistent'); }, 'Attempting to run unregistered tasks should throw an exception.'); + }); + task.options({ + done: test.done + }); + task.run('yay nay').start(); + }, + 'Task#run (signatures, queue order)': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name onto result.', result.pushTaskname); + task.registerTask('b', 'Push task name onto result.', result.pushTaskname); + task.registerTask('c', 'Push task name onto result.', result.pushTaskname); + task.registerTask('d', 'Push task name onto result.', result.pushTaskname); + task.registerTask('e', 'Push task name onto result.', result.pushTaskname); + task.registerTask('f', 'Push task name onto result.', result.pushTaskname); + task.registerTask('g', 'Push task name onto result.', result.pushTaskname); + task.options({ + done: function() { + test.strictEqual(result.getJoined(), 'abcdefg', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('a').run('b', 'c').run(['d', 'e']).run('f g').start(); + }, + 'Task#run (colon separated arguments)': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name and args onto result.', function(x, y) { result.push([1, this.name, this.nameArgs, x, y]); }); + task.registerTask('a:b', 'Push task name and args onto result.', function(x, y) { result.push([2, this.name, this.nameArgs, x, y]); }); + task.registerTask('a:b:c', 'Push task name and args onto result.', function(x, y) { result.push([3, this.name, this.nameArgs, x, y]); }); + task.options({ + done: function() { + test.deepEqual(result.get(), [ + [1, 'a', 'a', undefined, undefined], + [2, 'a:b', 'a:b', undefined, undefined], + [3, 'a:b:c', 'a:b:c', undefined, undefined], + [1, 'a', 'a:x', 'x', undefined], + [1, 'a', 'a:x:y', 'x', 'y'], + [2, 'a:b', 'a:b:x', 'x', undefined], + [2, 'a:b', 'a:b:x:y', 'x', 'y'] + ], 'Named tasks should be called as-specified if possible, and arguments should be passed properly.'); + test.done(); + } + }); + task.run('a a:b a:b:c a:x a:x:y a:b:x a:b:x:y').start(); + }, + 'Task#run (nested tasks, queue order)': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name onto result and run other tasks.', function() { result.push(this.name); task.run('b e'); }); + task.registerTask('b', 'Push task name onto result and run other tasks.', function() { result.push(this.name); task.run('c d'); }); + task.registerTask('c', 'Push task name onto result.', result.pushTaskname); + task.registerTask('d', 'Push task name onto result.', result.pushTaskname); + task.registerTask('e', 'Push task name onto result and run other tasks.', function() { result.push(this.name); task.run('f'); }); + task.registerTask('f', 'Push task name onto result.', result.pushTaskname); + task.registerTask('g', 'Push task name onto result.', result.pushTaskname); + task.options({ + done: function() { + test.strictEqual(result.getJoined(), 'abcdefg', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('a g').start(); + }, + 'Task#run (async, nested tasks, queue order)': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name onto result and run other tasks.', function() { result.push(this.name); task.run('b e'); delay(this.async()); }); + task.registerTask('b', 'Push task name onto result and run other tasks.', function() { result.push(this.name); delay(this.async()); task.run('c d'); }); + task.registerTask('c', 'Push task name onto result.', result.pushTaskname); + task.registerTask('d', 'Push task name onto result.', result.pushTaskname); + task.registerTask('e', 'Push task name onto result and run other tasks.', function() { delay(this.async()); result.push(this.name); task.run('f'); }); + task.registerTask('f', 'Push task name onto result.', result.pushTaskname); + task.registerTask('g', 'Push task name onto result.', result.pushTaskname); + task.options({ + done: function() { + test.strictEqual(result.getJoined(), 'abcdefg', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('a g').start(); + }, + 'Task#current': function(test) { + test.expect(8); + var task = this.task; + test.deepEqual(task.current, {}, 'Should start empty.'); + task.registerTask('a', 'Sample task.', function() { + test.equal(task.current, this, 'This and task.current should be the same object.'); + test.equal(task.current.nameArgs, 'a:b:c', 'Should be task name + args, as-specified.'); + test.equal(task.current.name, 'a', 'Should be just the task name, no args.'); + test.equal(typeof task.current.async, 'function', 'Should be a function.'); + test.deepEqual(task.current.args, ['b', 'c'], 'Should be an array of args.'); + test.deepEqual(task.current.flags, {b: true, c: true}, 'Should be a map of flags.'); + }); + task.options({ + done: function() { + test.deepEqual(task.current, {}, 'Should be empty again once tasks are done.'); + test.done(); + } + }); + task.run('a:b:c').start(); + }, + 'Task#clearQueue': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('a', 'Push task name onto result.', result.pushTaskname); + task.registerTask('b', 'Push task name onto result.', result.pushTaskname); + task.registerTask('c', 'Clear the queue.', function() { + result.push(this.name); + task.clearQueue().run('f'); + }); + task.registerTask('d', 'Push task name onto result.', result.pushTaskname); + task.registerTask('e', 'Push task name onto result.', result.pushTaskname); + task.registerTask('f', 'Push task name onto result.', result.pushTaskname); + task.options({ + done: function() { + test.strictEqual(result.getJoined(), 'abcf', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('a b c d e').start(); + }, + 'Task#mark': function(test) { + // test.expect(1); + var task = this.task; + task.registerTask('a', 'Explode.', function() { + throw task.taskError('whoops.'); + }); + task.registerTask('b', 'This task should never run.', result.pushTaskname); + task.registerTask('c', 'This task should never run.', result.pushTaskname); + + task.registerTask('d', 'Push task name onto result.', result.pushTaskname); + task.registerTask('e', 'Explode.', function() { + throw task.taskError('whoops.'); + }); + task.registerTask('f', 'This task should never run.', result.pushTaskname); + + task.registerTask('g', 'Push task name onto result.', result.pushTaskname); + task.registerTask('h', 'Push task name onto result.', result.pushTaskname); + task.registerTask('i', 'Explode.', function() { + throw task.taskError('whoops.'); + }); + + task.registerTask('j', 'Run a task and push task name onto result.', function() { + task.run('k'); + result.push(this.name); + }); + task.registerTask('k', 'Explode.', function() { + throw task.taskError('whoops.'); + }); + task.registerTask('l', 'This task should never run.', result.pushTaskname); + + task.registerTask('m', 'Push task name onto result.', result.pushTaskname); + task.registerTask('n', 'Run a task and push task name onto result.', function() { + task.run('o'); + result.push(this.name); + }); + task.registerTask('o', 'Explode.', function() { + throw task.taskError('whoops.'); + }); + + task.registerTask('p', 'Push task name onto result.', result.pushTaskname); + + task.options({ + error: function(e) { + result.push('!' + this.name); + task.clearQueue({untilMarker: true}); + }, + done: function() { + test.strictEqual(result.getJoined(), '!ad!egh!ij!kmn!op', 'The specified tasks should have run, in-order.'); + test.done(); + } + }); + task.run('a b c').mark().run('d e f').mark().run('g h i').mark().run('j l').mark().run('m n').mark().run('p').mark().start(); + }, + 'Task#requires': function(test) { + test.expect(1); + var task = this.task; + task.registerTask('notrun', 'This task is never run.', function() {}); + task.registerTask('a', 'Push task name onto result, but fail.', function() { + result.push(this.name); + return false; + }); + task.registerTask('b', 'Push task name onto result, but fail.', function() { + delay(this.async().bind(this, false)); + result.push(this.name); + }); + task.registerTask('c', 'Succeed.', result.pushTaskname); + task.registerTask('d', 'Succeed.', result.pushTaskname); + task.registerTask('e', 'Succeed because all required tasks ran and succeeded.', function() { + task.requires('c d'); + result.push(this.name); + }); + task.registerTask('x', 'Fail because a required task never ran.', function() { + task.requires('c notrun d'); + result.push(this.name); + }); + task.registerTask('y', 'Fail because a synchronous required task has failed.', function() { + task.requires('a c d'); + result.push(this.name); + }); + task.registerTask('z', 'Fail because an asynchronous required task has failed.', function() { + task.requires('b c d'); + result.push(this.name); + }); + task.options({ + error: function(e) { + result.push('!' + this.name); + }, + done: function() { + test.strictEqual(result.getJoined(), 'a!ab!bcde!x!y!z', 'Tasks whose requirements have failed or are missing should not run.'); + test.done(); + } + }); + task.run('a b c d e x y z').start(); + } +}; + +exports['Task#parseArgs'] = { + setUp: function(done) { + var task = requireTask().create(); + this.parseTest = function() { + return task.parseArgs(arguments); + }; + done(); + }, + 'single task string': function(test) { + test.expect(1); + test.deepEqual(this.parseTest('foo'), ['foo'], 'string should be split into array.'); + test.done(); + }, + 'multiple task string': function(test) { + test.expect(1); + test.deepEqual(this.parseTest('foo bar baz'), ['foo', 'bar', 'baz'], 'string should be split into array.'); + test.done(); + }, + 'arguments': function(test) { + test.expect(1); + test.deepEqual(this.parseTest('foo', 'bar', 'baz'), ['foo', 'bar', 'baz'], 'arguments should be converted to array.'); + test.done(); + }, + 'array': function(test) { + test.expect(1); + test.deepEqual(this.parseTest(['foo', 'bar', 'baz']), ['foo', 'bar', 'baz'], 'passed array should be used.'); + test.done(); + }, + 'object': function(test) { + test.expect(1); + var obj = {}; + test.deepEqual(this.parseTest(obj), [obj], 'single object should be returned as array.'); + test.done(); + }, + 'nothing': function(test) { + test.expect(1); + test.deepEqual(this.parseTest(), [], 'should return an empty array if nothing passed.'); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/package.json b/node_modules/grunt-coffee/package.json new file mode 100644 index 0000000..527bf27 --- /dev/null +++ b/node_modules/grunt-coffee/package.json @@ -0,0 +1,79 @@ +{ + "name": "grunt-coffee", + "description": "JavaScripts your Coffee", + "version": "0.0.6", + "homepage": "https://github.com/avalade/grunt-coffee", + "author": { + "name": "Aaron D. Valade", + "email": "adv@alum.mit.edu" + }, + "contributors": [ + { + "name": "Derek Lindahl", + "url": "https://github.com/dlindahl" + }, + { + "name": "Tim Oxley", + "url": "https://github.com/timoxley" + }, + { + "name": "Pete Bacon Darwin", + "url": "https://github.com/petebacondarwin" + }, + { + "name": "Kevin Rockwood", + "url": "https://github.com/rockwood" + }, + { + "name": "Ken 'Elf' Matheiu Sternberg", + "url": "https://github.com/elfsternberg" + }, + { + "name": "siriux", + "url": "https://github.com/siriux" + }, + { + "name": "Enleur", + "url": "https://github.com/Enleur" + }, + { + "name": "brewster1134", + "url": "https://github.com/brewster1134" + } + ], + "repository": { + "type": "git", + "url": "git://github.com/avalade/grunt-coffee.git" + }, + "bugs": { + "url": "https://github.com/avalade/grunt-coffee/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/avalade/grunt-coffee/blob/master/LICENSE-MIT" + } + ], + "main": "grunt.js", + "engines": { + "node": "*" + }, + "scripts": { + "test": "grunt test" + }, + "dependencies": { + "grunt": "~0.3.8", + "coffee-script": "~1.3.1" + }, + "devDependencies": { + "grunt": "~0.3.8", + "coffee-script": "~1.3.1" + }, + "keywords": [ + "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", + "_from": "grunt-coffee" +} diff --git a/node_modules/grunt-coffee/tasks/coffee.js b/node_modules/grunt-coffee/tasks/coffee.js new file mode 100644 index 0000000..68ee8e2 --- /dev/null +++ b/node_modules/grunt-coffee/tasks/coffee.js @@ -0,0 +1,82 @@ +/* + * grunt-coffee + * https://github.com/avalade/grunt-coffee + * + * Copyright (c) 2012 Aaron D. Valade + * Licensed under the MIT license. + */ + +module.exports = function(grunt) { + var path = require('path'); + + // Please see the grunt documentation for more information regarding task and + // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md + + // ========================================================================== + // TASKS + // ========================================================================== + + grunt.registerMultiTask('coffee', 'Compile CoffeeScript files', function() { + var dest = this.file.dest, + options = this.data.options, + extension = this.data.extension; + + grunt.file.expandFiles(this.file.src).forEach(function(filepath) { + grunt.helper('coffee', filepath, dest, grunt.utils._.clone(options), extension); + }); + + if (grunt.task.current.errorCount) { + return false; + } else { + return true; + } + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + grunt.registerHelper('coffee', function(src, destPath, options, extension) { + var coffee = require('coffee-script'), + js = ''; + + options = options || {}; + extension = typeof extension === "undefined" ? '.js' : extension; + + if( destPath && options.preserve_dirs ){ + var dirname = path.dirname(src); + if ( options.base_path ) { + dirname = dirname.replace(new RegExp('^'+options.base_path), ''); + } + destPath = path.join(destPath, dirname); + } else if( !destPath ){ + destPath = path.dirname(src); + } + + var dest = path.join(destPath, path.basename(src, '.coffee') + extension); + + // De-dup dest if we have .js.js - see issue #16 + if (dest.match(/\.js\.js/)) { + dest = dest.replace(/\.js\.js/, ".js"); + } + + if (path.extname(src) === '.js') { + grunt.file.copy(src, dest); + return true; + } + + if( options.bare !== false ) { + options.bare = true; + } + + try { + js = coffee.compile(grunt.file.read(src), options); + grunt.file.write(dest, js); + return true; + } catch (e) { + grunt.log.error("Error in " + src + ":\n" + e); + return false; + } + }); + +}; diff --git a/node_modules/grunt-coffee/test/coffee_test.js b/node_modules/grunt-coffee/test/coffee_test.js new file mode 100644 index 0000000..026a42d --- /dev/null +++ b/node_modules/grunt-coffee/test/coffee_test.js @@ -0,0 +1,153 @@ +var grunt = require('grunt'), + fs = require('fs'), + path = require('path'); + +fs.existsSync = fs.existsSync ? fs.existsSync : path.existsSync; + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +var src = 'test/fixtures/hello_world.coffee'; +var dupExtSrc = 'test/fixtures/duplicate_extension.js.coffee'; +var jsSrc = 'test/fixtures/js_hello_world.js'; +var outputFolder = 'tmp/js'; +var expectedJSFile = 'test/fixtures/hello_world.js'; + +exports['coffee'] = { + setUp: function(done) { + done(); + }, + + tearDown: function(done) { + /** A simple rm -rf function **/ + var rmFiles = function(filesToDelete) { + function helper(filesToDelete) { + if (filesToDelete.length === 0) { + return; + } + + var file = filesToDelete.shift(); + var stats = fs.statSync(file); + if (stats.isDirectory()) { + var subfiles = fs.readdirSync(file); + for (var i = 0; i < subfiles.length; i++) { + filesToDelete.push(path.join(file, subfiles[i])); + } + } else { + fs.unlinkSync(file); + if (fs.readdirSync(path.dirname(file)).length === 0) { + fs.rmdirSync(path.dirname(file)); + } + } + helper(filesToDelete); + } + + helper(filesToDelete); + }; + + if (fs.existsSync(expectedJSFile)) { + fs.unlinkSync(expectedJSFile); + } + + if (fs.existsSync(outputFolder)) { + rmFiles([outputFolder]); + } + done(); + }, + + 'helper': function(test) { + test.expect(2); + + grunt.helper('coffee', [src], outputFolder); + test.equal(grunt.file.read(outputFolder + '/hello_world.js'), + '\nconsole.log("Hello CoffeeScript!");\n', + 'it should compile the coffee'); + + grunt.helper('coffee', [src], outputFolder, { bare:false }); + test.equal(grunt.file.read(outputFolder + '/hello_world.js'), + '(function() {\n\n console.log("Hello CoffeeScript!");\n\n}).call(this);\n', + 'it should compile the coffee'); + + test.done(); + }, + + 'helper-nodest': function(test) { + test.expect(1); + grunt.helper('coffee', [src]); + test.equal(grunt.file.read(expectedJSFile), + '\nconsole.log("Hello CoffeeScript!");\n', + 'it should compile the coffee'); + test.done(); + }, + + 'helper-dirs': function(test) { + test.expect(1); + grunt.helper('coffee', [src], outputFolder, { preserve_dirs:true }); + test.equal(grunt.file.read(path.join(outputFolder, expectedJSFile)), + '\nconsole.log("Hello CoffeeScript!");\n', + 'it should compile the coffee'); + test.done(); + }, + + 'helper-dirs-base': function(test) { + var base = 'test'; + test.expect(1); + grunt.helper('coffee', + [src], + outputFolder, + { + preserve_dirs:true, + base_path:base + }); + test.equal( + grunt.file.read( + path.join(outputFolder, expectedJSFile.replace(new RegExp('^'+base), '')) + ), + '\nconsole.log("Hello CoffeeScript!");\n', + 'it should compile the coffee'); + test.done(); + }, + + 'helper-extension': function(test) { + test.expect(1); + grunt.helper('coffee', [src], outputFolder, {}, '.coffee.js'); + test.ok(fs.existsSync(path.join(outputFolder, "hello_world.coffee.js"))); + test.done(); + }, + + 'helper-duplicate-extension': function(test) { + test.expect(1); + grunt.helper('coffee', [dupExtSrc], outputFolder, {}); + test.ok(fs.existsSync(path.join(outputFolder, "duplicate_extension.js"))); + test.done(); + }, + + 'helper-js-file-passthrough': function(test) { + test.expect(2); + grunt.helper('coffee', [jsSrc], outputFolder, {preserve_dirs: true}); + test.ok(fs.existsSync(path.join(outputFolder, jsSrc))); + test.equal( + grunt.file.read(path.join(outputFolder, jsSrc)), + 'console.log("Hello world!");\n', + 'it should just copy javascript files' + ); + test.done(); + } +}; diff --git a/node_modules/grunt-coffee/test/fixtures/duplicate_extension.js.coffee b/node_modules/grunt-coffee/test/fixtures/duplicate_extension.js.coffee new file mode 100644 index 0000000..35c84fe --- /dev/null +++ b/node_modules/grunt-coffee/test/fixtures/duplicate_extension.js.coffee @@ -0,0 +1 @@ +console.log "Hello CoffeeScript!" diff --git a/node_modules/grunt-coffee/test/fixtures/hello_world.coffee b/node_modules/grunt-coffee/test/fixtures/hello_world.coffee new file mode 100644 index 0000000..35c84fe --- /dev/null +++ b/node_modules/grunt-coffee/test/fixtures/hello_world.coffee @@ -0,0 +1 @@ +console.log "Hello CoffeeScript!" diff --git a/node_modules/grunt-coffee/test/fixtures/js_hello_world.js b/node_modules/grunt-coffee/test/fixtures/js_hello_world.js new file mode 100644 index 0000000..940a3ff --- /dev/null +++ b/node_modules/grunt-coffee/test/fixtures/js_hello_world.js @@ -0,0 +1 @@ +console.log("Hello world!"); diff --git a/node_modules/grunt-mocha/.npmignore b/node_modules/grunt-mocha/.npmignore new file mode 100644 index 0000000..60c4f0c --- /dev/null +++ b/node_modules/grunt-mocha/.npmignore @@ -0,0 +1,16 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +npm-debug.log +.DS_Store \ No newline at end of file diff --git a/node_modules/grunt-mocha/HISTORY.md b/node_modules/grunt-mocha/HISTORY.md new file mode 100644 index 0000000..c4bb5d7 --- /dev/null +++ b/node_modules/grunt-mocha/HISTORY.md @@ -0,0 +1,29 @@ +# 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 + +# 0.1.2 +* Added example for non-AMD usage. Modified mocha-helper to be included in page (optional) +* Added duration + +# 0.1.1 + +* Consistency +* Make growl optional + +# 0.1.0 + +init \ No newline at end of file diff --git a/node_modules/grunt-mocha/LICENSE-MIT b/node_modules/grunt-mocha/LICENSE-MIT new file mode 100644 index 0000000..887a2f1 --- /dev/null +++ b/node_modules/grunt-mocha/LICENSE-MIT @@ -0,0 +1,23 @@ +Copyright (c) 2012 Kelly Miyashiro +Copyright (c) 2012 "Cowboy" Ben Alman + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/grunt-mocha/README.md b/node_modules/grunt-mocha/README.md new file mode 100644 index 0000000..cfef80a --- /dev/null +++ b/node_modules/grunt-mocha/README.md @@ -0,0 +1,100 @@ +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](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 + +### 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). + +In this case you shouldn't include `mocha-helper.js` (it will be included automatically) and tests will be run from `mocha-helper.js`. + +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 + +### Grunt and this plugin + +First, make sure you have grunt installed globally, `npm install grunt -g` + +Install 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` + +Then add this line to your project's `grunt.js` gruntfile at the bottom: + +```javascript +grunt.loadNpmTasks('grunt-mocha'); +``` + +Also add this to the ```grunt.initConfig``` object in the same file: + +```javascript +mocha: { + index: ['specs/index.html'] +}, +``` + +Replace ```specs/index.html``` with the location of your mocha spec running html file. + +Now you can run the mocha task with `grunt mocha`, but it won't work. That's because you need... + +### PhantomJS + +This 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). + +### Mocha + +Use [Mocha](http://visionmedia.github.com/mocha/) + +### Maybe Growl? + +Growl support is optional. I'm not sure what the Windows situation is with growl. + +### Hacks + +The 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. + +## License +Copyright (c) 2012 Kelly Miyashiro +Licensed under the MIT license. \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/grunt.js b/node_modules/grunt-mocha/example/grunt.js new file mode 100644 index 0000000..07f03db --- /dev/null +++ b/node_modules/grunt-mocha/example/grunt.js @@ -0,0 +1,83 @@ +/*global config:true, task:true*/ +module.exports = function(grunt) { + // Grunt utilities. + var task = grunt.task; + var file = grunt.file; + var utils = grunt.utils; + var log = grunt.log; + var verbose = grunt.verbose; + var fail = grunt.fail; + var option = grunt.option; + var config = grunt.config; + var template = grunt.template; + + grunt.initConfig({ + options: { + testFiles: [ + 'js/model/**/*.js', + 'js/collection/**/*.js', + 'js/router/**/*.js', + 'js/view/**/*.js', + 'js/libs/acme/**/*.js' + ] + }, + test: { + files: ['test/**/*.js'] + }, + watch: { + // Just for example: + // testAdmin: { + // files: [ + // '', + // 'test/admin/specs/*.js' + // ], + // tasks: 'mocha' + // }, + + // If you want to watch files and run tests automatically on change + test: { + files: [ 'js/**/*.js', 'test/spec/**/*.js' ], + tasks: 'mocha' + } + }, + 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 + mocha: { + ignoreLeaks: false, + grep: 'food' + }, + + // Indicates whether 'mocha.run()' should be executed in + // 'mocha-helper.js' + run: true + } + } + }); + + // @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/js/apple.js b/node_modules/grunt-mocha/example/js/apple.js new file mode 100644 index 0000000..2ea2ed6 --- /dev/null +++ b/node_modules/grunt-mocha/example/js/apple.js @@ -0,0 +1,9 @@ +var Apple = function(opts) { + opts = opts || {}; + + this.name = opts.name || 'Fuji'; + + this.sound = opts.sound || 'crunch'; + + return this; +} \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/js/wombat.js b/node_modules/grunt-mocha/example/js/wombat.js new file mode 100644 index 0000000..59e4778 --- /dev/null +++ b/node_modules/grunt-mocha/example/js/wombat.js @@ -0,0 +1,13 @@ +var Wombat = function(opts) { + opts = opts || {}; + + this.name = opts.name || 'Wally'; + + this.eat = function(food) { + if (!food) throw Error('D:'); + + return 'nom nom'; + } + + return this; +}; \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/test/css/mocha.css b/node_modules/grunt-mocha/example/test/css/mocha.css new file mode 100644 index 0000000..8076d0e --- /dev/null +++ b/node_modules/grunt-mocha/example/test/css/mocha.css @@ -0,0 +1,199 @@ +@charset "UTF-8"; +body { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 60px 50px; +} + +#mocha ul, #mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, #mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; +} + +#mocha .test:hover h2::after { + position: relative; + top: 0; + right: -10px; + content: '(view source)'; + font-size: 12px; + font-family: arial; + color: #888; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial; +} + +#mocha .test.pass.medium .duration { + background: #C09853; +} + +#mocha .test.pass.slow .duration { + background: #B94A48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: white; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; +} + +#mocha .test pre { + display: inline-block; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; +} + +#report.pass .test.fail { + display: none; +} + +#report.fail .test.pass { + display: none; +} + +#error { + color: #c00; + font-size: 1.5 em; + font-weight: 100; + letter-spacing: 1px; +} + +#stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; +} + +#stats .progress { + float: right; + padding-top: 0; +} + +#stats em { + color: black; +} + +#stats a { + text-decoration: none; + color: inherit; +} + +#stats a:hover { + border-bottom: 1px solid #eee; +} + +#stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/test/js/chai.js b/node_modules/grunt-mocha/example/test/js/chai.js new file mode 100644 index 0000000..d263fab --- /dev/null +++ b/node_modules/grunt-mocha/example/test/js/chai.js @@ -0,0 +1,3470 @@ +!function (name, context, definition) { + if (typeof module !== 'undefined') module.exports = definition(name, context); + else if (typeof define === 'function' && typeof define.amd === 'object') define(definition); + else context[name] = definition(name, context); +}('chai', this, function (name, context) { + + + function require(p) { + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + + require.modules = {}; + + require.resolve = function (path) { + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + + require.register = function (path, fn) { + require.modules[path] = fn; + }; + + require.relative = function (parent) { + return function(p){ + if ('.' != p[0]) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + require.alias = function (from, to) { + var fn = require.modules[from]; + require.modules[to] = fn; + }; + + + require.register("chai.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + var used = [] + , exports = module.exports = {}; + + /*! + * Chai version + */ + + exports.version = '1.1.0'; + + /*! + * Primary `Assertion` prototype + */ + + exports.Assertion = require('./chai/assertion'); + + /*! + * Assertion Error + */ + + exports.AssertionError = require('./chai/browser/error'); + + /*! + * Utils for plugins (not exported) + */ + + var util = require('./chai/utils'); + + /** + * # .use(function) + * + * Provides a way to extend the internals of Chai + * + * @param {Function} + * @returns {this} for chaining + * @api public + */ + + exports.use = function (fn) { + if (!~used.indexOf(fn)) { + fn(this, util); + used.push(fn); + } + + return this; + }; + + /*! + * Core Assertions + */ + + var core = require('./chai/core/assertions'); + exports.use(core); + + /*! + * Expect interface + */ + + var expect = require('./chai/interface/expect'); + exports.use(expect); + + /*! + * Should interface + */ + + var should = require('./chai/interface/should'); + exports.use(should); + + /*! + * Assert interface + */ + + var assert = require('./chai/interface/assert'); + exports.use(assert); + + }); // module: chai.js + + require.register("chai/assertion.js", function(module, exports, require){ + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies. + */ + + var AssertionError = require('./browser/error') + , util = require('./utils') + , flag = util.flag; + + /*! + * Module export. + */ + + module.exports = Assertion; + + + /*! + * Assertion Constructor + * + * Creates object for chaining. + * + * @api private + */ + + function Assertion (obj, msg, stack) { + flag(this, 'ssfi', stack || arguments.callee); + flag(this, 'object', obj); + flag(this, 'message', msg); + } + + /*! + * ### Assertion.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message + * + * Assertion.includeStack = true; // enable stack on error + * + * @api public + */ + + Assertion.includeStack = false; + + Assertion.addProperty = function (name, fn) { + util.addProperty(this.prototype, name, fn); + }; + + Assertion.addMethod = function (name, fn) { + util.addMethod(this.prototype, name, fn); + }; + + Assertion.addChainableMethod = function (name, fn, chainingBehavior) { + util.addChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + Assertion.overwriteProperty = function (name, fn) { + util.overwriteProperty(this.prototype, name, fn); + }; + + Assertion.overwriteMethod = function (name, fn) { + util.overwriteMethod(this.prototype, name, fn); + }; + + /*! + * ### .assert(expression, message, negateMessage, expected, actual) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String} message to display if fails + * @param {String} negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @api private + */ + + Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual) { + var msg = util.getMessage(this, arguments) + , actual = util.getActual(this, arguments) + , ok = util.test(this, arguments); + + if (!ok) { + throw new AssertionError({ + message: msg + , actual: actual + , expected: expected + , stackStartFunction: (Assertion.includeStack) ? this.assert : flag(this, 'ssfi') + }); + } + }; + + /*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */ + + Object.defineProperty(Assertion.prototype, '_obj', + { get: function () { + return flag(this, 'object'); + } + , set: function (val) { + flag(this, 'object', val); + } + }); + + }); // module: chai/assertion.js + + require.register("chai/browser/error.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = AssertionError; + + function AssertionError (options) { + options = options || {}; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + + if (options.stackStartFunction && Error.captureStackTrace) { + var stackStartFunction = options.stackStartFunction; + Error.captureStackTrace(this, stackStartFunction); + } + } + + AssertionError.prototype = Object.create(Error.prototype); + AssertionError.prototype.name = 'AssertionError'; + AssertionError.prototype.constructor = AssertionError; + + AssertionError.prototype.toString = function() { + return this.message; + }; + + }); // module: chai/browser/error.js + + require.register("chai/core/assertions.js", function(module, exports, require){ + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, _) { + var Assertion = chai.Assertion + , toString = Object.prototype.toString + , flag = _.flag; + + /** + * ### Language Chains + * + * The following are provide as chainable getters to + * improve the readability of your assertions. They + * do not provide an testing capability unless they + * have been overwritten by a plugin. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - and + * - have + * - with + * + * @name language chains + * @api public + */ + + [ 'to', 'be', 'been' + , 'is', 'and', 'have' + , 'with', 'that' ].forEach(function (chain) { + Assertion.addProperty(chain, function () { + return this; + }); + }); + + /** + * ### .not + * + * Negates any of assertions following in the chain. + * + * expect(foo).to.not.equal('bar'); + * expect(goodFn).to.not.throw(Error); + * expect({ foo: 'baz' }).to.have.property('foo') + * .and.not.equal('bar'); + * + * @name not + * @api public + */ + + Assertion.addProperty('not', function () { + flag(this, 'negate', true); + }); + + /** + * ### .deep + * + * Sets the `deep` flag, later used by the `equal` and + * `property` assertions. + * + * expect(foo).to.deep.equal({ bar: 'baz' }); + * expect({ foo: { bar: { baz: 'quux' } } }) + * .to.have.deep.property('foo.bar.baz', 'quux'); + * + * @name deep + * @api public + */ + + Assertion.addProperty('deep', function () { + flag(this, 'deep', true); + }); + + /** + * ### .a(type) + * + * The `a` and `an` assertions are aliases that can be + * used either as language chains or to assert a value's + * type (as revealed by `Object.prototype.toString`). + * + * // typeof + * expect('test').to.be.a('string'); + * expect({ foo: 'bar' }).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * + * // language chain + * expect(foo).to.be.an.instanceof(Foo); + * + * @name a + * @alias an + * @param {String} type + * @api public + */ + + function an(type) { + var obj = flag(this, 'object') + , klassStart = type.charAt(0).toUpperCase() + , klass = klassStart + type.slice(1) + , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a '; + + this.assert( + '[object ' + klass + ']' === toString.call(obj) + , 'expected #{this} to be ' + article + type + , 'expected #{this} not to be ' + article + type + ); + } + + Assertion.addChainableMethod('an', an); + Assertion.addChainableMethod('a', an); + + /** + * ### .include(value) + * + * The `include` and `contain` assertions can be used as either property + * based language chains or as methods to assert the inclusion of an object + * in an array or a substring in a string. When used as language chains, + * they toggle the `contain` flag for the `keys` assertion. + * + * expect([1,2,3]).to.include(2); + * expect('foobar').to.contain('foo'); + * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); + * + * @name include + * @alias contain + * @param {Object|String|Number} obj + * @api public + */ + + function includeChainingBehavior () { + flag(this, 'contains', true); + } + + function include (val) { + var obj = flag(this, 'object') + this.assert( + ~obj.indexOf(val) + , 'expected #{this} to include ' + _.inspect(val) + , 'expected #{this} to not include ' + _.inspect(val)); + } + + Assertion.addChainableMethod('include', include, includeChainingBehavior); + Assertion.addChainableMethod('contain', include, includeChainingBehavior); + + /** + * ### .ok + * + * Asserts that the target is truthy. + * + * expect('everthing').to.be.ok; + * expect(1).to.be.ok; + * expect(false).to.not.be.ok; + * expect(undefined).to.not.be.ok; + * expect(null).to.not.be.ok; + * + * @name ok + * @api public + */ + + Assertion.addProperty('ok', function () { + this.assert( + flag(this, 'object') + , 'expected #{this} to be truthy' + , 'expected #{this} to be falsy'); + }); + + /** + * ### .true + * + * Asserts that the target is `true`. + * + * expect(true).to.be.true; + * expect(1).to.not.be.true; + * + * @name true + * @api public + */ + + Assertion.addProperty('true', function () { + this.assert( + true === flag(this, 'object') + , 'expected #{this} to be true' + , 'expected #{this} to be false' + , this.negate ? false : true + ); + }); + + /** + * ### .false + * + * Asserts that the target is `false`. + * + * expect(false).to.be.false; + * expect(0).to.not.be.false; + * + * @name false + * @api public + */ + + Assertion.addProperty('false', function () { + this.assert( + false === flag(this, 'object') + , 'expected #{this} to be false' + , 'expected #{this} to be true' + , this.negate ? true : false + ); + }); + + /** + * ### .null + * + * Asserts that the target is `null`. + * + * expect(null).to.be.null; + * expect(undefined).not.to.be.null; + * + * @name null + * @api public + */ + + Assertion.addProperty('null', function () { + this.assert( + null === flag(this, 'object') + , 'expected #{this} to be null' + , 'expected #{this} not to be null' + ); + }); + + /** + * ### .undefined + * + * Asserts that the target is `undefined`. + * + * expect(undefined).to.be.undefined; + * expect(null).to.not.be.undefined; + * + * @name undefined + * @api public + */ + + Assertion.addProperty('undefined', function () { + this.assert( + undefined === flag(this, 'object') + , 'expected #{this} to be undefined' + , 'expected #{this} not to be undefined' + ); + }); + + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi' + * , bar = null + * , baz; + * + * expect(foo).to.exist; + * expect(bar).to.not.exist; + * expect(baz).to.not.exist; + * + * @name exist + * @api public + */ + + Assertion.addProperty('exist', function () { + this.assert( + null != flag(this, 'object') + , 'expected #{this} to exist' + , 'expected #{this} to not exist' + ); + }); + + + /** + * ### .empty + * + * Asserts that the target's length is `0`. For arrays, it checks + * the `length` property. For objects, it gets the count of + * enumerable keys. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * expect({}).to.be.empty; + * + * @name empty + * @api public + */ + + Assertion.addProperty('empty', function () { + var obj = flag(this, 'object') + , expected = obj; + + if (Array.isArray(obj) || 'string' === typeof object) { + expected = obj.length; + } else if (typeof obj === 'object') { + expected = Object.keys(obj).length; + } + + this.assert( + !expected + , 'expected #{this} to be empty' + , 'expected #{this} not to be empty' + ); + }); + + /** + * ### .arguments + * + * Asserts that the target is an arguments object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * @name arguments + * @alias Arguments + * @api public + */ + + function checkArguments () { + var obj = flag(this, 'object') + , type = Object.prototype.toString.call(obj); + this.assert( + '[object Arguments]' === type + , 'expected #{this} to be arguments but got ' + type + , 'expected #{this} to not be arguments' + ); + } + + Assertion.addProperty('arguments', checkArguments); + Assertion.addProperty('Arguments', checkArguments); + + /** + * ### .equal(value) + * + * Asserts that the target is strictly equal (`===`) to `value`. + * Alternately, if the `deep` flag is set, asserts that + * the target is deeply equal to `value`. + * + * expect('hello').to.equal('hello'); + * expect(42).to.equal(42); + * expect(1).to.not.equal(true); + * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); + * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); + * + * @name equal + * @alias eq + * @alias deep.equal + * @param {Mixed} value + * @api public + */ + + function assertEqual (val) { + var obj = flag(this, 'object'); + if (flag(this, 'deep')) { + return this.eql(val); + } else { + this.assert( + val === obj + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{exp}' + , val + ); + } + } + + Assertion.addMethod('equal', assertEqual); + Assertion.addMethod('eq', assertEqual); + + /** + * ### .eql(value) + * + * Asserts that the target is deeply equal to `value`. + * + * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); + * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); + * + * @name eql + * @param {Mixed} value + * @api public + */ + + Assertion.addMethod('eql', function (obj) { + this.assert( + _.eql(obj, flag(this, 'object')) + , 'expected #{this} to deeply equal #{exp}' + , 'expected #{this} to not deeply equal #{exp}' + , obj + ); + }); + + /** + * ### .above(value) + * + * Asserts that the target is greater than `value`. + * + * expect(10).to.be.above(5); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} value + * @api public + */ + + function assertAbove (n) { + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len > n + , 'expected #{this} to have a length above #{exp} but got #{act}' + , 'expected #{this} to not have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj > n + , 'expected #{this} to be above ' + n + , 'expected #{this} to be below ' + n + ); + } + } + + Assertion.addMethod('above', assertAbove); + Assertion.addMethod('gt', assertAbove); + Assertion.addMethod('greaterThan', assertAbove); + + /** + * ### .below(value) + * + * Asserts that the target is less than `value`. + * + * expect(5).to.be.below(10); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} value + * @api public + */ + + function assertBelow (n) { + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len < n + , 'expected #{this} to have a length below #{exp} but got #{act}' + , 'expected #{this} to not have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj < n + , 'expected #{this} to be below ' + n + , 'expected #{this} to be above ' + n + ); + } + } + + Assertion.addMethod('below', assertBelow); + Assertion.addMethod('lt', assertBelow); + Assertion.addMethod('lessThan', assertBelow); + + /** + * ### .within(start, finish) + * + * Asserts that the target is within a range. + * + * expect(7).to.be.within(5,10); + * + * Can also be used in conjunction with `length` to + * assert a length range. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name within + * @param {Number} start lowerbound inclusive + * @param {Number} finish upperbound inclusive + * @api public + */ + + Assertion.addMethod('within', function (start, finish) { + var obj = flag(this, 'object') + , range = start + '..' + finish; + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len >= start && len <= finish + , 'expected #{this} to have a length within ' + range + , 'expected #{this} to not have a length within ' + range + ); + } else { + this.assert( + obj >= start && obj <= finish + , 'expected #{this} to be within ' + range + , 'expected #{this} to not be within ' + range + ); + } + }); + + /** + * ### .instanceof(constructor) + * + * Asserts that the target is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , Chai = new Tea('chai'); + * + * expect(Chai).to.be.an.instanceof(Tea); + * expect([ 1, 2, 3 ]).to.be.instanceof(Array); + * + * @name instanceof + * @param {Constructor} constructor + * @alias instanceOf + * @api public + */ + + function assertInstanceOf (constructor) { + var name = _.getName(constructor); + this.assert( + flag(this, 'object') instanceof constructor + , 'expected #{this} to be an instance of ' + name + , 'expected #{this} to not be an instance of ' + name + ); + }; + + Assertion.addMethod('instanceof', assertInstanceOf); + Assertion.addMethod('instanceOf', assertInstanceOf); + + /** + * ### .property(name, [value]) + * + * Asserts that the target has a property `name`, optionally asserting that + * the value of that property is strictly equal to `value`. + * If the `deep` flag is set, you can use dot- and bracket-notation for deep + * references into objects and arrays. + * + * // simple referencing + * var obj = { foo: 'bar' }; + * expect(obj).to.have.property('foo'); + * expect(obj).to.have.property('foo', 'bar'); + * + * // deep referencing + * var deepObj = { + * green: { tea: 'matcha' } + * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] + * }; + + * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); + * + * You can also use an array as the starting point of a `deep.property` + * assertion, or traverse nested arrays. + * + * var arr = [ + * [ 'chai', 'matcha', 'konacha' ] + * , [ { tea: 'chai' } + * , { tea: 'matcha' } + * , { tea: 'konacha' } ] + * ]; + * + * expect(arr).to.have.deep.property('[0][1]', 'matcha'); + * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); + * + * Furthermore, `property` changes the subject of the assertion + * to be the value of that property from the original object. This + * permits for further chainable assertions on that property. + * + * expect(obj).to.have.property('foo') + * .that.is.a('string'); + * expect(deepObj).to.have.property('green') + * .that.is.an('object') + * .that.deep.equals({ tea: 'matcha' }); + * expect(deepObj).to.have.property('teas') + * .that.is.an('array') + * .with.deep.property('[2]') + * .that.deep.equals({ tea: 'konacha' }); + * + * @name property + * @alias deep.property + * @param {String} name + * @param {Mixed} value (optional) + * @returns value of property for chaining + * @api public + */ + + Assertion.addMethod('property', function (name, val) { + var obj = flag(this, 'object') + , value = flag(this, 'deep') ? _.getPathValue(name, obj) : obj[name] + , descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' + , negate = flag(this, 'negate'); + + if (negate && undefined !== val) { + if (undefined === value) { + throw new Error(_.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); + } + } else { + this.assert( + undefined !== value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + , 'expected #{this} to not have ' + descriptor + _.inspect(name)); + } + + if (undefined !== val) { + this.assert( + val === value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' + , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' + , val + , value + ); + } + + flag(this, 'object', value); + }); + + + /** + * ### .ownProperty(name) + * + * Asserts that the target has an own property `name`. + * + * expect('test').to.have.ownProperty('length'); + * + * @name ownProperty + * @alias haveOwnProperty + * @param {String} name + * @api public + */ + + function assertOwnProperty (name) { + var obj = flag(this, 'object'); + this.assert( + obj.hasOwnProperty(name) + , 'expected #{this} to have own property ' + _.inspect(name) + , 'expected #{this} to not have own property ' + _.inspect(name) + ); + } + + Assertion.addMethod('ownProperty', assertOwnProperty); + Assertion.addMethod('haveOwnProperty', assertOwnProperty); + + /** + * ### .length(value) + * + * Asserts that the target's `length` property has + * the expected value. + * + * expect([ 1, 2, 3]).to.have.length(3); + * expect('foobar').to.have.length(6); + * + * Can also be used as a chain precursor to a value + * comparison for the length property. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name length + * @alias lengthOf + * @param {Number} length + * @api public + */ + + function assertLengthChain () { + flag(this, 'doLength', true); + } + + function assertLength (n) { + var obj = flag(this, 'object'); + new Assertion(obj).to.have.property('length'); + var len = obj.length; + + this.assert( + len == n + , 'expected #{this} to have a length of #{exp} but got #{act}' + , 'expected #{this} to not have a length of #{act}' + , n + , len + ); + } + + Assertion.addChainableMethod('length', assertLength, assertLengthChain); + Assertion.addMethod('lengthOf', assertLength, assertLengthChain); + + /** + * ### .match(regexp) + * + * Asserts that the target matches a regular expression. + * + * expect('foobar').to.match(/^foo/); + * + * @name match + * @param {RegExp} RegularExpression + * @api public + */ + + Assertion.addMethod('match', function (re) { + var obj = flag(this, 'object'); + this.assert( + re.exec(obj) + , 'expected #{this} to match ' + re + , 'expected #{this} not to match ' + re + ); + }); + + /** + * ### .string(string) + * + * Asserts that the string target contains another string. + * + * expect('foobar').to.have.string('bar'); + * + * @name string + * @param {String} string + * @api public + */ + + Assertion.addMethod('string', function (str) { + var obj = flag(this, 'object'); + new Assertion(obj).is.a('string'); + + this.assert( + ~obj.indexOf(str) + , 'expected #{this} to contain ' + _.inspect(str) + , 'expected #{this} to not contain ' + _.inspect(str) + ); + }); + + + /** + * ### .keys(key1, [key2], [...]) + * + * Asserts that the target has exactly the given keys, or + * asserts the inclusion of some keys when using the + * `include` or `contain` modifiers. + * + * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); + * + * @name keys + * @alias key + * @param {String...|Array} keys + * @api public + */ + + function assertKeys (keys) { + var obj = flag(this, 'object') + , str + , ok = true; + + keys = keys instanceof Array + ? keys + : Array.prototype.slice.call(arguments); + + if (!keys.length) throw new Error('keys required'); + + var actual = Object.keys(obj) + , len = keys.length; + + // Inclusion + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + + // Strict + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } + + // Key string + if (len > 1) { + keys = keys.map(function(key){ + return _.inspect(key); + }); + var last = keys.pop(); + str = keys.join(', ') + ', and ' + last; + } else { + str = _.inspect(keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; + + // Assertion + this.assert( + ok + , 'expected #{this} to ' + str + , 'expected #{this} to not ' + str + ); + } + + Assertion.addMethod('keys', assertKeys); + Assertion.addMethod('key', assertKeys); + + /** + * ### .throw(constructor) + * + * Asserts that the function target will throw a specific error, or specific type of error + * (as determined using `instanceof`), optionally with a RegExp or string inclusion test + * for the error's message. + * + * var err = new ReferenceError('This is a bad function.'); + * var fn = function () { throw err; } + * expect(fn).to.throw(ReferenceError); + * expect(fn).to.throw(Error); + * expect(fn).to.throw(/bad function/); + * expect(fn).to.not.throw('good function'); + * expect(fn).to.throw(ReferenceError, /bad function/); + * expect(fn).to.throw(err); + * expect(fn).to.not.throw(new RangeError('Out of range.')); + * + * Please note that when a throw expectation is negated, it will check each + * parameter independently, starting with error constructor type. The appropriate way + * to check for the existence of a type of error but for a message that does not match + * is to use `and`. + * + * expect(fn).to.throw(ReferenceError) + * .and.not.throw(/good function/); + * + * @name throw + * @alias throws + * @alias Throw + * @param {ErrorConstructor} constructor + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + function assertThrows (constructor, msg) { + var obj = flag(this, 'object'); + new Assertion(obj).is.a('function'); + + var thrown = false + , desiredError = null + , name = null; + + if (arguments.length === 0) { + msg = null; + constructor = null; + } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { + msg = constructor; + constructor = null; + } else if (constructor && constructor instanceof Error) { + desiredError = constructor; + constructor = null; + msg = null; + } else if (typeof constructor === 'function') { + name = (new constructor()).name; + } else { + constructor = null; + } + + try { + obj(); + } catch (err) { + // first, check desired error + if (desiredError) { + this.assert( + err === desiredError + , 'expected #{this} to throw ' + _.inspect(desiredError) + ' but ' + _.inspect(err) + ' was thrown' + , 'expected #{this} to not throw ' + _.inspect(desiredError) + ); + return this; + } + // next, check constructor + if (constructor) { + this.assert( + err instanceof constructor + , 'expected #{this} to throw ' + name + ' but a ' + err.name + ' was thrown' + , 'expected #{this} to not throw ' + name ); + if (!msg) return this; + } + // next, check message + if (err.message && msg && msg instanceof RegExp) { + this.assert( + msg.exec(err.message) + , 'expected #{this} to throw error matching ' + msg + ' but got ' + _.inspect(err.message) + , 'expected #{this} to throw error not matching ' + msg + ); + return this; + } else if (err.message && msg && 'string' === typeof msg) { + this.assert( + ~err.message.indexOf(msg) + , 'expected #{this} to throw error including #{exp} but got #{act}' + , 'expected #{this} to throw error not including #{act}' + , msg + , err.message + ); + return this; + } else { + thrown = true; + } + } + + var expectedThrown = name ? name : desiredError ? _.inspect(desiredError) : 'an error'; + + this.assert( + thrown === true + , 'expected #{this} to throw ' + expectedThrown + , 'expected #{this} to not throw ' + expectedThrown + ); + }; + + Assertion.addMethod('throw', assertThrows); + Assertion.addMethod('throws', assertThrows); + Assertion.addMethod('Throw', assertThrows); + + /** + * ### .respondTo(method) + * + * Asserts that the object or class target will respond to a method. + * + * Klass.prototype.bar = function(){}; + * expect(Klass).to.respondTo('bar'); + * expect(obj).to.respondTo('bar'); + * + * To check if a constructor will respond to a static function, + * set the `itself` flag. + * + * Klass.baz = function(){}; + * expect(Klass).itself.to.respondTo('baz'); + * + * @name respondTo + * @param {String} method + * @api public + */ + + Assertion.addMethod('respondTo', function (method) { + var obj = flag(this, 'object') + , itself = flag(this, 'itself') + , context = ('function' === typeof obj && !itself) + ? obj.prototype[method] + : obj[method]; + + this.assert( + 'function' === typeof context + , 'expected #{this} to respond to ' + _.inspect(method) + , 'expected #{this} to not respond to ' + _.inspect(method) + ); + }); + + /** + * ### .itself + * + * Sets the `itself` flag, later used by the `respondTo` assertion. + * + * function Foo() {} + * Foo.bar = function() {} + * Foo.prototype.baz = function() {} + * + * expect(Foo).itself.to.respondTo('bar'); + * expect(Foo).itself.not.to.respondTo('baz'); + * + * @name itself + * @api public + */ + + Assertion.addProperty('itself', function () { + flag(this, 'itself', true); + }); + + /** + * ### .satisfy(method) + * + * Asserts that the target passes a given truth test. + * + * expect(1).to.satisfy(function(num) { return num > 0; }); + * + * @name satisfy + * @param {Function} matcher + * @api public + */ + + Assertion.addMethod('satisfy', function (matcher) { + var obj = flag(this, 'object'); + this.assert( + matcher(obj) + , 'expected #{this} to satisfy ' + _.inspect(matcher) + , 'expected #{this} to not satisfy' + _.inspect(matcher) + , this.negate ? false : true + , matcher(obj) + ); + }); + + /** + * ### .closeTo(expected, delta) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * expect(1.5).to.be.closeTo(1, 0.5); + * + * @name closeTo + * @param {Number} expected + * @param {Number} delta + * @api public + */ + + Assertion.addMethod('closeTo', function (expected, delta) { + var obj = flag(this, 'object'); + this.assert( + Math.abs(obj - expected) <= delta + , 'expected #{this} to be close to ' + expected + ' +/- ' + delta + , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta + ); + }); + + }; + + }); // module: chai/core/assertions.js + + require.register("chai/interface/assert.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + + module.exports = function (chai, util) { + + /*! + * Chai dependencies. + */ + + var Assertion = chai.Assertion + , flag = util.flag; + + /*! + * Module export. + */ + + /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @api public + */ + + var assert = chai.assert = function (express, errmsg) { + var test = new Assertion(null); + test.assert( + express + , errmsg + , '[ negation message unavailable ]' + ); + }; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @api public + */ + + assert.fail = function (actual, expected, message, operator) { + throw new chai.AssertionError({ + actual: actual + , expected: expected + , message: message + , operator: operator + , stackStartFunction: assert.fail + }); + }; + + /** + * ### .ok(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.ok('everything', 'everything is ok'); + * assert.ok(false, 'this will fail'); + * + * @name ok + * @param {Mixed} object to test + * @param {String} message + * @api public + */ + + assert.ok = function (val, msg) { + new Assertion(val, msg).is.ok; + }; + + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.equal = function (act, exp, msg) { + var test = new Assertion(act, msg); + + test.assert( + exp == flag(test, 'object') + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{act}' + , exp + , act + ); + }; + + /** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notEqual = function (act, exp, msg) { + var test = new Assertion(act, msg); + + test.assert( + exp != flag(test, 'object') + , 'expected #{this} to not equal #{exp}' + , 'expected #{this} to equal #{act}' + , exp + , act + ); + }; + + /** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.strictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.equal(exp); + }; + + /** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notStrictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.equal(exp); + }; + + /** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.deepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.eql(exp); + }; + + /** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notDeepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.eql(exp); + }; + + /** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isTrue = function (val, msg) { + new Assertion(val, msg).is['true']; + }; + + /** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFalse = function (val, msg) { + new Assertion(val, msg).is['false']; + }; + + /** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNull = function (val, msg) { + new Assertion(val, msg).to.equal(null); + }; + + /** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNull = function (val, msg) { + new Assertion(val, msg).to.not.equal(null); + }; + + /** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isUndefined = function (val, msg) { + new Assertion(val, msg).to.equal(undefined); + }; + + /** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isDefined = function (val, msg) { + new Assertion(val, msg).to.not.equal(undefined); + }; + + /** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFunction = function (val, msg) { + new Assertion(val, msg).to.be.a('function'); + }; + + /** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotFunction = function (val, msg) { + new Assertion(val, msg).to.not.be.a('function'); + }; + + /** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object (as revealed by + * `Object.prototype.toString`). + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isObject = function (val, msg) { + new Assertion(val, msg).to.be.a('object'); + }; + + /** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object. + * + * var selection = 'chai' + * assert.isObject(selection, 'tea selection is not an object'); + * assert.isObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotObject = function (val, msg) { + new Assertion(val, msg).to.not.be.a('object'); + }; + + /** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isArray = function (val, msg) { + new Assertion(val, msg).to.be.an('array'); + }; + + /** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotArray = function (val, msg) { + new Assertion(val, msg).to.not.be.an('array'); + }; + + /** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isString = function (val, msg) { + new Assertion(val, msg).to.be.a('string'); + }; + + /** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotString = function (val, msg) { + new Assertion(val, msg).to.not.be.a('string'); + }; + + /** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @api public + */ + + assert.isNumber = function (val, msg) { + new Assertion(val, msg).to.be.a('number'); + }; + + /** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNumber = function (val, msg) { + new Assertion(val, msg).to.not.be.a('number'); + }; + + /** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isBoolean = function (val, msg) { + new Assertion(val, msg).to.be.a('boolean'); + }; + + /** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotBoolean = function (val, msg) { + new Assertion(val, msg).to.not.be.a('boolean'); + }; + + /** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @api public + */ + + assert.typeOf = function (val, type, msg) { + new Assertion(val, msg).to.be.a(type); + }; + + /** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @api public + */ + + assert.notTypeOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.a(type); + }; + + /** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.instanceOf = function (val, type, msg) { + new Assertion(val, msg).to.be.instanceOf(type); + }; + + /** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.notInstanceOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.instanceOf(type); + }; + + /** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Works + * for strings and arrays. + * + * assert.include('foobar', 'bar', 'foobar contains string "bar"'); + * assert.include([ 1, 2, 3 ], 3, 'array contains value'); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @api public + */ + + assert.include = function (exp, inc, msg) { + var obj = new Assertion(exp, msg); + + if (Array.isArray(exp)) { + obj.to.include(inc); + } else if ('string' === typeof exp) { + obj.to.contain.string(inc); + } + }; + + /** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.match = function (exp, re, msg) { + new Assertion(exp, msg).to.match(re); + }; + + /** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.notMatch = function (exp, re, msg) { + new Assertion(exp, msg).to.not.match(re); + }; + + /** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a property named by `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.property = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.property(prop); + }; + + /** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.property(prop); + }; + + /** + * ### .deepProperty(object, property, [message]) + * + * Asserts that `object` has a property named by `property`, which can be a + * string using dot- and bracket-notation for deep reference. + * + * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name deepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.deepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.deep.property(prop); + }; + + /** + * ### .notDeepProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for deep reference. + * + * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notDeepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notDeepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop); + }; + + /** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.property(prop, val); + }; + + /** + * ### .propertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. + * + * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); + * + * @name propertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.property(prop, val); + }; + + /** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for deep + * reference. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.deep.property(prop, val); + }; + + /** + * ### .deepPropertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. `property` can use dot- and + * bracket-notation for deep reference. + * + * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * + * @name deepPropertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop, val); + }; + + /** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` property with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 5, 'string has length of 6'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @api public + */ + + assert.lengthOf = function (exp, len, msg) { + new Assertion(exp, msg).to.have.length(len); + }; + + /** + * ### .throws(function, [constructor/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * assert.throw(fn, ReferenceError, 'function throws a reference error'); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.Throw = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.Throw(type); + }; + + /** + * ### .doesNotThrow(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * assert.doesNotThrow(fn, Error, 'function does not throw'); + * + * @name doesNotThrow + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.doesNotThrow = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.not.Throw(type); + }; + + /** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @api public + */ + + assert.operator = function (val, operator, val2, msg) { + if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) { + throw new Error('Invalid operator "' + operator + '"'); + } + var test = new Assertion(eval(val + operator + val2), msg); + test.assert( + true === flag(test, 'object') + , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) + , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); + }; + + /*! + * Undocumented / untested + */ + + assert.ifError = function (val, msg) { + new Assertion(val, msg).to.not.be.ok; + }; + + /*! + * Aliases. + */ + + (function alias(name, as){ + assert[as] = assert[name]; + return alias; + }) + ('Throw', 'throw') + ('Throw', 'throws'); + }; + + }); // module: chai/interface/assert.js + + require.register("chai/interface/expect.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, util) { + chai.expect = function (val, message) { + return new chai.Assertion(val, message); + }; + }; + + + }); // module: chai/interface/expect.js + + require.register("chai/interface/should.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, util) { + var Assertion = chai.Assertion; + + function loadShould () { + // modify Object.prototype to have `should` + Object.defineProperty(Object.prototype, 'should', + { set: function () {} + , get: function(){ + if (this instanceof String || this instanceof Number) { + return new Assertion(this.constructor(this)); + } else if (this instanceof Boolean) { + return new Assertion(this == true); + } + return new Assertion(this); + } + , configurable: true + }); + + var should = {}; + + should.equal = function (val1, val2) { + new Assertion(val1).to.equal(val2); + }; + + should.Throw = function (fn, errt, errs) { + new Assertion(fn).to.Throw(errt, errs); + }; + + should.exist = function (val) { + new Assertion(val).to.exist; + } + + // negation + should.not = {} + + should.not.equal = function (val1, val2) { + new Assertion(val1).to.not.equal(val2); + }; + + should.not.Throw = function (fn, errt, errs) { + new Assertion(fn).to.not.Throw(errt, errs); + }; + + should.not.exist = function (val) { + new Assertion(val).to.not.exist; + } + + should['throw'] = should['Throw']; + should.not['throw'] = should.not['Throw']; + + return should; + }; + + chai.should = loadShould; + chai.Should = loadShould; + }; + + }); // module: chai/interface/should.js + + require.register("chai/utils/addChainableMethod.js", function(module, exports, require){ + /*! + * Chai - addChainingMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies + */ + + var transferFlags = require('./transferFlags'); + + /** + * ### addChainableMethod (ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @name addChainableMethod + * @api public + */ + + module.exports = function (ctx, name, method, chainingBehavior) { + if (typeof chainingBehavior !== 'function') + chainingBehavior = function () { }; + + Object.defineProperty(ctx, name, + { get: function () { + chainingBehavior.call(this); + + var assert = function () { + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; + + // Re-enumerate every time to better accomodate plugins. + var asserterNames = Object.getOwnPropertyNames(ctx); + asserterNames.forEach(function (asserterName) { + var pd = Object.getOwnPropertyDescriptor(ctx, asserterName) + , functionProtoPD = Object.getOwnPropertyDescriptor(Function.prototype, asserterName); + // Avoid trying to overwrite things that we can't, like `length` and `arguments`. + if (functionProtoPD && !functionProtoPD.configurable) return; + if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69 + Object.defineProperty(assert, asserterName, pd); + }); + + transferFlags(this, assert); + return assert; + } + , configurable: true + }); + }; + + }); // module: chai/utils/addChainableMethod.js + + require.register("chai/utils/addMethod.js", function(module, exports, require){ + /*! + * Chai - addMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### addMethod (ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @name addMethod + * @api public + */ + + module.exports = function (ctx, name, method) { + ctx[name] = function () { + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; + }; + + }); // module: chai/utils/addMethod.js + + require.register("chai/utils/addProperty.js", function(module, exports, require){ + /*! + * Chai - addProperty utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### addProperty (ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @name addProperty + * @api public + */ + + module.exports = function (ctx, name, getter) { + Object.defineProperty(ctx, name, + { get: function () { + var result = getter.call(this); + return result === undefined ? this : result; + } + , configurable: true + }); + }; + + }); // module: chai/utils/addProperty.js + + require.register("chai/utils/eql.js", function(module, exports, require){ + // This is directly from Node.js assert + // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js + + + module.exports = _deepEqual; + + // For browser implementation + if (!Buffer) { + var Buffer = { + isBuffer: function () { + return false; + } + }; + } + + function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (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 _deepEqual(a, b); + } + try { + var ka = Object.keys(a), + kb = Object.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 (!_deepEqual(a[key], b[key])) return false; + } + return true; + } + }); // module: chai/utils/eql.js + + require.register("chai/utils/flag.js", function(module, exports, require){ + /*! + * Chai - flag utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### flag(object ,key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object (constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @name flag + * @api private + */ + + module.exports = function (obj, key, value) { + var flags = obj.__flags || (obj.__flags = Object.create(null)); + if (arguments.length === 3) { + flags[key] = value; + } else { + return flags[key]; + } + }; + + }); // module: chai/utils/flag.js + + require.register("chai/utils/getActual.js", function(module, exports, require){ + /*! + * Chai - getActual utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * # getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + + module.exports = function (obj, args) { + var actual = args[4]; + return 'undefined' !== actual ? actual : obj.obj; + }; + + }); // module: chai/utils/getActual.js + + require.register("chai/utils/getMessage.js", function(module, exports, require){ + /*! + * Chai - message composition utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependancies + */ + + var flag = require('./flag') + , getActual = require('./getActual') + , inspect = require('./inspect'); + + /** + * # getMessage(object, message, negateMessage) + * + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. + * + * Messsage template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + + module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , val = flag(obj, 'object') + , expected = args[3] + , actual = getActual(obj, args) + , msg = negate ? args[2] : args[1] + , flagMsg = flag(obj, 'message'); + + msg = msg || ''; + msg = msg + .replace(/#{this}/g, inspect(val)) + .replace(/#{act}/g, inspect(actual)) + .replace(/#{exp}/g, inspect(expected)); + + return flagMsg ? flagMsg + ': ' + msg : msg; + }; + + }); // module: chai/utils/getMessage.js + + require.register("chai/utils/getName.js", function(module, exports, require){ + /*! + * Chai - getName utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * # getName(func) + * + * Gets the name of a function, in a cross-browser way. + * + * @param {Function} a function (usually a constructor) + */ + + module.exports = function (func) { + if (func.name) return func.name; + + var match = /^\s?function ([^(]*)\(/.exec(func); + return match && match[1] ? match[1] : ""; + }; + + }); // module: chai/utils/getName.js + + require.register("chai/utils/getPathValue.js", function(module, exports, require){ + /*! + * Chai - getPathValue utility + * Copyright(c) 2012 Jake Luer + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ + + /** + * ### .getPathValue(path, object) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue('prop1.str', obj); // Hello + * getPathValue('prop1.att[2]', obj); // b + * getPathValue('prop2.arr[0].nested', obj); // Universe + * + * @param {String} path + * @param {Object} object + * @returns {Object} value or `undefined` + * @name getPathValue + * @api public + */ + + var getPathValue = module.exports = function (path, obj) { + var parsed = parsePath(path); + return _getPathValue(parsed, obj); + }; + + /*! + * ## parsePath(path) + * + * Helper function used to parse string object + * paths. Use in conjunction with `_getPathValue`. + * + * var parsed = parsePath('myobject.property.subprop'); + * + * ### Paths: + * + * * Can be as near infinitely deep and nested + * * Arrays are also valid using the formal `myobject.document[3].property`. + * + * @param {String} path + * @returns {Object} parsed + * @api private + */ + + function parsePath (path) { + var str = path.replace(/\[/g, '.[') + , parts = str.match(/(\\\.|[^.]+?)+/g); + return parts.map(function (value) { + var re = /\[(\d+)\]$/ + , mArr = re.exec(value) + if (mArr) return { i: parseFloat(mArr[1]) }; + else return { p: value }; + }); + }; + + /*! + * ## _getPathValue(parsed, obj) + * + * Helper companion function for `.parsePath` that returns + * the value located at the parsed address. + * + * var value = getPathValue(parsed, obj); + * + * @param {Object} parsed definition from `parsePath`. + * @param {Object} object to search against + * @returns {Object|Undefined} value + * @api private + */ + + function _getPathValue (parsed, obj) { + var tmp = obj + , res; + for (var i = 0, l = parsed.length; i < l; i++) { + var part = parsed[i]; + if (tmp) { + if ('undefined' !== typeof part.p) + tmp = tmp[part.p]; + else if ('undefined' !== typeof part.i) + tmp = tmp[part.i]; + if (i == (l - 1)) res = tmp; + } else { + res = undefined; + } + } + return res; + }; + + }); // module: chai/utils/getPathValue.js + + require.register("chai/utils/index.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */ + + /*! + * Main exports + */ + + var exports = module.exports = {}; + + /*! + * test utility + */ + + exports.test = require('./test'); + + /*! + * message utility + */ + + exports.getMessage = require('./getMessage'); + + /*! + * actual utility + */ + + exports.getActual = require('./getActual'); + + /*! + * Inspect util + */ + + exports.inspect = require('./inspect'); + + /*! + * Flag utility + */ + + exports.flag = require('./flag'); + + /*! + * Flag transferring utility + */ + + exports.transferFlags = require('./transferFlags'); + + /*! + * Deep equal utility + */ + + exports.eql = require('./eql'); + + /*! + * Deep path value + */ + + exports.getPathValue = require('./getPathValue'); + + /*! + * Function name + */ + + exports.getName = require('./getName'); + + /*! + * add Property + */ + + exports.addProperty = require('./addProperty'); + + /*! + * add Method + */ + + exports.addMethod = require('./addMethod'); + + /*! + * overwrite Property + */ + + exports.overwriteProperty = require('./overwriteProperty'); + + /*! + * overwrite Method + */ + + exports.overwriteMethod = require('./overwriteMethod'); + + /*! + * Add a chainable method + */ + + exports.addChainableMethod = require('./addChainableMethod'); + + + }); // module: chai/utils/index.js + + require.register("chai/utils/inspect.js", function(module, exports, require){ + // This is (almost) directly from Node.js utils + // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js + + var getName = require('./getName'); + + module.exports = inspect; + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + */ + function inspect(obj, showHidden, depth, colors) { + var ctx = { + showHidden: showHidden, + seen: [], + stylize: function (str) { return str; } + }; + return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); + } + + function formatValue(ctx, 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.inspect !== exports.inspect && + // 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 + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var visibleKeys = Object.keys(value); + var keys = ctx.showHidden ? Object.getOwnPropertyNames(value) : visibleKeys; + + // Some type of object without properties can be shortcutted. + // In IE, errors have a single `stack` property, or if they are vanilla `Error`, + // a `stack` plus `description` property; ignore those for consistency. + if (keys.length === 0 || (isError(value) && ( + (keys.length === 1 && keys[0] === 'stack') || + (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') + ))) { + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + return ctx.stylize('[Function' + nameSuffix + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + base = ' [Function' + nameSuffix + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + return formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); + } + + + function formatPrimitive(ctx, value) { + switch (typeof value) { + case 'undefined': + return ctx.stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + + case 'number': + return ctx.stylize('' + value, 'number'); + + case 'boolean': + return ctx.stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return ctx.stylize('null', 'null'); + } + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (Object.prototype.hasOwnProperty.call(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Setter]', 'special'); + } + } + } + if (visibleKeys.indexOf(key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(value[key]) < 0) { + if (recurseTimes === null) { + str = formatValue(ctx, value[key], null); + } else { + str = formatValue(ctx, value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (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 = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; + } + + + function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + function isArray(ar) { + return Array.isArray(ar) || + (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + } + + function isRegExp(re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + } + + function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + } + + function isError(e) { + return typeof e === 'object' && objectToString(e) === '[object Error]'; + } + + function objectToString(o) { + return Object.prototype.toString.call(o); + } + + }); // module: chai/utils/inspect.js + + require.register("chai/utils/overwriteMethod.js", function(module, exports, require){ + /*! + * Chai - overwriteMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### overwriteMethod (ctx, name, fn) + * + * Overwites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @name overwriteMethod + * @api public + */ + + module.exports = function (ctx, name, method) { + var _method = ctx[name] + , _super = function () { return this; }; + + if (_method && 'function' === typeof _method) + _super = _method; + + ctx[name] = function () { + var result = method(_super).apply(this, arguments); + return result === undefined ? this : result; + } + }; + + }); // module: chai/utils/overwriteMethod.js + + require.register("chai/utils/overwriteProperty.js", function(module, exports, require){ + /*! + * Chai - overwriteProperty utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### overwriteProperty (ctx, name, fn) + * + * Overwites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @name overwriteProperty + * @api public + */ + + module.exports = function (ctx, name, getter) { + var _get = Object.getOwnPropertyDescriptor(ctx, name) + , _super = function () {}; + + if (_get && 'function' === typeof _get.get) + _super = _get.get + + Object.defineProperty(ctx, name, + { get: function () { + var result = getter(_super).call(this); + return result === undefined ? this : result; + } + , configurable: true + }); + }; + + }); // module: chai/utils/overwriteProperty.js + + require.register("chai/utils/test.js", function(module, exports, require){ + /*! + * Chai - test utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependancies + */ + + var flag = require('./flag'); + + /** + * # test(object, expression) + * + * Test and object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + + module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , expr = args[0]; + return negate ? !expr : expr; + }; + + }); // module: chai/utils/test.js + + require.register("chai/utils/transferFlags.js", function(module, exports, require){ + /*! + * Chai - transferFlags utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### transferFlags(assertion, object, includeAll = true) + * + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, and `message`) + * will not be transferred. + * + * + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); + * + * var anotherAsseriton = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); + * + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags too; usually a new assertion + * @param {Boolean} includeAll + * @name getAllFlags + * @api private + */ + + module.exports = function (assertion, object, includeAll) { + var flags = assertion.__flags || (assertion.__flags = Object.create(null)); + + if (!object.__flags) { + object.__flags = Object.create(null); + } + + includeAll = arguments.length === 3 ? includeAll : true; + + for (var flag in flags) { + if (includeAll || + (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { + object.__flags[flag] = flags[flag]; + } + } + }; + + }); // module: chai/utils/transferFlags.js + + require.alias("./chai.js", "chai"); + + return require('chai'); +}); \ No newline at end of file diff --git a/node_modules/grunt-mocha/example/test/js/mocha.js b/node_modules/grunt-mocha/example/test/js/mocha.js new file mode 100644 index 0000000..f67fd02 --- /dev/null +++ b/node_modules/grunt-mocha/example/test/js/mocha.js @@ -0,0 +1,4868 @@ +;(function(){ + + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("browser/debug.js", function(module, exports, require){ + +module.exports = function(type){ + return function(){ + + } +}; +}); // module: browser/debug.js + +require.register("browser/diff.js", function(module, exports, require){ + +}); // module: browser/diff.js + +require.register("browser/events.js", function(module, exports, require){ + +/** + * Module exports. + */ + +exports.EventEmitter = EventEmitter; + +/** + * Check if `obj` is an array. + */ + +function isArray(obj) { + return '[object Array]' == {}.toString.call(obj); +} + +/** + * Event emitter constructor. + * + * @api public + */ + +function EventEmitter(){}; + +/** + * Adds a listener. + * + * @api public + */ + +EventEmitter.prototype.on = function (name, fn) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = fn; + } else if (isArray(this.$events[name])) { + this.$events[name].push(fn); + } else { + this.$events[name] = [this.$events[name], fn]; + } + + return this; +}; + +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +/** + * Adds a volatile listener. + * + * @api public + */ + +EventEmitter.prototype.once = function (name, fn) { + var self = this; + + function on () { + self.removeListener(name, on); + fn.apply(this, arguments); + }; + + on.listener = fn; + this.on(name, on); + + return this; +}; + +/** + * Removes a listener. + * + * @api public + */ + +EventEmitter.prototype.removeListener = function (name, fn) { + if (this.$events && this.$events[name]) { + var list = this.$events[name]; + + if (isArray(list)) { + var pos = -1; + + for (var i = 0, l = list.length; i < l; i++) { + if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { + pos = i; + break; + } + } + + if (pos < 0) { + return this; + } + + list.splice(pos, 1); + + if (!list.length) { + delete this.$events[name]; + } + } else if (list === fn || (list.listener && list.listener === fn)) { + delete this.$events[name]; + } + } + + return this; +}; + +/** + * Removes all listeners for an event. + * + * @api public + */ + +EventEmitter.prototype.removeAllListeners = function (name) { + if (name === undefined) { + this.$events = {}; + return this; + } + + if (this.$events && this.$events[name]) { + this.$events[name] = null; + } + + return this; +}; + +/** + * Gets all listeners for a certain event. + * + * @api public + */ + +EventEmitter.prototype.listeners = function (name) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = []; + } + + if (!isArray(this.$events[name])) { + this.$events[name] = [this.$events[name]]; + } + + return this.$events[name]; +}; + +/** + * Emits an event. + * + * @api public + */ + +EventEmitter.prototype.emit = function (name) { + if (!this.$events) { + return false; + } + + var handler = this.$events[name]; + + if (!handler) { + return false; + } + + var args = [].slice.call(arguments, 1); + + if ('function' == typeof handler) { + handler.apply(this, args); + } else if (isArray(handler)) { + var listeners = handler.slice(); + + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + } else { + return false; + } + + return true; +}; +}); // module: browser/events.js + +require.register("browser/fs.js", function(module, exports, require){ + +}); // module: browser/fs.js + +require.register("browser/path.js", function(module, exports, require){ + +}); // module: browser/path.js + +require.register("browser/progress.js", function(module, exports, require){ + +/** + * Expose `Progress`. + */ + +module.exports = Progress; + +/** + * Initialize a new `Progress` indicator. + */ + +function Progress() { + this.percent = 0; + this.size(0); + this.fontSize(11); + this.font('helvetica, arial, sans-serif'); +} + +/** + * Set progress size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.size = function(n){ + this._size = n; + return this; +}; + +/** + * Set text to `str`. + * + * @param {String} str + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.text = function(str){ + this._text = str; + return this; +}; + +/** + * Set font size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.fontSize = function(n){ + this._fontSize = n; + return this; +}; + +/** + * Set font `family`. + * + * @param {String} family + * @return {Progress} for chaining + */ + +Progress.prototype.font = function(family){ + this._font = family; + return this; +}; + +/** + * Update percentage to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + */ + +Progress.prototype.update = function(n){ + this.percent = n; + return this; +}; + +/** + * Draw on `ctx`. + * + * @param {CanvasRenderingContext2d} ctx + * @return {Progress} for chaining + */ + +Progress.prototype.draw = function(ctx){ + var percent = Math.min(this.percent, 100) + , size = this._size + , half = size / 2 + , x = half + , y = half + , rad = half - 1 + , fontSize = this._fontSize; + + ctx.font = fontSize + 'px ' + this._font; + + var angle = Math.PI * 2 * (percent / 100); + ctx.clearRect(0, 0, size, size); + + // outer circle + ctx.strokeStyle = '#9f9f9f'; + ctx.beginPath(); + ctx.arc(x, y, rad, 0, angle, false); + ctx.stroke(); + + // inner circle + ctx.strokeStyle = '#eee'; + ctx.beginPath(); + ctx.arc(x, y, rad - 1, 0, angle, true); + ctx.stroke(); + + // text + var text = this._text || (percent | 0) + '%' + , w = ctx.measureText(text).width; + + ctx.fillText( + text + , x - w / 2 + 1 + , y + fontSize / 2 - 1); + + return this; +}; + +}); // module: browser/progress.js + +require.register("browser/tty.js", function(module, exports, require){ + +exports.isatty = function(){ + return true; +}; + +exports.getWindowSize = function(){ + return [window.innerHeight, window.innerWidth]; +}; +}); // module: browser/tty.js + +require.register("context.js", function(module, exports, require){ + +/** + * Expose `Context`. + */ + +module.exports = Context; + +/** + * Initialize a new `Context`. + * + * @api private + */ + +function Context(){} + +/** + * Set or get the context `Runnable` to `runnable`. + * + * @param {Runnable} runnable + * @return {Context} + * @api private + */ + +Context.prototype.runnable = function(runnable){ + if (0 == arguments.length) return this._runnable; + this.test = this._runnable = runnable; + return this; +}; + +/** + * Set test timeout `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.timeout = function(ms){ + this.runnable().timeout(ms); + return this; +}; + +/** + * 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`. + * + * @return {String} + * @api private + */ + +Context.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_runnable' == key) return; + if ('test' == key) return; + return val; + }, 2); +}; + +}); // module: context.js + +require.register("hook.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Hook`. + */ + +module.exports = Hook; + +/** + * Initialize a new `Hook` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Hook(title, fn) { + Runnable.call(this, title, fn); + this.type = 'hook'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Hook.prototype = new Runnable; +Hook.prototype.constructor = Hook; + + +/** + * Get or set the test `err`. + * + * @param {Error} err + * @return {Error} + * @api public + */ + +Hook.prototype.error = function(err){ + if (0 == arguments.length) { + var err = this._error; + this._error = null; + return err; + } + + this._error = err; +}; + + +}); // module: hook.js + +require.register("interfaces/bdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * BDD-style interface: + * + * describe('Array', function(){ + * describe('#indexOf()', function(){ + * it('should return -1 when not present', function(){ + * + * }); + * + * it('should return the index when present', function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.describe = context.context = function(title, fn){ + var suite = Suite.create(suites[0], title); + 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()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.it = context.specify = function(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); + }; + }); +}; + +}); // module: interfaces/bdd.js + +require.register("interfaces/exports.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * exports.Array = { + * '#indexOf()': { + * 'should return -1 when the value is not present': function(){ + * + * }, + * + * 'should return the correct index when the value is present': function(){ + * + * } + * } + * }; + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('require', visit); + + function visit(obj) { + var suite; + for (var key in obj) { + if ('function' == typeof obj[key]) { + var fn = obj[key]; + switch (key) { + case 'before': + suites[0].beforeAll(fn); + break; + case 'after': + suites[0].afterAll(fn); + break; + case 'beforeEach': + suites[0].beforeEach(fn); + break; + case 'afterEach': + suites[0].afterEach(fn); + break; + default: + suites[0].addTest(new Test(key, fn)); + } + } else { + var suite = Suite.create(suites[0], key); + suites.unshift(suite); + visit(obj[key]); + suites.shift(); + } + } + } +}; +}); // module: interfaces/exports.js + +require.register("interfaces/index.js", function(module, exports, require){ + +exports.bdd = require('./bdd'); +exports.tdd = require('./tdd'); +exports.qunit = require('./qunit'); +exports.exports = require('./exports'); + +}); // module: interfaces/index.js + +require.register("interfaces/qunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * QUnit-style interface: + * + * suite('Array'); + * + * test('#length', function(){ + * var arr = [1,2,3]; + * ok(arr.length == 3); + * }); + * + * test('#indexOf()', function(){ + * var arr = [1,2,3]; + * ok(arr.indexOf(1) == 0); + * ok(arr.indexOf(2) == 1); + * ok(arr.indexOf(3) == 2); + * }); + * + * suite('String'); + * + * test('#length', function(){ + * ok('foo'.length == 3); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title`. + */ + + context.suite = function(title){ + if (suites.length > 1) suites.shift(); + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + suites[0].addTest(new Test(title, fn)); + }; + }); +}; + +}); // module: interfaces/qunit.js + +require.register("interfaces/tdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * suite('Array', function(){ + * suite('#indexOf()', function(){ + * suiteSetup(function(){ + * + * }); + * + * test('should return -1 when not present', function(){ + * + * }); + * + * test('should return the index when present', function(){ + * + * }); + * + * suiteTeardown(function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before each test case. + */ + + context.setup = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.teardown = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Execute before the suite. + */ + + context.suiteSetup = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after the suite. + */ + + context.suiteTeardown = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.suite = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn(); + suites.shift(); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn){ + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(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()); + }; + }); +}; + +}); // module: interfaces/tdd.js + +require.register("mocha.js", function(module, exports, require){ +/*! + * mocha + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var path = require('browser/path') + , utils = require('./utils'); + +/** + * Expose `Mocha`. + */ + +exports = module.exports = Mocha; + +/** + * Expose internals. + */ + +exports.utils = utils; +exports.interfaces = require('./interfaces'); +exports.reporters = require('./reporters'); +exports.Runnable = require('./runnable'); +exports.Context = require('./context'); +exports.Runner = require('./runner'); +exports.Suite = require('./suite'); +exports.Hook = require('./hook'); +exports.Test = require('./test'); + +/** + * Return image `name` path. + * + * @param {String} name + * @return {String} + * @api private + */ + +function image(name) { + return __dirname + '/../images/' + name + '.png'; +} + +/** + * Setup mocha with `options`. + * + * Options: + * + * - `ui` name "bdd", "tdd", "exports" etc + * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` + * - `globals` array of accepted globals + * - `timeout` timeout in milliseconds + * - `slow` milliseconds to wait before considering a test slow + * - `ignoreLeaks` ignore global leaks + * - `grep` string or regexp to filter tests with + * + * @param {Object} options + * @api public + */ + +function Mocha(options) { + options = options || {}; + this.files = []; + this.options = options; + this.grep(options.grep); + this.suite = new exports.Suite('', new exports.Context); + this.ui(options.ui); + this.reporter(options.reporter); + if (options.timeout) this.timeout(options.timeout); + if (options.slow) this.slow(options.slow); +} + +/** + * Add test `file`. + * + * @param {String} file + * @api public + */ + +Mocha.prototype.addFile = function(file){ + this.files.push(file); + return this; +}; + +/** + * Set reporter to `reporter`, defaults to "dot". + * + * @param {String|Function} reporter name of a reporter or a reporter constructor + * @api public + */ + +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; +}; + +/** + * Set test UI `name`, defaults to "bdd". + * + * @param {String} bdd + * @api public + */ + +Mocha.prototype.ui = function(name){ + name = name || 'bdd'; + this._ui = exports.interfaces[name]; + if (!this._ui) throw new Error('invalid interface "' + name + '"'); + this._ui = this._ui(this.suite); + return this; +}; + +/** + * Load registered files. + * + * @api private + */ + +Mocha.prototype.loadFiles = function(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, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + --pending || (fn && fn()); + }); +}; + +/** + * Enable growl support. + * + * @api private + */ + +Mocha.prototype._growl = function(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function(){ + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + name: 'mocha' + , title: 'Passed' + , image: image('ok') + }); + } + }); +}; + +/** + * Add regexp to grep, if `re` is a string it is escaped. + * + * @param {RegExp|String} re + * @return {Mocha} + * @api public + */ + +Mocha.prototype.grep = function(re){ + this.options.grep = 'string' == typeof 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. + * + * @param {Function} fn + * @return {Runner} + * @api public + */ + +Mocha.prototype.run = function(fn){ + 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, options.invert); + if (options.globals) runner.globals(options.globals); + 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){ + +/** + * Module dependencies. + */ + +var tty = require('browser/tty') + , diff = require('browser/diff') + , ms = require('../ms'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Check if both stdio streams are associated with a tty. + */ + +var isatty = tty.isatty(1) && tty.isatty(2); + +/** + * Expose `Base`. + */ + +exports = module.exports = Base; + +/** + * Enable coloring by default. + */ + +exports.useColors = isatty; + +/** + * Default color map. + */ + +exports.colors = { + 'pass': 90 + , 'fail': 31 + , 'bright pass': 92 + , 'bright fail': 91 + , 'bright yellow': 93 + , 'pending': 36 + , 'suite': 0 + , 'error title': 0 + , 'error message': 31 + , 'error stack': 90 + , 'checkmark': 32 + , 'fast': 90 + , 'medium': 33 + , 'slow': 31 + , 'green': 32 + , 'light': 90 + , 'diff gutter': 90 + , 'diff added': 42 + , 'diff removed': 41 +}; + +/** + * Color `str` with the given `type`, + * allowing colors to be disabled, + * as well as user-defined color + * schemes. + * + * @param {String} type + * @param {String} str + * @return {String} + * @api private + */ + +var color = exports.color = function(type, str) { + if (!exports.useColors) return str; + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; +}; + +/** + * Expose term window size, with some + * defaults for when stderr is not a tty. + */ + +exports.window = { + width: isatty + ? process.stdout.getWindowSize + ? process.stdout.getWindowSize(1)[0] + : tty.getWindowSize()[1] + : 75 +}; + +/** + * Expose some basic cursor interactions + * that are common among reporters. + */ + +exports.cursor = { + hide: function(){ + process.stdout.write('\u001b[?25l'); + }, + + show: function(){ + process.stdout.write('\u001b[?25h'); + }, + + deleteLine: function(){ + process.stdout.write('\u001b[2K'); + }, + + beginningOfLine: function(){ + process.stdout.write('\u001b[0G'); + }, + + CR: function(){ + exports.cursor.deleteLine(); + exports.cursor.beginningOfLine(); + } +}; + +/** + * Outut the given `failures` as a list. + * + * @param {Array} failures + * @api public + */ + +exports.list = function(failures){ + console.error(); + failures.forEach(function(test, i){ + // format + var fmt = color('error title', ' %s) %s:\n') + + color('error message', ' %s') + + color('error stack', '\n%s\n'); + + // msg + var err = test.err + , message = err.message || '' + , stack = err.stack || message + , index = stack.indexOf(message) + message.length + , msg = stack.slice(0, index) + , actual = err.actual + , expected = err.expected; + + // actual / expected diff + if ('string' == typeof actual && 'string' == typeof expected) { + var len = Math.max(actual.length, expected.length); + + if (len < 20) msg = errorDiff(err, 'Chars'); + else msg = errorDiff(err, 'Words'); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i){ + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + color('diff removed', 'actual') + + ' ' + + color('diff added', 'expected') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + + fmt = color('error title', ' %s) %s:\n%s') + + color('error stack', '\n%s\n'); + } + + // indent stack trace without msg + stack = stack.slice(index ? index + 1 : index) + .replace(/^/gm, ' '); + + console.error(fmt, (i + 1), test.fullTitle(), msg, stack); + }); +}; + +/** + * Initialize a new `Base` reporter. + * + * All other reporters generally + * inherit from this reporter, providing + * stats such as test duration, number + * of tests passed / failed etc. + * + * @param {Runner} runner + * @api public + */ + +function Base(runner) { + var self = this + , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } + , failures = this.failures = []; + + if (!runner) return; + this.runner = runner; + + runner.on('start', function(){ + stats.start = new Date; + }); + + runner.on('suite', function(suite){ + stats.suites = stats.suites || 0; + suite.root || stats.suites++; + }); + + runner.on('test end', function(test){ + stats.tests = stats.tests || 0; + stats.tests++; + }); + + runner.on('pass', function(test){ + stats.passes = stats.passes || 0; + + var medium = test.slow() / 2; + test.speed = test.duration > test.slow() + ? 'slow' + : test.duration > medium + ? 'medium' + : 'fast'; + + stats.passes++; + }); + + runner.on('fail', function(test, err){ + stats.failures = stats.failures || 0; + stats.failures++; + test.err = err; + failures.push(test); + }); + + runner.on('end', function(){ + stats.end = new Date; + stats.duration = new Date - stats.start; + }); + + runner.on('pending', function(){ + stats.pending++; + }); +} + +/** + * Output common epilogue used by many of + * the bundled reporters. + * + * @api public + */ + +Base.prototype.epilogue = function(){ + var stats = this.stats + , fmt + , tests; + + console.log(); + + function pluralize(n) { + return 1 == n ? 'test' : 'tests'; + } + + // failure + if (stats.failures) { + fmt = color('bright fail', ' ✖') + + color('fail', ' %d of %d %s failed') + + color('light', ':') + + console.error(fmt, + stats.failures, + this.runner.total, + pluralize(this.runner.total)); + + Base.list(this.failures); + console.error(); + return; + } + + // pass + fmt = color('bright pass', ' ✔') + + color('green', ' %d %s complete') + + color('light', ' (%s)'); + + console.log(fmt, + stats.tests || 0, + pluralize(stats.tests), + ms(stats.duration)); + + // pending + if (stats.pending) { + fmt = color('pending', ' •') + + color('pending', ' %d %s pending'); + + console.log(fmt, stats.pending, pluralize(stats.pending)); + } + + console.log(); +}; + +/** + * Pad the given `str` to `len`. + * + * @param {String} str + * @param {String} len + * @return {String} + * @api private + */ + +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Return a character diff for `err`. + * + * @param {Error} err + * @return {String} + * @api private + */ + +function errorDiff(err, type) { + return diff['diff' + type](err.actual, err.expected).map(function(str){ + 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; + }).join(''); +} + +/** + * Color lines for `str`, using the color `name`. + * + * @param {String} name + * @param {String} str + * @return {String} + * @api private + */ + +function colorLines(name, str) { + return str.split('\n').map(function(str){ + return color(name, str); + }).join('\n'); +} + +}); // module: reporters/base.js + +require.register("reporters/doc.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Doc`. + */ + +exports = module.exports = Doc; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Doc(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , indents = 2; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('suite', function(suite){ + if (suite.root) return; + ++indents; + console.log('%s
            ', indent()); + ++indents; + console.log('%s

            %s

            ', indent(), suite.title); + console.log('%s
            ', indent()); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + console.log('%s
            ', indent()); + --indents; + console.log('%s
            ', indent()); + --indents; + }); + + runner.on('pass', function(test){ + console.log('%s
            %s
            ', indent(), test.title); + var code = utils.escape(utils.clean(test.fn.toString())); + console.log('%s
            %s
            ', indent(), code); + }); +} + +}); // module: reporters/doc.js + +require.register("reporters/dot.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = Dot; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Dot(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , c = '․' + , n = 0; + + runner.on('start', function(){ + process.stdout.write('\n '); + }); + + runner.on('pending', function(test){ + 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', c)); + } else { + 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', c)); + }); + + runner.on('end', function(){ + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Dot.prototype = new Base; +Dot.prototype.constructor = Dot; + +}); // module: reporters/dot.js + +require.register("reporters/html-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var JSONCov = require('./json-cov') + , fs = require('browser/fs'); + +/** + * Expose `HTMLCov`. + */ + +exports = module.exports = HTMLCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTMLCov(runner) { + var jade = require('jade') + , file = __dirname + '/templates/coverage.jade' + , str = fs.readFileSync(file, 'utf8') + , fn = jade.compile(str, { filename: file }) + , self = this; + + JSONCov.call(this, runner, false); + + runner.on('end', function(){ + process.stdout.write(fn({ + cov: self.cov + , coverageClass: coverageClass + })); + }); +} + +/** + * Return coverage class for `n`. + * + * @return {String} + * @api private + */ + +function coverageClass(n) { + if (n >= 75) return 'high'; + if (n >= 50) return 'medium'; + if (n >= 25) return 'low'; + return 'terrible'; +} +}); // module: reporters/html-cov.js + +require.register("reporters/html.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , Progress = require('../browser/progress') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Doc`. + */ + +exports = module.exports = HTML; + +/** + * Stats template. + */ + +var statsTemplate = ''; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTML(runner, root) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , 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('
              ') + , stack = [report] + , 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); + + if (progress) progress.size(40); + + runner.on('suite', function(suite){ + if (suite.root) return; + + // suite + var url = '?grep=' + encodeURIComponent(suite.fullTitle()); + var el = fragment('
            • %s

            • ', url, escape(suite.title)); + + // container + stack[0].appendChild(el); + stack.unshift(document.createElement('ul')); + el.appendChild(stack[0]); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + stack.shift(); + }); + + runner.on('fail', function(test, err){ + if ('hook' == test.type || err.uncaught) runner.emit('test end', test); + }); + + runner.on('test end', function(test){ + window.scrollTo(0, document.body.scrollHeight); + + // TODO: add to stats + var percent = stats.tests / total * 100 | 0; + if (progress) progress.update(percent).draw(ctx); + + // update stats + var ms = new Date - stats.start; + text(passes, stats.passes); + text(failures, stats.failures); + text(duration, (ms / 1000).toFixed(2)); + + // test + if ('passed' == test.state) { + var el = fragment('
            • %e%ems

            • ', test.speed, test.title, test.duration); + } else if (test.pending) { + var el = fragment('
            • %e

            • ', test.title); + } else { + var el = fragment('
            • %e

            • ', test.title); + var str = test.err.stack || test.err.toString(); + + // FF / Opera do not add the message + if (!~str.indexOf(test.err.message)) { + str = test.err.message + '\n' + str; + } + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if ('[object Error]' == str) str = test.err.message; + + // Safari doesn't give you a stack. Let's at least provide a source line. + if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { + str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; + } + + el.appendChild(fragment('
              %e
              ', str)); + } + + // toggle 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'; + } + + stack[0].appendChild(el); + }); +} + +/** + * Display error `msg`. + */ + +function error(msg) { + document.body.appendChild(fragment('
              %s
              ', msg)); +} + +/** + * Return a DOM fragment from `html`. + */ + +function fragment(html) { + var args = arguments + , div = document.createElement('div') + , i = 1; + + div.innerHTML = html.replace(/%([se])/g, function(_, type){ + switch (type) { + case 's': return String(args[i++]); + case 'e': return escape(args[i++]); + } + }); + + return div.firstChild; +} + +/** + * Set `el` text to `str`. + */ + +function text(el, str) { + if (el.textContent) { + el.textContent = str; + } else { + el.innerText = str; + } +} + +/** + * Listen on `event` with callback `fn`. + */ + +function on(el, event, fn) { + if (el.addEventListener) { + el.addEventListener(event, fn, false); + } else { + el.attachEvent('on' + event, fn); + } +} + +}); // module: reporters/html.js + +require.register("reporters/index.js", function(module, exports, require){ + +exports.Base = require('./base'); +exports.Dot = require('./dot'); +exports.Doc = require('./doc'); +exports.TAP = require('./tap'); +exports.JSON = require('./json'); +exports.HTML = require('./html'); +exports.List = require('./list'); +exports.Min = require('./min'); +exports.Spec = require('./spec'); +exports.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.Teamcity = require('./teamcity'); + +}); // module: reporters/index.js + +require.register("reporters/json-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSONCov`. + */ + +exports = module.exports = JSONCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @param {Boolean} output + * @api public + */ + +function JSONCov(runner, output) { + var self = this + , output = 1 == arguments.length ? true : output; + + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var cov = global._$jscoverage || {}; + var result = self.cov = map(cov); + result.stats = self.stats; + result.tests = tests.map(clean); + result.failures = failures.map(clean); + result.passes = passes.map(clean); + if (!output) return; + process.stdout.write(JSON.stringify(result, null, 2 )); + }); +} + +/** + * Map jscoverage data to a JSON structure + * suitable for reporting. + * + * @param {Object} cov + * @return {Object} + * @api private + */ + +function map(cov) { + var ret = { + instrumentation: 'node-jscoverage' + , sloc: 0 + , hits: 0 + , misses: 0 + , coverage: 0 + , files: [] + }; + + for (var filename in cov) { + var data = coverage(filename, cov[filename]); + ret.files.push(data); + ret.hits += data.hits; + ret.misses += data.misses; + ret.sloc += data.sloc; + } + + if (ret.sloc > 0) { + ret.coverage = (ret.hits / ret.sloc) * 100; + } + + return ret; +}; + +/** + * Map jscoverage data for a single source file + * to a JSON structure suitable for reporting. + * + * @param {String} filename name of the source file + * @param {Object} data jscoverage coverage data + * @return {Object} + * @api private + */ + +function coverage(filename, data) { + var ret = { + filename: filename, + coverage: 0, + hits: 0, + misses: 0, + sloc: 0, + source: {} + }; + + data.source.forEach(function(line, num){ + num++; + + if (data[num] === 0) { + ret.misses++; + ret.sloc++; + } else if (data[num] !== undefined) { + ret.hits++; + ret.sloc++; + } + + ret.source[num] = { + source: line + , coverage: data[num] === undefined + ? '' + : data[num] + }; + }); + + ret.coverage = ret.hits / ret.sloc * 100; + + return ret; +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} + +}); // module: reporters/json-cov.js + +require.register("reporters/json-stream.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total; + + runner.on('start', function(){ + console.log(JSON.stringify(['start', { total: total }])); + }); + + runner.on('pass', function(test){ + console.log(JSON.stringify(['pass', clean(test)])); + }); + + runner.on('fail', function(test, err){ + console.log(JSON.stringify(['fail', clean(test)])); + }); + + runner.on('end', function(){ + process.stdout.write(JSON.stringify(['end', self.stats])); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json-stream.js + +require.register("reporters/json.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `JSON`. + */ + +exports = module.exports = JSONReporter; + +/** + * Initialize a new `JSON` reporter. + * + * @param {Runner} runner + * @api public + */ + +function JSONReporter(runner) { + var self = this; + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var obj = { + stats: self.stats + , tests: tests.map(clean) + , failures: failures.map(clean) + , passes: passes.map(clean) + }; + + process.stdout.write(JSON.stringify(obj, null, 2)); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json.js + +require.register("reporters/landing.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Landing`. + */ + +exports = module.exports = Landing; + +/** + * Airplane color. + */ + +Base.colors.plane = 0; + +/** + * Airplane crash color. + */ + +Base.colors['plane crash'] = 31; + +/** + * Runway color. + */ + +Base.colors.runway = 90; + +/** + * Initialize a new `Landing` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Landing(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , total = runner.total + , stream = process.stdout + , plane = color('plane', '✈') + , crashed = -1 + , n = 0; + + function runway() { + var buf = Array(width).join('-'); + return ' ' + color('runway', buf); + } + + runner.on('start', function(){ + stream.write('\n '); + cursor.hide(); + }); + + runner.on('test end', function(test){ + // check if the plane crashed + var col = -1 == crashed + ? width * ++n / total | 0 + : crashed; + + // show the crash + if ('failed' == test.state) { + plane = color('plane crash', '✈'); + crashed = col; + } + + // render landing strip + stream.write('\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('\u001b[0m'); + }); + + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Landing.prototype = new Base; +Landing.prototype.constructor = Landing; + +}); // module: reporters/landing.js + +require.register("reporters/list.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 0; + + runner.on('start', function(){ + console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = color('checkmark', ' -') + + color('pending', ' %s'); + console.log(fmt, test.fullTitle()); + }); + + runner.on('pass', function(test){ + var fmt = color('checkmark', ' ✓') + + color('pass', ' %s: ') + + color(test.speed, '%dms'); + cursor.CR(); + console.log(fmt, test.fullTitle(), test.duration); + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +List.prototype = new Base; +List.prototype.constructor = List; + + +}); // module: reporters/list.js + +require.register("reporters/markdown.js", function(module, exports, require){ +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Markdown`. + */ + +exports = module.exports = Markdown; + +/** + * Initialize a new `Markdown` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Markdown(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , level = 0 + , buf = ''; + + function title(str) { + return Array(level).join('#') + ' ' + str; + } + + function indent() { + return Array(level).join(' '); + } + + function mapTOC(suite, obj) { + var ret = obj; + obj = obj[suite.title] = obj[suite.title] || { suite: suite }; + suite.suites.forEach(function(suite){ + mapTOC(suite, obj); + }); + return ret; + } + + function stringifyTOC(obj, level) { + ++level; + var buf = ''; + var link; + for (var key in obj) { + if ('suite' == key) continue; + if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; + if (key) buf += Array(level).join(' ') + link; + buf += stringifyTOC(obj[key], level); + } + --level; + return buf; + } + + function generateTOC(suite) { + var obj = mapTOC(suite, {}); + return stringifyTOC(obj, 0); + } + + generateTOC(runner.suite); + + runner.on('suite', function(suite){ + ++level; + var slug = utils.slug(suite.fullTitle()); + buf += '' + '\n'; + buf += title(suite.title) + '\n'; + }); + + runner.on('suite end', function(suite){ + --level; + }); + + runner.on('pass', function(test){ + var code = utils.clean(test.fn.toString()); + buf += test.title + '.\n'; + buf += '\n```js\n'; + buf += code + '\n'; + buf += '```\n\n'; + }); + + runner.on('end', function(){ + process.stdout.write('# TOC\n'); + process.stdout.write(generateTOC(runner.suite)); + process.stdout.write(buf); + }); +} +}); // module: reporters/markdown.js + +require.register("reporters/min.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Min`. + */ + +exports = module.exports = Min; + +/** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @param {Runner} runner + * @api public + */ + +function Min(runner) { + Base.call(this, runner); + + runner.on('start', function(){ + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position + process.stdout.write('\u001b[1;3H'); + }); + + runner.on('end', this.epilogue.bind(this)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Min.prototype = new Base; +Min.prototype.constructor = Min; + +}); // module: reporters/min.js + +require.register("reporters/nyan.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = NyanCat; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function NyanCat(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , rainbowColors = this.rainbowColors = self.generateColors() + , colorIndex = this.colorIndex = 0 + , numerOfLines = this.numberOfLines = 4 + , trajectories = this.trajectories = [[], [], [], []] + , nyanCatWidth = this.nyanCatWidth = 11 + , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) + , scoreboardWidth = this.scoreboardWidth = 5 + , tick = this.tick = 0 + , n = 0; + + runner.on('start', function(){ + Base.cursor.hide(); + self.draw('start'); + }); + + runner.on('pending', function(test){ + self.draw('pending'); + }); + + runner.on('pass', function(test){ + self.draw('pass'); + }); + + runner.on('fail', function(test, err){ + self.draw('fail'); + }); + + runner.on('end', function(){ + Base.cursor.show(); + for (var i = 0; i < self.numberOfLines; i++) write('\n'); + self.epilogue(); + }); +} + +/** + * Draw the nyan cat with runner `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.draw = function(status){ + this.appendRainbow(); + this.drawScoreboard(); + this.drawRainbow(); + this.drawNyanCat(status); + this.tick = !this.tick; +}; + +/** + * Draw the "scoreboard" showing the number + * of passes, failures and pending tests. + * + * @api private + */ + +NyanCat.prototype.drawScoreboard = function(){ + var stats = this.stats; + var colors = Base.colors; + + function draw(color, n) { + write(' '); + write('\u001b[' + color + 'm' + n + '\u001b[0m'); + write('\n'); + } + + draw(colors.green, stats.passes); + draw(colors.fail, stats.failures); + draw(colors.pending, stats.pending); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Append the rainbow. + * + * @api private + */ + +NyanCat.prototype.appendRainbow = function(){ + var segment = this.tick ? '_' : '-'; + var rainbowified = this.rainbowify(segment); + + for (var index = 0; index < this.numberOfLines; index++) { + var trajectory = this.trajectories[index]; + if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); + trajectory.push(rainbowified); + } +}; + +/** + * Draw the rainbow. + * + * @api private + */ + +NyanCat.prototype.drawRainbow = function(){ + var self = this; + + this.trajectories.forEach(function(line, index) { + write('\u001b[' + self.scoreboardWidth + 'C'); + write(line.join('')); + write('\n'); + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw the nyan cat with `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.drawNyanCat = function(status) { + var self = this; + var startWidth = this.scoreboardWidth + this.trajectories[0].length; + + [0, 1, 2, 3].forEach(function(index) { + write('\u001b[' + startWidth + 'C'); + + switch (index) { + case 0: + write('_,------,'); + write('\n'); + break; + case 1: + var padding = self.tick ? ' ' : ' '; + write('_|' + padding + '/\\_/\\ '); + write('\n'); + break; + case 2: + var padding = self.tick ? '_' : '__'; + var tail = self.tick ? '~' : '^'; + var face; + switch (status) { + case 'pass': + face = '( ^ .^)'; + break; + case 'fail': + face = '( o .o)'; + break; + default: + face = '( - .-)'; + } + write(tail + '|' + padding + face + ' '); + write('\n'); + break; + case 3: + var padding = self.tick ? ' ' : ' '; + write(padding + '"" "" '); + write('\n'); + break; + } + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Move cursor up `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorUp = function(n) { + write('\u001b[' + n + 'A'); +}; + +/** + * Move cursor down `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorDown = function(n) { + write('\u001b[' + n + 'B'); +}; + +/** + * Generate rainbow colors. + * + * @return {Array} + * @api private + */ + +NyanCat.prototype.generateColors = function(){ + var colors = []; + + for (var i = 0; i < (6 * 7); i++) { + var pi3 = Math.floor(Math.PI / 3); + var n = (i * (1.0 / 6)); + var r = Math.floor(3 * Math.sin(n) + 3); + var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); + var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); + colors.push(36 * r + 6 * g + b + 16); + } + + return colors; +}; + +/** + * Apply rainbow to the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +NyanCat.prototype.rainbowify = function(str){ + var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; + this.colorIndex += 1; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; +}; + +/** + * Stdout helper. + */ + +function write(string) { + process.stdout.write(string); +} + +/** + * Inherit from `Base.prototype`. + */ + +NyanCat.prototype = new Base; +NyanCat.prototype.constructor = NyanCat; + + +}); // module: reporters/nyan.js + +require.register("reporters/progress.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Progress`. + */ + +exports = module.exports = Progress; + +/** + * General progress bar color. + */ + +Base.colors.progress = 90; + +/** + * Initialize a new `Progress` bar test reporter. + * + * @param {Runner} runner + * @param {Object} options + * @api public + */ + +function Progress(runner, options) { + Base.call(this, runner); + + var self = this + , options = options || {} + , stats = this.stats + , width = Base.window.width * .50 | 0 + , total = runner.total + , complete = 0 + , max = Math.max; + + // default chars + options.open = options.open || '['; + options.complete = options.complete || '▬'; + options.incomplete = options.incomplete || '⋅'; + options.close = options.close || ']'; + options.verbose = false; + + // tests started + runner.on('start', function(){ + console.log(); + cursor.hide(); + }); + + // tests complete + runner.on('test end', function(){ + complete++; + var incomplete = total - complete + , percent = complete / total + , n = width * percent | 0 + , i = width - n; + + cursor.CR(); + process.stdout.write('\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)); + process.stdout.write(color('progress', options.close)); + if (options.verbose) { + process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); + } + }); + + // tests are complete, output some stats + // and the failures if any + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Progress.prototype = new Base; +Progress.prototype.constructor = Progress; + + +}); // module: reporters/progress.js + +require.register("reporters/spec.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Spec`. + */ + +exports = module.exports = Spec; + +/** + * Initialize a new `Spec` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Spec(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , indents = 0 + , n = 0; + + function indent() { + return Array(indents).join(' ') + } + + runner.on('start', function(){ + console.log(); + }); + + runner.on('suite', function(suite){ + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function(suite){ + --indents; + if (1 == indents) console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function(test){ + if ('fast' == test.speed) { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s '); + cursor.CR(); + console.log(fmt, test.title); + } else { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s ') + + color(test.speed, '(%dms)'); + cursor.CR(); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Spec.prototype = new Base; +Spec.prototype.constructor = Spec; + + +}); // module: reporters/spec.js + +require.register("reporters/tap.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `TAP`. + */ + +exports = module.exports = TAP; + +/** + * Initialize a new `TAP` reporter. + * + * @param {Runner} runner + * @api public + */ + +function TAP(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 1; + + runner.on('start', function(){ + var total = runner.grepTotal(runner.suite); + console.log('%d..%d', 1, total); + }); + + runner.on('test end', function(){ + ++n; + }); + + runner.on('pending', function(test){ + console.log('ok %d %s # SKIP -', n, title(test)); + }); + + runner.on('pass', function(test){ + console.log('ok %d %s', n, title(test)); + }); + + runner.on('fail', function(test, err){ + console.log('not ok %d %s', n, title(test)); + console.log(err.stack.replace(/^/gm, ' ')); + }); +} + +/** + * Return a TAP-safe title of `test` + * + * @param {Object} test + * @return {String} + * @api private + */ + +function title(test) { + return test.fullTitle().replace(/#/g, ''); +} + +}); // module: reporters/tap.js + +require.register("reporters/teamcity.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Teamcity`. + */ + +exports = module.exports = Teamcity; + +/** + * Initialize a new `Teamcity` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Teamcity(runner) { + Base.call(this, runner); + var stats = this.stats; + + runner.on('start', function() { + console.log("##teamcity[testSuiteStarted name='mocha.suite']"); + }); + + runner.on('test', function(test) { + console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); + }); + + runner.on('fail', function(test, err) { + console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); + }); + + runner.on('pending', function(test) { + console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); + }); + + runner.on('test end', function(test) { + console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); + }); + + runner.on('end', function() { + console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); + }); +} + +/** + * Escape the given `str`. + */ + +function escape(str) { + return str + .replace(/\|/g, "||") + .replace(/\n/g, "|n") + .replace(/\r/g, "|r") + .replace(/\[/g, "|[") + .replace(/\]/g, "|]") + .replace(/\u0085/g, "|x") + .replace(/\u2028/g, "|l") + .replace(/\u2029/g, "|p") + .replace(/'/g, "|'"); +} + +}); // module: reporters/teamcity.js + +require.register("reporters/xunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `XUnit`. + */ + +exports = module.exports = XUnit; + +/** + * Initialize a new `XUnit` reporter. + * + * @param {Runner} runner + * @api public + */ + +function XUnit(runner) { + Base.call(this, runner); + var stats = this.stats + , tests = [] + , self = this; + + runner.on('pass', function(test){ + tests.push(test); + }); + + runner.on('fail', function(test){ + tests.push(test); + }); + + runner.on('end', function(){ + console.log(tag('testsuite', { + name: 'Mocha Tests' + , tests: stats.tests + , failures: stats.failures + , errors: stats.failures + , skip: stats.tests - stats.failures - stats.passes + , timestamp: (new Date).toUTCString() + , time: stats.duration / 1000 + }, false)); + + tests.forEach(test); + console.log(''); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +XUnit.prototype = new Base; +XUnit.prototype.constructor = XUnit; + + +/** + * Output tag for the given `test.` + */ + +function test(test) { + var attrs = { + classname: test.parent.fullTitle() + , name: test.title + , time: test.duration / 1000 + }; + + if ('failed' == test.state) { + var err = test.err; + attrs.message = escape(err.message); + console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); + } else if (test.pending) { + console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); + } else { + console.log(tag('testcase', attrs, true) ); + } +} + +/** + * HTML tag helper. + */ + +function tag(name, attrs, close, content) { + var end = close ? '/>' : '>' + , pairs = [] + , tag; + + for (var key in attrs) { + pairs.push(key + '="' + escape(attrs[key]) + '"'); + } + + tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; + if (content) tag += content + ''; +} + +}); // module: reporters/xunit.js + +require.register("runnable.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runnable'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Runnable`. + */ + +module.exports = Runnable; + +/** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Runnable(title, fn) { + this.title = title; + this.fn = fn; + this.async = fn && fn.length; + this.sync = ! this.async; + this._timeout = 2000; + this._slow = 75; + this.timedOut = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runnable.prototype = new EventEmitter; +Runnable.prototype.constructor = Runnable; + + +/** + * Set & get timeout `ms`. + * + * @param {Number} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + debug('timeout %d', ms); + this._timeout = ms; + if (this.timer) this.resetTimeout(); + return this; +}; + +/** + * 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. + * + * @return {String} + * @api public + */ + +Runnable.prototype.fullTitle = function(){ + return this.parent.fullTitle() + ' ' + this.title; +}; + +/** + * Clear the timeout. + * + * @api private + */ + +Runnable.prototype.clearTimeout = function(){ + clearTimeout(this.timer); +}; + +/** + * Inspect the runnable void of private properties. + * + * @return {String} + * @api private + */ + +Runnable.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_' == key[0]) return; + if ('parent' == key) return '#'; + if ('ctx' == key) return '#'; + return val; + }, 2); +}; + +/** + * Reset the timeout. + * + * @api private + */ + +Runnable.prototype.resetTimeout = function(){ + var self = this + , ms = this.timeout(); + + this.clearTimeout(); + if (ms) { + this.timer = setTimeout(function(){ + self.callback(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } +}; + +/** + * Run the test and invoke `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runnable.prototype.run = function(fn){ + var self = this + , ms = this.timeout() + , start = new Date + , ctx = this.ctx + , finished + , emitted; + + if (ctx) ctx.runnable(this); + + // timeout + if (this.async) { + if (ms) { + this.timer = setTimeout(function(){ + done(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } + } + + // called multiple times + function multiple(err) { + if (emitted) return; + emitted = true; + self.emit('error', err || new Error('done() called multiple times')); + } + + // finished + function done(err) { + if (self.timedOut) return; + if (finished) return multiple(err); + self.clearTimeout(); + self.duration = new Date - start; + finished = true; + fn(err); + } + + // for .resetTimeout() + this.callback = done; + + // async + if (this.async) { + try { + this.fn.call(ctx, function(err){ + if (err instanceof Error) return done(err); + if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); + done(); + }); + } catch (err) { + done(err); + } + return; + } + + // sync + try { + if (!this.pending) this.fn.call(ctx); + this.duration = new Date - start; + fn(); + } catch (err) { + fn(err); + } +}; + +}); // module: runnable.js + +require.register("runner.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runner') + , Test = require('./test') + , utils = require('./utils') + , filter = utils.filter + , keys = utils.keys + , noop = function(){}; + +/** + * Expose `Runner`. + */ + +module.exports = Runner; + +/** + * Initialize a `Runner` for the given `suite`. + * + * Events: + * + * - `start` execution started + * - `end` execution complete + * - `suite` (suite) test suite execution started + * - `suite end` (suite) all tests (and sub-suites) have finished + * - `test` (test) test execution started + * - `test end` (test) test completed + * - `hook` (hook) hook execution started + * - `hook end` (hook) hook complete + * - `pass` (test) test passed + * - `fail` (test, err) test failed + * + * @api public + */ + +function Runner(suite) { + var self = this; + this._globals = []; + this.suite = suite; + this.total = suite.total(); + this.failures = 0; + this.on('test end', function(test){ self.checkGlobals(test); }); + this.on('hook end', function(hook){ self.checkGlobals(hook); }); + this.grep(/.*/); + this.globals(utils.keys(global).concat(['errno'])); +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runner.prototype = new EventEmitter; +Runner.prototype.constructor = Runner; + + +/** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @param {RegExp} re + * @param {Boolean} invert + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.grep = function(re, invert){ + debug('grep %s', re); + this._grep = re; + this._invert = invert; + this.total = this.grepTotal(this.suite); + return this; +}; + +/** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @param {Suite} suite + * @return {Number} + * @api public + */ + +Runner.prototype.grepTotal = function(suite) { + var self = this; + var total = 0; + + suite.eachTest(function(test){ + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (match) total++; + }); + + return total; +}; + +/** + * Allow the given `arr` of globals. + * + * @param {Array} arr + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.globals = function(arr){ + if (0 == arguments.length) return this._globals; + debug('globals %j', arr); + utils.forEach(arr, function(arr){ + this._globals.push(arr); + }, this); + return this; +}; + +/** + * Check for global variable leaks. + * + * @api private + */ + +Runner.prototype.checkGlobals = function(test){ + if (this.ignoreLeaks) return; + var 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) { + this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); + } else if (leaks.length) { + this.fail(test, new Error('global leak detected: ' + leaks[0])); + } +}; + +/** + * Fail the given `test`. + * + * @param {Test} test + * @param {Error} err + * @api private + */ + +Runner.prototype.fail = function(test, err){ + ++this.failures; + test.state = 'failed'; + if ('string' == typeof err) { + err = new Error('the string "' + err + '" was thrown, throw an Error :)'); + } + this.emit('fail', test, err); +}; + +/** + * Fail the given `hook` with `err`. + * + * Hook failures (currently) hard-end due + * to that fact that a failing hook will + * surely cause subsequent tests to fail, + * causing jumbled reporting. + * + * @param {Hook} hook + * @param {Error} err + * @api private + */ + +Runner.prototype.failHook = function(hook, err){ + this.fail(hook, err); + this.emit('end'); +}; + +/** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @param {String} name + * @param {Function} function + * @api private + */ + +Runner.prototype.hook = function(name, fn){ + var suite = this.suite + , hooks = suite['_' + name] + , self = this + , timer; + + function next(i) { + var hook = hooks[i]; + if (!hook) return fn(); + self.currentRunnable = hook; + + self.emit('hook', hook); + + hook.on('error', function(err){ + self.failHook(hook, err); + }); + + hook.run(function(err){ + hook.removeAllListeners('error'); + var testError = hook.error(); + if (testError) self.fail(self.test, testError); + if (err) return self.failHook(hook, err); + self.emit('hook end', hook); + next(++i); + }); + } + + process.nextTick(function(){ + next(0); + }); +}; + +/** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err)`. + * + * @param {String} name + * @param {Array} suites + * @param {Function} fn + * @api private + */ + +Runner.prototype.hooks = function(name, suites, fn){ + var self = this + , orig = this.suite; + + function next(suite) { + self.suite = suite; + + if (!suite) { + self.suite = orig; + return fn(); + } + + self.hook(name, function(err){ + if (err) { + self.suite = orig; + return fn(err); + } + + next(suites.pop()); + }); + } + + next(suites.pop()); +}; + +/** + * Run hooks from the top level down. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookUp = function(name, fn){ + var suites = [this.suite].concat(this.parents()).reverse(); + this.hooks(name, suites, fn); +}; + +/** + * Run hooks from the bottom up. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookDown = function(name, fn){ + var suites = [this.suite].concat(this.parents()); + this.hooks(name, suites, fn); +}; + +/** + * Return an array of parent Suites from + * closest to furthest. + * + * @return {Array} + * @api private + */ + +Runner.prototype.parents = function(){ + var suite = this.suite + , suites = []; + while (suite = suite.parent) suites.push(suite); + return suites; +}; + +/** + * Run the current test and callback `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTest = function(fn){ + var test = this.test + , self = this; + + try { + test.on('error', function(err){ + self.fail(test, err); + }); + test.run(fn); + } catch (err) { + fn(err); + } +}; + +/** + * Run tests in the given `suite` and invoke + * the callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTests = function(suite, fn){ + var self = this + , tests = suite.tests + , test; + + function next(err) { + // if we bail after first err + if (self.failures && suite._bail) return fn(); + + // next test + test = tests.shift(); + + // all done + if (!test) return fn(); + + // grep + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (!match) return next(); + + // pending + if (test.pending) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + + // execute test and hook(s) + self.emit('test', self.test = test); + self.hookDown('beforeEach', function(){ + self.currentRunnable = self.test; + self.runTest(function(err){ + test = self.test; + + if (err) { + self.fail(test, err); + self.emit('test end', test); + return self.hookUp('afterEach', next); + } + + test.state = 'passed'; + self.emit('pass', test); + self.emit('test end', test); + self.hookUp('afterEach', next); + }); + }); + } + + this.next = next; + next(); +}; + +/** + * Run the given `suite` and invoke the + * callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runSuite = function(suite, fn){ + var total = this.grepTotal(suite) + , self = this + , i = 0; + + debug('run suite %s', suite.fullTitle()); + + if (!total) return fn(); + + this.emit('suite', this.suite = suite); + + function next() { + var curr = suite.suites[i++]; + if (!curr) return done(); + self.runSuite(curr, next); + } + + function done() { + self.suite = suite; + self.hook('afterAll', function(){ + self.emit('suite end', suite); + fn(); + }); + } + + this.hook('beforeAll', function(){ + self.runTests(suite, next); + }); +}; + +/** + * Handle uncaught exceptions. + * + * @param {Error} err + * @api private + */ + +Runner.prototype.uncaught = function(err){ + debug('uncaught exception %s', err.message); + var runnable = this.currentRunnable; + if (!runnable || 'failed' == runnable.state) return; + runnable.clearTimeout(); + err.uncaught = true; + this.fail(runnable, err); + + // recover from test + if ('test' == runnable.type) { + this.emit('test end', runnable); + this.hookUp('afterEach', this.next); + return; + } + + // bail on hooks + this.emit('end'); +}; + +/** + * Run the root suite and invoke `fn(failures)` + * on completion. + * + * @param {Function} fn + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.run = function(fn){ + var self = this + , fn = fn || function(){}; + + debug('start'); + + // uncaught callback + function uncaught(err) { + self.uncaught(err); + } + + // callback + this.on('end', function(){ + debug('end'); + process.removeListener('uncaughtException', uncaught); + fn(self.failures); + }); + + // run suites + this.emit('start'); + this.runSuite(this.suite, function(){ + debug('finished running'); + self.emit('end'); + }); + + // uncaught exception + process.on('uncaughtException', uncaught); + + return this; +}; + +/** + * Filter leaks with the given globals flagged as `ok`. + * + * @param {Array} ok + * @param {Array} globals + * @return {Array} + * @api private + */ + +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; + }); + return matched.length == 0 && (!global.navigator || 'onerror' !== key); + }); +} + +}); // module: runner.js + +require.register("suite.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:suite') + , milliseconds = require('./ms') + , utils = require('./utils') + , Hook = require('./hook'); + +/** + * Expose `Suite`. + */ + +exports = module.exports = Suite; + +/** + * Create a new `Suite` with the given `title` + * and parent `Suite`. When a suite with the + * same title is already present, that suite + * is returned to provide nicer reporter + * and more flexible meta-testing. + * + * @param {Suite} parent + * @param {String} title + * @return {Suite} + * @api public + */ + +exports.create = function(parent, title){ + var suite = new Suite(title, parent.ctx); + suite.parent = parent; + if (parent.pending) suite.pending = true; + title = suite.fullTitle(); + parent.addSuite(suite); + return suite; +}; + +/** + * Initialize a new `Suite` with the given + * `title` and `ctx`. + * + * @param {String} title + * @param {Context} ctx + * @api private + */ + +function Suite(title, ctx) { + this.title = title; + this.ctx = ctx; + this.suites = []; + this.tests = []; + this.pending = false; + this._beforeEach = []; + this._beforeAll = []; + this._afterEach = []; + this._afterAll = []; + this.root = !title; + this._timeout = 2000; + this._slow = 75; + this._bail = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Suite.prototype = new EventEmitter; +Suite.prototype.constructor = Suite; + + +/** + * Return a clone of this `Suite`. + * + * @return {Suite} + * @api private + */ + +Suite.prototype.clone = function(){ + var suite = new Suite(this.title); + debug('clone'); + suite.ctx = this.ctx; + suite.timeout(this.timeout()); + suite.slow(this.slow()); + suite.bail(this.bail()); + return suite; +}; + +/** + * Set timeout `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + if ('string' == 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. + * + * @parma {Boolean} bail + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.bail = function(bail){ + if (0 == arguments.length) return this._bail; + debug('bail %s', bail); + this._bail = bail; + return this; +}; + +/** + * Run `fn(test[, done])` before running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeAll = function(fn){ + 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); + return this; +}; + +/** + * Run `fn(test[, done])` after running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +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); + return this; +}; + +/** + * Run `fn(test[, done])` before each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +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); + return this; +}; + +/** + * Run `fn(test[, done])` after each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +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); + return this; +}; + +/** + * Add a test `suite`. + * + * @param {Suite} suite + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addSuite = function(suite){ + suite.parent = this; + suite.timeout(this.timeout()); + suite.slow(this.slow()); + suite.bail(this.bail()); + this.suites.push(suite); + this.emit('suite', suite); + return this; +}; + +/** + * Add a `test` to this suite. + * + * @param {Test} test + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addTest = function(test){ + test.parent = this; + test.timeout(this.timeout()); + test.slow(this.slow()); + test.ctx = this.ctx; + this.tests.push(test); + this.emit('test', test); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Suite.prototype.fullTitle = function(){ + if (this.parent) { + var full = this.parent.fullTitle(); + if (full) return full + ' ' + this.title; + } + return this.title; +}; + +/** + * Return the total number of tests. + * + * @return {Number} + * @api public + */ + +Suite.prototype.total = function(){ + return utils.reduce(this.suites, function(sum, suite){ + return sum + suite.total(); + }, 0) + this.tests.length; +}; + +/** + * Iterates through each suite recursively to find + * all tests. Applies a function in the format + * `fn(test)`. + * + * @param {Function} fn + * @return {Suite} + * @api private + */ + +Suite.prototype.eachTest = function(fn){ + utils.forEach(this.tests, fn); + utils.forEach(this.suites, function(suite){ + suite.eachTest(fn); + }); + return this; +}; + +}); // module: suite.js + +require.register("test.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Test(title, fn) { + Runnable.call(this, title, fn); + this.pending = !fn; + this.type = 'test'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Test.prototype = new Runnable; +Test.prototype.constructor = Test; + + +}); // module: test.js + +require.register("utils.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var fs = require('browser/fs') + , path = require('browser/path') + , join = path.join + , debug = require('browser/debug')('mocha:watch'); + +/** + * Ignored directories. + */ + +var ignore = ['node_modules', '.git']; + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Array#forEach (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.forEach = function(arr, fn, scope){ + for (var i = 0, l = arr.length; i < l; i++) + fn.call(scope, arr[i], i); +}; + +/** + * Array#indexOf (<=IE8) + * + * @parma {Array} arr + * @param {Object} obj to find index of + * @param {Number} start + * @api private + */ + +exports.indexOf = function(arr, obj, start){ + for (var i = start || 0, l = arr.length; i < l; i++) { + if (arr[i] === obj) + return i; + } + return -1; +}; + +/** + * Array#reduce (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} initial value + * @api private + */ + +exports.reduce = function(arr, fn, val){ + var rval = val; + + for (var i = 0, l = arr.length; i < l; i++) { + rval = fn(rval, arr[i], i, arr); + } + + return rval; +}; + +/** + * Array#filter (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @api private + */ + +exports.filter = function(arr, fn){ + var ret = []; + + for (var i = 0, l = arr.length; i < l; i++) { + var val = arr[i]; + if (fn(val, i, arr)) ret.push(val); + } + + return ret; +}; + +/** + * Object.keys (<=IE8) + * + * @param {Object} obj + * @return {Array} keys + * @api private + */ + +exports.keys = Object.keys || function(obj) { + var keys = [] + , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 + + for (var key in obj) { + if (has.call(obj, key)) { + keys.push(key); + } + } + + return keys; +}; + +/** + * Watch the given `files` for changes + * and invoke `fn(file)` on modification. + * + * @param {Array} files + * @param {Function} fn + * @api private + */ + +exports.watch = function(files, fn){ + var options = { interval: 100 }; + files.forEach(function(file){ + debug('file %s', file); + fs.watchFile(file, options, function(curr, prev){ + if (prev.mtime < curr.mtime) fn(file); + }); + }); +}; + +/** + * Ignored files. + */ + +function ignored(path){ + return !~ignore.indexOf(path); +} + +/** + * Lookup files in the given `dir`. + * + * @return {Array} + * @api private + */ + +exports.files = function(dir, ret){ + ret = ret || []; + + fs.readdirSync(dir) + .filter(ignored) + .forEach(function(path){ + path = join(dir, path); + if (fs.statSync(path).isDirectory()) { + exports.files(path, ret); + } else if (path.match(/\.(js|coffee)$/)) { + ret.push(path); + } + }); + + return ret; +}; + +/** + * Compute a slug from the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.slug = function(str){ + return str + .toLowerCase() + .replace(/ +/g, '-') + .replace(/[^-\w]/g, ''); +}; + +/** + * Strip the function definition from `str`, + * and re-indent for pre whitespace. + */ + +exports.clean = function(str) { + str = str + .replace(/^function *\(.*\) *{/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length + , re = new RegExp('^ {' + spaces + '}', 'gm'); + + str = str.replace(re, ''); + + return exports.trim(str); +}; + +/** + * Escape regular expression characters in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +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. + * + * These are meant only to allow + * mocha.js to run untouched, not + * to allow running node code in + * the browser. + */ + +process = {}; +process.exit = function(status){}; +process.stdout = {}; +global = window; + +/** + * next tick implementation. + */ + +process.nextTick = (function(){ + // postMessage behaves badly on IE8 + if (window.ActiveXObject || !window.postMessage) { + return function(fn){ fn() }; + } + + // based on setZeroTimeout by David Baron + // - http://dbaron.org/log/20100309-faster-timeouts + var timeouts = [] + , name = 'mocha-zero-timeout' + + window.addEventListener('message', function(e){ + if (e.source == window && e.data == name) { + if (e.stopPropagation) e.stopPropagation(); + if (timeouts.length) timeouts.shift()(); + } + }, true); + + return function(fn){ + timeouts.push(fn); + window.postMessage(name, '*'); + } +})(); + +/** + * Remove uncaughtException listener. + */ + +process.removeListener = function(e){ + if ('uncaughtException' == e) { + window.onerror = null; + } +}; + +/** + * Implements uncaughtException listener. + */ + +process.on = function(e, fn){ + if ('uncaughtException' == e) { + window.onerror = fn; + } +}; + +// boot +;(function(){ + + /** + * Expose mocha. + */ + + var Mocha = window.Mocha = require('mocha'), + mocha = window.mocha = new Mocha({ reporter: 'html' }); + + /** + * Override ui to ensure that the ui functions are initialized. + * Normally this would happen in Mocha.prototype.loadFiles. + */ + + 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) opts = { ui: opts }; + for (var opt in opts) this[opt](opts[opt]); + return this; + }; + + /** + * Run mocha, returning the Runner. + */ + + mocha.run = function(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/spec/apple.js b/node_modules/grunt-mocha/example/test/spec/apple.js new file mode 100644 index 0000000..f5cc3f7 --- /dev/null +++ b/node_modules/grunt-mocha/example/test/spec/apple.js @@ -0,0 +1,13 @@ +describe('Apple', function() { + beforeEach(function() { + this.apple = new Apple(); + }); + + afterEach(function() { + delete this.apple; + }); + + it('should go crunch', function() { + expect(this.apple).property('sound', 'crunch'); + }); +}); diff --git a/node_modules/grunt-mocha/example/test/spec/wombat.js b/node_modules/grunt-mocha/example/test/spec/wombat.js new file mode 100644 index 0000000..4f3918e --- /dev/null +++ b/node_modules/grunt-mocha/example/test/spec/wombat.js @@ -0,0 +1,29 @@ +describe('Wombat', function() { + beforeEach(function() { + this.wombat = new Wombat(); + }); + + afterEach(function() { + delete this.wombat; + }); + + it('should create a wombat with defaults', function() { + expect(this.wombat).property('name', 'Wally'); + }); + + it('should name itself if name passed in options', function() { + this.wombat = new Wombat({ name: 'Matt' }); + expect(this.wombat).property('name', 'Matt'); + }); + + describe('#eat', function() { + it('should throw if no food passed', function() { + expect(this.wombat.eat).to.throw('D:'); + }); + + it('should return noms if food passed', function() { + expect(this.wombat.eat('apple')).to.eql('nom nom'); + }); + }); + +}); diff --git a/node_modules/grunt-mocha/example/test/test.html b/node_modules/grunt-mocha/example/test/test.html new file mode 100644 index 0000000..658f42f --- /dev/null +++ b/node_modules/grunt-mocha/example/test/test.html @@ -0,0 +1,51 @@ + + + + + Example Mocha Test + + + + +
              + + + + + + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 0000000..a4b7b49 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/growl/History.md @@ -0,0 +1,63 @@ + +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 +================== + + * Merge pull request #16 from KyleAMathews/patch-1 + * Fixes #15 + +1.5.0 / 2012-02-08 +================== + + * Added windows support [perfusorius] + +1.4.1 / 2011-12-28 +================== + + * Fixed: dont exit(). Closes #9 + +1.4.0 / 2011-12-17 +================== + + * Changed API: `growl.notify()` -> `growl()` + +1.3.0 / 2011-12-17 +================== + + * Added support for Ubuntu/Debian/Linux users [niftylettuce] + * Fixed: send notifications even if title not specified [alessioalex] + +1.2.0 / 2011-10-06 +================== + + * Add support for priority. + +1.1.0 / 2011-03-15 +================== + + * Added optional callbacks + * Added parsing of version + +1.0.1 / 2010-03-26 +================== + + * Fixed; sys.exec -> child_process.exec to support latest node + +1.0.0 / 2010-03-19 +================== + + * Initial release diff --git a/node_modules/grunt-mocha/node_modules/growl/Readme.md b/node_modules/grunt-mocha/node_modules/growl/Readme.md new file mode 100644 index 0000000..48d717c --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/growl/Readme.md @@ -0,0 +1,99 @@ +# 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). + +## 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 + +### Ubuntu (Linux): + + Install `notify-send` through the [libnotify-bin](http://packages.ubuntu.com/libnotify-bin) package: + + $ sudo apt-get install libnotify-bin + + Install [npm](http://npmjs.org/) and run: + + $ npm install growl + +### Windows: + + Download and install [Growl for Windows](http://www.growlforwindows.com/gfw/default.aspx) + + Download [growlnotify](http://www.growlforwindows.com/gfw/help/growlnotify.aspx) - **IMPORTANT :** Unpack growlnotify to a folder that is present in your path! + + Install [npm](http://npmjs.org/) and run: + + $ npm install growl + +## Examples + +Callback functions are optional + + var growl = require('growl') + growl('You have mail!') + growl('5 new messages', { sticky: true }) + growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true }) + growl('Message with title', { title: 'Title'}) + growl('Set priority', { priority: 2 }) + growl('Show Safari icon', { image: 'Safari' }) + growl('Show icon', { image: 'path/to/icon.icns' }) + growl('Show image', { image: 'path/to/my.image.png' }) + growl('Show png filesystem icon', { image: 'png' }) + growl('Show pdf filesystem icon', { image: 'article.pdf' }) + growl('Show pdf filesystem icon', { image: 'article.pdf' }, function(err){ + // ... notified + }) + +## Options + + - title + - notification title + - name + - application name + - priority + - priority for the notification (default is 0) + - sticky + - weither or not the notification should remainin until closed + - image + - Auto-detects the context: + - path to an icon sets --iconpath + - path to an image sets --image + - capitalized word sets --appIcon + - filename uses extname as --icon + - otherwise treated as --icon + +## License + +(The MIT License) + +Copyright (c) 2009 TJ Holowaychuk + +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-mocha/node_modules/growl/lib/growl.js b/node_modules/grunt-mocha/node_modules/growl/lib/growl.js new file mode 100644 index 0000000..04f4f9b --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/growl/lib/growl.js @@ -0,0 +1,234 @@ +// Growl - Copyright TJ Holowaychuk (MIT Licensed) + +/** + * Module dependencies. + */ + +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': + 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 = { + type: "Linux" + , pkg: "notify-send" + , msg: '' + , sticky: '-t 0' + , icon: '-i' + , priority: { + cmd: '-u' + , range: [ + "low" + , "normal" + , "critical" + ] + } + }; + break; + case 'Windows_NT': + cmd = { + type: "Windows" + , pkg: "growlnotify" + , msg: '' + , sticky: '/s:true' + , title: '/t:' + , icon: '/i:' + , priority: { + cmd: '/p:' + , range: [ + -2 + , -1 + , 0 + , 1 + , 2 + ] + } + }; + break; +} + +/** + * Expose `growl`. + */ + +exports = module.exports = growl; + +/** + * Node-growl version. + */ + +exports.version = '1.4.1' + +/** + * Send growl notification _msg_ with _options_. + * + * Options: + * + * - title Notification title + * - sticky Make the notification stick (defaults to false) + * - priority Specify an int or named key (default is 0) + * - name Application name (defaults to growlnotify) + * - image + * - path to an icon sets --iconpath + * - path to an image sets --image + * - capitalized word sets --appIcon + * - filename uses extname as --icon + * - otherwise treated as --icon + * + * Examples: + * + * growl('New email') + * growl('5 new emails', { title: 'Thunderbird' }) + * growl('Email sent', function(){ + * // ... notification sent + * }) + * + * @param {string} msg + * @param {object} options + * @param {function} fn + * @api public + */ + +function growl(msg, options, fn) { + var image + , args + , options = options || {} + , fn = fn || function(){}; + + // noop + if (!cmd) return fn(new Error('growl not supported on this platform')); + args = [cmd.pkg]; + + // image + if (image = options.image) { + switch(cmd.type) { + case 'Darwin-Growl': + var flag, ext = path.extname(image).substr(1) + flag = flag || ext == 'icns' && 'iconpath' + flag = flag || /^[A-Z]/.test(image) && 'appIcon' + flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image' + flag = flag || ext && (image = ext) && 'icon' + flag = flag || 'icon' + args.push('--' + flag, image) + 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 + quote(image)); + break; + } + } + + // sticky + if (options.sticky) args.push(cmd.sticky); + + // priority + if (options.priority) { + var priority = options.priority + ''; + var checkindexOf = cmd.priority.range.indexOf(priority); + if (~cmd.priority.range.indexOf(priority)) { + args.push(cmd.priority, options.priority); + } + } + + // name + if (options.name && cmd.type === "Darwin-Growl") { + args.push('--name', options.name); + } + + switch(cmd.type) { + 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(quote(msg)); + if (options.title) args.push(quote(options.title)); + break; + case 'Linux': + if (options.title) { + args.push(quote(options.title)); + args.push(cmd.msg); + args.push(quote(msg)); + } else { + args.push(quote(msg)); + } + break; + case 'Windows': + args.push(quote(msg)); + if (options.title) args.push(cmd.title + quote(options.title)); + break; + } + + // execute + exec(args.join(' '), fn); +}; diff --git a/node_modules/grunt-mocha/node_modules/growl/package.json b/node_modules/grunt-mocha/node_modules/growl/package.json new file mode 100644 index 0000000..caf06b7 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/growl/package.json @@ -0,0 +1,14 @@ +{ + "name": "growl", + "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). \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 new file mode 100644 index 0000000..cf22d90 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/growl/test.js @@ -0,0 +1,20 @@ + +var growl = require('./lib/growl') + +growl('You have mail!') +growl('5 new messages', { sticky: true }) +growl('5 new emails', { title: 'Email Client', image: 'Safari', sticky: true }) +growl('Message with title', { title: 'Title'}) +growl('Set priority', { priority: 2 }) +growl('Show Safari icon', { image: 'Safari' }) +growl('Show icon', { image: 'path/to/icon.icns' }) +growl('Show image', { image: 'path/to/my.image.png' }) +growl('Show png filesystem icon', { image: 'png' }) +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/.npmignore b/node_modules/grunt-mocha/node_modules/temporary/.npmignore new file mode 100644 index 0000000..3b3a32f --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/.npmignore @@ -0,0 +1,22 @@ +tmp +node_modules +*._ +*.tmp +.monitor +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.vi +*~ +.DS_Store +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject diff --git a/node_modules/grunt-mocha/node_modules/temporary/.travis.yml b/node_modules/grunt-mocha/node_modules/temporary/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 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/Makefile b/node_modules/grunt-mocha/node_modules/temporary/Makefile new file mode 100644 index 0000000..98957d6 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/Makefile @@ -0,0 +1,11 @@ +TESTS = test/*.test.js + +test: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter spec \ + $(TESTS) + +clean: + rm -f examples/tmp/* + +.PHONY: test clean diff --git a/node_modules/grunt-mocha/node_modules/temporary/Readme.md b/node_modules/grunt-mocha/node_modules/temporary/Readme.md new file mode 100644 index 0000000..858510f --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/Readme.md @@ -0,0 +1,82 @@ +[![Build Status](https://secure.travis-ci.org/vesln/temporary.png)](http://travis-ci.org/vesln/temporary) + +# temporary - The lord of tmp. + +## Intro + +Temporary provides an easy way to create temporary files and directories. +It will create a temporary file/directory with a unique name. + +## Features + +- Generates unique name. +- Auto-discovers tmp dir. + +## Installation + + $ npm install temporary + +## Usage + + var Tempfile = require('temporary/file'); + var Tempdir = require('temporary/dir'); + var file = new Tempfile; + var dir = new Tempdir; + + console.log(file.path); // path. + console.log(dir.path); // path. + + file.unlink(); + dir.rmdir(); + +## Methods + +### File + +- File.readFile +- File.readFileSync +- File.writeFile +- File.writeFileSync +- File.open +- File.openSync +- File.close +- File.closeSync +- File.unlink +- File.unlinkSync + +### Dir + +- Dir.rmdir +- Dir.rmdirSync + +## Tests + + $ make test + +## Contribution + +Bug fixes and features are welcomed. + +## License + +MIT License + +Copyright (C) 2012 Veselin Todorov + +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. \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/dir.js b/node_modules/grunt-mocha/node_modules/temporary/dir.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-mocha/node_modules/temporary/examples/dir.js b/node_modules/grunt-mocha/node_modules/temporary/examples/dir.js new file mode 100644 index 0000000..5182b83 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/examples/dir.js @@ -0,0 +1,18 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +var Tempdir = require('../lib/dir'); +var dir = new Tempdir('foo') // name - optional + +console.log(dir.path); // path. + +/** + * You can also use: + * + * dir.rmdir + * dir.rmdirSync + */ \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/examples/file.js b/node_modules/grunt-mocha/node_modules/temporary/examples/file.js new file mode 100644 index 0000000..6a3fe31 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/examples/file.js @@ -0,0 +1,26 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +var Tempfile = require('../lib/file'); +var file = new Tempfile('foo') // name - optional + +console.log(file.path); // file path. + +/** + * You can also use: + * + * file.readFile + * file.readFileSync + * file.writeFile + * file.writeFileSync + * file.open + * file.openSync + * file.close + * file.closeSync + * file.unlink + * file.unlinkSync + */ \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/file.js b/node_modules/grunt-mocha/node_modules/temporary/file.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-mocha/node_modules/temporary/index.js b/node_modules/grunt-mocha/node_modules/temporary/index.js new file mode 100644 index 0000000..b1ec2b7 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/index.js @@ -0,0 +1,26 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('package')(module); + +/** + * Version. + */ +module.exports.version = package.version; + +/** + * Exporting the temp file + */ +module.exports.File = require('./file'); + +/** + * Exporting the temp directory. + */ +module.exports.Dir = require('./dir'); \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/lib/base.js b/node_modules/grunt-mocha/node_modules/temporary/lib/base.js new file mode 100644 index 0000000..a3e95c8 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/base.js @@ -0,0 +1,80 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); + +/** + * Base constructor. + * + * @param {String|null} name + */ +function Base(name) { + this.init(name); +}; + +/** + * Initializes the class. + * + * @param {String|null} name + */ +Base.prototype.init = function(name) { + var filename = generator.build(name); + this.create(filename); + this.path = filename; +}; + +/** + * Converts the arguments object to array and + * append `this.path` as first element. + * + * @returns {Array} + */ +Base.prototype.prepareArgs = function(args) { + args = Array.prototype.slice.call(args); + args.unshift(this.path); + return args; +}; + +/** + * Renames the dir/file. + * + * @param {String} name + * @param {Function} cb Callback. + */ +Base.prototype.rename = function(name, cb) { + var self = this; + var args = arguments; + var tmp = path.normalize(path.dirname(self.path) + '/' + name); + + fs.rename(this.path, tmp, function(err) { + self.path = tmp; + if (args.length === 2) cb(err); + }); +}; + +/** + * Renames the dir/file sync. + * + * @param {String} name + */ +Base.prototype.renameSync = function(name) { + var tmp = path.normalize(path.dirname(this.path) + '/' + name); + var result = fs.renameSync(this.path, tmp); + this.path = tmp; + return result; +}; + +/** + * Exporting the lib. + */ +module.exports = Base; diff --git a/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js b/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js new file mode 100644 index 0000000..c09b46d --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/detector.js @@ -0,0 +1,44 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Detection stolen from NPM (https://github.com/isaacs/npm/) + * + * Copyright 2009, 2010, 2011 Isaac Z. Schlueter (the "Author") + * MIT License (https://github.com/isaacs/npm/blob/master/LICENSE) + */ + +/** + * Detector namespace. + * + * @type {Object} + */ +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() { + 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/lib/dir.js b/node_modules/grunt-mocha/node_modules/temporary/lib/dir.js new file mode 100644 index 0000000..73acecc --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/dir.js @@ -0,0 +1,57 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); +var Base = require('./base'); + +/** + * Dir constructor. + * + * @param {String|null} name + */ +function Dir(name) { + this.init(name); +}; + +/** + * Dir extends from tmp. + */ +Dir.prototype.__proto__ = Base.prototype; + +/** + * Creates new file. + * + * @param {String} dirname + */ +Dir.prototype.create = function(dirname) { + return fs.mkdirSync(path.normalize(dirname), 0777); +}; + +/** + * Asynchronous dir. + */ +Dir.prototype.rmdir = function() { + fs.rmdir.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous rmdir. + */ +Dir.prototype.rmdirSync = function() { + return fs.rmdirSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Exporting the lib. + */ +module.exports = Dir; diff --git a/node_modules/grunt-mocha/node_modules/temporary/lib/file.js b/node_modules/grunt-mocha/node_modules/temporary/lib/file.js new file mode 100644 index 0000000..49de026 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/file.js @@ -0,0 +1,113 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var generator = require('./generator'); +var detector = require('./detector'); +var Base = require('./base'); + +/** + * File constructor. + * + * @param {String|null} name + */ +function File(name) { + this.init(name); +}; + +/** + * File extends from tmp. + */ +File.prototype.__proto__ = Base.prototype; + +/** + * Creates new file. + * + * @param {String} filename + */ +File.prototype.create = function(filename) { + return fs.writeFileSync(path.normalize(filename), ''); +}; + +/** + * Asynchronously reads the entire contents of a file. + */ +File.prototype.readFile = function() { + fs.readFile.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous read. + */ +File.prototype.readFileSync = function() { + return fs.readFileSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronously writes data to a file. + */ +File.prototype.writeFile = function() { + fs.writeFile.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous writes data to a file. + */ +File.prototype.writeFileSync = function() { + return fs.writeFileSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronous file open. + */ +File.prototype.open = function() { + fs.open.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous open. + */ +File.prototype.openSync = function() { + return fs.openSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Asynchronous close. + */ +File.prototype.close = function() { + fs.close.apply(fs, Array.prototype.slice.call(arguments)); +}; + +/** + * Synchronous close. + */ +File.prototype.closeSync = function() { + return fs.closeSync.apply(fs, Array.prototype.slice.call(arguments)); +}; + +/** + * Asynchronous unlink. + */ +File.prototype.unlink = function() { + fs.unlink.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Synchronous unlink. + */ +File.prototype.unlinkSync = function() { + return fs.unlinkSync.apply(fs, this.prepareArgs(arguments)); +}; + +/** + * Exporting the lib. + */ +module.exports = File; diff --git a/node_modules/grunt-mocha/node_modules/temporary/lib/generator.js b/node_modules/grunt-mocha/node_modules/temporary/lib/generator.js new file mode 100644 index 0000000..a68f0ba --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/lib/generator.js @@ -0,0 +1,48 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var detector = require('./detector'); +var existsSync = fs.existsSync || path.existsSync; + +/** + * Generator namespace. + * + * @type {Object} + */ +var generator = module.exports; + +/** + * Generates random name. + * + * @returns {String} + */ +generator.name = function() { + var id = null; + var tmp = detector.tmp(); + do { + id = Date.now() + Math.random(); + } while(existsSync(tmp + '/' + id)); + + return id + ''; +}; + +/** + * Buld a full name. (tmp dir + name). + * + * @param {String} name + * @returns {String} + */ +generator.build = function(name) { + var filename = detector.tmp(); + if (name) filename += name + '.'; + return filename + this.name(); +}; diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.npmignore b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.npmignore new file mode 100644 index 0000000..3b3a32f --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.npmignore @@ -0,0 +1,22 @@ +tmp +node_modules +*._ +*.tmp +.monitor +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.vi +*~ +.DS_Store +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.travis.yml b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.travis.yml new file mode 100644 index 0000000..b8e1f17 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/History.md b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/History.md new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Makefile b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Makefile new file mode 100644 index 0000000..277485c --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Makefile @@ -0,0 +1,12 @@ +TESTS = $(shell find test -iname \*.test.js) + +test: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + $(TESTS) + +clean: + rm -f examples/tmp/* + +.PHONY: test clean \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Readme.md b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Readme.md new file mode 100644 index 0000000..c531965 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/Readme.md @@ -0,0 +1,54 @@ +[![Build Status](https://secure.travis-ci.org/vesln/package.png)](http://travis-ci.org/vesln/package) + +# package - Easy package.json exports. + +## Intro + +This module provides an easy and simple way to export package.json data. + +## Installation + + $ npm install package + +## Usage + + var package = require('package')(module); // contains package.json data. + var yourAwesomeModule = {}; + yourAwesomeModule.version = package.version; + +## Tests + + $ make test + +## Contribution + +Bug fixes and features are welcomed. + +## Other similar modules + +- pkginfo (https://github.com/indexzero/node-pkginfo) by indexzero. +- JSON.parse + fs.readFile + +## License + +MIT License + +Copyright (C) 2012 Veselin Todorov + +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. \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/custom_path.js b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/custom_path.js new file mode 100644 index 0000000..a03c0cc --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/custom_path.js @@ -0,0 +1,14 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ + +var package = require('../')(__dirname + '/..'); // parent dir. + +console.log(package); // This will contain the package.json data. \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/module.js b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/module.js new file mode 100644 index 0000000..c479069 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/examples/module.js @@ -0,0 +1,14 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ + +var package = require('../')(module); + +console.log(package); // This will contain the package.json data. \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/lib/package.js b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/lib/package.js new file mode 100644 index 0000000..348db0c --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/lib/package.js @@ -0,0 +1,64 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var exists = fs.existsSync || path.existsSync; + +/** + * Package. + * + * @param {String|null} location + * @returns {Object} package.json data + */ +var package = function(location) { + if (location === Object(location)) { + location = package.discover(location); + } + return package.read(path.normalize(location + '/package.json')); +}; + +/** + * Reads and parses a package.json file. + * + * @param {String} file + * @returns {Object} package.json data + */ +package.read = function(file) { + var data = fs.readFileSync(file, 'utf8'); + return JSON.parse(data); +}; + +/** + * Makes an atempt to find package.json file. + * + * @returns {Object} package.json data + */ +package.discover = function(module) { + var location = path.dirname(module.filename); + var found = null; + + while (!found) { + if (exists(location + '/package.json')) { + found = location; + } else if (location !== '/') { + location = path.dirname(location); + } else { + throw new Error('package.json can not be located'); + } + } + + return found; +}; + +/** + * Exporting the lib. + */ +module.exports = package; 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 new file mode 100644 index 0000000..3df7344 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/package.json @@ -0,0 +1,32 @@ +{ + "name": "package", + "version": "1.0.1", + "description": "Easy package.json exports.", + "keywords": [ + "package.json" + ], + "author": { + "name": "Veselin Todorov", + "email": "hi@vesln.com" + }, + "devDependencies": { + "mocha": "0.3.3", + "should": "0.3.2" + }, + "repository": { + "type": "git", + "url": "http://github.com/vesln/package.git" + }, + "homepage": "http://github.com/vesln/package", + "scripts": { + "test": "make test" + }, + "main": "./lib/package", + "engines": { + "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/node_modules/package/test/index.test.js b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/index.test.js new file mode 100644 index 0000000..c43364b --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/index.test.js @@ -0,0 +1,42 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('../'); + +describe('package', function() { + describe('read', function() { + it('should read and parse .json file', function() { + var result = package.read(__dirname + '/support/package.json'); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); + }); + + it('should read and parse given .json file', function() { + var result = package(__dirname + '/support'); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); + + it('should autodiscover, read and parse package.json', function() { + var result = package(module); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js new file mode 100644 index 0000000..99c012e --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/nested/two/nested.test.js @@ -0,0 +1,22 @@ +/** + * package - Easy package.json exports. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var package = require('../../../'); + +describe('nested package json', function() { + it('should autodiscover, read and parse package.json', function() { + var result = package(module); + result.should.eql({ + name: 'test-package-json-file', + version: '0.0.1', + private: true + }); + }); +}); \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/package.json b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/package.json new file mode 100644 index 0000000..ed5e671 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-package-json-file" + , "version": "0.0.1" + , "private": true +} \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/support/package.json b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/support/package.json new file mode 100644 index 0000000..ed5e671 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/node_modules/package/test/support/package.json @@ -0,0 +1,5 @@ +{ + "name": "test-package-json-file" + , "version": "0.0.1" + , "private": true +} \ No newline at end of file diff --git a/node_modules/grunt-mocha/node_modules/temporary/package.json b/node_modules/grunt-mocha/node_modules/temporary/package.json new file mode 100644 index 0000000..0b67aae --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/package.json @@ -0,0 +1,39 @@ +{ + "name": "temporary", + "version": "0.0.5", + "description": "The lord of tmp.", + "keywords": [ + "tmp", + "temp", + "tempfile", + "tempdirectory" + ], + "author": { + "name": "Veselin Todorov", + "email": "hi@vesln.com" + }, + "dependencies": { + "package": ">= 1.0.0 < 1.2.0" + }, + "devDependencies": { + "mocha": "1.2.x", + "chai": "*", + "sinon": "1.2.0" + }, + "repository": { + "type": "git", + "url": "http://github.com/vesln/temporary.git" + }, + "homepage": "http://github.com/vesln/temporary", + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "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.", + "readmeFilename": "Readme.md", + "_id": "temporary@0.0.5", + "_from": "temporary@~0.0.2" +} diff --git a/node_modules/grunt-mocha/node_modules/temporary/test/base.test.js b/node_modules/grunt-mocha/node_modules/temporary/test/base.test.js new file mode 100644 index 0000000..2fdea28 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/test/base.test.js @@ -0,0 +1,57 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var path = require('path'); +var fs = require('fs'); +var existsSync = fs.existsSync || path.existsSync; + +var Base = require('../lib/base'); +var generator = require('../lib/generator'); +var should = require('chai').should(); + +Base.prototype.create = function() {}; + +describe('Base', function() { + describe('rename', function() { + it('should rename the directory', function(done) { + var tmp = new Base; + tmp.path = generator.build(); + fs.mkdirSync(path.normalize(tmp.path), 0777); + existsSync(tmp.path).should.be.ok; + tmp.rename('foo', function(err) { + existsSync(tmp.path).should.be.ok; + done(); + }); + }); + }); + + describe('renameSync', function() { + it('should rename the directory', function() { + var tmp = new Base('foo'); + tmp.path = generator.build(); + fs.mkdirSync(path.normalize(tmp.path), 0777); + var oldPath = tmp.path; + existsSync(tmp.path).should.be.ok; + tmp.renameSync('foo3'); + existsSync(tmp.path).should.be.ok; + path.should.not.eql(oldPath); + }); + }); + + describe('prepareArgs', function() { + it('should convert object to array and append path as first element', function() { + var tmp = new Base('foo'); + var args = { 0: 'foo' }; + args.length = 1; + tmp.path = generator.build(); + tmp.prepareArgs(args).should.eql([tmp.path, 'foo']); + }); + }); +}); diff --git a/node_modules/grunt-mocha/node_modules/temporary/test/detector.test.js b/node_modules/grunt-mocha/node_modules/temporary/test/detector.test.js new file mode 100644 index 0000000..ed48366 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/test/detector.test.js @@ -0,0 +1,24 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var detector = require('../lib/detector'); +var should = require('chai').should(); + +describe('detector', function() { + describe('tmp', function() { + it('should return the tmp dir of the system', function() { + var tmp = process.env.TMPDIR + || process.env.TMP + || process.env.TEMP + || (process.platform === "win32" ? "c:\\windows\\temp\\" : "/tmp/"); + detector.tmp().should.eql(tmp); + }); + }); +}); diff --git a/node_modules/grunt-mocha/node_modules/temporary/test/dir.test.js b/node_modules/grunt-mocha/node_modules/temporary/test/dir.test.js new file mode 100644 index 0000000..8875a88 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/test/dir.test.js @@ -0,0 +1,44 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var fs = require('fs'); +var path = require('path'); +var existsSync = fs.existsSync || path.existsSync; + +var Tempdir = require('../lib/dir'); +var sinon = require('sinon'); +var should = require('chai').should(); + +describe('Tempdir', function() { + it('should create file', function() { + var tmp = new Tempdir('foo'); + existsSync(tmp.path).should.be.ok; + }); + + describe('rmdir', function() { + it('should remove the directory', function() { + var tmp = new Tempdir('foo'); + sinon.spy(fs, 'rmdir'); + tmp.rmdir(); + fs.rmdir.getCall(0).args[0].should.eql(tmp.path); + fs.rmdir.restore(); + }); + }); + + describe('rmdirSync', function() { + it('should remove the directory', function() { + var tmp = new Tempdir('foo'); + sinon.spy(fs, 'rmdirSync'); + tmp.rmdirSync(); + fs.rmdirSync.getCall(0).args[0].should.eql(tmp.path); + fs.rmdirSync.restore(); + }); + }); +}); diff --git a/node_modules/grunt-mocha/node_modules/temporary/test/file.test.js b/node_modules/grunt-mocha/node_modules/temporary/test/file.test.js new file mode 100644 index 0000000..9927e31 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/test/file.test.js @@ -0,0 +1,126 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var path = require('path'); +var fs = require('fs'); +var existsSync = fs.existsSync || path.existsSync; + +var Tempfile = require('../lib/file'); +var sinon = require('sinon'); +var should = require('chai').should(); + +describe('Tempfile', function() { + it('should create file', function() { + var tmp = new Tempfile('foo'); + existsSync(tmp.path).should.be.ok; + }); + + describe('readFile', function() { + it('should call fs.readfile', function() { + sinon.spy(fs, 'readFile'); + var tmp = new Tempfile; + tmp.readFile(); + fs.readFile.getCall(0).args[0].should.eql(tmp.path); + fs.readFile.restore(); + }); + }); + + describe('readFileSync', function() { + it('should call fs.readfileSync', function() { + sinon.spy(fs, 'readFileSync'); + var tmp = new Tempfile; + tmp.readFileSync(); + fs.readFileSync.getCall(0).args[0].should.eql(tmp.path); + fs.readFileSync.restore(); + }); + }); + + describe('writeFile', function() { + it('should call fs.readfile', function() { + sinon.spy(fs, 'writeFile'); + var tmp = new Tempfile; + tmp.writeFile(); + fs.writeFile.getCall(0).args[0].should.eql(tmp.path); + fs.writeFile.restore(); + }); + }); + + describe('writeFileSync', function() { + it('should call fs.writeFileSync', function() { + sinon.spy(fs, 'writeFileSync'); + var tmp = new Tempfile; + tmp.writeFileSync(); + fs.writeFileSync.getCall(0).args[0].should.eql(tmp.path); + fs.writeFileSync.restore(); + }); + }); + + describe('open', function() { + it('should call fs.open', function() { + sinon.spy(fs, 'open'); + var tmp = new Tempfile; + tmp.open('r'); + fs.open.getCall(0).args[0].should.eql(tmp.path); + fs.open.restore(); + }); + }); + + describe('openSync', function() { + it('should call fs.openSync', function() { + sinon.spy(fs, 'openSync'); + var tmp = new Tempfile; + tmp.openSync('r'); + fs.openSync.getCall(0).args[0].should.eql(tmp.path); + fs.openSync.restore(); + }); + }); + + describe('close', function() { + it('should call fs.close', function() { + sinon.spy(fs, 'close'); + var tmp = new Tempfile; + var fd = tmp.openSync('r'); + tmp.close(fd); + fs.close.getCall(0).args[0].should.eql(fd); + fs.close.restore(); + }); + }); + + describe('closeSync', function() { + it('should call fs.closeSync', function() { + sinon.spy(fs, 'closeSync'); + var tmp = new Tempfile; + var fd = tmp.openSync('r'); + tmp.closeSync(fd); + fs.closeSync.getCall(0).args[0].should.eql(fd); + fs.closeSync.restore(); + }); + }); + + describe('unlink', function() { + it('should call fs.unlink', function() { + sinon.spy(fs, 'unlink'); + var tmp = new Tempfile; + tmp.unlink(); + fs.unlink.getCall(0).args[0].should.eql(tmp.path); + fs.unlink.restore(); + }); + }); + + describe('unlinkSync', function() { + it('should call fs.readfileSync', function() { + sinon.spy(fs, 'unlinkSync'); + var tmp = new Tempfile; + tmp.unlinkSync(); + fs.unlinkSync.getCall(0).args[0].should.eql(tmp.path); + fs.unlinkSync.restore(); + }); + }); +}); diff --git a/node_modules/grunt-mocha/node_modules/temporary/test/generator.test.js b/node_modules/grunt-mocha/node_modules/temporary/test/generator.test.js new file mode 100644 index 0000000..2483a91 --- /dev/null +++ b/node_modules/grunt-mocha/node_modules/temporary/test/generator.test.js @@ -0,0 +1,29 @@ +/** + * Temporary - The lord of tmp. + * + * Author: Veselin Todorov + * Licensed under the MIT License. + */ + +/** + * Dependencies. + */ +var generator = require('../lib/generator'); +var detector = require('../lib/detector'); +var should = require('chai').should(); + +describe('generator', function() { + describe('name', function() { + it('should unique generate name', function() { + generator.name().should.be.ok; + }); + }); + + describe('build', function() { + it('should build full names', function() { + var tmp = detector.tmp(); + generator.build().should.match(new RegExp("^" + tmp)); + generator.build('foo').should.match(new RegExp("^" + tmp + 'foo.')); + }); + }); +}); diff --git a/node_modules/grunt-mocha/package.json b/node_modules/grunt-mocha/package.json new file mode 100644 index 0000000..0958781 --- /dev/null +++ b/node_modules/grunt-mocha/package.json @@ -0,0 +1,45 @@ +{ + "name": "grunt-mocha", + "description": "Grunt task for running Mocha specs", + "version": "0.1.7", + "homepage": "https://github.com/kmiyashiro/grunt-mocha", + "author": { + "name": "Kelly Miyashiro", + "email": "miyashiro.kelly@gmail.com", + "url": "http://non-diligent.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/kmiyashiro/grunt-mocha.git" + }, + "bugs": { + "url": "https://github.com/kmiyashiro/grunt-mocha/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/kmiyashiro/grunt-mocha/blob/master/LICENSE-MIT" + } + ], + "main": "grunt.js", + "engines": { + "node": "*" + }, + "dependencies": { + "temporary": "~0.0.2", + "growl": "~1" + }, + "devDependencies": { + "grunt": "~0.3" + }, + "optionalDependencies": { + "growl": "~1" + }, + "keywords": [ + "gruntplugin" + ], + "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 new file mode 100644 index 0000000..d15c539 --- /dev/null +++ b/node_modules/grunt-mocha/tasks/mocha.js @@ -0,0 +1,307 @@ +// Important: You must install `temporary`: `npm install` +/* + * grunt + * https://github.com/cowboy/grunt + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * http://benalman.com/about/license/ + * + * Mocha task + * Copyright (c) 2012 Kelly Miyashiro + * Licensed under the MIT license. + * http://benalman.com/about/license/ + */ + +module.exports = function(grunt) { + // Grunt utilities. + var task = grunt.task; + var file = grunt.file; + var utils = grunt.utils; + var log = grunt.log; + var verbose = grunt.verbose; + var fail = grunt.fail; + var option = grunt.option; + var config = grunt.config; + var template = grunt.template; + + // Nodejs libs. + var fs = require('fs'); + var path = require('path'); + + // External libs. + var Tempfile = require('temporary/lib/file'); + var growl; + + // Growl is optional + try { + growl = require('growl'); + } catch(e) { + growl = function(){}; + verbose.write('Growl not found, npm install growl for Growl support'); + } + + // Keep track of the last-started module, test and status. + var currentModule, currentTest, status; + // Keep track of the last-started test(s). + var unfinished = {}; + + // Allow an error message to retain its color when split across multiple lines. + function formatMessage(str) { + return String(str).split('\n').map(function(s) { return s.magenta; }).join('\n'); + } + + // Keep track of failed assertions for pretty-printing. + var failedAssertions = []; + function logFailedAssertions() { + var assertion; + // Print each assertion error. + while (assertion = failedAssertions.shift()) { + verbose.or.error(assertion.testName); + log.error('Message: ' + formatMessage(assertion.message)); + if (assertion.actual !== assertion.expected) { + log.error('Actual: ' + formatMessage(assertion.actual)); + log.error('Expected: ' + formatMessage(assertion.expected)); + } + if (assertion.source) { + log.error(assertion.source.replace(/ {4}(at)/g, ' $1')); + } + log.writeln(); + } + } + + // Handle methods passed from PhantomJS, including Mocha hooks. + var phantomHandlers = { + // Mocha hooks. + suiteStart: function(name) { + unfinished[name] = true; + currentModule = name; + }, + suiteDone: function(name, failed, passed, total) { + delete unfinished[name]; + }, + testStart: function(name) { + currentTest = (currentModule ? currentModule + ' - ' : '') + name; + verbose.write(currentTest + '...'); + }, + testFail: function(name, result) { + result.testName = currentTest; + failedAssertions.push(result); + }, + testDone: function(title, state) { + // Log errors if necessary, otherwise success. + if (state == 'failed') { + // list assertions + if (option('verbose')) { + log.error(); + logFailedAssertions(); + } else { + log.write('F'.red); + } + } else { + verbose.ok().or.write('.'); + } + }, + done: function(failed, passed, total, duration) { + var nDuration = parseFloat(duration) || 0; + status.failed += failed; + status.passed += passed; + status.total += total; + status.duration += Math.round(nDuration*100)/100; + // Print assertion errors here, if verbose mode is disabled. + if (!option('verbose')) { + if (failed > 0) { + log.writeln(); + logFailedAssertions(); + } else { + log.ok(); + } + } + }, + // Error handlers. + done_fail: function(url) { + verbose.write('Running PhantomJS...').or.write('...'); + log.error(); + grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90); + }, + done_timeout: function() { + log.writeln(); + grunt.warn('PhantomJS timed out, possibly due to a missing Mocha run() call.', 90); + }, + + // console.log pass-through. + // console: console.log.bind(console), + // Debugging messages. + debug: log.debug.bind(log, 'phantomjs') + }; + + // ========================================================================== + // TASKS + // ========================================================================== + + 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(); + + // Reset status. + status = {failed: 0, passed: 0, total: 0, duration: 0}; + + // Process each filepath in-order. + utils.async.forEachSeries(urls, function(url, next) { + var basename = path.basename(url); + verbose.subhead('Testing ' + basename).or.write('Testing ' + basename); + + // Create temporary file to be used for grunt-phantom communication. + var tempfile = new Tempfile(); + // Timeout ID. + var id; + // The number of tempfile lines already read. + var n = 0; + + // Reset current module. + currentModule = null; + + // Clean up. + function cleanup() { + clearTimeout(id); + tempfile.unlink(); + } + + // It's simple. As Mocha tests, assertions and modules begin and complete, + // the results are written as JSON to a temporary file. This polling loop + // checks that file for new lines, and for each one parses its JSON and + // executes the corresponding method with the specified arguments. + (function loopy() { + // Disable logging temporarily. + log.muted = true; + // Read the file, splitting lines on \n, and removing a trailing line. + var lines = file.read(tempfile.path).split('\n').slice(0, -1); + // Re-enable logging. + log.muted = false; + // Iterate over all lines that haven't already been processed. + var done = lines.slice(n).some(function(line) { + // Get args and method. + var args = JSON.parse(line); + 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, + // but stops further iteration from occurring. + return (/^done/).test(method); + }); + + if (done) { + // All done. + cleanup(); + next(); + } else { + // Update n so previously processed lines are ignored. + n = lines.length; + // Check back in a little bit. + id = setTimeout(loopy, 100); + } + }()); + + // Launch PhantomJS. + grunt.helper('phantomjs', { + code: 90, + args: [ + // The main script file. + task.getFile('mocha/phantom-mocha-runner.js'), + // The temporary file used for communications. + tempfile.path, + // The Mocha helper file to be injected. + // task.getFile('../test/run-mocha.js'), + 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') + ], + done: function(err) { + if (err) { + cleanup(); + done(); + } + }, + }); + }, function(err) { + // All tests have been run. + + // Log results. + if (status.failed > 0) { + growl(status.failed + ' of ' + status.total + ' tests failed!', { + image: __dirname + '/mocha/error.png', + title: 'Tests Failed', + priority: 3 + }); + grunt.warn(status.failed + '/' + status.total + ' assertions failed (' + + status.duration + 's)', Math.min(99, 90 + status.failed)); + } else { + growl('All Clear: ' + status.total + ' tests passed', { + title: 'Tests Passed', + image: __dirname + '/mocha/ok.png' + }); + verbose.writeln(); + log.ok(status.total + ' assertions passed (' + status.duration + 's)'); + } + + // All done! + done(); + }); + }); + + // ========================================================================== + // HELPERS + // ========================================================================== + + grunt.registerHelper('phantomjs', function(options) { + return utils.spawn({ + cmd: 'phantomjs', + args: options.args + }, function(err, result, code) { + if (!err) { return options.done(null); } + // Something went horribly wrong. + verbose.or.writeln(); + log.write('Running PhantomJS...').error(); + if (code === 127) { + log.errorlns( + 'In order for this task to work properly, PhantomJS 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. ' + + 'See the grunt FAQ for PhantomJS installation instructions: ' + + 'https://github.com/cowboy/grunt/blob/master/docs/faq.md' + ); + grunt.warn('PhantomJS not found.', options.code); + } else { + result.split('\n').forEach(log.error, log); + grunt.warn('PhantomJS exited unexpectedly with exit code ' + code + '.', options.code); + } + options.done(code); + }); + }); + +}; diff --git a/node_modules/grunt-mocha/tasks/mocha/error.png b/node_modules/grunt-mocha/tasks/mocha/error.png new file mode 100644 index 0000000..490822a Binary files /dev/null and b/node_modules/grunt-mocha/tasks/mocha/error.png differ diff --git a/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js b/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js new file mode 100644 index 0000000..b8aae3f --- /dev/null +++ b/node_modules/grunt-mocha/tasks/mocha/mocha-helper.js @@ -0,0 +1,96 @@ +/* + * Is injected into the spec runner file + + * Copyright (c) 2012 Kelly Miyashiro + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * http://benalman.com/about/license/ + */ + +/*global mocha:true, alert:true*/ + +(function() { + // Send messages to the parent phantom.js process via alert! Good times!! + function sendMessage() { + var args = [].slice.call(arguments); + alert(JSON.stringify(args)); + } + + var GruntReporter = function(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); + }); + }; + + 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(); + } + } +}()); diff --git a/node_modules/grunt-mocha/tasks/mocha/ok.png b/node_modules/grunt-mocha/tasks/mocha/ok.png new file mode 100644 index 0000000..2983c0b Binary files /dev/null and b/node_modules/grunt-mocha/tasks/mocha/ok.png differ diff --git a/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js b/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js new file mode 100644 index 0000000..1aac8ca --- /dev/null +++ b/node_modules/grunt-mocha/tasks/mocha/phantom-mocha-runner.js @@ -0,0 +1,112 @@ +/* + * grunt + * https://github.com/cowboy/grunt + * + * Adapated for Mocha by Kelly Miyashiro (miyashiro.kelly@gmail.com) + * + * Copyright (c) 2012 "Cowboy" Ben Alman + * Licensed under the MIT license. + * http://benalman.com/about/license/ + */ + +/*global phantom:true*/ + +var fs = require('fs'); +var system = require('system'); + +// The temporary file used for communications. +var tmpfile = system.args[1]; +// The Mocha helper file to be injected. +var mochaHelper = system.args[2]; +// The Mocha .html test file to run. +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(); + +// Messages are sent to the parent by appending them to the tempfile. +function sendMessage(args) { + last = new Date(); + fs.write(tmpfile, JSON.stringify(args) + '\n', 'a'); + // Exit when all done. + if (/^done/.test(args[0])) { + phantom.exit(); + } +} + +// Send a debugging message. +function sendDebugMessage() { + sendMessage(['debug'].concat([].slice.call(arguments))); +} + +// Abort if Mocha doesn't do anything for a while. +setInterval(function() { + if (new Date() - last > 5000) { + sendMessage(['done_timeout']); + } +}, 1000); + +// Create a new page. +var page = require('webpage').create(); + +// Mocha sends its messages via alert(jsonstring); +page.onAlert = function(args) { + sendMessage(JSON.parse(args)); +}; + +page.onError = function(msg, trace) { + var error = 'Page error: ' + msg + '\n'; + trace.forEach(function(item) { + error += ' ' + item.file + ':' + item.line + '\n'; + }); + sendDebugMessage(error); +}; + +// Additional message sending +page.onConsoleMessage = function(message) { + var output; + sendMessage(['console', message]); +}; + +// Keep track if Mocha has been injected already +var injected; + +page.onResourceRequested = function(request) { + if (/\/mocha\.js$/.test(request.url)) { + // Reset injected to false, if for some reason a redirect occurred and + // the test page (including mocha.js) had to be re-requested. + injected = false; + } + sendDebugMessage('onResourceRequested', request.url); +}; +page.onResourceReceived = function(request) { + if (request.stage === 'end') { + sendDebugMessage('onResourceReceived', request.url); + } +}; + +page.onInitialized = function() { + page.evaluate(function(config) { + window.PHANTOMJS = config ? JSON.parse(config) : {}; + }, configStr); +}; + +page.open(url, function(status) { + // Only execute this code if Mocha has not yet been injected. + if (injected) { return; } + injected = true; + // The window has loaded. + if (status !== 'success') { + // File loading failure. + sendMessage(['done_fail', url]); + } else { + // Inject Mocha helper file. + sendDebugMessage('inject', mochaHelper); + page.injectJs(mochaHelper); + // Because injection happens after window load, "begin" must be sent + // manually. + sendMessage(['begin']); + } +}); diff --git a/node_modules/grunt-mocha/tasks/mocha/phantom.json b/node_modules/grunt-mocha/tasks/mocha/phantom.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/node_modules/grunt-mocha/tasks/mocha/phantom.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..836bc89 --- /dev/null +++ b/package.json @@ -0,0 +1,48 @@ +{ + "name": "jquery-endless-scroll", + "version": "2.0.0", + "title": "jQuery Endless Scroll", + "author": { + "name": "Fred Wu", + "url": "http://fredwu.me/" + }, + "repository": { + "type": "git", + "url": "git://github.com/fredwu/jquery-endless-scroll.git" + }, + "bugs": { + "url": "https://github.com/fredwu/jquery-endless-scroll/issues" + }, + "licenses": [{ + "type": "MIT", + "url": "http://fredwu.mit-license.org/" + }], + "description": "Endless/infinite scrolling/pagination.", + "keywords": [ + "endless", + "infinite", + "scroll", + "pagination" + ], + "homepage": "https://github.com/fredwu/jquery-endless-scroll", + "maintainers": [{ + "name": "Fred Wu", + "url": "http://fredwu.me/" + }], + "files": [ + "js/jquery-endless-scroll.js" + ], + "main": "./js/jquery-endless-scroll.js", + "devDependencies": { + "coffee-script": "1.x", + "mocha": "1.x", + "grunt": ">= 0.3.0" + }, + "bundleDependencies": [ + "grunt-coffee", + "grunt-mocha" + ], + "scripts": { + "test": "grunt" + } +} diff --git a/src/jquery.endless-scroll.coffee b/src/jquery.endless-scroll.coffee index 8c5674d..b4e16e8 100644 --- a/src/jquery.endless-scroll.coffee +++ b/src/jquery.endless-scroll.coffee @@ -1,13 +1,11 @@ ### Endless Scroll plugin for jQuery - v1.8.0 + v2.0.0.dev Copyright (c) 2008-2012 Fred Wu - Dual licensed under the MIT and GPL licenses: - http://www.opensource.org/licenses/mit-license.php - http://www.gnu.org/licenses/gpl.html + Licensed under the MIT licenses: http://www.opensource.org/licenses/mit-license.php ### ### @@ -18,253 +16,89 @@ // using some custom options $("#images").endlessScroll({ - fireOnce: false, + fireOnce: false, fireDelay: false, - loader: '
              ', - callback: function(){ + loader: '
              ', + callback: function(){ alert('test'); } }); Configuration options: - pagesToKeep integer the number of 'pages' to keep before either end of the scrolling content are discarded, - by default (value set to `null`) no content will be discarded + pagesToKeep integer the number of 'pages' to keep before either end of the scrolling content are + discarded, by default (value set to `null`) no content will be discarded + inflowPixels integer the number of pixels from the boundary of the element that triggers the event + fireOnce boolean only fire once until the execution of the current event is completed + fireDelay integer delay the subsequent firing, in milliseconds, 0 or false to disable delay + loader string the HTML to be displayed during loading + content string|function Plain HTML content to insert after each call, can be either a string or a function that returns a string, when passed as a function it accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' + insertBefore string jQuery selector syntax: where to put the loader as well as the plain HTML data + insertAfter string jQuery selector syntax: where to put the loader as well as the plain HTML data + intervalFrequency integer set the frequency of the scroll event checking, the larger the frequency number, the less memory it consumes - but also the less sensitive the event trigger becomes - ceaseFireOnEmpty boolean ceases fire automatically when the content is empty, set it to `false` if you are using - `callback` instead of `content` for loading content + + ceaseFireOnEmpty boolean ceases fire automatically when the content is empty, set it to `false` if you are + using `callback` instead of `content` for loading content + resetCounter function resets the fire sequence counter if the function returns true, this function could also perform hook actions since it is applied at the start of the event + callback function callback function, accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' + ceaseFire function stops the event (no more endless scrolling) if the function returns true, accepts three arguments: - the number of times the event triggered during the current page session - a positive or negative value that represents the scroll direction sequence + the number of times the event triggered during the current page + session + a positive or negative integer that represents the scroll + direction sequence a string of either 'prev' or 'next' ### +window.EndlessScroll = EndlessScroll + class EndlessScroll defaults = - pagesToKeep: null - inflowPixels: 50 - fireOnce: true - fireDelay: 150 - loader: 'Loading...' - content: '' - insertBefore: null - insertAfter: null + topPixels: 50 + bottomPixels: 50 intervalFrequency: 250 - ceaseFireOnEmpty: true - resetCounter: -> false - callback: -> true - ceaseFire: -> false constructor: (scope, options) -> - @options = $.extend({}, defaults, options) - @pagesStack = [0] - @scrollDirection = 'next' - @firing = true - @fired = false - @fireSequence = 0 - @pageSequence = 0 - @nextSequence = 1 - @prevSequence = -1 - @lastScrollTop = 0 - @insertLocation = @options.insertAfter - @didScroll = false - @isScrollable = true - @target = scope - @targetId = '' - @content = '' - @lastContent = 'dummy' - @innerWrap = $('.endless_scroll_inner_wrap', @target) - - @handleDeprecatedOptions() - @setInsertPositionsWhenNecessary() - - $(scope).scroll => - @detectTarget(scope) - @detectScrollDirection() + @options = $.extend {}, defaults, options run: -> - setInterval (=> - return unless @shouldTryFiring() - return if @ceaseFireWhenNecessary() - return unless @shouldBeFiring() - - @resetFireSequenceWhenNecessary() - @acknowledgeFiring() - @insertLoader() - - if @hasContent() - @showContent() - @fireCallback() - @cleanUpPagesWhenNecessary() - @delayFiringWhenNecessary() - - @removeLoader() - @lastContent = @content - ), @options.intervalFrequency - - handleDeprecatedOptions: -> - @options.content = @options.data if @options.data - @options.inflowPixels = @options.bottomPixels if @options.bottomPixels - - setInsertPositionsWhenNecessary: -> - container = "#{@target.selector} div.endless_scroll_inner_wrap" - - @options.insertBefore = "#{container} div:first" if defaults.insertBefore is null - @options.insertAfter = "#{container} div:last" if defaults.insertAfter is null - - detectTarget: (scope) -> - @target = scope - @targetId = $(@target).attr('id') - - detectScrollDirection: -> - @didScroll = true - currentScrollTop = $(@target).scrollTop() - - if currentScrollTop > @lastScrollTop - @scrollDirection = 'next' - else - @scrollDirection = 'prev' - - @lastScrollTop = currentScrollTop - - shouldTryFiring: -> - shouldTryOrNot = @didScroll and @firing is true - @didScroll = false if shouldTryOrNot - shouldTryOrNot - - ceaseFireWhenNecessary: -> - if @options.ceaseFireOnEmpty is true and @lastContent is '' or - @options.ceaseFire.apply(@target, [@fireSequence, @pageSequence, @scrollDirection]) - @firing = false + setInterval -> true - else - false - - wrapContainer: (target) -> - if @innerWrap.length is 0 - @innerWrap = $(target).wrapInner('
              ') - .wrapInner('
              ') - .find('.endless_scroll_inner_wrap') - - scrollableAreaMargin: (innerWrap, target) -> - switch @scrollDirection - when 'next' - margin = innerWrap.height() - $(target).height() <= $(target).scrollTop() + @options.inflowPixels - target.scrollTop(innerWrap.height() - $(target).height() - @options.inflowPixels) if margin - when 'prev' - margin = $(target).scrollTop() <= @options.inflowPixels - target.scrollTop(@options.inflowPixels) if margin - - margin - - calculateScrollableCanvas: -> - if @target[0] is document or @target[0] is window - @wrapContainer("body") - @isScrollable = @scrollableAreaMargin($(document), $(window)) - else - @wrapContainer(@target) - @isScrollable = @innerWrap.length > 0 and @scrollableAreaMargin(@innerWrap, @target) - - shouldBeFiring: -> - @calculateScrollableCanvas() - - @isScrollable and ( - @options.fireOnce is false or ( - @options.fireOnce is true and @fired isnt true - ) - ) - - resetFireSequenceWhenNecessary: -> - @fireSequence = 0 if @options.resetCounter.apply(@target) is true - - acknowledgeFiring: -> - @fired = true - @fireSequence++ - - switch @scrollDirection - when 'next' then @pageSequence = @nextSequence++ - when 'prev' then @pageSequence = @prevSequence-- - - insertContent: (content) -> - switch @scrollDirection - when 'next' then $(@options.insertAfter).after(content) - when 'prev' then $(@options.insertBefore).before(content) - - insertLoader: -> - @insertContent( - "
              #{@options.loader}
              " - ) - - removeLoader: -> - $('.endless_scroll_loader_' + @targetId).fadeOut -> - $(this).remove() - - hasContent: -> - if typeof @options.content is 'function' - @content = @options.content.apply(@target, [@fireSequence, @pageSequence, @scrollDirection]) - else - @content = @options.content - - @content isnt false - - showContent: -> - $('#endless_scroll_content_current').removeAttr 'id' - @insertContent( - "
              #{@content}
              " - ) - - fireCallback: -> - @options.callback.apply @target, [@fireSequence, @pageSequence, @scrollDirection] - - cleanUpPagesWhenNecessary: -> - return unless @options.pagesToKeep >= 1 - - switch @scrollDirection - when 'next' then @pagesStack.push(@pageSequence) - when 'prev' then @pagesStack.unshift(@pageSequence) - - if @pagesStack.length > @options.pagesToKeep - switch @scrollDirection - when 'next' then pageToRemove = @prevSequence = @pagesStack.shift() - when 'prev' then pageToRemove = @nextSequence = @pagesStack.pop() + , @options.intervalFrequency - @removePage(pageToRemove) - @calculateScrollableCanvas() +class Whether + @DocumentIsScrollableDownward: (options) -> + $(document).height() - $(window).height() <= + $(window).scrollTop() + options.bottomPixels - removePage: (page) -> - $(".endless_scroll_content[data-page='#{page}']", @target).remove() - delayFiringWhenNecessary: -> - if @options.fireDelay > 0 - $('body').after '
              ' - $('#endless_scroll_marker').fadeTo @options.fireDelay, 1, => - $('#endless_scroll_marker').remove() - @fired = false - else - @fired = false +dependencyLib = if typeof Zepto is 'undefined' then jQuery else Zepto (($) -> $.fn.endlessScroll = (options) -> new EndlessScroll(this, options).run() -)(jQuery) \ No newline at end of file +)(dependencyLib) diff --git a/test/chai.js b/test/chai.js new file mode 100644 index 0000000..a033c23 --- /dev/null +++ b/test/chai.js @@ -0,0 +1,3590 @@ +!function (name, context, definition) { + if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { + module.exports = definition(); + } else if (typeof define === 'function' && typeof define.amd === 'object') { + define(function () { + return definition(); + }); + } else { + context[name] = definition(); + } +}('chai', this, function () { + + function require(p) { + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + + require.modules = {}; + + require.resolve = function (path) { + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + + require.register = function (path, fn) { + require.modules[path] = fn; + }; + + require.relative = function (parent) { + return function(p){ + if ('.' != p[0]) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + require.alias = function (from, to) { + var fn = require.modules[from]; + require.modules[to] = fn; + }; + + + require.register("chai.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + var used = [] + , exports = module.exports = {}; + + /*! + * Chai version + */ + + exports.version = '1.2.0'; + + /*! + * Primary `Assertion` prototype + */ + + exports.Assertion = require('./chai/assertion'); + + /*! + * Assertion Error + */ + + exports.AssertionError = require('./chai/browser/error'); + + /*! + * Utils for plugins (not exported) + */ + + var util = require('./chai/utils'); + + /** + * # .use(function) + * + * Provides a way to extend the internals of Chai + * + * @param {Function} + * @returns {this} for chaining + * @api public + */ + + exports.use = function (fn) { + if (!~used.indexOf(fn)) { + fn(this, util); + used.push(fn); + } + + return this; + }; + + /*! + * Core Assertions + */ + + var core = require('./chai/core/assertions'); + exports.use(core); + + /*! + * Expect interface + */ + + var expect = require('./chai/interface/expect'); + exports.use(expect); + + /*! + * Should interface + */ + + var should = require('./chai/interface/should'); + exports.use(should); + + /*! + * Assert interface + */ + + var assert = require('./chai/interface/assert'); + exports.use(assert); + + }); // module: chai.js + + require.register("chai/assertion.js", function(module, exports, require){ + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies. + */ + + var AssertionError = require('./browser/error') + , util = require('./utils') + , flag = util.flag; + + /*! + * Module export. + */ + + module.exports = Assertion; + + + /*! + * Assertion Constructor + * + * Creates object for chaining. + * + * @api private + */ + + function Assertion (obj, msg, stack) { + flag(this, 'ssfi', stack || arguments.callee); + flag(this, 'object', obj); + flag(this, 'message', msg); + } + + /*! + * ### Assertion.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message + * + * Assertion.includeStack = true; // enable stack on error + * + * @api public + */ + + Assertion.includeStack = false; + + Assertion.addProperty = function (name, fn) { + util.addProperty(this.prototype, name, fn); + }; + + Assertion.addMethod = function (name, fn) { + util.addMethod(this.prototype, name, fn); + }; + + Assertion.addChainableMethod = function (name, fn, chainingBehavior) { + util.addChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + Assertion.overwriteProperty = function (name, fn) { + util.overwriteProperty(this.prototype, name, fn); + }; + + Assertion.overwriteMethod = function (name, fn) { + util.overwriteMethod(this.prototype, name, fn); + }; + + /*! + * ### .assert(expression, message, negateMessage, expected, actual) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String} message to display if fails + * @param {String} negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @api private + */ + + Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual) { + var ok = util.test(this, arguments); + + if (!ok) { + var msg = util.getMessage(this, arguments) + , actual = util.getActual(this, arguments); + throw new AssertionError({ + message: msg + , actual: actual + , expected: expected + , stackStartFunction: (Assertion.includeStack) ? this.assert : flag(this, 'ssfi') + }); + } + }; + + /*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */ + + Object.defineProperty(Assertion.prototype, '_obj', + { get: function () { + return flag(this, 'object'); + } + , set: function (val) { + flag(this, 'object', val); + } + }); + + }); // module: chai/assertion.js + + require.register("chai/browser/error.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = AssertionError; + + function AssertionError (options) { + options = options || {}; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + + if (options.stackStartFunction && Error.captureStackTrace) { + var stackStartFunction = options.stackStartFunction; + Error.captureStackTrace(this, stackStartFunction); + } + } + + AssertionError.prototype = Object.create(Error.prototype); + AssertionError.prototype.name = 'AssertionError'; + AssertionError.prototype.constructor = AssertionError; + + AssertionError.prototype.toString = function() { + return this.message; + }; + + }); // module: chai/browser/error.js + + require.register("chai/core/assertions.js", function(module, exports, require){ + /*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, _) { + var Assertion = chai.Assertion + , toString = Object.prototype.toString + , flag = _.flag; + + /** + * ### Language Chains + * + * The following are provide as chainable getters to + * improve the readability of your assertions. They + * do not provide an testing capability unless they + * have been overwritten by a plugin. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - and + * - have + * - with + * + * @name language chains + * @api public + */ + + [ 'to', 'be', 'been' + , 'is', 'and', 'have' + , 'with', 'that' ].forEach(function (chain) { + Assertion.addProperty(chain, function () { + return this; + }); + }); + + /** + * ### .not + * + * Negates any of assertions following in the chain. + * + * expect(foo).to.not.equal('bar'); + * expect(goodFn).to.not.throw(Error); + * expect({ foo: 'baz' }).to.have.property('foo') + * .and.not.equal('bar'); + * + * @name not + * @api public + */ + + Assertion.addProperty('not', function () { + flag(this, 'negate', true); + }); + + /** + * ### .deep + * + * Sets the `deep` flag, later used by the `equal` and + * `property` assertions. + * + * expect(foo).to.deep.equal({ bar: 'baz' }); + * expect({ foo: { bar: { baz: 'quux' } } }) + * .to.have.deep.property('foo.bar.baz', 'quux'); + * + * @name deep + * @api public + */ + + Assertion.addProperty('deep', function () { + flag(this, 'deep', true); + }); + + /** + * ### .a(type) + * + * The `a` and `an` assertions are aliases that can be + * used either as language chains or to assert a value's + * type (as revealed by `Object.prototype.toString`). + * + * // typeof + * expect('test').to.be.a('string'); + * expect({ foo: 'bar' }).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * + * // language chain + * expect(foo).to.be.an.instanceof(Foo); + * + * @name a + * @alias an + * @param {String} type + * @api public + */ + + function an(type) { + var obj = flag(this, 'object') + , klassStart = type.charAt(0).toUpperCase() + , klass = klassStart + type.slice(1) + , article = ~[ 'A', 'E', 'I', 'O', 'U' ].indexOf(klassStart) ? 'an ' : 'a '; + + this.assert( + '[object ' + klass + ']' === toString.call(obj) + , 'expected #{this} to be ' + article + type + , 'expected #{this} not to be ' + article + type + ); + } + + Assertion.addChainableMethod('an', an); + Assertion.addChainableMethod('a', an); + + /** + * ### .include(value) + * + * The `include` and `contain` assertions can be used as either property + * based language chains or as methods to assert the inclusion of an object + * in an array or a substring in a string. When used as language chains, + * they toggle the `contain` flag for the `keys` assertion. + * + * expect([1,2,3]).to.include(2); + * expect('foobar').to.contain('foo'); + * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); + * + * @name include + * @alias contain + * @param {Object|String|Number} obj + * @api public + */ + + function includeChainingBehavior () { + flag(this, 'contains', true); + } + + function include (val) { + var obj = flag(this, 'object') + this.assert( + ~obj.indexOf(val) + , 'expected #{this} to include ' + _.inspect(val) + , 'expected #{this} to not include ' + _.inspect(val)); + } + + Assertion.addChainableMethod('include', include, includeChainingBehavior); + Assertion.addChainableMethod('contain', include, includeChainingBehavior); + + /** + * ### .ok + * + * Asserts that the target is truthy. + * + * expect('everthing').to.be.ok; + * expect(1).to.be.ok; + * expect(false).to.not.be.ok; + * expect(undefined).to.not.be.ok; + * expect(null).to.not.be.ok; + * + * @name ok + * @api public + */ + + Assertion.addProperty('ok', function () { + this.assert( + flag(this, 'object') + , 'expected #{this} to be truthy' + , 'expected #{this} to be falsy'); + }); + + /** + * ### .true + * + * Asserts that the target is `true`. + * + * expect(true).to.be.true; + * expect(1).to.not.be.true; + * + * @name true + * @api public + */ + + Assertion.addProperty('true', function () { + this.assert( + true === flag(this, 'object') + , 'expected #{this} to be true' + , 'expected #{this} to be false' + , this.negate ? false : true + ); + }); + + /** + * ### .false + * + * Asserts that the target is `false`. + * + * expect(false).to.be.false; + * expect(0).to.not.be.false; + * + * @name false + * @api public + */ + + Assertion.addProperty('false', function () { + this.assert( + false === flag(this, 'object') + , 'expected #{this} to be false' + , 'expected #{this} to be true' + , this.negate ? true : false + ); + }); + + /** + * ### .null + * + * Asserts that the target is `null`. + * + * expect(null).to.be.null; + * expect(undefined).not.to.be.null; + * + * @name null + * @api public + */ + + Assertion.addProperty('null', function () { + this.assert( + null === flag(this, 'object') + , 'expected #{this} to be null' + , 'expected #{this} not to be null' + ); + }); + + /** + * ### .undefined + * + * Asserts that the target is `undefined`. + * + * expect(undefined).to.be.undefined; + * expect(null).to.not.be.undefined; + * + * @name undefined + * @api public + */ + + Assertion.addProperty('undefined', function () { + this.assert( + undefined === flag(this, 'object') + , 'expected #{this} to be undefined' + , 'expected #{this} not to be undefined' + ); + }); + + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi' + * , bar = null + * , baz; + * + * expect(foo).to.exist; + * expect(bar).to.not.exist; + * expect(baz).to.not.exist; + * + * @name exist + * @api public + */ + + Assertion.addProperty('exist', function () { + this.assert( + null != flag(this, 'object') + , 'expected #{this} to exist' + , 'expected #{this} to not exist' + ); + }); + + + /** + * ### .empty + * + * Asserts that the target's length is `0`. For arrays, it checks + * the `length` property. For objects, it gets the count of + * enumerable keys. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * expect({}).to.be.empty; + * + * @name empty + * @api public + */ + + Assertion.addProperty('empty', function () { + var obj = flag(this, 'object') + , expected = obj; + + if (Array.isArray(obj) || 'string' === typeof object) { + expected = obj.length; + } else if (typeof obj === 'object') { + expected = Object.keys(obj).length; + } + + this.assert( + !expected + , 'expected #{this} to be empty' + , 'expected #{this} not to be empty' + ); + }); + + /** + * ### .arguments + * + * Asserts that the target is an arguments object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * @name arguments + * @alias Arguments + * @api public + */ + + function checkArguments () { + var obj = flag(this, 'object') + , type = Object.prototype.toString.call(obj); + this.assert( + '[object Arguments]' === type + , 'expected #{this} to be arguments but got ' + type + , 'expected #{this} to not be arguments' + ); + } + + Assertion.addProperty('arguments', checkArguments); + Assertion.addProperty('Arguments', checkArguments); + + /** + * ### .equal(value) + * + * Asserts that the target is strictly equal (`===`) to `value`. + * Alternately, if the `deep` flag is set, asserts that + * the target is deeply equal to `value`. + * + * expect('hello').to.equal('hello'); + * expect(42).to.equal(42); + * expect(1).to.not.equal(true); + * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); + * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); + * + * @name equal + * @alias equals + * @alias eq + * @alias deep.equal + * @param {Mixed} value + * @api public + */ + + function assertEqual (val) { + var obj = flag(this, 'object'); + if (flag(this, 'deep')) { + return this.eql(val); + } else { + this.assert( + val === obj + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{exp}' + , val + ); + } + } + + Assertion.addMethod('equal', assertEqual); + Assertion.addMethod('equals', assertEqual); + Assertion.addMethod('eq', assertEqual); + + /** + * ### .eql(value) + * + * Asserts that the target is deeply equal to `value`. + * + * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); + * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); + * + * @name eql + * @param {Mixed} value + * @api public + */ + + Assertion.addMethod('eql', function (obj) { + this.assert( + _.eql(obj, flag(this, 'object')) + , 'expected #{this} to deeply equal #{exp}' + , 'expected #{this} to not deeply equal #{exp}' + , obj + ); + }); + + /** + * ### .above(value) + * + * Asserts that the target is greater than `value`. + * + * expect(10).to.be.above(5); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} value + * @api public + */ + + function assertAbove (n) { + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len > n + , 'expected #{this} to have a length above #{exp} but got #{act}' + , 'expected #{this} to not have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj > n + , 'expected #{this} to be above ' + n + , 'expected #{this} to be below ' + n + ); + } + } + + Assertion.addMethod('above', assertAbove); + Assertion.addMethod('gt', assertAbove); + Assertion.addMethod('greaterThan', assertAbove); + + /** + * ### .below(value) + * + * Asserts that the target is less than `value`. + * + * expect(5).to.be.below(10); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} value + * @api public + */ + + function assertBelow (n) { + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len < n + , 'expected #{this} to have a length below #{exp} but got #{act}' + , 'expected #{this} to not have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj < n + , 'expected #{this} to be below ' + n + , 'expected #{this} to be above ' + n + ); + } + } + + Assertion.addMethod('below', assertBelow); + Assertion.addMethod('lt', assertBelow); + Assertion.addMethod('lessThan', assertBelow); + + /** + * ### .within(start, finish) + * + * Asserts that the target is within a range. + * + * expect(7).to.be.within(5,10); + * + * Can also be used in conjunction with `length` to + * assert a length range. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name within + * @param {Number} start lowerbound inclusive + * @param {Number} finish upperbound inclusive + * @api public + */ + + Assertion.addMethod('within', function (start, finish) { + var obj = flag(this, 'object') + , range = start + '..' + finish; + if (flag(this, 'doLength')) { + new Assertion(obj).to.have.property('length'); + var len = obj.length; + this.assert( + len >= start && len <= finish + , 'expected #{this} to have a length within ' + range + , 'expected #{this} to not have a length within ' + range + ); + } else { + this.assert( + obj >= start && obj <= finish + , 'expected #{this} to be within ' + range + , 'expected #{this} to not be within ' + range + ); + } + }); + + /** + * ### .instanceof(constructor) + * + * Asserts that the target is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , Chai = new Tea('chai'); + * + * expect(Chai).to.be.an.instanceof(Tea); + * expect([ 1, 2, 3 ]).to.be.instanceof(Array); + * + * @name instanceof + * @param {Constructor} constructor + * @alias instanceOf + * @api public + */ + + function assertInstanceOf (constructor) { + var name = _.getName(constructor); + this.assert( + flag(this, 'object') instanceof constructor + , 'expected #{this} to be an instance of ' + name + , 'expected #{this} to not be an instance of ' + name + ); + }; + + Assertion.addMethod('instanceof', assertInstanceOf); + Assertion.addMethod('instanceOf', assertInstanceOf); + + /** + * ### .property(name, [value]) + * + * Asserts that the target has a property `name`, optionally asserting that + * the value of that property is strictly equal to `value`. + * If the `deep` flag is set, you can use dot- and bracket-notation for deep + * references into objects and arrays. + * + * // simple referencing + * var obj = { foo: 'bar' }; + * expect(obj).to.have.property('foo'); + * expect(obj).to.have.property('foo', 'bar'); + * + * // deep referencing + * var deepObj = { + * green: { tea: 'matcha' } + * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] + * }; + + * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); + * + * You can also use an array as the starting point of a `deep.property` + * assertion, or traverse nested arrays. + * + * var arr = [ + * [ 'chai', 'matcha', 'konacha' ] + * , [ { tea: 'chai' } + * , { tea: 'matcha' } + * , { tea: 'konacha' } ] + * ]; + * + * expect(arr).to.have.deep.property('[0][1]', 'matcha'); + * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); + * + * Furthermore, `property` changes the subject of the assertion + * to be the value of that property from the original object. This + * permits for further chainable assertions on that property. + * + * expect(obj).to.have.property('foo') + * .that.is.a('string'); + * expect(deepObj).to.have.property('green') + * .that.is.an('object') + * .that.deep.equals({ tea: 'matcha' }); + * expect(deepObj).to.have.property('teas') + * .that.is.an('array') + * .with.deep.property('[2]') + * .that.deep.equals({ tea: 'konacha' }); + * + * @name property + * @alias deep.property + * @param {String} name + * @param {Mixed} value (optional) + * @returns value of property for chaining + * @api public + */ + + Assertion.addMethod('property', function (name, val) { + var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' + , negate = flag(this, 'negate') + , obj = flag(this, 'object') + , value = flag(this, 'deep') + ? _.getPathValue(name, obj) + : obj[name]; + + if (negate && undefined !== val) { + if (undefined === value) { + throw new Error(_.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); + } + } else { + this.assert( + undefined !== value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + , 'expected #{this} to not have ' + descriptor + _.inspect(name)); + } + + if (undefined !== val) { + this.assert( + val === value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' + , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' + , val + , value + ); + } + + flag(this, 'object', value); + }); + + + /** + * ### .ownProperty(name) + * + * Asserts that the target has an own property `name`. + * + * expect('test').to.have.ownProperty('length'); + * + * @name ownProperty + * @alias haveOwnProperty + * @param {String} name + * @api public + */ + + function assertOwnProperty (name) { + var obj = flag(this, 'object'); + this.assert( + obj.hasOwnProperty(name) + , 'expected #{this} to have own property ' + _.inspect(name) + , 'expected #{this} to not have own property ' + _.inspect(name) + ); + } + + Assertion.addMethod('ownProperty', assertOwnProperty); + Assertion.addMethod('haveOwnProperty', assertOwnProperty); + + /** + * ### .length(value) + * + * Asserts that the target's `length` property has + * the expected value. + * + * expect([ 1, 2, 3]).to.have.length(3); + * expect('foobar').to.have.length(6); + * + * Can also be used as a chain precursor to a value + * comparison for the length property. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name length + * @alias lengthOf + * @param {Number} length + * @api public + */ + + function assertLengthChain () { + flag(this, 'doLength', true); + } + + function assertLength (n) { + var obj = flag(this, 'object'); + new Assertion(obj).to.have.property('length'); + var len = obj.length; + + this.assert( + len == n + , 'expected #{this} to have a length of #{exp} but got #{act}' + , 'expected #{this} to not have a length of #{act}' + , n + , len + ); + } + + Assertion.addChainableMethod('length', assertLength, assertLengthChain); + Assertion.addMethod('lengthOf', assertLength, assertLengthChain); + + /** + * ### .match(regexp) + * + * Asserts that the target matches a regular expression. + * + * expect('foobar').to.match(/^foo/); + * + * @name match + * @param {RegExp} RegularExpression + * @api public + */ + + Assertion.addMethod('match', function (re) { + var obj = flag(this, 'object'); + this.assert( + re.exec(obj) + , 'expected #{this} to match ' + re + , 'expected #{this} not to match ' + re + ); + }); + + /** + * ### .string(string) + * + * Asserts that the string target contains another string. + * + * expect('foobar').to.have.string('bar'); + * + * @name string + * @param {String} string + * @api public + */ + + Assertion.addMethod('string', function (str) { + var obj = flag(this, 'object'); + new Assertion(obj).is.a('string'); + + this.assert( + ~obj.indexOf(str) + , 'expected #{this} to contain ' + _.inspect(str) + , 'expected #{this} to not contain ' + _.inspect(str) + ); + }); + + + /** + * ### .keys(key1, [key2], [...]) + * + * Asserts that the target has exactly the given keys, or + * asserts the inclusion of some keys when using the + * `include` or `contain` modifiers. + * + * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); + * + * @name keys + * @alias key + * @param {String...|Array} keys + * @api public + */ + + function assertKeys (keys) { + var obj = flag(this, 'object') + , str + , ok = true; + + keys = keys instanceof Array + ? keys + : Array.prototype.slice.call(arguments); + + if (!keys.length) throw new Error('keys required'); + + var actual = Object.keys(obj) + , len = keys.length; + + // Inclusion + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + + // Strict + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } + + // Key string + if (len > 1) { + keys = keys.map(function(key){ + return _.inspect(key); + }); + var last = keys.pop(); + str = keys.join(', ') + ', and ' + last; + } else { + str = _.inspect(keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; + + // Assertion + this.assert( + ok + , 'expected #{this} to ' + str + , 'expected #{this} to not ' + str + ); + } + + Assertion.addMethod('keys', assertKeys); + Assertion.addMethod('key', assertKeys); + + /** + * ### .throw(constructor) + * + * Asserts that the function target will throw a specific error, or specific type of error + * (as determined using `instanceof`), optionally with a RegExp or string inclusion test + * for the error's message. + * + * var err = new ReferenceError('This is a bad function.'); + * var fn = function () { throw err; } + * expect(fn).to.throw(ReferenceError); + * expect(fn).to.throw(Error); + * expect(fn).to.throw(/bad function/); + * expect(fn).to.not.throw('good function'); + * expect(fn).to.throw(ReferenceError, /bad function/); + * expect(fn).to.throw(err); + * expect(fn).to.not.throw(new RangeError('Out of range.')); + * + * Please note that when a throw expectation is negated, it will check each + * parameter independently, starting with error constructor type. The appropriate way + * to check for the existence of a type of error but for a message that does not match + * is to use `and`. + * + * expect(fn).to.throw(ReferenceError) + * .and.not.throw(/good function/); + * + * @name throw + * @alias throws + * @alias Throw + * @param {ErrorConstructor} constructor + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + function assertThrows (constructor, msg) { + var obj = flag(this, 'object'); + new Assertion(obj).is.a('function'); + + var thrown = false + , desiredError = null + , name = null; + + if (arguments.length === 0) { + msg = null; + constructor = null; + } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { + msg = constructor; + constructor = null; + } else if (constructor && constructor instanceof Error) { + desiredError = constructor; + constructor = null; + msg = null; + } else if (typeof constructor === 'function') { + name = (new constructor()).name; + } else { + constructor = null; + } + + try { + obj(); + } catch (err) { + // first, check desired error + if (desiredError) { + this.assert( + err === desiredError + , 'expected #{this} to throw ' + _.inspect(desiredError) + ' but ' + _.inspect(err) + ' was thrown' + , 'expected #{this} to not throw ' + _.inspect(desiredError) + ); + return this; + } + // next, check constructor + if (constructor) { + this.assert( + err instanceof constructor + , 'expected #{this} to throw ' + name + ' but a ' + err.name + ' was thrown' + , 'expected #{this} to not throw ' + name ); + if (!msg) return this; + } + // next, check message + if (err.message && msg && msg instanceof RegExp) { + this.assert( + msg.exec(err.message) + , 'expected #{this} to throw error matching ' + msg + ' but got ' + _.inspect(err.message) + , 'expected #{this} to throw error not matching ' + msg + ); + return this; + } else if (err.message && msg && 'string' === typeof msg) { + this.assert( + ~err.message.indexOf(msg) + , 'expected #{this} to throw error including #{exp} but got #{act}' + , 'expected #{this} to throw error not including #{act}' + , msg + , err.message + ); + return this; + } else { + thrown = true; + } + } + + var expectedThrown = name ? name : desiredError ? _.inspect(desiredError) : 'an error'; + + this.assert( + thrown === true + , 'expected #{this} to throw ' + expectedThrown + , 'expected #{this} to not throw ' + expectedThrown + ); + }; + + Assertion.addMethod('throw', assertThrows); + Assertion.addMethod('throws', assertThrows); + Assertion.addMethod('Throw', assertThrows); + + /** + * ### .respondTo(method) + * + * Asserts that the object or class target will respond to a method. + * + * Klass.prototype.bar = function(){}; + * expect(Klass).to.respondTo('bar'); + * expect(obj).to.respondTo('bar'); + * + * To check if a constructor will respond to a static function, + * set the `itself` flag. + * + * Klass.baz = function(){}; + * expect(Klass).itself.to.respondTo('baz'); + * + * @name respondTo + * @param {String} method + * @api public + */ + + Assertion.addMethod('respondTo', function (method) { + var obj = flag(this, 'object') + , itself = flag(this, 'itself') + , context = ('function' === typeof obj && !itself) + ? obj.prototype[method] + : obj[method]; + + this.assert( + 'function' === typeof context + , 'expected #{this} to respond to ' + _.inspect(method) + , 'expected #{this} to not respond to ' + _.inspect(method) + ); + }); + + /** + * ### .itself + * + * Sets the `itself` flag, later used by the `respondTo` assertion. + * + * function Foo() {} + * Foo.bar = function() {} + * Foo.prototype.baz = function() {} + * + * expect(Foo).itself.to.respondTo('bar'); + * expect(Foo).itself.not.to.respondTo('baz'); + * + * @name itself + * @api public + */ + + Assertion.addProperty('itself', function () { + flag(this, 'itself', true); + }); + + /** + * ### .satisfy(method) + * + * Asserts that the target passes a given truth test. + * + * expect(1).to.satisfy(function(num) { return num > 0; }); + * + * @name satisfy + * @param {Function} matcher + * @api public + */ + + Assertion.addMethod('satisfy', function (matcher) { + var obj = flag(this, 'object'); + this.assert( + matcher(obj) + , 'expected #{this} to satisfy ' + _.inspect(matcher) + , 'expected #{this} to not satisfy' + _.inspect(matcher) + , this.negate ? false : true + , matcher(obj) + ); + }); + + /** + * ### .closeTo(expected, delta) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * expect(1.5).to.be.closeTo(1, 0.5); + * + * @name closeTo + * @param {Number} expected + * @param {Number} delta + * @api public + */ + + Assertion.addMethod('closeTo', function (expected, delta) { + var obj = flag(this, 'object'); + this.assert( + Math.abs(obj - expected) <= delta + , 'expected #{this} to be close to ' + expected + ' +/- ' + delta + , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta + ); + }); + + }; + + }); // module: chai/core/assertions.js + + require.register("chai/interface/assert.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + + module.exports = function (chai, util) { + + /*! + * Chai dependencies. + */ + + var Assertion = chai.Assertion + , flag = util.flag; + + /*! + * Module export. + */ + + /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @api public + */ + + var assert = chai.assert = function (express, errmsg) { + var test = new Assertion(null); + test.assert( + express + , errmsg + , '[ negation message unavailable ]' + ); + }; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @api public + */ + + assert.fail = function (actual, expected, message, operator) { + throw new chai.AssertionError({ + actual: actual + , expected: expected + , message: message + , operator: operator + , stackStartFunction: assert.fail + }); + }; + + /** + * ### .ok(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.ok('everything', 'everything is ok'); + * assert.ok(false, 'this will fail'); + * + * @name ok + * @param {Mixed} object to test + * @param {String} message + * @api public + */ + + assert.ok = function (val, msg) { + new Assertion(val, msg).is.ok; + }; + + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.equal = function (act, exp, msg) { + var test = new Assertion(act, msg); + + test.assert( + exp == flag(test, 'object') + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{act}' + , exp + , act + ); + }; + + /** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notEqual = function (act, exp, msg) { + var test = new Assertion(act, msg); + + test.assert( + exp != flag(test, 'object') + , 'expected #{this} to not equal #{exp}' + , 'expected #{this} to equal #{act}' + , exp + , act + ); + }; + + /** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.strictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.equal(exp); + }; + + /** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notStrictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.equal(exp); + }; + + /** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.deepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.eql(exp); + }; + + /** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notDeepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.eql(exp); + }; + + /** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isTrue = function (val, msg) { + new Assertion(val, msg).is['true']; + }; + + /** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFalse = function (val, msg) { + new Assertion(val, msg).is['false']; + }; + + /** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNull = function (val, msg) { + new Assertion(val, msg).to.equal(null); + }; + + /** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNull = function (val, msg) { + new Assertion(val, msg).to.not.equal(null); + }; + + /** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isUndefined = function (val, msg) { + new Assertion(val, msg).to.equal(undefined); + }; + + /** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isDefined = function (val, msg) { + new Assertion(val, msg).to.not.equal(undefined); + }; + + /** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFunction = function (val, msg) { + new Assertion(val, msg).to.be.a('function'); + }; + + /** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotFunction = function (val, msg) { + new Assertion(val, msg).to.not.be.a('function'); + }; + + /** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object (as revealed by + * `Object.prototype.toString`). + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isObject = function (val, msg) { + new Assertion(val, msg).to.be.a('object'); + }; + + /** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object. + * + * var selection = 'chai' + * assert.isObject(selection, 'tea selection is not an object'); + * assert.isObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotObject = function (val, msg) { + new Assertion(val, msg).to.not.be.a('object'); + }; + + /** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isArray = function (val, msg) { + new Assertion(val, msg).to.be.an('array'); + }; + + /** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotArray = function (val, msg) { + new Assertion(val, msg).to.not.be.an('array'); + }; + + /** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isString = function (val, msg) { + new Assertion(val, msg).to.be.a('string'); + }; + + /** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotString = function (val, msg) { + new Assertion(val, msg).to.not.be.a('string'); + }; + + /** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @api public + */ + + assert.isNumber = function (val, msg) { + new Assertion(val, msg).to.be.a('number'); + }; + + /** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNumber = function (val, msg) { + new Assertion(val, msg).to.not.be.a('number'); + }; + + /** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isBoolean = function (val, msg) { + new Assertion(val, msg).to.be.a('boolean'); + }; + + /** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotBoolean = function (val, msg) { + new Assertion(val, msg).to.not.be.a('boolean'); + }; + + /** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @api public + */ + + assert.typeOf = function (val, type, msg) { + new Assertion(val, msg).to.be.a(type); + }; + + /** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @api public + */ + + assert.notTypeOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.a(type); + }; + + /** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.instanceOf = function (val, type, msg) { + new Assertion(val, msg).to.be.instanceOf(type); + }; + + /** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.notInstanceOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.instanceOf(type); + }; + + /** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Works + * for strings and arrays. + * + * assert.include('foobar', 'bar', 'foobar contains string "bar"'); + * assert.include([ 1, 2, 3 ], 3, 'array contains value'); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @api public + */ + + assert.include = function (exp, inc, msg) { + var obj = new Assertion(exp, msg); + + if (Array.isArray(exp)) { + obj.to.include(inc); + } else if ('string' === typeof exp) { + obj.to.contain.string(inc); + } + }; + + /** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.match = function (exp, re, msg) { + new Assertion(exp, msg).to.match(re); + }; + + /** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.notMatch = function (exp, re, msg) { + new Assertion(exp, msg).to.not.match(re); + }; + + /** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a property named by `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.property = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.property(prop); + }; + + /** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.property(prop); + }; + + /** + * ### .deepProperty(object, property, [message]) + * + * Asserts that `object` has a property named by `property`, which can be a + * string using dot- and bracket-notation for deep reference. + * + * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name deepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.deepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.deep.property(prop); + }; + + /** + * ### .notDeepProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for deep reference. + * + * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notDeepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notDeepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop); + }; + + /** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.property(prop, val); + }; + + /** + * ### .propertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. + * + * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); + * + * @name propertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.property(prop, val); + }; + + /** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for deep + * reference. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.deep.property(prop, val); + }; + + /** + * ### .deepPropertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. `property` can use dot- and + * bracket-notation for deep reference. + * + * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * + * @name deepPropertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop, val); + }; + + /** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` property with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 5, 'string has length of 6'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @api public + */ + + assert.lengthOf = function (exp, len, msg) { + new Assertion(exp, msg).to.have.length(len); + }; + + /** + * ### .throws(function, [constructor/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * assert.throw(fn, ReferenceError, 'function throws a reference error'); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.Throw = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.Throw(type); + }; + + /** + * ### .doesNotThrow(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * assert.doesNotThrow(fn, Error, 'function does not throw'); + * + * @name doesNotThrow + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.doesNotThrow = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.not.Throw(type); + }; + + /** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @api public + */ + + assert.operator = function (val, operator, val2, msg) { + if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) { + throw new Error('Invalid operator "' + operator + '"'); + } + var test = new Assertion(eval(val + operator + val2), msg); + test.assert( + true === flag(test, 'object') + , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) + , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); + }; + + /** + * ### .closeTo(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); + * + * @name closeTo + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @api public + */ + + assert.closeTo = function (act, exp, delta, msg) { + new Assertion(act, msg).to.be.closeTo(exp, delta); + }; + + /*! + * Undocumented / untested + */ + + assert.ifError = function (val, msg) { + new Assertion(val, msg).to.not.be.ok; + }; + + /*! + * Aliases. + */ + + (function alias(name, as){ + assert[as] = assert[name]; + return alias; + }) + ('Throw', 'throw') + ('Throw', 'throws'); + }; + + }); // module: chai/interface/assert.js + + require.register("chai/interface/expect.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, util) { + chai.expect = function (val, message) { + return new chai.Assertion(val, message); + }; + }; + + + }); // module: chai/interface/expect.js + + require.register("chai/interface/should.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011-2012 Jake Luer + * MIT Licensed + */ + + module.exports = function (chai, util) { + var Assertion = chai.Assertion; + + function loadShould () { + // modify Object.prototype to have `should` + Object.defineProperty(Object.prototype, 'should', + { set: function () {} + , get: function(){ + if (this instanceof String || this instanceof Number) { + return new Assertion(this.constructor(this)); + } else if (this instanceof Boolean) { + return new Assertion(this == true); + } + return new Assertion(this); + } + , configurable: true + }); + + var should = {}; + + should.equal = function (val1, val2) { + new Assertion(val1).to.equal(val2); + }; + + should.Throw = function (fn, errt, errs) { + new Assertion(fn).to.Throw(errt, errs); + }; + + should.exist = function (val) { + new Assertion(val).to.exist; + } + + // negation + should.not = {} + + should.not.equal = function (val1, val2) { + new Assertion(val1).to.not.equal(val2); + }; + + should.not.Throw = function (fn, errt, errs) { + new Assertion(fn).to.not.Throw(errt, errs); + }; + + should.not.exist = function (val) { + new Assertion(val).to.not.exist; + } + + should['throw'] = should['Throw']; + should.not['throw'] = should.not['Throw']; + + return should; + }; + + chai.should = loadShould; + chai.Should = loadShould; + }; + + }); // module: chai/interface/should.js + + require.register("chai/utils/addChainableMethod.js", function(module, exports, require){ + /*! + * Chai - addChainingMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependencies + */ + + var transferFlags = require('./transferFlags'); + + /** + * ### addChainableMethod (ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @name addChainableMethod + * @api public + */ + + module.exports = function (ctx, name, method, chainingBehavior) { + if (typeof chainingBehavior !== 'function') + chainingBehavior = function () { }; + + Object.defineProperty(ctx, name, + { get: function () { + chainingBehavior.call(this); + + var assert = function () { + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; + + // Re-enumerate every time to better accomodate plugins. + var asserterNames = Object.getOwnPropertyNames(ctx); + asserterNames.forEach(function (asserterName) { + var pd = Object.getOwnPropertyDescriptor(ctx, asserterName) + , functionProtoPD = Object.getOwnPropertyDescriptor(Function.prototype, asserterName); + // Avoid trying to overwrite things that we can't, like `length` and `arguments`. + if (functionProtoPD && !functionProtoPD.configurable) return; + if (asserterName === 'arguments') return; // @see chaijs/chai/issues/69 + Object.defineProperty(assert, asserterName, pd); + }); + + transferFlags(this, assert); + return assert; + } + , configurable: true + }); + }; + + }); // module: chai/utils/addChainableMethod.js + + require.register("chai/utils/addMethod.js", function(module, exports, require){ + /*! + * Chai - addMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### .addMethod (ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @name addMethod + * @api public + */ + + module.exports = function (ctx, name, method) { + ctx[name] = function () { + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; + }; + + }); // module: chai/utils/addMethod.js + + require.register("chai/utils/addProperty.js", function(module, exports, require){ + /*! + * Chai - addProperty utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### addProperty (ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @name addProperty + * @api public + */ + + module.exports = function (ctx, name, getter) { + Object.defineProperty(ctx, name, + { get: function () { + var result = getter.call(this); + return result === undefined ? this : result; + } + , configurable: true + }); + }; + + }); // module: chai/utils/addProperty.js + + require.register("chai/utils/eql.js", function(module, exports, require){ + // This is directly from Node.js assert + // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js + + + module.exports = _deepEqual; + + // For browser implementation + if (!Buffer) { + var Buffer = { + isBuffer: function () { + return false; + } + }; + } + + function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (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 _deepEqual(a, b); + } + try { + var ka = Object.keys(a), + kb = Object.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 (!_deepEqual(a[key], b[key])) return false; + } + return true; + } + }); // module: chai/utils/eql.js + + require.register("chai/utils/flag.js", function(module, exports, require){ + /*! + * Chai - flag utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### flag(object ,key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object (constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @name flag + * @api private + */ + + module.exports = function (obj, key, value) { + var flags = obj.__flags || (obj.__flags = Object.create(null)); + if (arguments.length === 3) { + flags[key] = value; + } else { + return flags[key]; + } + }; + + }); // module: chai/utils/flag.js + + require.register("chai/utils/getActual.js", function(module, exports, require){ + /*! + * Chai - getActual utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * # getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + + module.exports = function (obj, args) { + var actual = args[4]; + return 'undefined' !== actual ? actual : obj._obj; + }; + + }); // module: chai/utils/getActual.js + + require.register("chai/utils/getMessage.js", function(module, exports, require){ + /*! + * Chai - message composition utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependancies + */ + + var flag = require('./flag') + , getActual = require('./getActual') + , inspect = require('./inspect') + , objDisplay = require('./objDisplay'); + + /** + * ### .getMessage(object, message, negateMessage) + * + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. + * + * Messsage template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @name getMessage + * @api public + */ + + module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , val = flag(obj, 'object') + , expected = args[3] + , actual = getActual(obj, args) + , msg = negate ? args[2] : args[1] + , flagMsg = flag(obj, 'message'); + + msg = msg || ''; + msg = msg + .replace(/#{this}/g, objDisplay(val)) + .replace(/#{act}/g, objDisplay(actual)) + .replace(/#{exp}/g, objDisplay(expected)); + + return flagMsg ? flagMsg + ': ' + msg : msg; + }; + + }); // module: chai/utils/getMessage.js + + require.register("chai/utils/getName.js", function(module, exports, require){ + /*! + * Chai - getName utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * # getName(func) + * + * Gets the name of a function, in a cross-browser way. + * + * @param {Function} a function (usually a constructor) + */ + + module.exports = function (func) { + if (func.name) return func.name; + + var match = /^\s?function ([^(]*)\(/.exec(func); + return match && match[1] ? match[1] : ""; + }; + + }); // module: chai/utils/getName.js + + require.register("chai/utils/getPathValue.js", function(module, exports, require){ + /*! + * Chai - getPathValue utility + * Copyright(c) 2012 Jake Luer + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ + + /** + * ### .getPathValue(path, object) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue('prop1.str', obj); // Hello + * getPathValue('prop1.att[2]', obj); // b + * getPathValue('prop2.arr[0].nested', obj); // Universe + * + * @param {String} path + * @param {Object} object + * @returns {Object} value or `undefined` + * @name getPathValue + * @api public + */ + + var getPathValue = module.exports = function (path, obj) { + var parsed = parsePath(path); + return _getPathValue(parsed, obj); + }; + + /*! + * ## parsePath(path) + * + * Helper function used to parse string object + * paths. Use in conjunction with `_getPathValue`. + * + * var parsed = parsePath('myobject.property.subprop'); + * + * ### Paths: + * + * * Can be as near infinitely deep and nested + * * Arrays are also valid using the formal `myobject.document[3].property`. + * + * @param {String} path + * @returns {Object} parsed + * @api private + */ + + function parsePath (path) { + var str = path.replace(/\[/g, '.[') + , parts = str.match(/(\\\.|[^.]+?)+/g); + return parts.map(function (value) { + var re = /\[(\d+)\]$/ + , mArr = re.exec(value) + if (mArr) return { i: parseFloat(mArr[1]) }; + else return { p: value }; + }); + }; + + /*! + * ## _getPathValue(parsed, obj) + * + * Helper companion function for `.parsePath` that returns + * the value located at the parsed address. + * + * var value = getPathValue(parsed, obj); + * + * @param {Object} parsed definition from `parsePath`. + * @param {Object} object to search against + * @returns {Object|Undefined} value + * @api private + */ + + function _getPathValue (parsed, obj) { + var tmp = obj + , res; + for (var i = 0, l = parsed.length; i < l; i++) { + var part = parsed[i]; + if (tmp) { + if ('undefined' !== typeof part.p) + tmp = tmp[part.p]; + else if ('undefined' !== typeof part.i) + tmp = tmp[part.i]; + if (i == (l - 1)) res = tmp; + } else { + res = undefined; + } + } + return res; + }; + + }); // module: chai/utils/getPathValue.js + + require.register("chai/utils/index.js", function(module, exports, require){ + /*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */ + + /*! + * Main exports + */ + + var exports = module.exports = {}; + + /*! + * test utility + */ + + exports.test = require('./test'); + + /*! + * message utility + */ + + exports.getMessage = require('./getMessage'); + + /*! + * actual utility + */ + + exports.getActual = require('./getActual'); + + /*! + * Inspect util + */ + + exports.inspect = require('./inspect'); + + /*! + * Object Display util + */ + + exports.objDisplay = require('./objDisplay'); + + /*! + * Flag utility + */ + + exports.flag = require('./flag'); + + /*! + * Flag transferring utility + */ + + exports.transferFlags = require('./transferFlags'); + + /*! + * Deep equal utility + */ + + exports.eql = require('./eql'); + + /*! + * Deep path value + */ + + exports.getPathValue = require('./getPathValue'); + + /*! + * Function name + */ + + exports.getName = require('./getName'); + + /*! + * add Property + */ + + exports.addProperty = require('./addProperty'); + + /*! + * add Method + */ + + exports.addMethod = require('./addMethod'); + + /*! + * overwrite Property + */ + + exports.overwriteProperty = require('./overwriteProperty'); + + /*! + * overwrite Method + */ + + exports.overwriteMethod = require('./overwriteMethod'); + + /*! + * Add a chainable method + */ + + exports.addChainableMethod = require('./addChainableMethod'); + + + }); // module: chai/utils/index.js + + require.register("chai/utils/inspect.js", function(module, exports, require){ + // This is (almost) directly from Node.js utils + // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js + + var getName = require('./getName'); + + module.exports = inspect; + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + */ + function inspect(obj, showHidden, depth, colors) { + var ctx = { + showHidden: showHidden, + seen: [], + stylize: function (str) { return str; } + }; + return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); + } + + // https://gist.github.com/1044128/ + var getOuterHTML = function(element) { + if ('outerHTML' in element) return element.outerHTML; + var ns = "http://www.w3.org/1999/xhtml"; + var container = document.createElementNS(ns, '_'); + var elemProto = (window.HTMLElement || window.Element).prototype; + var xmlSerializer = new XMLSerializer(); + var html; + if (document.xmlVersion) { + return xmlSerializer.serializeToString(element); + } else { + container.appendChild(element.cloneNode(false)); + html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); + container.innerHTML = ''; + return html; + } + }; + + // Returns true if object is a DOM element. + var isDOMElement = function (object) { + if (typeof HTMLElement === 'object') { + return object instanceof HTMLElement; + } else { + return object && + typeof object === 'object' && + object.nodeType === 1 && + typeof object.nodeName === 'string'; + } + }; + + function formatValue(ctx, 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.inspect !== exports.inspect && + // 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 + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // If it's DOM elem, get outer HTML. + if (isDOMElement(value)) { + return getOuterHTML(value); + } + + // Look up the keys of the object. + var visibleKeys = Object.keys(value); + var keys = ctx.showHidden ? Object.getOwnPropertyNames(value) : visibleKeys; + + // Some type of object without properties can be shortcutted. + // In IE, errors have a single `stack` property, or if they are vanilla `Error`, + // a `stack` plus `description` property; ignore those for consistency. + if (keys.length === 0 || (isError(value) && ( + (keys.length === 1 && keys[0] === 'stack') || + (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') + ))) { + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + return ctx.stylize('[Function' + nameSuffix + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + base = ' [Function' + nameSuffix + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + return formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); + } + + + function formatPrimitive(ctx, value) { + switch (typeof value) { + case 'undefined': + return ctx.stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + + case 'number': + return ctx.stylize('' + value, 'number'); + + case 'boolean': + return ctx.stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return ctx.stylize('null', 'null'); + } + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (Object.prototype.hasOwnProperty.call(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Setter]', 'special'); + } + } + } + if (visibleKeys.indexOf(key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(value[key]) < 0) { + if (recurseTimes === null) { + str = formatValue(ctx, value[key], null); + } else { + str = formatValue(ctx, value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (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 = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; + } + + + function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + function isArray(ar) { + return Array.isArray(ar) || + (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + } + + function isRegExp(re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + } + + function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + } + + function isError(e) { + return typeof e === 'object' && objectToString(e) === '[object Error]'; + } + + function objectToString(o) { + return Object.prototype.toString.call(o); + } + + }); // module: chai/utils/inspect.js + + require.register("chai/utils/objDisplay.js", function(module, exports, require){ + /*! + * Chai - flag utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependancies + */ + + var inspect = require('./inspect'); + + /** + * ### .objDisplay (object) + * + * Determines if an object or an array matches + * criteria to be inspected in-line for error + * messages or should be truncated. + * + * @param {Mixed} javascript object to inspect + * @name objDisplay + * @api public + */ + + module.exports = function (obj) { + var str = inspect(obj) + , type = Object.prototype.toString.call(obj); + + if (str.length >= 40) { + if (type === '[object Array]') { + return '[ Array(' + obj.length + ') ]'; + } else if (type === '[object Object]') { + var keys = Object.keys(obj) + , kstr = keys.length > 2 + ? keys.splice(0, 2).join(', ') + ', ...' + : keys.join(', '); + return '{ Object (' + kstr + ') }'; + } else { + return str; + } + } else { + return str; + } + }; + + }); // module: chai/utils/objDisplay.js + + require.register("chai/utils/overwriteMethod.js", function(module, exports, require){ + /*! + * Chai - overwriteMethod utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### overwriteMethod (ctx, name, fn) + * + * Overwites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @name overwriteMethod + * @api public + */ + + module.exports = function (ctx, name, method) { + var _method = ctx[name] + , _super = function () { return this; }; + + if (_method && 'function' === typeof _method) + _super = _method; + + ctx[name] = function () { + var result = method(_super).apply(this, arguments); + return result === undefined ? this : result; + } + }; + + }); // module: chai/utils/overwriteMethod.js + + require.register("chai/utils/overwriteProperty.js", function(module, exports, require){ + /*! + * Chai - overwriteProperty utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### overwriteProperty (ctx, name, fn) + * + * Overwites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @name overwriteProperty + * @api public + */ + + module.exports = function (ctx, name, getter) { + var _get = Object.getOwnPropertyDescriptor(ctx, name) + , _super = function () {}; + + if (_get && 'function' === typeof _get.get) + _super = _get.get + + Object.defineProperty(ctx, name, + { get: function () { + var result = getter(_super).call(this); + return result === undefined ? this : result; + } + , configurable: true + }); + }; + + }); // module: chai/utils/overwriteProperty.js + + require.register("chai/utils/test.js", function(module, exports, require){ + /*! + * Chai - test utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /*! + * Module dependancies + */ + + var flag = require('./flag'); + + /** + * # test(object, expression) + * + * Test and object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + + module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , expr = args[0]; + return negate ? !expr : expr; + }; + + }); // module: chai/utils/test.js + + require.register("chai/utils/transferFlags.js", function(module, exports, require){ + /*! + * Chai - transferFlags utility + * Copyright(c) 2012 Jake Luer + * MIT Licensed + */ + + /** + * ### transferFlags(assertion, object, includeAll = true) + * + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, and `message`) + * will not be transferred. + * + * + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); + * + * var anotherAsseriton = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); + * + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags too; usually a new assertion + * @param {Boolean} includeAll + * @name getAllFlags + * @api private + */ + + module.exports = function (assertion, object, includeAll) { + var flags = assertion.__flags || (assertion.__flags = Object.create(null)); + + if (!object.__flags) { + object.__flags = Object.create(null); + } + + includeAll = arguments.length === 3 ? includeAll : true; + + for (var flag in flags) { + if (includeAll || + (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { + object.__flags[flag] = flags[flag]; + } + } + }; + + }); // module: chai/utils/transferFlags.js + + require.alias("./chai.js", "chai"); + + return require('chai'); +}); diff --git a/test/mocha.css b/test/mocha.css new file mode 100644 index 0000000..01bac1a --- /dev/null +++ b/test/mocha.css @@ -0,0 +1,199 @@ +@charset "UTF-8"; +body { + font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; + padding: 60px 50px; +} + +#mocha ul, #mocha li { + margin: 0; + padding: 0; +} + +#mocha ul { + list-style: none; +} + +#mocha h1, #mocha h2 { + margin: 0; +} + +#mocha h1 { + margin-top: 15px; + font-size: 1em; + font-weight: 200; +} + +#mocha h1 a { + text-decoration: none; + color: inherit; +} + +#mocha h1 a:hover { + text-decoration: underline; +} + +#mocha .suite .suite h1 { + margin-top: 0; + font-size: .8em; +} + +#mocha h2 { + font-size: 12px; + font-weight: normal; + cursor: pointer; +} + +#mocha .suite { + margin-left: 15px; +} + +#mocha .test { + margin-left: 15px; +} + +#mocha .test:hover h2::after { + position: relative; + top: 0; + right: -10px; + content: '(view source)'; + font-size: 12px; + font-family: arial; + color: #888; +} + +#mocha .test.pending:hover h2::after { + content: '(pending)'; + font-family: arial; +} + +#mocha .test.pass.medium .duration { + background: #C09853; +} + +#mocha .test.pass.slow .duration { + background: #B94A48; +} + +#mocha .test.pass::before { + content: '✓'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #00d6b2; +} + +#mocha .test.pass .duration { + font-size: 9px; + margin-left: 5px; + padding: 2px 5px; + color: white; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + box-shadow: inset 0 1px 1px rgba(0,0,0,.2); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +#mocha .test.pass.fast .duration { + display: none; +} + +#mocha .test.pending { + color: #0b97c4; +} + +#mocha .test.pending::before { + content: '◦'; + color: #0b97c4; +} + +#mocha .test.fail { + color: #c00; +} + +#mocha .test.fail pre { + color: black; +} + +#mocha .test.fail::before { + content: '✖'; + font-size: 12px; + display: block; + float: left; + margin-right: 5px; + color: #c00; +} + +#mocha .test pre.error { + color: #c00; +} + +#mocha .test pre { + display: inline-block; + font: 12px/1.5 monaco, monospace; + margin: 5px; + padding: 15px; + border: 1px solid #eee; + border-bottom-color: #ddd; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px #eee; +} + +#report.pass .test.fail { + display: none; +} + +#report.fail .test.pass { + display: none; +} + +#error { + color: #c00; + font-size: 1.5 em; + font-weight: 100; + letter-spacing: 1px; +} + +#stats { + position: fixed; + top: 15px; + right: 10px; + font-size: 12px; + margin: 0; + color: #888; +} + +#stats .progress { + float: right; + padding-top: 0; +} + +#stats em { + color: black; +} + +#stats a { + text-decoration: none; + color: inherit; +} + +#stats a:hover { + border-bottom: 1px solid #eee; +} + +#stats li { + display: inline-block; + margin: 0 5px; + list-style: none; + padding-top: 11px; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } diff --git a/test/mocha.js b/test/mocha.js new file mode 100644 index 0000000..c248bff --- /dev/null +++ b/test/mocha.js @@ -0,0 +1,4674 @@ +;(function(){ + + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("browser/debug.js", function(module, exports, require){ + +module.exports = function(type){ + return function(){ + + } +}; +}); // module: browser/debug.js + +require.register("browser/diff.js", function(module, exports, require){ + +}); // module: browser/diff.js + +require.register("browser/events.js", function(module, exports, require){ + +/** + * Module exports. + */ + +exports.EventEmitter = EventEmitter; + +/** + * Check if `obj` is an array. + */ + +function isArray(obj) { + return '[object Array]' == {}.toString.call(obj); +} + +/** + * Event emitter constructor. + * + * @api public + */ + +function EventEmitter(){}; + +/** + * Adds a listener. + * + * @api public + */ + +EventEmitter.prototype.on = function (name, fn) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = fn; + } else if (isArray(this.$events[name])) { + this.$events[name].push(fn); + } else { + this.$events[name] = [this.$events[name], fn]; + } + + return this; +}; + +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +/** + * Adds a volatile listener. + * + * @api public + */ + +EventEmitter.prototype.once = function (name, fn) { + var self = this; + + function on () { + self.removeListener(name, on); + fn.apply(this, arguments); + }; + + on.listener = fn; + this.on(name, on); + + return this; +}; + +/** + * Removes a listener. + * + * @api public + */ + +EventEmitter.prototype.removeListener = function (name, fn) { + if (this.$events && this.$events[name]) { + var list = this.$events[name]; + + if (isArray(list)) { + var pos = -1; + + for (var i = 0, l = list.length; i < l; i++) { + if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { + pos = i; + break; + } + } + + if (pos < 0) { + return this; + } + + list.splice(pos, 1); + + if (!list.length) { + delete this.$events[name]; + } + } else if (list === fn || (list.listener && list.listener === fn)) { + delete this.$events[name]; + } + } + + return this; +}; + +/** + * Removes all listeners for an event. + * + * @api public + */ + +EventEmitter.prototype.removeAllListeners = function (name) { + if (name === undefined) { + this.$events = {}; + return this; + } + + if (this.$events && this.$events[name]) { + this.$events[name] = null; + } + + return this; +}; + +/** + * Gets all listeners for a certain event. + * + * @api public + */ + +EventEmitter.prototype.listeners = function (name) { + if (!this.$events) { + this.$events = {}; + } + + if (!this.$events[name]) { + this.$events[name] = []; + } + + if (!isArray(this.$events[name])) { + this.$events[name] = [this.$events[name]]; + } + + return this.$events[name]; +}; + +/** + * Emits an event. + * + * @api public + */ + +EventEmitter.prototype.emit = function (name) { + if (!this.$events) { + return false; + } + + var handler = this.$events[name]; + + if (!handler) { + return false; + } + + var args = [].slice.call(arguments, 1); + + if ('function' == typeof handler) { + handler.apply(this, args); + } else if (isArray(handler)) { + var listeners = handler.slice(); + + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + } else { + return false; + } + + return true; +}; +}); // module: browser/events.js + +require.register("browser/fs.js", function(module, exports, require){ + +}); // module: browser/fs.js + +require.register("browser/path.js", function(module, exports, require){ + +}); // module: browser/path.js + +require.register("browser/progress.js", function(module, exports, require){ + +/** + * Expose `Progress`. + */ + +module.exports = Progress; + +/** + * Initialize a new `Progress` indicator. + */ + +function Progress() { + this.percent = 0; + this.size(0); + this.fontSize(11); + this.font('helvetica, arial, sans-serif'); +} + +/** + * Set progress size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.size = function(n){ + this._size = n; + return this; +}; + +/** + * Set text to `str`. + * + * @param {String} str + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.text = function(str){ + this._text = str; + return this; +}; + +/** + * Set font size to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + * @api public + */ + +Progress.prototype.fontSize = function(n){ + this._fontSize = n; + return this; +}; + +/** + * Set font `family`. + * + * @param {String} family + * @return {Progress} for chaining + */ + +Progress.prototype.font = function(family){ + this._font = family; + return this; +}; + +/** + * Update percentage to `n`. + * + * @param {Number} n + * @return {Progress} for chaining + */ + +Progress.prototype.update = function(n){ + this.percent = n; + return this; +}; + +/** + * Draw on `ctx`. + * + * @param {CanvasRenderingContext2d} ctx + * @return {Progress} for chaining + */ + +Progress.prototype.draw = function(ctx){ + var percent = Math.min(this.percent, 100) + , size = this._size + , half = size / 2 + , x = half + , y = half + , rad = half - 1 + , fontSize = this._fontSize; + + ctx.font = fontSize + 'px ' + this._font; + + var angle = Math.PI * 2 * (percent / 100); + ctx.clearRect(0, 0, size, size); + + // outer circle + ctx.strokeStyle = '#9f9f9f'; + ctx.beginPath(); + ctx.arc(x, y, rad, 0, angle, false); + ctx.stroke(); + + // inner circle + ctx.strokeStyle = '#eee'; + ctx.beginPath(); + ctx.arc(x, y, rad - 1, 0, angle, true); + ctx.stroke(); + + // text + var text = this._text || (percent | 0) + '%' + , w = ctx.measureText(text).width; + + ctx.fillText( + text + , x - w / 2 + 1 + , y + fontSize / 2 - 1); + + return this; +}; + +}); // module: browser/progress.js + +require.register("browser/tty.js", function(module, exports, require){ + +exports.isatty = function(){ + return true; +}; + +exports.getWindowSize = function(){ + return [window.innerHeight, window.innerWidth]; +}; +}); // module: browser/tty.js + +require.register("context.js", function(module, exports, require){ + +/** + * Expose `Context`. + */ + +module.exports = Context; + +/** + * Initialize a new `Context`. + * + * @api private + */ + +function Context(){} + +/** + * Set or get the context `Runnable` to `runnable`. + * + * @param {Runnable} runnable + * @return {Context} + * @api private + */ + +Context.prototype.runnable = function(runnable){ + if (0 == arguments.length) return this._runnable; + this.test = this._runnable = runnable; + return this; +}; + +/** + * Set test timeout `ms`. + * + * @param {Number} ms + * @return {Context} self + * @api private + */ + +Context.prototype.timeout = function(ms){ + this.runnable().timeout(ms); + return this; +}; + +/** + * Inspect the context void of `._runnable`. + * + * @return {String} + * @api private + */ + +Context.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_runnable' == key) return; + if ('test' == key) return; + return val; + }, 2); +}; + +}); // module: context.js + +require.register("hook.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Hook`. + */ + +module.exports = Hook; + +/** + * Initialize a new `Hook` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Hook(title, fn) { + Runnable.call(this, title, fn); + this.type = 'hook'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Hook.prototype = new Runnable; +Hook.prototype.constructor = Hook; + + +/** + * Get or set the test `err`. + * + * @param {Error} err + * @return {Error} + * @api public + */ + +Hook.prototype.error = function(err){ + if (0 == arguments.length) { + var err = this._error; + this._error = null; + return err; + } + + this._error = err; +}; + + +}); // module: hook.js + +require.register("interfaces/bdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * BDD-style interface: + * + * describe('Array', function(){ + * describe('#indexOf()', function(){ + * it('should return -1 when not present', function(){ + * + * }); + * + * it('should return the index when present', function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.describe = context.context = function(title, fn){ + var suite = Suite.create(suites[0], title); + 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()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.it = context.specify = function(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); + }; + }); +}; + +}); // module: interfaces/bdd.js + +require.register("interfaces/exports.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * exports.Array = { + * '#indexOf()': { + * 'should return -1 when the value is not present': function(){ + * + * }, + * + * 'should return the correct index when the value is present': function(){ + * + * } + * } + * }; + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('require', visit); + + function visit(obj) { + var suite; + for (var key in obj) { + if ('function' == typeof obj[key]) { + var fn = obj[key]; + switch (key) { + case 'before': + suites[0].beforeAll(fn); + break; + case 'after': + suites[0].afterAll(fn); + break; + case 'beforeEach': + suites[0].beforeEach(fn); + break; + case 'afterEach': + suites[0].afterEach(fn); + break; + default: + suites[0].addTest(new Test(key, fn)); + } + } else { + var suite = Suite.create(suites[0], key); + suites.unshift(suite); + visit(obj[key]); + suites.shift(); + } + } + } +}; +}); // module: interfaces/exports.js + +require.register("interfaces/index.js", function(module, exports, require){ + +exports.bdd = require('./bdd'); +exports.tdd = require('./tdd'); +exports.qunit = require('./qunit'); +exports.exports = require('./exports'); + +}); // module: interfaces/index.js + +require.register("interfaces/qunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * QUnit-style interface: + * + * suite('Array'); + * + * test('#length', function(){ + * var arr = [1,2,3]; + * ok(arr.length == 3); + * }); + * + * test('#indexOf()', function(){ + * var arr = [1,2,3]; + * ok(arr.indexOf(1) == 0); + * ok(arr.indexOf(2) == 1); + * ok(arr.indexOf(3) == 2); + * }); + * + * suite('String'); + * + * test('#length', function(){ + * ok('foo'.length == 3); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context){ + + /** + * Execute before running tests. + */ + + context.before = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after running tests. + */ + + context.after = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Execute before each test case. + */ + + context.beforeEach = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.afterEach = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Describe a "suite" with the given `title`. + */ + + context.suite = function(title){ + if (suites.length > 1) suites.shift(); + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(title, fn){ + suites[0].addTest(new Test(title, fn)); + }; + }); +}; + +}); // module: interfaces/qunit.js + +require.register("interfaces/tdd.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Suite = require('../suite') + , Test = require('../test'); + +/** + * TDD-style interface: + * + * suite('Array', function(){ + * suite('#indexOf()', function(){ + * suiteSetup(function(){ + * + * }); + * + * test('should return -1 when not present', function(){ + * + * }); + * + * test('should return the index when present', function(){ + * + * }); + * + * suiteTeardown(function(){ + * + * }); + * }); + * }); + * + */ + +module.exports = function(suite){ + var suites = [suite]; + + suite.on('pre-require', function(context, file, mocha){ + + /** + * Execute before each test case. + */ + + context.setup = function(fn){ + suites[0].beforeEach(fn); + }; + + /** + * Execute after each test case. + */ + + context.teardown = function(fn){ + suites[0].afterEach(fn); + }; + + /** + * Execute before the suite. + */ + + context.suiteSetup = function(fn){ + suites[0].beforeAll(fn); + }; + + /** + * Execute after the suite. + */ + + context.suiteTeardown = function(fn){ + suites[0].afterAll(fn); + }; + + /** + * Describe a "suite" with the given `title` + * and callback `fn` containing nested suites + * and/or tests. + */ + + context.suite = function(title, fn){ + var suite = Suite.create(suites[0], title); + suites.unshift(suite); + fn(); + suites.shift(); + return suite; + }; + + /** + * Exclusive test-case. + */ + + context.suite.only = function(title, fn){ + var suite = context.suite(title, fn); + mocha.grep(suite.fullTitle()); + }; + + /** + * Describe a specification or test-case + * with the given `title` and callback `fn` + * acting as a thunk. + */ + + context.test = function(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()); + }; + }); +}; + +}); // module: interfaces/tdd.js + +require.register("mocha.js", function(module, exports, require){ +/*! + * mocha + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var path = require('browser/path'); + +/** + * Expose `Mocha`. + */ + +exports = module.exports = Mocha; + +/** + * Expose internals. + */ + +exports.utils = require('./utils'); +exports.interfaces = require('./interfaces'); +exports.reporters = require('./reporters'); +exports.Runnable = require('./runnable'); +exports.Context = require('./context'); +exports.Runner = require('./runner'); +exports.Suite = require('./suite'); +exports.Hook = require('./hook'); +exports.Test = require('./test'); + +/** + * Return image `name` path. + * + * @param {String} name + * @return {String} + * @api private + */ + +function image(name) { + return __dirname + '/../images/' + name + '.png'; +} + +/** + * Setup mocha with `options`. + * + * Options: + * + * - `ui` name "bdd", "tdd", "exports" etc + * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` + * - `globals` array of accepted globals + * - `timeout` timeout in milliseconds + * - `ignoreLeaks` ignore global leaks + * - `grep` string or regexp to filter tests with + * + * @param {Object} options + * @api public + */ + +function Mocha(options) { + options = options || {}; + this.files = []; + this.options = options; + this.grep(options.grep); + this.suite = new exports.Suite('', new exports.Context); + this.ui(options.ui); + this.reporter(options.reporter); + if (options.timeout) this.suite.timeout(options.timeout); +} + +/** + * Add test `file`. + * + * @param {String} file + * @api public + */ + +Mocha.prototype.addFile = function(file){ + this.files.push(file); + return this; +}; + +/** + * Set reporter to `name`, defaults to "dot". + * + * @param {String} name + * @api public + */ + +Mocha.prototype.reporter = function(name){ + name = name || 'dot'; + this._reporter = require('./reporters/' + name); + if (!this._reporter) throw new Error('invalid reporter "' + name + '"'); + return this; +}; + +/** + * Set test UI `name`, defaults to "bdd". + * + * @param {String} bdd + * @api public + */ + +Mocha.prototype.ui = function(name){ + name = name || 'bdd'; + this._ui = exports.interfaces[name]; + if (!this._ui) throw new Error('invalid interface "' + name + '"'); + this._ui = this._ui(this.suite); + return this; +}; + +/** + * Load registered files. + * + * @api private + */ + +Mocha.prototype.loadFiles = function(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, self); + suite.emit('require', require(file), file, self); + suite.emit('post-require', global, file, self); + --pending || (fn && fn()); + }); +}; + +/** + * Enable growl support. + * + * @api private + */ + +Mocha.prototype._growl = function(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function(){ + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + name: 'mocha' + , title: 'Passed' + , image: image('ok') + }); + } + }); +}; + +/** + * Add regexp to grep for to the options object + * + * @param {RegExp} or {String} re + * @return {Mocha} + * @api public + */ + +Mocha.prototype.grep = function(re){ + this.options.grep = 'string' == typeof re + ? new RegExp(re) + : re; + return this; +}; + +/** + * 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 growl support. + * + * @return {Mocha} + * @api public + */ + +Mocha.prototype.growl = function(){ + this.options.growl = true; + return this; +}; + +/** + * Ignore `globals`. + * + * @param {Array} globals + * @return {Mocha} + * @api public + */ + +Mocha.prototype.globals = function(globals){ + this.options.globals = globals; + return this; +}; + +/** + * Run tests and invoke `fn()` when complete. + * + * @param {Function} fn + * @return {Runner} + * @api public + */ + +Mocha.prototype.run = function(fn){ + this.loadFiles(); + var suite = this.suite; + var options = this.options; + var runner = new exports.Runner(suite); + var reporter = new this._reporter(runner); + runner.ignoreLeaks = options.ignoreLeaks; + if (options.grep) runner.grep(options.grep, options.invert); + if (options.globals) runner.globals(options.globals); + if (options.growl) this._growl(runner, reporter); + return runner.run(fn); +}; + +}); // module: mocha.js + +require.register("reporters/base.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var tty = require('browser/tty') + , diff = require('browser/diff'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Check if both stdio streams are associated with a tty. + */ + +var isatty = tty.isatty(1) && tty.isatty(2); + +/** + * Expose `Base`. + */ + +exports = module.exports = Base; + +/** + * Enable coloring by default. + */ + +exports.useColors = isatty; + +/** + * Default color map. + */ + +exports.colors = { + 'pass': 90 + , 'fail': 31 + , 'bright pass': 92 + , 'bright fail': 91 + , 'bright yellow': 93 + , 'pending': 36 + , 'suite': 0 + , 'error title': 0 + , 'error message': 31 + , 'error stack': 90 + , 'checkmark': 32 + , 'fast': 90 + , 'medium': 33 + , 'slow': 31 + , 'green': 32 + , 'light': 90 + , 'diff gutter': 90 + , 'diff added': 42 + , 'diff removed': 41 +}; + +/** + * Color `str` with the given `type`, + * allowing colors to be disabled, + * as well as user-defined color + * schemes. + * + * @param {String} type + * @param {String} str + * @return {String} + * @api private + */ + +var color = exports.color = function(type, str) { + if (!exports.useColors) return str; + return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; +}; + +/** + * Expose term window size, with some + * defaults for when stderr is not a tty. + */ + +exports.window = { + width: isatty + ? process.stdout.getWindowSize + ? process.stdout.getWindowSize(1)[0] + : tty.getWindowSize()[1] + : 75 +}; + +/** + * Expose some basic cursor interactions + * that are common among reporters. + */ + +exports.cursor = { + hide: function(){ + process.stdout.write('\u001b[?25l'); + }, + + show: function(){ + process.stdout.write('\u001b[?25h'); + }, + + deleteLine: function(){ + process.stdout.write('\u001b[2K'); + }, + + beginningOfLine: function(){ + process.stdout.write('\u001b[0G'); + }, + + CR: function(){ + exports.cursor.deleteLine(); + exports.cursor.beginningOfLine(); + } +}; + +/** + * A test is considered slow if it + * exceeds the following value in milliseconds. + */ + +exports.slow = 75; + +/** + * Outut the given `failures` as a list. + * + * @param {Array} failures + * @api public + */ + +exports.list = function(failures){ + console.error(); + failures.forEach(function(test, i){ + // format + var fmt = color('error title', ' %s) %s:\n') + + color('error message', ' %s') + + color('error stack', '\n%s\n'); + + // msg + var err = test.err + , message = err.message || '' + , stack = err.stack || message + , index = stack.indexOf(message) + message.length + , msg = stack.slice(0, index) + , actual = err.actual + , expected = err.expected; + + // actual / expected diff + if ('string' == typeof actual && 'string' == typeof expected) { + var len = Math.max(actual.length, expected.length); + + if (len < 20) msg = errorDiff(err, 'Chars'); + else msg = errorDiff(err, 'Words'); + + // linenos + var lines = msg.split('\n'); + if (lines.length > 4) { + var width = String(lines.length).length; + msg = lines.map(function(str, i){ + return pad(++i, width) + ' |' + ' ' + str; + }).join('\n'); + } + + // legend + msg = '\n' + + color('diff removed', 'actual') + + ' ' + + color('diff added', 'expected') + + '\n\n' + + msg + + '\n'; + + // indent + msg = msg.replace(/^/gm, ' '); + + fmt = color('error title', ' %s) %s:\n%s') + + color('error stack', '\n%s\n'); + } + + // indent stack trace without msg + stack = stack.slice(index ? index + 1 : index) + .replace(/^/gm, ' '); + + console.error(fmt, (i + 1), test.fullTitle(), msg, stack); + }); +}; + +/** + * Initialize a new `Base` reporter. + * + * All other reporters generally + * inherit from this reporter, providing + * stats such as test duration, number + * of tests passed / failed etc. + * + * @param {Runner} runner + * @api public + */ + +function Base(runner) { + var self = this + , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } + , failures = this.failures = []; + + if (!runner) return; + this.runner = runner; + + runner.on('start', function(){ + stats.start = new Date; + }); + + runner.on('suite', function(suite){ + stats.suites = stats.suites || 0; + suite.root || stats.suites++; + }); + + runner.on('test end', function(test){ + stats.tests = stats.tests || 0; + stats.tests++; + }); + + runner.on('pass', function(test){ + stats.passes = stats.passes || 0; + + var medium = exports.slow / 2; + test.speed = test.duration > exports.slow + ? 'slow' + : test.duration > medium + ? 'medium' + : 'fast'; + + stats.passes++; + }); + + runner.on('fail', function(test, err){ + stats.failures = stats.failures || 0; + stats.failures++; + test.err = err; + failures.push(test); + }); + + runner.on('end', function(){ + stats.end = new Date; + stats.duration = new Date - stats.start; + }); + + runner.on('pending', function(){ + stats.pending++; + }); +} + +/** + * Output common epilogue used by many of + * the bundled reporters. + * + * @api public + */ + +Base.prototype.epilogue = function(){ + var stats = this.stats + , fmt + , tests; + + console.log(); + + function pluralize(n) { + return 1 == n ? 'test' : 'tests'; + } + + // failure + if (stats.failures) { + fmt = color('bright fail', ' ✖') + + color('fail', ' %d of %d %s failed') + + color('light', ':') + + console.error(fmt, + stats.failures, + this.runner.total, + pluralize(this.runner.total)); + + Base.list(this.failures); + console.error(); + return; + } + + // pass + fmt = color('bright pass', ' ✔') + + color('green', ' %d %s complete') + + color('light', ' (%dms)'); + + console.log(fmt, + stats.tests || 0, + pluralize(stats.tests), + stats.duration); + + // pending + if (stats.pending) { + fmt = color('pending', ' •') + + color('pending', ' %d %s pending'); + + console.log(fmt, stats.pending, pluralize(stats.pending)); + } + + console.log(); +}; + +/** + * Pad the given `str` to `len`. + * + * @param {String} str + * @param {String} len + * @return {String} + * @api private + */ + +function pad(str, len) { + str = String(str); + return Array(len - str.length + 1).join(' ') + str; +} + +/** + * Return a character diff for `err`. + * + * @param {Error} err + * @return {String} + * @api private + */ + +function errorDiff(err, type) { + return diff['diff' + type](err.actual, err.expected).map(function(str){ + if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join(''); + if (str.added) return colorLines('diff added', str.value); + if (str.removed) return colorLines('diff removed', str.value); + return str.value; + }).join(''); +} + +/** + * Color lines for `str`, using the color `name`. + * + * @param {String} name + * @param {String} str + * @return {String} + * @api private + */ + +function colorLines(name, str) { + return str.split('\n').map(function(str){ + return color(name, str); + }).join('\n'); +} + +}); // module: reporters/base.js + +require.register("reporters/doc.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Doc`. + */ + +exports = module.exports = Doc; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Doc(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , indents = 2; + + function indent() { + return Array(indents).join(' '); + } + + runner.on('suite', function(suite){ + if (suite.root) return; + ++indents; + console.log('%s
              ', indent()); + ++indents; + console.log('%s

              %s

              ', indent(), suite.title); + console.log('%s
              ', indent()); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + console.log('%s
              ', indent()); + --indents; + console.log('%s
              ', indent()); + --indents; + }); + + runner.on('pass', function(test){ + console.log('%s
              %s
              ', indent(), test.title); + var code = utils.escape(utils.clean(test.fn.toString())); + console.log('%s
              %s
              ', indent(), code); + }); +} + +}); // module: reporters/doc.js + +require.register("reporters/dot.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = Dot; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Dot(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , c = '․' + , n = 0; + + runner.on('start', function(){ + process.stdout.write('\n '); + }); + + runner.on('pending', function(test){ + 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', c)); + } else { + 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', c)); + }); + + runner.on('end', function(){ + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Dot.prototype = new Base; +Dot.prototype.constructor = Dot; + +}); // module: reporters/dot.js + +require.register("reporters/html-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var JSONCov = require('./json-cov') + , fs = require('browser/fs'); + +/** + * Expose `HTMLCov`. + */ + +exports = module.exports = HTMLCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTMLCov(runner) { + var jade = require('jade') + , file = __dirname + '/templates/coverage.jade' + , str = fs.readFileSync(file, 'utf8') + , fn = jade.compile(str, { filename: file }) + , self = this; + + JSONCov.call(this, runner, false); + + runner.on('end', function(){ + process.stdout.write(fn({ + cov: self.cov + , coverageClass: coverageClass + })); + }); +} + +/** + * Return coverage class for `n`. + * + * @return {String} + * @api private + */ + +function coverageClass(n) { + if (n >= 75) return 'high'; + if (n >= 50) return 'medium'; + if (n >= 25) return 'low'; + return 'terrible'; +} +}); // module: reporters/html-cov.js + +require.register("reporters/html.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , Progress = require('../browser/progress') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Doc`. + */ + +exports = module.exports = HTML; + +/** + * Stats template. + */ + +var statsTemplate = '
              '; + +/** + * Initialize a new `Doc` reporter. + * + * @param {Runner} runner + * @api public + */ + +function HTML(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , root = document.getElementById('mocha') + , stat = fragment(statsTemplate) + , items = stat.getElementsByTagName('li') + , passes = items[1].getElementsByTagName('em')[0] + , 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('
                ') + , stack = [report] + , progress + , ctx + + 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); + + if (progress) progress.size(40); + + runner.on('suite', function(suite){ + if (suite.root) return; + + // suite + var grep = '^' + encodeURIComponent(utils.escapeRegexp(suite.fullTitle())); + var url = location.protocol + '//' + location.host + location.pathname + '?grep=' + grep; + var el = fragment('
              • %s

              • ', url, escape(suite.title)); + + // container + stack[0].appendChild(el); + stack.unshift(document.createElement('ul')); + el.appendChild(stack[0]); + }); + + runner.on('suite end', function(suite){ + if (suite.root) return; + stack.shift(); + }); + + runner.on('fail', function(test, err){ + if ('hook' == test.type || err.uncaught) runner.emit('test end', test); + }); + + runner.on('test end', function(test){ + window.scrollTo(0, document.body.scrollHeight); + + // TODO: add to stats + var percent = stats.tests / total * 100 | 0; + if (progress) progress.update(percent).draw(ctx); + + // update stats + var ms = new Date - stats.start; + text(passes, stats.passes); + text(failures, stats.failures); + text(duration, (ms / 1000).toFixed(2)); + + // test + if ('passed' == test.state) { + var el = fragment('
              • %e%ems

              • ', test.speed, test.title, test.duration); + } else if (test.pending) { + var el = fragment('
              • %e

              • ', test.title); + } else { + var el = fragment('
              • %e

              • ', test.title); + var str = test.err.stack || test.err.toString(); + + // FF / Opera do not add the message + if (!~str.indexOf(test.err.message)) { + str = test.err.message + '\n' + str; + } + + // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we + // check for the result of the stringifying. + if ('[object Error]' == str) str = test.err.message; + + // Safari doesn't give you a stack. Let's at least provide a source line. + if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { + str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; + } + + el.appendChild(fragment('
                %e
                ', str)); + } + + // toggle 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'; + } + + stack[0].appendChild(el); + }); +} + +/** + * Display error `msg`. + */ + +function error(msg) { + document.body.appendChild(fragment('
                %s
                ', msg)); +} + +/** + * Return a DOM fragment from `html`. + */ + +function fragment(html) { + var args = arguments + , div = document.createElement('div') + , i = 1; + + div.innerHTML = html.replace(/%([se])/g, function(_, type){ + switch (type) { + case 's': return String(args[i++]); + case 'e': return escape(args[i++]); + } + }); + + return div.firstChild; +} + +/** + * Set `el` text to `str`. + */ + +function text(el, str) { + if (el.textContent) { + el.textContent = str; + } else { + el.innerText = str; + } +} + +/** + * Listen on `event` with callback `fn`. + */ + +function on(el, event, fn) { + if (el.addEventListener) { + el.addEventListener(event, fn, false); + } else { + el.attachEvent('on' + event, fn); + } +} + +}); // module: reporters/html.js + +require.register("reporters/index.js", function(module, exports, require){ + +exports.Base = require('./base'); +exports.Dot = require('./dot'); +exports.Doc = require('./doc'); +exports.TAP = require('./tap'); +exports.JSON = require('./json'); +exports.HTML = require('./html'); +exports.List = require('./list'); +exports.Min = require('./min'); +exports.Spec = require('./spec'); +exports.Nyan = require('./nyan'); +exports.XUnit = require('./xunit'); +exports.Progress = require('./progress'); +exports.Landing = require('./landing'); +exports.JSONCov = require('./json-cov'); +exports.HTMLCov = require('./html-cov'); +exports.JSONStream = require('./json-stream'); +exports.Teamcity = require('./teamcity'); + +}); // module: reporters/index.js + +require.register("reporters/json-cov.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `JSONCov`. + */ + +exports = module.exports = JSONCov; + +/** + * Initialize a new `JsCoverage` reporter. + * + * @param {Runner} runner + * @param {Boolean} output + * @api public + */ + +function JSONCov(runner, output) { + var self = this + , output = 1 == arguments.length ? true : output; + + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var cov = global._$jscoverage || {}; + var result = self.cov = map(cov); + result.stats = self.stats; + result.tests = tests.map(clean); + result.failures = failures.map(clean); + result.passes = passes.map(clean); + if (!output) return; + process.stdout.write(JSON.stringify(result, null, 2 )); + }); +} + +/** + * Map jscoverage data to a JSON structure + * suitable for reporting. + * + * @param {Object} cov + * @return {Object} + * @api private + */ + +function map(cov) { + var ret = { + instrumentation: 'node-jscoverage' + , sloc: 0 + , hits: 0 + , misses: 0 + , coverage: 0 + , files: [] + }; + + for (var filename in cov) { + var data = coverage(filename, cov[filename]); + ret.files.push(data); + ret.hits += data.hits; + ret.misses += data.misses; + ret.sloc += data.sloc; + } + + if (ret.sloc > 0) { + ret.coverage = (ret.hits / ret.sloc) * 100; + } + + return ret; +}; + +/** + * Map jscoverage data for a single source file + * to a JSON structure suitable for reporting. + * + * @param {String} filename name of the source file + * @param {Object} data jscoverage coverage data + * @return {Object} + * @api private + */ + +function coverage(filename, data) { + var ret = { + filename: filename, + coverage: 0, + hits: 0, + misses: 0, + sloc: 0, + source: {} + }; + + data.source.forEach(function(line, num){ + num++; + + if (data[num] === 0) { + ret.misses++; + ret.sloc++; + } else if (data[num] !== undefined) { + ret.hits++; + ret.sloc++; + } + + ret.source[num] = { + source: line + , coverage: data[num] === undefined + ? '' + : data[num] + }; + }); + + ret.coverage = ret.hits / ret.sloc * 100; + + return ret; +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} + +}); // module: reporters/json-cov.js + +require.register("reporters/json-stream.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total; + + runner.on('start', function(){ + console.log(JSON.stringify(['start', { total: total }])); + }); + + runner.on('pass', function(test){ + console.log(JSON.stringify(['pass', clean(test)])); + }); + + runner.on('fail', function(test, err){ + console.log(JSON.stringify(['fail', clean(test)])); + }); + + runner.on('end', function(){ + process.stdout.write(JSON.stringify(['end', self.stats])); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json-stream.js + +require.register("reporters/json.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `JSON`. + */ + +exports = module.exports = JSONReporter; + +/** + * Initialize a new `JSON` reporter. + * + * @param {Runner} runner + * @api public + */ + +function JSONReporter(runner) { + var self = this; + Base.call(this, runner); + + var tests = [] + , failures = [] + , passes = []; + + runner.on('test end', function(test){ + tests.push(test); + }); + + runner.on('pass', function(test){ + passes.push(test); + }); + + runner.on('fail', function(test){ + failures.push(test); + }); + + runner.on('end', function(){ + var obj = { + stats: self.stats + , tests: tests.map(clean) + , failures: failures.map(clean) + , passes: passes.map(clean) + }; + + process.stdout.write(JSON.stringify(obj, null, 2)); + }); +} + +/** + * Return a plain-object representation of `test` + * free of cyclic properties etc. + * + * @param {Object} test + * @return {Object} + * @api private + */ + +function clean(test) { + return { + title: test.title + , fullTitle: test.fullTitle() + , duration: test.duration + } +} +}); // module: reporters/json.js + +require.register("reporters/landing.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Landing`. + */ + +exports = module.exports = Landing; + +/** + * Airplane color. + */ + +Base.colors.plane = 0; + +/** + * Airplane crash color. + */ + +Base.colors['plane crash'] = 31; + +/** + * Runway color. + */ + +Base.colors.runway = 90; + +/** + * Initialize a new `Landing` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Landing(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , total = runner.total + , stream = process.stdout + , plane = color('plane', '✈') + , crashed = -1 + , n = 0; + + function runway() { + var buf = Array(width).join('-'); + return ' ' + color('runway', buf); + } + + runner.on('start', function(){ + stream.write('\n '); + cursor.hide(); + }); + + runner.on('test end', function(test){ + // check if the plane crashed + var col = -1 == crashed + ? width * ++n / total | 0 + : crashed; + + // show the crash + if ('failed' == test.state) { + plane = color('plane crash', '✈'); + crashed = col; + } + + // render landing strip + stream.write('\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('\u001b[0m'); + }); + + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Landing.prototype = new Base; +Landing.prototype.constructor = Landing; + +}); // module: reporters/landing.js + +require.register("reporters/list.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `List`. + */ + +exports = module.exports = List; + +/** + * Initialize a new `List` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function List(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , n = 0; + + runner.on('start', function(){ + console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = color('checkmark', ' -') + + color('pending', ' %s'); + console.log(fmt, test.fullTitle()); + }); + + runner.on('pass', function(test){ + var fmt = color('checkmark', ' ✓') + + color('pass', ' %s: ') + + color(test.speed, '%dms'); + cursor.CR(); + console.log(fmt, test.fullTitle(), test.duration); + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +List.prototype = new Base; +List.prototype.constructor = List; + + +}); // module: reporters/list.js + +require.register("reporters/markdown.js", function(module, exports, require){ +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils'); + +/** + * Expose `Markdown`. + */ + +exports = module.exports = Markdown; + +/** + * Initialize a new `Markdown` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Markdown(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , level = 0 + , buf = ''; + + function title(str) { + return Array(level).join('#') + ' ' + str; + } + + function indent() { + return Array(level).join(' '); + } + + function mapTOC(suite, obj) { + var ret = obj; + obj = obj[suite.title] = obj[suite.title] || { suite: suite }; + suite.suites.forEach(function(suite){ + mapTOC(suite, obj); + }); + return ret; + } + + function stringifyTOC(obj, level) { + ++level; + var buf = ''; + var link; + for (var key in obj) { + if ('suite' == key) continue; + if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; + if (key) buf += Array(level).join(' ') + link; + buf += stringifyTOC(obj[key], level); + } + --level; + return buf; + } + + function generateTOC(suite) { + var obj = mapTOC(suite, {}); + return stringifyTOC(obj, 0); + } + + generateTOC(runner.suite); + + runner.on('suite', function(suite){ + ++level; + var slug = utils.slug(suite.fullTitle()); + buf += '' + '\n'; + buf += title(suite.title) + '\n'; + }); + + runner.on('suite end', function(suite){ + --level; + }); + + runner.on('pass', function(test){ + var code = utils.clean(test.fn.toString()); + buf += test.title + '.\n'; + buf += '\n```js\n'; + buf += code + '\n'; + buf += '```\n\n'; + }); + + runner.on('end', function(){ + process.stdout.write('# TOC\n'); + process.stdout.write(generateTOC(runner.suite)); + process.stdout.write(buf); + }); +} +}); // module: reporters/markdown.js + +require.register("reporters/min.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Min`. + */ + +exports = module.exports = Min; + +/** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @param {Runner} runner + * @api public + */ + +function Min(runner) { + Base.call(this, runner); + + runner.on('start', function(){ + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position + process.stdout.write('\u001b[1;3H'); + }); + + runner.on('end', this.epilogue.bind(this)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Min.prototype = new Base; +Min.prototype.constructor = Min; + +}); // module: reporters/min.js + +require.register("reporters/nyan.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , color = Base.color; + +/** + * Expose `Dot`. + */ + +exports = module.exports = NyanCat; + +/** + * Initialize a new `Dot` matrix test reporter. + * + * @param {Runner} runner + * @api public + */ + +function NyanCat(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , width = Base.window.width * .75 | 0 + , rainbowColors = this.rainbowColors = self.generateColors() + , colorIndex = this.colorIndex = 0 + , numerOfLines = this.numberOfLines = 4 + , trajectories = this.trajectories = [[], [], [], []] + , nyanCatWidth = this.nyanCatWidth = 11 + , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) + , scoreboardWidth = this.scoreboardWidth = 5 + , tick = this.tick = 0 + , n = 0; + + runner.on('start', function(){ + Base.cursor.hide(); + self.draw('start'); + }); + + runner.on('pending', function(test){ + self.draw('pending'); + }); + + runner.on('pass', function(test){ + self.draw('pass'); + }); + + runner.on('fail', function(test, err){ + self.draw('fail'); + }); + + runner.on('end', function(){ + Base.cursor.show(); + for (var i = 0; i < self.numberOfLines; i++) write('\n'); + self.epilogue(); + }); +} + +/** + * Draw the nyan cat with runner `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.draw = function(status){ + this.appendRainbow(); + this.drawScoreboard(); + this.drawRainbow(); + this.drawNyanCat(status); + this.tick = !this.tick; +}; + +/** + * Draw the "scoreboard" showing the number + * of passes, failures and pending tests. + * + * @api private + */ + +NyanCat.prototype.drawScoreboard = function(){ + var stats = this.stats; + var colors = Base.colors; + + function draw(color, n) { + write(' '); + write('\u001b[' + color + 'm' + n + '\u001b[0m'); + write('\n'); + } + + draw(colors.green, stats.passes); + draw(colors.fail, stats.failures); + draw(colors.pending, stats.pending); + write('\n'); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Append the rainbow. + * + * @api private + */ + +NyanCat.prototype.appendRainbow = function(){ + var segment = this.tick ? '_' : '-'; + var rainbowified = this.rainbowify(segment); + + for (var index = 0; index < this.numberOfLines; index++) { + var trajectory = this.trajectories[index]; + if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); + trajectory.push(rainbowified); + } +}; + +/** + * Draw the rainbow. + * + * @api private + */ + +NyanCat.prototype.drawRainbow = function(){ + var self = this; + + this.trajectories.forEach(function(line, index) { + write('\u001b[' + self.scoreboardWidth + 'C'); + write(line.join('')); + write('\n'); + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Draw the nyan cat with `status`. + * + * @param {String} status + * @api private + */ + +NyanCat.prototype.drawNyanCat = function(status) { + var self = this; + var startWidth = this.scoreboardWidth + this.trajectories[0].length; + + [0, 1, 2, 3].forEach(function(index) { + write('\u001b[' + startWidth + 'C'); + + switch (index) { + case 0: + write('_,------,'); + write('\n'); + break; + case 1: + var padding = self.tick ? ' ' : ' '; + write('_|' + padding + '/\\_/\\ '); + write('\n'); + break; + case 2: + var padding = self.tick ? '_' : '__'; + var tail = self.tick ? '~' : '^'; + var face; + switch (status) { + case 'pass': + face = '( ^ .^)'; + break; + case 'fail': + face = '( o .o)'; + break; + default: + face = '( - .-)'; + } + write(tail + '|' + padding + face + ' '); + write('\n'); + break; + case 3: + var padding = self.tick ? ' ' : ' '; + write(padding + '"" "" '); + write('\n'); + break; + } + }); + + this.cursorUp(this.numberOfLines); +}; + +/** + * Move cursor up `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorUp = function(n) { + write('\u001b[' + n + 'A'); +}; + +/** + * Move cursor down `n`. + * + * @param {Number} n + * @api private + */ + +NyanCat.prototype.cursorDown = function(n) { + write('\u001b[' + n + 'B'); +}; + +/** + * Generate rainbow colors. + * + * @return {Array} + * @api private + */ + +NyanCat.prototype.generateColors = function(){ + var colors = []; + + for (var i = 0; i < (6 * 7); i++) { + var pi3 = Math.floor(Math.PI / 3); + var n = (i * (1.0 / 6)); + var r = Math.floor(3 * Math.sin(n) + 3); + var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); + var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); + colors.push(36 * r + 6 * g + b + 16); + } + + return colors; +}; + +/** + * Apply rainbow to the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +NyanCat.prototype.rainbowify = function(str){ + var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; + this.colorIndex += 1; + return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; +}; + +/** + * Stdout helper. + */ + +function write(string) { + process.stdout.write(string); +} + +/** + * Inherit from `Base.prototype`. + */ + +NyanCat.prototype = new Base; +NyanCat.prototype.constructor = NyanCat; + + +}); // module: reporters/nyan.js + +require.register("reporters/progress.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Progress`. + */ + +exports = module.exports = Progress; + +/** + * General progress bar color. + */ + +Base.colors.progress = 90; + +/** + * Initialize a new `Progress` bar test reporter. + * + * @param {Runner} runner + * @param {Object} options + * @api public + */ + +function Progress(runner, options) { + Base.call(this, runner); + + var self = this + , options = options || {} + , stats = this.stats + , width = Base.window.width * .50 | 0 + , total = runner.total + , complete = 0 + , max = Math.max; + + // default chars + options.open = options.open || '['; + options.complete = options.complete || '▬'; + options.incomplete = options.incomplete || '⋅'; + options.close = options.close || ']'; + options.verbose = false; + + // tests started + runner.on('start', function(){ + console.log(); + cursor.hide(); + }); + + // tests complete + runner.on('test end', function(){ + complete++; + var incomplete = total - complete + , percent = complete / total + , n = width * percent | 0 + , i = width - n; + + cursor.CR(); + process.stdout.write('\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)); + process.stdout.write(color('progress', options.close)); + if (options.verbose) { + process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); + } + }); + + // tests are complete, output some stats + // and the failures if any + runner.on('end', function(){ + cursor.show(); + console.log(); + self.epilogue(); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +Progress.prototype = new Base; +Progress.prototype.constructor = Progress; + + +}); // module: reporters/progress.js + +require.register("reporters/spec.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `Spec`. + */ + +exports = module.exports = Spec; + +/** + * Initialize a new `Spec` test reporter. + * + * @param {Runner} runner + * @api public + */ + +function Spec(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , indents = 0 + , n = 0; + + function indent() { + return Array(indents).join(' ') + } + + runner.on('start', function(){ + console.log(); + }); + + runner.on('suite', function(suite){ + ++indents; + console.log(color('suite', '%s%s'), indent(), suite.title); + }); + + runner.on('suite end', function(suite){ + --indents; + if (1 == indents) console.log(); + }); + + runner.on('test', function(test){ + process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); + }); + + runner.on('pending', function(test){ + var fmt = indent() + color('pending', ' - %s'); + console.log(fmt, test.title); + }); + + runner.on('pass', function(test){ + if ('fast' == test.speed) { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s '); + cursor.CR(); + console.log(fmt, test.title); + } else { + var fmt = indent() + + color('checkmark', ' ✓') + + color('pass', ' %s ') + + color(test.speed, '(%dms)'); + cursor.CR(); + console.log(fmt, test.title, test.duration); + } + }); + + runner.on('fail', function(test, err){ + cursor.CR(); + console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); + }); + + runner.on('end', self.epilogue.bind(self)); +} + +/** + * Inherit from `Base.prototype`. + */ + +Spec.prototype = new Base; +Spec.prototype.constructor = Spec; + + +}); // module: reporters/spec.js + +require.register("reporters/tap.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , cursor = Base.cursor + , color = Base.color; + +/** + * Expose `TAP`. + */ + +exports = module.exports = TAP; + +/** + * Initialize a new `TAP` reporter. + * + * @param {Runner} runner + * @api public + */ + +function TAP(runner) { + Base.call(this, runner); + + var self = this + , stats = this.stats + , total = runner.total + , n = 1; + + runner.on('start', function(){ + console.log('%d..%d', 1, total); + }); + + runner.on('test end', function(){ + ++n; + }); + + runner.on('pending', function(test){ + console.log('ok %d %s # SKIP -', n, title(test)); + }); + + runner.on('pass', function(test){ + console.log('ok %d %s', n, title(test)); + }); + + runner.on('fail', function(test, err){ + console.log('not ok %d %s', n, title(test)); + console.log(err.stack.replace(/^/gm, ' ')); + }); +} + +/** + * Return a TAP-safe title of `test` + * + * @param {Object} test + * @return {String} + * @api private + */ + +function title(test) { + return test.fullTitle().replace(/#/g, ''); +} + +}); // module: reporters/tap.js + +require.register("reporters/teamcity.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base'); + +/** + * Expose `Teamcity`. + */ + +exports = module.exports = Teamcity; + +/** + * Initialize a new `Teamcity` reporter. + * + * @param {Runner} runner + * @api public + */ + +function Teamcity(runner) { + Base.call(this, runner); + var stats = this.stats; + + runner.on('start', function() { + console.log("##teamcity[testSuiteStarted name='mocha.suite']"); + }); + + runner.on('test', function(test) { + console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); + }); + + runner.on('fail', function(test, err) { + console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); + }); + + runner.on('pending', function(test) { + console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); + }); + + runner.on('test end', function(test) { + console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); + }); + + runner.on('end', function() { + console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); + }); +} + +/** + * Escape the given `str`. + */ + +function escape(str) { + return str + .replace(/\|/g, "||") + .replace(/\n/g, "|n") + .replace(/\r/g, "|r") + .replace(/\[/g, "|[") + .replace(/\]/g, "|]") + .replace(/\u0085/g, "|x") + .replace(/\u2028/g, "|l") + .replace(/\u2029/g, "|p") + .replace(/'/g, "|'"); +} + +}); // module: reporters/teamcity.js + +require.register("reporters/xunit.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Base = require('./base') + , utils = require('../utils') + , escape = utils.escape; + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `XUnit`. + */ + +exports = module.exports = XUnit; + +/** + * Initialize a new `XUnit` reporter. + * + * @param {Runner} runner + * @api public + */ + +function XUnit(runner) { + Base.call(this, runner); + var stats = this.stats + , tests = [] + , self = this; + + runner.on('pass', function(test){ + tests.push(test); + }); + + runner.on('fail', function(test){ + tests.push(test); + }); + + runner.on('end', function(){ + console.log(tag('testsuite', { + name: 'Mocha Tests' + , tests: stats.tests + , failures: stats.failures + , errors: stats.failures + , skip: stats.tests - stats.failures - stats.passes + , timestamp: (new Date).toUTCString() + , time: stats.duration / 1000 + }, false)); + + tests.forEach(test); + console.log(''); + }); +} + +/** + * Inherit from `Base.prototype`. + */ + +XUnit.prototype = new Base; +XUnit.prototype.constructor = XUnit; + + +/** + * Output tag for the given `test.` + */ + +function test(test) { + var attrs = { + classname: test.parent.fullTitle() + , name: test.title + , time: test.duration / 1000 + }; + + if ('failed' == test.state) { + var err = test.err; + attrs.message = escape(err.message); + console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); + } else if (test.pending) { + console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); + } else { + console.log(tag('testcase', attrs, true) ); + } +} + +/** + * HTML tag helper. + */ + +function tag(name, attrs, close, content) { + var end = close ? '/>' : '>' + , pairs = [] + , tag; + + for (var key in attrs) { + pairs.push(key + '="' + escape(attrs[key]) + '"'); + } + + tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; + if (content) tag += content + ''; +} + +}); // module: reporters/xunit.js + +require.register("runnable.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runnable'); + +/** + * Save timer references to avoid Sinon interfering (see GH-237). + */ + +var Date = global.Date + , setTimeout = global.setTimeout + , setInterval = global.setInterval + , clearTimeout = global.clearTimeout + , clearInterval = global.clearInterval; + +/** + * Expose `Runnable`. + */ + +module.exports = Runnable; + +/** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Runnable(title, fn) { + this.title = title; + this.fn = fn; + this.async = fn && fn.length; + this.sync = ! this.async; + this._timeout = 2000; + this.timedOut = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runnable.prototype = new EventEmitter; +Runnable.prototype.constructor = Runnable; + + +/** + * Set & get timeout `ms`. + * + * @param {Number} ms + * @return {Runnable|Number} ms or self + * @api private + */ + +Runnable.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + debug('timeout %d', ms); + this._timeout = ms; + if (this.timer) this.resetTimeout(); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Runnable.prototype.fullTitle = function(){ + return this.parent.fullTitle() + ' ' + this.title; +}; + +/** + * Clear the timeout. + * + * @api private + */ + +Runnable.prototype.clearTimeout = function(){ + clearTimeout(this.timer); +}; + +/** + * Inspect the runnable void of private properties. + * + * @return {String} + * @api private + */ + +Runnable.prototype.inspect = function(){ + return JSON.stringify(this, function(key, val){ + if ('_' == key[0]) return; + if ('parent' == key) return '#'; + if ('ctx' == key) return '#'; + return val; + }, 2); +}; + +/** + * Reset the timeout. + * + * @api private + */ + +Runnable.prototype.resetTimeout = function(){ + var self = this + , ms = this.timeout(); + + this.clearTimeout(); + if (ms) { + this.timer = setTimeout(function(){ + self.callback(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } +}; + +/** + * Run the test and invoke `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runnable.prototype.run = function(fn){ + var self = this + , ms = this.timeout() + , start = new Date + , ctx = this.ctx + , finished + , emitted; + + if (ctx) ctx.runnable(this); + + // timeout + if (this.async) { + if (ms) { + this.timer = setTimeout(function(){ + done(new Error('timeout of ' + ms + 'ms exceeded')); + self.timedOut = true; + }, ms); + } + } + + // called multiple times + function multiple(err) { + if (emitted) return; + emitted = true; + self.emit('error', err || new Error('done() called multiple times')); + } + + // finished + function done(err) { + if (self.timedOut) return; + if (finished) return multiple(err); + self.clearTimeout(); + self.duration = new Date - start; + finished = true; + fn(err); + } + + // for .resetTimeout() + this.callback = done; + + // async + if (this.async) { + try { + this.fn.call(ctx, function(err){ + if (err instanceof Error) return done(err); + if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); + done(); + }); + } catch (err) { + done(err); + } + return; + } + + // sync + try { + if (!this.pending) this.fn.call(ctx); + this.duration = new Date - start; + fn(); + } catch (err) { + fn(err); + } +}; + +}); // module: runnable.js + +require.register("runner.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:runner') + , Test = require('./test') + , utils = require('./utils') + , filter = utils.filter + , keys = utils.keys + , noop = function(){}; + +/** + * Expose `Runner`. + */ + +module.exports = Runner; + +/** + * Initialize a `Runner` for the given `suite`. + * + * Events: + * + * - `start` execution started + * - `end` execution complete + * - `suite` (suite) test suite execution started + * - `suite end` (suite) all tests (and sub-suites) have finished + * - `test` (test) test execution started + * - `test end` (test) test completed + * - `hook` (hook) hook execution started + * - `hook end` (hook) hook complete + * - `pass` (test) test passed + * - `fail` (test, err) test failed + * + * @api public + */ + +function Runner(suite) { + var self = this; + this._globals = []; + this.suite = suite; + this.total = suite.total(); + this.failures = 0; + this.on('test end', function(test){ self.checkGlobals(test); }); + this.on('hook end', function(hook){ self.checkGlobals(hook); }); + this.grep(/.*/); + this.globals(utils.keys(global).concat(['errno'])); +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Runner.prototype = new EventEmitter; +Runner.prototype.constructor = Runner; + + +/** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @param {RegExp} re + * @param {Boolean} invert + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.grep = function(re, invert){ + debug('grep %s', re); + this._grep = re; + this._invert = invert; + this.total = this.grepTotal(this.suite); + return this; +}; + +/** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @param {Suite} suite + * @return {Number} + * @api public + */ + +Runner.prototype.grepTotal = function(suite) { + var self = this; + var total = 0; + + suite.eachTest(function(test){ + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (match) total++; + }); + + return total; +}; + +/** + * Allow the given `arr` of globals. + * + * @param {Array} arr + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.globals = function(arr){ + if (0 == arguments.length) return this._globals; + debug('globals %j', arr); + utils.forEach(arr, function(arr){ + this._globals.push(arr); + }, this); + return this; +}; + +/** + * Check for global variable leaks. + * + * @api private + */ + +Runner.prototype.checkGlobals = function(test){ + if (this.ignoreLeaks) return; + var leaks = filterLeaks(this._globals); + + this._globals = this._globals.concat(leaks); + + if (leaks.length > 1) { + this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); + } else if (leaks.length) { + this.fail(test, new Error('global leak detected: ' + leaks[0])); + } +}; + +/** + * Fail the given `test`. + * + * @param {Test} test + * @param {Error} err + * @api private + */ + +Runner.prototype.fail = function(test, err){ + ++this.failures; + test.state = 'failed'; + if ('string' == typeof err) { + err = new Error('the string "' + err + '" was thrown, throw an Error :)'); + } + this.emit('fail', test, err); +}; + +/** + * Fail the given `hook` with `err`. + * + * Hook failures (currently) hard-end due + * to that fact that a failing hook will + * surely cause subsequent tests to fail, + * causing jumbled reporting. + * + * @param {Hook} hook + * @param {Error} err + * @api private + */ + +Runner.prototype.failHook = function(hook, err){ + this.fail(hook, err); + this.emit('end'); +}; + +/** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @param {String} name + * @param {Function} function + * @api private + */ + +Runner.prototype.hook = function(name, fn){ + var suite = this.suite + , hooks = suite['_' + name] + , ms = suite._timeout + , self = this + , timer; + + function next(i) { + var hook = hooks[i]; + if (!hook) return fn(); + self.currentRunnable = hook; + + self.emit('hook', hook); + + hook.on('error', function(err){ + self.failHook(hook, err); + }); + + hook.run(function(err){ + hook.removeAllListeners('error'); + var testError = hook.error(); + if (testError) self.fail(self.test, testError); + if (err) return self.failHook(hook, err); + self.emit('hook end', hook); + next(++i); + }); + } + + process.nextTick(function(){ + next(0); + }); +}; + +/** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err)`. + * + * @param {String} name + * @param {Array} suites + * @param {Function} fn + * @api private + */ + +Runner.prototype.hooks = function(name, suites, fn){ + var self = this + , orig = this.suite; + + function next(suite) { + self.suite = suite; + + if (!suite) { + self.suite = orig; + return fn(); + } + + self.hook(name, function(err){ + if (err) { + self.suite = orig; + return fn(err); + } + + next(suites.pop()); + }); + } + + next(suites.pop()); +}; + +/** + * Run hooks from the top level down. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookUp = function(name, fn){ + var suites = [this.suite].concat(this.parents()).reverse(); + this.hooks(name, suites, fn); +}; + +/** + * Run hooks from the bottom up. + * + * @param {String} name + * @param {Function} fn + * @api private + */ + +Runner.prototype.hookDown = function(name, fn){ + var suites = [this.suite].concat(this.parents()); + this.hooks(name, suites, fn); +}; + +/** + * Return an array of parent Suites from + * closest to furthest. + * + * @return {Array} + * @api private + */ + +Runner.prototype.parents = function(){ + var suite = this.suite + , suites = []; + while (suite = suite.parent) suites.push(suite); + return suites; +}; + +/** + * Run the current test and callback `fn(err)`. + * + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTest = function(fn){ + var test = this.test + , self = this; + + try { + test.on('error', function(err){ + self.fail(test, err); + }); + test.run(fn); + } catch (err) { + fn(err); + } +}; + +/** + * Run tests in the given `suite` and invoke + * the callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runTests = function(suite, fn){ + var self = this + , tests = suite.tests + , test; + + function next(err) { + // if we bail after first err + if (self.failures && suite._bail) return fn(); + + // next test + test = tests.shift(); + + // all done + if (!test) return fn(); + + // grep + var match = self._grep.test(test.fullTitle()); + if (self._invert) match = !match; + if (!match) return next(); + + // pending + if (test.pending) { + self.emit('pending', test); + self.emit('test end', test); + return next(); + } + + // execute test and hook(s) + self.emit('test', self.test = test); + self.hookDown('beforeEach', function(){ + self.currentRunnable = self.test; + self.runTest(function(err){ + test = self.test; + + if (err) { + self.fail(test, err); + self.emit('test end', test); + return self.hookUp('afterEach', next); + } + + test.state = 'passed'; + self.emit('pass', test); + self.emit('test end', test); + self.hookUp('afterEach', next); + }); + }); + } + + this.next = next; + next(); +}; + +/** + * Run the given `suite` and invoke the + * callback `fn()` when complete. + * + * @param {Suite} suite + * @param {Function} fn + * @api private + */ + +Runner.prototype.runSuite = function(suite, fn){ + var total = this.grepTotal(suite) + , self = this + , i = 0; + + debug('run suite %s', suite.fullTitle()); + + if (!total) return fn(); + + this.emit('suite', this.suite = suite); + + function next() { + var curr = suite.suites[i++]; + if (!curr) return done(); + self.runSuite(curr, next); + } + + function done() { + self.suite = suite; + self.hook('afterAll', function(){ + self.emit('suite end', suite); + fn(); + }); + } + + this.hook('beforeAll', function(){ + self.runTests(suite, next); + }); +}; + +/** + * Handle uncaught exceptions. + * + * @param {Error} err + * @api private + */ + +Runner.prototype.uncaught = function(err){ + debug('uncaught exception %s', err.message); + var runnable = this.currentRunnable; + if (!runnable || 'failed' == runnable.state) return; + runnable.clearTimeout(); + err.uncaught = true; + this.fail(runnable, err); + + // recover from test + if ('test' == runnable.type) { + this.emit('test end', runnable); + this.hookUp('afterEach', this.next); + return; + } + + // bail on hooks + this.emit('end'); +}; + +/** + * Run the root suite and invoke `fn(failures)` + * on completion. + * + * @param {Function} fn + * @return {Runner} for chaining + * @api public + */ + +Runner.prototype.run = function(fn){ + var self = this + , fn = fn || function(){}; + + debug('start'); + + // uncaught callback + function uncaught(err) { + self.uncaught(err); + } + + // callback + this.on('end', function(){ + debug('end'); + process.removeListener('uncaughtException', uncaught); + fn(self.failures); + }); + + // run suites + this.emit('start'); + this.runSuite(this.suite, function(){ + debug('finished running'); + self.emit('end'); + }); + + // uncaught exception + process.on('uncaughtException', uncaught); + + return this; +}; + +/** + * Filter leaks with the given globals flagged as `ok`. + * + * @param {Array} ok + * @return {Array} + * @api private + */ + +function filterLeaks(ok) { + return filter(keys(global), function(key){ + var matched = filter(ok, function(ok){ + if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); + return key == ok; + }); + return matched.length == 0 && (!global.navigator || 'onerror' !== key); + }); +} +}); // module: runner.js + +require.register("suite.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var EventEmitter = require('browser/events').EventEmitter + , debug = require('browser/debug')('mocha:suite') + , utils = require('./utils') + , Hook = require('./hook'); + +/** + * Expose `Suite`. + */ + +exports = module.exports = Suite; + +/** + * Create a new `Suite` with the given `title` + * and parent `Suite`. When a suite with the + * same title is already present, that suite + * is returned to provide nicer reporter + * and more flexible meta-testing. + * + * @param {Suite} parent + * @param {String} title + * @return {Suite} + * @api public + */ + +exports.create = function(parent, title){ + var suite = new Suite(title, parent.ctx); + suite.parent = parent; + if (parent.pending) suite.pending = true; + title = suite.fullTitle(); + parent.addSuite(suite); + return suite; +}; + +/** + * Initialize a new `Suite` with the given + * `title` and `ctx`. + * + * @param {String} title + * @param {Context} ctx + * @api private + */ + +function Suite(title, ctx) { + this.title = title; + this.ctx = ctx; + this.suites = []; + this.tests = []; + this.pending = false; + this._beforeEach = []; + this._beforeAll = []; + this._afterEach = []; + this._afterAll = []; + this.root = !title; + this._timeout = 2000; + this._bail = false; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Suite.prototype = new EventEmitter; +Suite.prototype.constructor = Suite; + + +/** + * Return a clone of this `Suite`. + * + * @return {Suite} + * @api private + */ + +Suite.prototype.clone = function(){ + var suite = new Suite(this.title); + debug('clone'); + suite.ctx = this.ctx; + suite.timeout(this.timeout()); + suite.bail(this.bail()); + return suite; +}; + +/** + * Set timeout `ms` or short-hand such as "2s". + * + * @param {Number|String} ms + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.timeout = function(ms){ + if (0 == arguments.length) return this._timeout; + if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000; + debug('timeout %d', ms); + this._timeout = parseInt(ms, 10); + return this; +}; + +/** + * Sets whether to bail after first error. + * + * @parma {Boolean} bail + * @return {Suite|Number} for chaining + * @api private + */ + +Suite.prototype.bail = function(bail){ + if (0 == arguments.length) return this._bail; + debug('bail %s', bail); + this._bail = bail; + return this; +}; + +/** + * Run `fn(test[, done])` before running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._beforeAll.push(hook); + this.emit('beforeAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after running tests. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterAll = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after all" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._afterAll.push(hook); + this.emit('afterAll', hook); + return this; +}; + +/** + * Run `fn(test[, done])` before each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.beforeEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"before each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._beforeEach.push(hook); + this.emit('beforeEach', hook); + return this; +}; + +/** + * Run `fn(test[, done])` after each test case. + * + * @param {Function} fn + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.afterEach = function(fn){ + if (this.pending) return this; + var hook = new Hook('"after each" hook', fn); + hook.parent = this; + hook.timeout(this.timeout()); + hook.ctx = this.ctx; + this._afterEach.push(hook); + this.emit('afterEach', hook); + return this; +}; + +/** + * Add a test `suite`. + * + * @param {Suite} suite + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addSuite = function(suite){ + suite.parent = this; + suite.timeout(this.timeout()); + suite.bail(this.bail()); + this.suites.push(suite); + this.emit('suite', suite); + return this; +}; + +/** + * Add a `test` to this suite. + * + * @param {Test} test + * @return {Suite} for chaining + * @api private + */ + +Suite.prototype.addTest = function(test){ + test.parent = this; + test.timeout(this.timeout()); + test.ctx = this.ctx; + this.tests.push(test); + this.emit('test', test); + return this; +}; + +/** + * Return the full title generated by recursively + * concatenating the parent's full title. + * + * @return {String} + * @api public + */ + +Suite.prototype.fullTitle = function(){ + if (this.parent) { + var full = this.parent.fullTitle(); + if (full) return full + ' ' + this.title; + } + return this.title; +}; + +/** + * Return the total number of tests. + * + * @return {Number} + * @api public + */ + +Suite.prototype.total = function(){ + return utils.reduce(this.suites, function(sum, suite){ + return sum + suite.total(); + }, 0) + this.tests.length; +}; + +/** + * Iterates through each suite recursively to find + * all tests. Applies a function in the format + * `fn(test)`. + * + * @param {Function} fn + * @return {Suite} + * @api private + */ + +Suite.prototype.eachTest = function(fn){ + utils.forEach(this.tests, fn); + utils.forEach(this.suites, function(suite){ + suite.eachTest(fn); + }); + return this; +}; + +}); // module: suite.js + +require.register("test.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var Runnable = require('./runnable'); + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @param {String} title + * @param {Function} fn + * @api private + */ + +function Test(title, fn) { + Runnable.call(this, title, fn); + this.pending = !fn; + this.type = 'test'; +} + +/** + * Inherit from `Runnable.prototype`. + */ + +Test.prototype = new Runnable; +Test.prototype.constructor = Test; + + +}); // module: test.js + +require.register("utils.js", function(module, exports, require){ + +/** + * Module dependencies. + */ + +var fs = require('browser/fs') + , path = require('browser/path') + , join = path.join + , debug = require('browser/debug')('mocha:watch'); + +/** + * Ignored directories. + */ + +var ignore = ['node_modules', '.git']; + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Array#forEach (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.forEach = function(arr, fn, scope) { + for (var i = 0, l = arr.length; i < l; i++) + fn.call(scope, arr[i], i); +}; + +/** + * Array#indexOf (<=IE8) + * + * @parma {Array} arr + * @param {Object} obj to find index of + * @param {Number} start + * @api private + */ + +exports.indexOf = function (arr, obj, start) { + for (var i = start || 0, l = arr.length; i < l; i++) { + if (arr[i] === obj) + return i; + } + return -1; +}; + +/** + * Array#reduce (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} initial value + * @param {Object} scope + * @api private + */ + +exports.reduce = function(arr, fn, val, scope) { + var rval = val; + + for (var i = 0, l = arr.length; i < l; i++) { + rval = fn.call(scope, rval, arr[i], i, arr); + } + + return rval; +}; + +/** + * Array#filter (<=IE8) + * + * @param {Array} array + * @param {Function} fn + * @param {Object} scope + * @api private + */ + +exports.filter = function(arr, fn, scope) { + var ret = []; + + for (var i = 0, l = arr.length; i < l; i++) { + var val = arr[i]; + if (fn.call(scope, val, i, arr)) + ret.push(val); + } + + return ret; +}; + +/** + * Object.keys (<=IE8) + * + * @param {Object} obj + * @return {Array} keys + * @api private + */ + +exports.keys = Object.keys || function(obj) { + var keys = [] + , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 + + for (var key in obj) { + if (has.call(obj, key)) { + keys.push(key); + } + } + + return keys; +}; + +/** + * Watch the given `files` for changes + * and invoke `fn(file)` on modification. + * + * @param {Array} files + * @param {Function} fn + * @api private + */ + +exports.watch = function(files, fn){ + var options = { interval: 100 }; + files.forEach(function(file){ + debug('file %s', file); + fs.watchFile(file, options, function(curr, prev){ + if (prev.mtime < curr.mtime) fn(file); + }); + }); +}; + +/** + * Ignored files. + */ + +function ignored(path){ + return !~ignore.indexOf(path); +} + +/** + * Lookup files in the given `dir`. + * + * @return {Array} + * @api private + */ + +exports.files = function(dir, ret){ + ret = ret || []; + + fs.readdirSync(dir) + .filter(ignored) + .forEach(function(path){ + path = join(dir, path); + if (fs.statSync(path).isDirectory()) { + exports.files(path, ret); + } else if (path.match(/\.(js|coffee)$/)) { + ret.push(path); + } + }); + + return ret; +}; + +/** + * Compute a slug from the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.slug = function(str){ + return str + .toLowerCase() + .replace(/ +/g, '-') + .replace(/[^-\w]/g, ''); +}; + +/** + * Strip the function definition from `str`, + * and re-indent for pre whitespace. + */ + +exports.clean = function(str) { + str = str + .replace(/^function *\(.*\) *{/, '') + .replace(/\s+\}$/, ''); + + var spaces = str.match(/^\n?( *)/)[1].length + , re = new RegExp('^ {' + spaces + '}', 'gm'); + + str = str.replace(re, ''); + + return exports.trim(str); +}; + +/** + * Escape regular expression characters in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +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, ''); +}; +}); // module: utils.js +/** + * Node shims. + * + * These are meant only to allow + * mocha.js to run untouched, not + * to allow running node code in + * the browser. + */ + +process = {}; +process.exit = function(status){}; +process.stdout = {}; +global = window; + +/** + * next tick implementation. + */ + +process.nextTick = (function(){ + // postMessage behaves badly on IE8 + if (window.ActiveXObject || !window.postMessage) { + return function(fn){ fn() }; + } + + // based on setZeroTimeout by David Baron + // - http://dbaron.org/log/20100309-faster-timeouts + var timeouts = [] + , name = 'mocha-zero-timeout' + + window.addEventListener('message', function(e){ + if (e.source == window && e.data == name) { + if (e.stopPropagation) e.stopPropagation(); + if (timeouts.length) timeouts.shift()(); + } + }, true); + + return function(fn){ + timeouts.push(fn); + window.postMessage(name, '*'); + } +})(); + +/** + * Remove uncaughtException listener. + */ + +process.removeListener = function(e){ + if ('uncaughtException' == e) { + window.onerror = null; + } +}; + +/** + * Implements uncaughtException listener. + */ + +process.on = function(e, fn){ + if ('uncaughtException' == e) { + window.onerror = fn; + } +}; + +/** + * Expose mocha. + */ + +window.mocha = require('mocha'); + +// boot +;(function(){ + var utils = mocha.utils + , options = {} + + // TODO: use new Mocha here... not mocha.grep etc + + 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. + */ + + function highlightCode() { + var code = document.getElementsByTagName('code'); + for (var i = 0, len = code.length; i < len; ++i) { + code[i].innerHTML = highlight(code[i].innerHTML); + } + } + + /** + * Parse the given `qs`. + */ + + function parse(qs) { + return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){ + var i = pair.indexOf('=') + , key = pair.slice(0, i) + , val = pair.slice(++i); + + obj[key] = decodeURIComponent(val); + return obj; + }, {}); + } + + /** + * Grep. + */ + + mocha.grep = function(str){ + options.grep = new RegExp(utils.escapeRegexp(str)); + }; + + /** + * 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, null, mocha); + }; + + /** + * Run mocha, returning the Runner. + */ + + 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.grep) runner.grep(options.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); + }; +})(); +})(); \ No newline at end of file diff --git a/test/test-jquery-endless-scroll.coffee b/test/test-jquery-endless-scroll.coffee new file mode 100644 index 0000000..c39b4e3 --- /dev/null +++ b/test/test-jquery-endless-scroll.coffee @@ -0,0 +1,46 @@ +describe 'jQuery EndlessScroll', -> + + beforeEach -> + $.unstubAll() + + describe 'Instance', -> + + it 'initiates an instance', -> + new EndlessScroll(this, {}) + + it 'responds to a #run() function', -> + EndlessScroll.should.respondTo('run') + + it 'wraps with a jQuery object', -> + $().endlessScroll() + + describe 'Instance Options', -> + + it 'has default options', -> + subject = new EndlessScroll + subject.options.intervalFrequency.should.eql(250) + + it 'passes in custom options', -> + subjectA = new EndlessScroll(this, intervalFrequency: 42) + subjectB = new EndlessScroll(this, intervalFrequency: 1337) + + subjectA.options.intervalFrequency.should.eql(42) + subjectB.options.intervalFrequency.should.eql(1337) + + describe 'Whether Class (Boolean Calculation)', -> + + beforeEach -> + $(document).stub('height', 1000) + $(window).stub('height', 600) + + it '#DocumentIsScrollableDownward - TRUE', -> + $(window).stub('scrollTop', 500) + + result = Whether.DocumentIsScrollableDownward(bottomPixels: 50) + result.should.be.true + + it '#DocumentIsScrollableDownward - FALSE', -> + $(window).stub('scrollTop', 100) + + result = Whether.DocumentIsScrollableDownward(bottomPixels: 50) + result.should.be.false diff --git a/test/test-jquery-endless-scroll.js b/test/test-jquery-endless-scroll.js new file mode 100644 index 0000000..09b1c04 --- /dev/null +++ b/test/test-jquery-endless-scroll.js @@ -0,0 +1,60 @@ +(function() { + + describe('jQuery EndlessScroll', function() { + beforeEach(function() { + return $.unstubAll(); + }); + describe('Instance', function() { + it('initiates an instance', function() { + return new EndlessScroll(this, {}); + }); + it('responds to a #run() function', function() { + return EndlessScroll.should.respondTo('run'); + }); + return it('wraps with a jQuery object', function() { + return $().endlessScroll(); + }); + }); + describe('Instance Options', function() { + it('has default options', function() { + var subject; + subject = new EndlessScroll; + return subject.options.intervalFrequency.should.eql(250); + }); + return it('passes in custom options', function() { + var subjectA, subjectB; + subjectA = new EndlessScroll(this, { + intervalFrequency: 42 + }); + subjectB = new EndlessScroll(this, { + intervalFrequency: 1337 + }); + subjectA.options.intervalFrequency.should.eql(42); + return subjectB.options.intervalFrequency.should.eql(1337); + }); + }); + return describe('Whether Class (Boolean Calculation)', function() { + beforeEach(function() { + $(document).stub('height', 1000); + return $(window).stub('height', 600); + }); + it('#DocumentIsScrollableDownward - TRUE', function() { + var result; + $(window).stub('scrollTop', 500); + result = Whether.DocumentIsScrollableDownward({ + bottomPixels: 50 + }); + return result.should.be["true"]; + }); + return it('#DocumentIsScrollableDownward - FALSE', function() { + var result; + $(window).stub('scrollTop', 100); + result = Whether.DocumentIsScrollableDownward({ + bottomPixels: 50 + }); + return result.should.be["false"]; + }); + }); + }); + +}).call(this); diff --git a/test/tests-jquery.html b/test/tests-jquery.html new file mode 100644 index 0000000..1702ee9 --- /dev/null +++ b/test/tests-jquery.html @@ -0,0 +1,28 @@ + + + Endless Scroll Tests (jQuery) + + + + + + + + + + + + + + + + + +
                + + diff --git a/test/tests-zepto.html b/test/tests-zepto.html new file mode 100644 index 0000000..39475c9 --- /dev/null +++ b/test/tests-zepto.html @@ -0,0 +1,28 @@ + + + Endless Scroll Tests (Zepto) + + + + + + + + + + + + + + + + + +
                + +