From: Jack Allnutt Date: Sat, 17 Sep 2011 14:01:44 +0000 (+0100) Subject: Updating npm externals X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=b58015cbd0dac3c974feafc63e024f6eed1b86a7;p=KiwiIRC.git Updating npm externals --- diff --git a/node/app.js b/node/app.js index 6243647..b320641 100644 --- a/node/app.js +++ b/node/app.js @@ -596,9 +596,12 @@ this.httpHandler = function (request, response) { } response.end(); } else { - kiwi.jade.renderFile(__dirname + '/client/index.html.jade', { locals: { "touchscreen": touchscreen, "debug": debug, "server_set": server_set, "server": server, "nick": nick, "agent": agent, "config": kiwi.config }}, function (err, html) { + fs.readFile(__dirname + '/client/index.html.jade', 'utf8', function (err, str) { + var html, hash2; if (!err) { - var hash2 = crypto.createHash('md5').update(html).digest('base64'); + html = kiwi.jade.compile(str)({ "touchscreen": touchscreen, "debug": debug, "server_set": server_set, "server": server, "nick": nick, "agent": agent, "config": kiwi.config }); + console.log(typeof html, html); + hash2 = crypto.createHash('md5').update(html).digest('base64'); kiwi.cache.html[hash] = {"html": html, "hash": hash2}; if (request.headers['if-none-match'] === hash2) { response.statusCode = 304; diff --git a/node/node_modules/___uglify-js.npm/package/.gitignore b/node/node_modules/___uglify-js.npm/package/.gitignore deleted file mode 100644 index d97eaa0..0000000 --- a/node/node_modules/___uglify-js.npm/package/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -.tmp*~ -*.local.* -.pinf-* \ No newline at end of file diff --git a/node/node_modules/___uglify-js.npm/package/README.html b/node/node_modules/___uglify-js.npm/package/README.html deleted file mode 100644 index 8bc5da6..0000000 --- a/node/node_modules/___uglify-js.npm/package/README.html +++ /dev/null @@ -1,835 +0,0 @@ - - - - -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). -
    • -
    -
  • -
- - - -
- -
-

1.1 Unsafe transformations

-
- - -

-UglifyJS tries its best to achieve great compression while leaving the -semantics of the code intact. In general, if your code logic is broken by -UglifyJS then it's a bug in UglifyJS and you should report it and I should -fix it. :-) -

-

-However, I opted to include the following potentially unsafe transformations -as default behavior. Discussion is welcome, if you have ideas of how to -handle this better, or any objections to these optimizations, please let me -know. -

- -
- -
-

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.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). - -
  • -
  • ---extra — enable additional optimizations that have not yet been -extensively tested. These might, or might not, break your code. If you -find a bug using this option, please report a test case. - -
  • -
  • ---unsafe — enable other additional optimizations that are known to be -unsafe in some contrived situations, but could still be generally useful. -For now only this: - -
      -
    • -foo.toString() ==> foo+"" - -
    • -
    -
  • -
  • ---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. -
  • -
- - - -
- -
-

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_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. - -
    • -
    -
  • -
  • -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.5 Compression – how good is it?

-
- - -

-(XXX: this is somewhat outdated. On the jQuery source code we beat Closure -by 168 bytes (560 after gzip) and by many seconds.) -

-

-There are a few popular JS minifiers nowadays – the two most well known -being the GoogleClosure (GCL) compiler and the YUI compressor. For some -reason they are both written in Java. I didn't really hope to beat any of -them, but finally I did – UglifyJS compresses better than the YUI -compressor, and safer than GoogleClosure. -

-

-I tested it on two big libraries. DynarchLIB is my own, and it's big enough -to contain probably all the JavaScript tricks known to mankind. jQuery is -definitely the most popular JavaScript library (to some people, it's a -synonym to JavaScript itself). -

-

-I cannot swear that there are no bugs in the generated codes, but they -appear to work fine. -

-

-Compression results: -

- - -- - - - - - - - -
LibraryOrig. sizeUglifyJSYUIGCL
DynarchLIB636896241441246452 (+5011)240439 (-1002) (buggy)
jQuery1638557200679702 (+7696)71858 (-148)
- - -

-UglifyJS is the fastest to run. On my laptop UglifyJS takes 1.35s for -DynarchLIB, while YUI takes 2.7s and GCL takes 6.5s. -

-

-GoogleClosure does a lot of smart ass optimizations. I had to strive really -hard to get close to it. It should be possible to even beat it, but then -again, GCL has a gazillion lines of code and runs terribly slow, so I'm not -sure it worths spending the effort to save a few bytes. Also, GCL doesn't -cope with eval() or with{} – it just dumps a warning and proceeds to -mangle names anyway; my DynarchLIB compiled with it is buggy because of -this. -

-

-UglifyJS consists of ~1100 lines of code for the tokenizer/parser, and ~1100 -lines for the compressor and code generator. That should make it very -maintainable and easily extensible, so I would say it has a good place in -this field and it's bound to become the de-facto standard JS minifier. And -I shall rule the world. :-) Use it, and spread the word! -

-
- -
- -
-

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-07-14 12:50:31 EEST

-

HTML generated by org-mode 7.01trans in emacs 23

-
-
- - diff --git a/node/node_modules/___uglify-js.npm/package/README.org b/node/node_modules/___uglify-js.npm/package/README.org deleted file mode 100644 index f0ae354..0000000 --- a/node/node_modules/___uglify-js.npm/package/README.org +++ /dev/null @@ -1,437 +0,0 @@ -#+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). - -** <> - -UglifyJS tries its best to achieve great compression while leaving the -semantics of the code intact. In general, if your code logic is broken by -UglifyJS then it's a bug in UglifyJS and you should report it and I should -fix it. :-) - -However, I opted to include the following potentially unsafe transformations -as default behavior. Discussion is welcome, if you have ideas of how to -handle this better, or any objections to these optimizations, please let me -know. - -*** 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 - -** 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). - -- =--extra= --- enable additional optimizations that have not yet been - extensively tested. These might, or might not, break your code. If you - find a bug using this option, please report a test case. - -- =--unsafe= --- enable other additional optimizations that are known to be - unsafe in some contrived situations, but could still be generally useful. - For now only this: - - - foo.toString() ==> foo+"" - -- =--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 and Css test - - - COLOR ME PINK - - -## Get Involved - -If you want to use this project and something is missing then send me a message. I'm very busy and have several open source projects I manage. I'll contribute to this project as I have time, but if there is more interest for some particular aspect, I'll work on it a lot faster. Also you're welcome to fork this project and send me patches/pull-requests. - -## About Performance - -The haml compiler isn't built for speed, it's built for maintainability. The actual generated templates, however are blazing fast. I benchmarked them with over 65 million renders per second on a small (20 line) template with some dynamic data on my laptop. Compare this to the 629 compiles per second I got out of the compiler. The idea is that you pre-compile your templates and reuse them on every request. While 629 per second is nothing compared to 65 million, that still means that your server with over 600 different views can boot up in about a second. I think that's fine for something that only happens every few weeks. - -## License - -Haml-js is [licensed][] under the [MIT license][]. - -[MIT license]: http://creativecommons.org/licenses/MIT/ -[licensed]: http://github.com/creationix/haml-js/blob/master/LICENSE -[jquery-haml]: http://github.com/creationix/jquery-haml -[haml]: http://haml-lang.com/ -[test.js]: http://github.com/creationix/haml-js/blob/master/test/test.js - - - - diff --git a/node/node_modules/jade/benchmarks/haml-js/lib/haml.js b/node/node_modules/jade/benchmarks/haml-js/lib/haml.js deleted file mode 100755 index b5ec4d3..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/lib/haml.js +++ /dev/null @@ -1,506 +0,0 @@ -var Haml; - -(function () { - - var matchers, self_close_tags, embedder, forceXML; - - function html_escape(text) { - return (text + ""). - replace(/&/g, "&"). - replace(//g, ">"). - replace(/\"/g, """); - } - - function render_attribs(attribs) { - var key, value, result = []; - for (key in attribs) { - if (key !== '_content' && attribs.hasOwnProperty(key)) { - switch (attribs[key]) { - case 'undefined': - case 'false': - case 'null': - case '""': - break; - default: - try { - value = JSON.parse("[" + attribs[key] +"]")[0]; - if (value === true) { - value = key; - } else if (typeof value === 'string' && embedder.test(value)) { - value = '" +\n' + parse_interpol(html_escape(value)) + ' +\n"'; - } else { - value = html_escape(value); - } - result.push(" " + key + '=\\"' + value + '\\"'); - } catch (e) { - result.push(" " + key + '=\\"" + html_escape(' + attribs[key] + ') + "\\"'); - } - } - } - } - return result.join(""); - } - - // Parse the attribute block using a state machine - function parse_attribs(line) { - var attributes = {}, - l = line.length, - i, c, - count = 1, - quote = false, - skip = false, - open, close, joiner, seperator, - pair = { - start: 1, - middle: null, - end: null - }; - - if (!(l > 0 && (line.charAt(0) === '{' || line.charAt(0) === '('))) { - return { - _content: line[0] === ' ' ? line.substr(1, l) : line - }; - } - open = line.charAt(0); - close = (open === '{') ? '}' : ')'; - joiner = (open === '{') ? ':' : '='; - seperator = (open === '{') ? ',' : ' '; - - function process_pair() { - if (typeof pair.start === 'number' && - typeof pair.middle === 'number' && - typeof pair.end === 'number') { - var key = line.substr(pair.start, pair.middle - pair.start).trim(), - value = line.substr(pair.middle + 1, pair.end - pair.middle - 1).trim(); - attributes[key] = value; - } - pair = { - start: null, - middle: null, - end: null - }; - } - - for (i = 1; count > 0; i += 1) { - - // If we reach the end of the line, then there is a problem - if (i > l) { - throw "Malformed attribute block"; - } - - c = line.charAt(i); - if (skip) { - skip = false; - } else { - if (quote) { - if (c === '\\') { - skip = true; - } - if (c === quote) { - quote = false; - } - } else { - if (c === '"' || c === "'") { - quote = c; - } - - if (count === 1) { - if (c === joiner) { - pair.middle = i; - } - if (c === seperator || c === close) { - pair.end = i; - process_pair(); - if (c === seperator) { - pair.start = i + 1; - } - } - } - - if (c === open || c === "(") { - count += 1; - } - if (c === close || (count > 1 && c === ")")) { - count -= 1; - } - } - } - } - attributes._content = line.substr(i, line.length); - return attributes; - } - - // Split interpolated strings into an array of literals and code fragments. - function parse_interpol(value) { - var items = [], - pos = 0, - next = 0, - match; - while (true) { - // Match up to embedded string - next = value.substr(pos).search(embedder); - if (next < 0) { - if (pos < value.length) { - items.push(JSON.stringify(value.substr(pos))); - } - break; - } - items.push(JSON.stringify(value.substr(pos, next))); - pos += next; - - // Match embedded string - match = value.substr(pos).match(embedder); - next = match[0].length; - if (next < 0) { break; } - items.push(match[1] || match[2]); - pos += next; - } - return items.filter(function (part) { return part && part.length > 0}).join(" +\n"); - } - - // Used to find embedded code in interpolated strings. - embedder = /\#\{([^}]*)\}/; - - self_close_tags = ["meta", "img", "link", "br", "hr", "input", "area", "base"]; - - // All matchers' regexps should capture leading whitespace in first capture - // and trailing content in last capture - matchers = [ - // html tags - { - regexp: /^(\s*)((?:[.#%][a-z_\-][a-z0-9_:\-]*)+)(.*)$/i, - process: function () { - var tag, classes, ids, attribs, content; - tag = this.matches[2]; - classes = tag.match(/\.([a-z_\-][a-z0-9_\-]*)/gi); - ids = tag.match(/\#([a-z_\-][a-z0-9_\-]*)/gi); - tag = tag.match(/\%([a-z_\-][a-z0-9_:\-]*)/gi); - - // Default to
tag - tag = tag ? tag[0].substr(1, tag[0].length) : 'div'; - - attribs = this.matches[3]; - if (attribs) { - attribs = parse_attribs(attribs); - if (attribs._content) { - this.contents.unshift(attribs._content.trim()); - delete(attribs._content); - } - } else { - attribs = {}; - } - - if (classes) { - classes = classes.map(function (klass) { - return klass.substr(1, klass.length); - }).join(' '); - if (attribs['class']) { - try { - attribs['class'] = JSON.stringify(classes + " " + JSON.parse(attribs['class'])); - } catch (e) { - attribs['class'] = JSON.stringify(classes + " ") + " + " + attribs['class']; - } - } else { - attribs['class'] = JSON.stringify(classes); - } - } - if (ids) { - ids = ids.map(function (id) { - return id.substr(1, id.length); - }).join(' '); - if (attribs.id) { - attribs.id = JSON.stringify(ids + " ") + attribs.id; - } else { - attribs.id = JSON.stringify(ids); - } - } - - attribs = render_attribs(attribs); - - content = this.render_contents(); - if (content === '""') { - content = ''; - } - - if (forceXML ? content.length > 0 : self_close_tags.indexOf(tag) == -1) { - return '"<' + tag + attribs + '>"' + - (content.length > 0 ? ' + \n' + content : "") + - ' + \n""'; - } else { - return '"<' + tag + attribs + ' />"'; - } - } - }, - - // each loops - { - regexp: /^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i, - process: function () { - var ivar = this.matches[2] || '__key__', // index - vvar = this.matches[3], // value - avar = this.matches[4], // array - rvar = '__result__'; // results - - if (this.matches[5]) { - this.contents.unshift(this.matches[5]); - } - return '(function () { ' + - 'var ' + rvar + ' = [], ' + ivar + ', ' + vvar + '; ' + - 'for (' + ivar + ' in ' + avar + ') { ' + - 'if (' + avar + '.hasOwnProperty(' + ivar + ')) { ' + - vvar + ' = ' + avar + '[' + ivar + ']; ' + - rvar + '.push(\n' + (this.render_contents() || "''") + '\n); ' + - '} } return ' + rvar + '.join(""); }).call(this)'; - } - }, - - // if statements - { - regexp: /^(\s*):if\s+(.*)\s*$/i, - process: function () { - var condition = this.matches[2]; - return '(function () { ' + - 'if (' + condition + ') { ' + - 'return (\n' + (this.render_contents() || '') + '\n);' + - '} else { return ""; } }).call(this)'; - } - }, - - // declarations - { - regexp: /^()!!!(?:\s*(.*))\s*$/, - process: function () { - var line = ''; - switch ((this.matches[2] || '').toLowerCase()) { - case '': - // XHTML 1.0 Transitional - line = ''; - break; - case 'strict': - case '1.0': - // XHTML 1.0 Strict - line = ''; - break; - case 'frameset': - // XHTML 1.0 Frameset - line = ''; - break; - case '5': - // XHTML 5 - line = ''; - break; - case '1.1': - // XHTML 1.1 - line = ''; - break; - case 'basic': - // XHTML Basic 1.1 - line = ''; - break; - case 'mobile': - // XHTML Mobile 1.2 - line = ''; - break; - case 'xml': - // XML - line = ""; - break; - case 'xml iso-8859-1': - // XML iso-8859-1 - line = ""; - break; - } - return JSON.stringify(line + "\n"); - } - }, - - // Embedded markdown. Needs to be added to exports externally. - { - regexp: /^(\s*):markdown\s*$/i, - process: function () { - return parse_interpol(exports.Markdown.encode(this.contents.join("\n"))); - } - }, - - // script blocks - { - regexp: /^(\s*):(?:java)?script\s*$/, - process: function () { - return parse_interpol('\n\n"); - } - }, - - // css blocks - { - regexp: /^(\s*):css\s*$/, - process: function () { - return JSON.stringify('\n\n"); - } - }, - - ]; - - function compile(lines) { - var block = false, - output = []; - - // If lines is a string, turn it into an array - if (typeof lines === 'string') { - lines = lines.trim().split("\n"); - } - - lines.forEach(function(line) { - var match, found = false; - - // Collect all text as raw until outdent - if (block) { - match = block.check_indent(line); - if (match) { - block.contents.push(match[1] || ""); - return; - } else { - output.push(block.process()); - block = false; - } - } - - matchers.forEach(function (matcher) { - if (!found) { - match = matcher.regexp(line); - if (match) { - block = { - contents: [], - matches: match, - check_indent: new RegExp("^(?:\\s*|" + match[1] + " (.*))$"), - process: matcher.process, - render_contents: function () { - return compile(this. contents); - } - }; - found = true; - } - } - }); - - // Match plain text - if (!found) { - output.push(function () { - // Escaped plain text - if (line[0] === '\\') { - return parse_interpol(line.substr(1, line.length)); - } - - // Plain variable data - if (line[0] === '=') { - line = line.substr(1, line.length).trim(); - try { - return parse_interpol(JSON.parse(line)); - } catch (e) { - return line; - } - } - - // HTML escape variable data - if (line.substr(0, 2) === "&=") { - line = line.substr(2, line.length).trim(); - try { - return JSON.stringify(html_escape(JSON.parse(line))); - } catch (e2) { - return 'html_escape(' + line + ')'; - } - } - - // Plain text - return parse_interpol(line); - }()); - } - - }); - if (block) { - output.push(block.process()); - } - return output.filter(function (part) { return part && part.length > 0}).join(" +\n"); - }; - - function optimize(js) { - var new_js = [], buffer = [], part, end; - - function flush() { - if (buffer.length > 0) { - new_js.push(JSON.stringify(buffer.join("")) + end); - buffer = []; - } - } - js.split("\n").forEach(function (line) { - part = line.match(/^(\".*\")(\s*\+\s*)?$/); - if (!part) { - flush(); - new_js.push(line); - return; - } - end = part[2] || ""; - part = part[1]; - try { - buffer.push(JSON.parse(part)); - } catch (e) { - flush(); - new_js.push(line); - } - }); - flush(); - return new_js.join("\n"); - }; - - function render(text, options) { - options = options || {}; - text = text || ""; - var js = compile(text); - if (options.optimize) { - js = Haml.optimize(js); - } - return execute(js, options.context || Haml, options.locals); - }; - - function execute(js, self, locals) { - return (function () { - with(locals || {}) { - try { - return eval("(" + js + ")"); - } catch (e) { - return "\n
" + html_escape(e.stack) + "
\n"; - } - - } - }).call(self); - }; - - Haml = function Haml(haml, xml) { - forceXML = xml; - var js = optimize(compile(haml)); - return new Function("locals", - html_escape + "\n" + - "with(locals || {}) {\n" + - " try {\n" + - " return (" + js + ");\n" + - " } catch (e) {\n" + - " return \"\\n
\" + html_escape(e.stack) + \"
\\n\";\n" + - " }\n" + - "}"); - } - Haml.compile = compile; - Haml.optimize = optimize; - Haml.render = render; - Haml.execute = execute; - -}()); - -// Hook into module system -if (typeof module !== 'undefined') { - module.exports = Haml; -} diff --git a/node/node_modules/jade/benchmarks/haml-js/package.json b/node/node_modules/jade/benchmarks/haml-js/package.json deleted file mode 100644 index e08678b..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "haml", - "description": "Haml ported to server-side Javascript. This is a traditional server-side templating language.", - "keywords": ["haml", "template"], - "main" : "./lib/haml", - "author": "Tim Caswell ", - "version": "0.2.5" -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.haml b/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.haml deleted file mode 100644 index 9e66fd4..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.haml +++ /dev/null @@ -1,4 +0,0 @@ -%tag(name="value" name2=true ns:tag=100) -%input#space-end(type="hidden" value="3" ) -%input#space-start( type="hidden" value="3" ) -%input#space-middle(type="hidden" value="3") diff --git a/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.html b/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.html deleted file mode 100644 index ef8ce3c..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/alt_attribs.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.haml b/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.haml deleted file mode 100644 index ac22bdc..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.haml +++ /dev/null @@ -1,5 +0,0 @@ -%div - Does not close properly - %div Nested same level as next div -%div - Will be nested, but should be top level \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.html b/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.html deleted file mode 100644 index 67983ee..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/div_nesting.html +++ /dev/null @@ -1 +0,0 @@ -
Does not close properly
Nested same level as next div
Will be nested, but should be top level
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/doctype.haml b/node/node_modules/jade/benchmarks/haml-js/test/doctype.haml deleted file mode 100644 index b08273b..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/doctype.haml +++ /dev/null @@ -1,5 +0,0 @@ -!!! -!!! strict -!!! 1.1 -!!! 5 -!!! xml diff --git a/node/node_modules/jade/benchmarks/haml-js/test/doctype.html b/node/node_modules/jade/benchmarks/haml-js/test/doctype.html deleted file mode 100644 index df8955f..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/doctype.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.haml b/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.haml deleted file mode 100644 index 72591af..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.haml +++ /dev/null @@ -1,6 +0,0 @@ -%head - :javascript - Page.chapter = #{JSON.stringify(chapter)}; -%body - %h1 Welcome #{name} - %div{class: "div_#{id}"} diff --git a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.html b/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.html deleted file mode 100644 index 8fa69ec..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.html +++ /dev/null @@ -1,7 +0,0 @@ - - -

Welcome Tim

\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.js b/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.js deleted file mode 100644 index 5e04d9d..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/embedded_code.js +++ /dev/null @@ -1,7 +0,0 @@ -{ - locals: { - chapter: {name: "Ninja", page: 42}, - name: "Tim", - id: 42 - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/foreach.haml b/node/node_modules/jade/benchmarks/haml-js/test/foreach.haml deleted file mode 100644 index 9ab286f..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/foreach.haml +++ /dev/null @@ -1,12 +0,0 @@ -:each color in colors - .preview{style: "color: " + color + ";"}&= name -:each item in data - :if item.age < 100 - %dl - :each name, value in item - %dt&= name - %dd&= value -:each number in [1,2,3,4,5,6,7] - = number -:for word in "Hello World".split(" ") - = word \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/foreach.html b/node/node_modules/jade/benchmarks/haml-js/test/foreach.html deleted file mode 100644 index 2f81fd1..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/foreach.html +++ /dev/null @@ -1 +0,0 @@ -
My Rainbow
My Rainbow
My Rainbow
name
Tim Caswell
age
27
1234567HelloWorld \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/foreach.js b/node/node_modules/jade/benchmarks/haml-js/test/foreach.js deleted file mode 100644 index 97de8e1..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/foreach.js +++ /dev/null @@ -1,10 +0,0 @@ -{ - locals: { - colors: ["#f80", "#08f", "#4f4"], - name: "My Rainbow", - data: [ - {name: "Tim Caswell", age: 27}, - {name: "John Smith", age: 107}, - ] - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/meta.haml b/node/node_modules/jade/benchmarks/haml-js/test/meta.haml deleted file mode 100644 index 59700e7..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/meta.haml +++ /dev/null @@ -1 +0,0 @@ -%meta(http-equiv="content-type" content="text/html; charset=UTF-8") diff --git a/node/node_modules/jade/benchmarks/haml-js/test/meta.html b/node/node_modules/jade/benchmarks/haml-js/test/meta.html deleted file mode 100644 index fec8b93..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/meta.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/nanline.haml b/node/node_modules/jade/benchmarks/haml-js/test/nanline.haml deleted file mode 100644 index f57fe22..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/nanline.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html - %head - %title atomix - - %script(src='atomix_xlib.js') diff --git a/node/node_modules/jade/benchmarks/haml-js/test/nanline.html b/node/node_modules/jade/benchmarks/haml-js/test/nanline.html deleted file mode 100644 index 78e1623..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/nanline.html +++ /dev/null @@ -1,2 +0,0 @@ - -atomix \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.haml b/node/node_modules/jade/benchmarks/haml-js/test/nested_context.haml deleted file mode 100644 index 907c484..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.haml +++ /dev/null @@ -1,6 +0,0 @@ -%p= this.name -#main - :each item in items - .item= this.name + ": " + item - :if items - #cool= this.name \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.html b/node/node_modules/jade/benchmarks/haml-js/test/nested_context.html deleted file mode 100644 index 0aa937e..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.html +++ /dev/null @@ -1 +0,0 @@ -

Frank

Frank: 1
Frank: 2
Frank: 3
Frank
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.js b/node/node_modules/jade/benchmarks/haml-js/test/nested_context.js deleted file mode 100644 index f823655..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/nested_context.js +++ /dev/null @@ -1,8 +0,0 @@ -{ - context: { - name: "Frank" - }, - locals: { - items: [1,2,3] - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.haml b/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.haml deleted file mode 100644 index 05ccbee..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.haml +++ /dev/null @@ -1,8 +0,0 @@ -%html - %body - %div#a - %div I do not self close. - :javascript - (function(){ - document.getElementById('a').textContent='I self close'; - })(); diff --git a/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.html b/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.html deleted file mode 100644 index 5067557..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/no_self_close_div.html +++ /dev/null @@ -1,9 +0,0 @@ -
I do not self close.
- - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.haml b/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.haml deleted file mode 100644 index 4e70727..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.haml +++ /dev/null @@ -1,8 +0,0 @@ -#plain= "Plain Text" -#escaped&= "" -%input{checked: true} -%input{checked: false} -%input{checked: null} -%input{checked: undefined} -%input{checked: 0} -%input{checked: ""} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.html b/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.html deleted file mode 100644 index b390396..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/non-string-attribs.html +++ /dev/null @@ -1 +0,0 @@ -
Plain Text
<escaped>
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/script_css.haml b/node/node_modules/jade/benchmarks/haml-js/test/script_css.haml deleted file mode 100644 index ed9a9d4..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/script_css.haml +++ /dev/null @@ -1,12 +0,0 @@ -%head - :javascript - function greet(message) { - alert("Message from MCP: " + message); - } - %title Script and Css test - :css - body { - color: pink; - } -%body{onload: "greet(\"I'm Pink\")"} COLOR ME PINK - diff --git a/node/node_modules/jade/benchmarks/haml-js/test/script_css.html b/node/node_modules/jade/benchmarks/haml-js/test/script_css.html deleted file mode 100644 index f4bd4c4..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/script_css.html +++ /dev/null @@ -1,15 +0,0 @@ - - -Script and Css test - -COLOR ME PINK \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/self_close.haml b/node/node_modules/jade/benchmarks/haml-js/test/self_close.haml deleted file mode 100644 index a26cdcd..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/self_close.haml +++ /dev/null @@ -1,8 +0,0 @@ -%html - %head - :if url !='/' - %script - %meta{name: "test", value:"Monkey"} - %body - %a{ href: url } - link \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/self_close.html b/node/node_modules/jade/benchmarks/haml-js/test/self_close.html deleted file mode 100644 index 90b50a0..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/self_close.html +++ /dev/null @@ -1 +0,0 @@ -link \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/self_close.js b/node/node_modules/jade/benchmarks/haml-js/test/self_close.js deleted file mode 100644 index 5f6f85c..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/self_close.js +++ /dev/null @@ -1,5 +0,0 @@ -{ - locals: { - url: "http://nodejs.org/" - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/standard.haml b/node/node_modules/jade/benchmarks/haml-js/test/standard.haml deleted file mode 100644 index 955fe05..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/standard.haml +++ /dev/null @@ -1,14 +0,0 @@ -!!! XML -!!! strict -%html{ xmlns: "http://www.w3.org/1999/xhtml" } - %head - %title - Sample haml template - %body - .profile - .left.column - #date= print_date() - #address= current_user.address - .right.column - #email= current_user.email - #bio= current_user.bio \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/standard.html b/node/node_modules/jade/benchmarks/haml-js/test/standard.html deleted file mode 100644 index bb24daa..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/standard.html +++ /dev/null @@ -1,3 +0,0 @@ - - -Sample haml template
January 1, 2009
Richardson, TX
tim@creationix.com
Experienced software professional...
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/standard.js b/node/node_modules/jade/benchmarks/haml-js/test/standard.js deleted file mode 100644 index 23abf66..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/standard.js +++ /dev/null @@ -1,12 +0,0 @@ -{ - locals: { - print_date: function () { - return 'January 1, 2009'; - }, - current_user: { - address: "Richardson, TX", - email: "tim@creationix.com", - bio: "Experienced software professional..." - } - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml-js/test/test-commonjs.js b/node/node_modules/jade/benchmarks/haml-js/test/test-commonjs.js deleted file mode 100644 index b20c2ac..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/test-commonjs.js +++ /dev/null @@ -1,23 +0,0 @@ -var FILE = require("file"); -var ASSERT = require("assert"); - -var Haml = require("../lib/haml"); - -FILE.glob("test/*.haml").forEach(function(hamlFile) { - exports["test " + hamlFile] = function() { - var scopeFile = hamlFile.replace(/haml$/, "js"); - var htmlFile = hamlFile.replace(/haml$/, "html"); - - var haml = FILE.read(hamlFile); - var expected = FILE.read(htmlFile); - var scope = FILE.exists(scopeFile) ? eval("("+FILE.read(scopeFile)+")") : {}; - - var js = Haml.compile(haml); - var js_opt = Haml.optimize(js); - var actual = Haml.execute(js_opt, scope.context, scope.locals); - ASSERT.equal(actual.trim(), expected.trim()); - } -}); - -if (module == require.main) - require("os").exit(require("test").run(exports)); diff --git a/node/node_modules/jade/benchmarks/haml-js/test/test.js b/node/node_modules/jade/benchmarks/haml-js/test/test.js deleted file mode 100644 index 9bbcadb..0000000 --- a/node/node_modules/jade/benchmarks/haml-js/test/test.js +++ /dev/null @@ -1,52 +0,0 @@ -var fs = require('fs'); -var assert = require('assert'); -var sys = require('sys'); - -var Haml = require("../lib/haml"); - -fs.readdir('.', function (err, files) { - files.forEach(function (haml_file) { - var m = haml_file.match(/^(.*)\.haml/), - base; - if (!m) { - return; - } - base = m[1]; - - function load_haml(scope) { - fs.readFile(haml_file, "utf8", function (err, haml) { - fs.readFile(base + ".html", "utf8", function (err, expected) { - try { - var js = Haml.compile(haml); - var js_opt = Haml.optimize(js); - var actual = Haml(haml).call(scope.context, scope.locals); - assert.equal(actual, expected); - - sys.puts(haml_file + " Passed") - } catch (e) { - var message = e.name; - if (e.message) { message += ": " + e.message; } - sys.error(haml_file + " FAILED") - sys.error(message); - sys.error("\nJS:\n\n" + js); - sys.error("\nOptimized JS:\n\n" + js_opt); - sys.error("\nActual:\n\n" + actual); - sys.error("\nExpected:\n\n" + expected); - process.exit(); - } - }); - }); - } - - // Load scope - if (files.indexOf(base + ".js") >= 0) { - fs.readFile(base + ".js", "utf8", function (err, js) { - load_haml(eval("(" + js + ")")); - }); - } else { - load_haml({}); - } - }); -}); - - diff --git a/node/node_modules/jade/benchmarks/haml.js b/node/node_modules/jade/benchmarks/haml.js deleted file mode 100644 index 7afbf36..0000000 --- a/node/node_modules/jade/benchmarks/haml.js +++ /dev/null @@ -1,25 +0,0 @@ - -/** - * Module dependencies. - */ - -var bm = require('./common'), - haml = require('./haml-js/lib/haml'), - fs = require('fs'); - -var str = fs.readFileSync(__dirname + '/example.haml', 'ascii'); - -var n = bm.times; -bm.start('haml-js compilation'); -while (n--) { - haml(str); -} -bm.stop(); - -var n = bm.times; -var fn = haml(str); -bm.start('haml-js execution'); -while (n--) { - fn.call('whatever scope', bm.locals); -} -bm.stop(); \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/.gitmodules b/node/node_modules/jade/benchmarks/haml/.gitmodules deleted file mode 100644 index 83fc8f9..0000000 --- a/node/node_modules/jade/benchmarks/haml/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "benchmarks/haml-js"] - path = benchmarks/haml-js - url = git://github.com/creationix/haml-js.git diff --git a/node/node_modules/jade/benchmarks/haml/.ignore b/node/node_modules/jade/benchmarks/haml/.ignore deleted file mode 100644 index 81736c9..0000000 --- a/node/node_modules/jade/benchmarks/haml/.ignore +++ /dev/null @@ -1 +0,0 @@ -benchmarks \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/History.md b/node/node_modules/jade/benchmarks/haml/History.md deleted file mode 100644 index 814f78c..0000000 --- a/node/node_modules/jade/benchmarks/haml/History.md +++ /dev/null @@ -1,88 +0,0 @@ - -0.4.5 / 2010-06-04 -================== - - * Ignoring stray indent - -0.4.4 / 2010-05-27 -================== - - * Fixed arbitrary whitespace support - -0.4.3 / 2010-05-25 -================== - - * Fixed support for CRLF / CR line-endings, converted on input - * Exporting HamlError - -0.4.2 / 2010-05-25 -================== - - * Added HamlError - * Buffer newline indentation. Closes #23 - * Benchmarks with node-bench - -0.4.1 / 2010-05-17 -================== - - * Fixed "- each" with non-enumerables, no longer throws exception - * Fixed array iteration - -0.4.0 / 2010-05-06 -================== - - * Using Function constructor instead of eval() - * Performance enhanced by faster iteration implementation for "- each" - -0.3.1 / 2010-04-26 -================== - - * Fixed support for tags with hypens (both namespace / tag name, ex: "fb:login-button") - -0.3.0 / 2010-04-16 -================== - - * Added xml namespace support - * Added xml support - -0.2.0 / 2010-04-06 -================== - - * Added conditional comment support [ciaranj] - * Fixed; Trimming input string before tokenization - * Fixed issue requiring quoting of "for" when used in attrs [aheckmann] - * Fixed; Exposing Haml compilation cache. Closes #12 - * Fixed :javascript "type" attr, now "text/javascript" [aheckmann] - -0.1.0 / 2010-03-31 -================== - - * Added "cache" option, making haml.js over 90 times faster than haml-js - * Improved textBlock whitespace replication - * Fixed empty tags followed by class / ids on new lines. Closes #6 - -0.0.4 / 2010-03-29 -================== - - * Added better error reporting - -0.0.3 / 2010-03-29 -================== - - * Added "filename" option support to aid in error reporting - * Added exports.compile() to create intermediate javascript - * Added `make benchmark` - * Changed; caching function templates to increase performance - * Fixed; ids and classes allowing underscores. Closes #5 - * Fixed outdent issue when \n is not followed by whitespace. Closes #8 - -0.0.2 / 2010-03-26 -================== - - * Added haml.js vs haml-js benchmarks - * Fixed; commenting :javascript CDATA - -0.0.1 / 2010-03-26 -================== - - * Initial release diff --git a/node/node_modules/jade/benchmarks/haml/Makefile b/node/node_modules/jade/benchmarks/haml/Makefile deleted file mode 100644 index 5580ecf..0000000 --- a/node/node_modules/jade/benchmarks/haml/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -test: - @node spec/node.js - -benchmark: - @node-bench benchmarks/run.js - -.PHONY: test benchmark \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/Readme.md b/node/node_modules/jade/benchmarks/haml/Readme.md deleted file mode 100644 index c629679..0000000 --- a/node/node_modules/jade/benchmarks/haml/Readme.md +++ /dev/null @@ -1,339 +0,0 @@ - -# Haml.js - - High performance JavaScript [Haml](http://haml-lang.com) implementation for [nodejs](http://nodejs.org) - - For a higher quality implementation you may want to look at my [Jade](http://jade-lang.com) template engine, - however the syntax is slightly different. Jade's engine may be back-ported to haml.js in the future. - -## Installation - - Install the [Kiwi package manager for nodejs](http://github.com/visionmedia/kiwi) - and run: - - $ kiwi install haml - - node> require('haml') - -Or npm: - - $ npm install hamljs - - node> require('hamljs') - -## About - - Benchmarks rendering the same 21 line haml file located at _benchmarks/page.haml_, - shows that this library is nearly **65%** or **3 times** faster than haml-js. - - Winner: haml.js - Compared with next highest (haml-js), it's: - 65.39% faster - 2.89 times as fast - 0 order(s) of magnitude faster - - Haml.js attempts to comply with the original [Haml](http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html) - implementation as well as possible. There are no magic "plugins" like - found in other JavaScript haml implementations, for example the following - will work just fine: - - - if (items) - %ul - - for (var i = 0; i < items.length; ++i) - %li= items[i] - - Iteration is the one exception to these magical plugins, - since this is **ugly** in JavaScript, you may also: - - - if (items) - %ul - - each item in items - %li= item - -## Usage - - var haml = require('haml') - haml.render('a string of haml', { a: 'hash', of: 'options' }) - -## Options - - * context - - when passed the value of "this" becomes the given "context" object - * locals - - when passed all members of this object become available to this template - * filename - - required when _cache_ is enabled - * cache - - compiled intermediate javascript is cached in memory keyed by _filename_ - -## Tags - - %div text - -html: - -
text
- -## Classes - - %div.article.first - article text here - and here - -html: - -
- article text here and here -
- -## Div Class Shortcut - - .comment hey - -html: - -
hey
- -## Div Id Shortcut - - #article-1 foo - -html: - -
foo
- -## Combining Ids and Classes - -You may chain id and classes in any order: - - .article#first.summary content - -html: - -
context
- -## Attributes - - %a{ href: 'http://google.com', title: 'Google It' } Google - -html: - - Google - -Attribute keys such as "for" are automatically quoted -by haml.js, so instead of: - - %label{ 'for': 'something' } - -you should: - - %label{ for: 'something' } - -which will render: - - - -## Boolean Attributes - - %input{ type: 'checkbox', checked: true } - -html: - - - -## Combining Attributes, Ids, and Classes - -Wemay also contain id and classes before or after: - - %a.button{ href: 'http://google.com', title: 'Google It' }.first Google - -html: - - Google - -## Code - -Code starting with a hyphen will be executed but -not buffered, where as code using the equals sign -will be buffered: - - - a = 1 - - b = 2 - = a + b - -html: - - 3 - -HTML buffered with equals sign will **always** be escaped: - - = "
" - -html: - - <br/> - -To prevent escaping of HTML entities we can use _!=_: - - != "
" - -html: - -
- -## Iteration - - %ul - - each item in items - %li= item - -html: - -
    -
  • one
  • -
  • two
  • -
  • three
  • -
- -If you require the key or index of the object -or array during iteration simple append a comma -following another id: - - %ul - - each item, index in items - %li= item + '(' + index + ')' - -html: - -
    -
  • one(0)
  • -
  • two(1)
  • -
  • three(2)
  • -
- -## Doctypes - -Defaults to transitional: - - !!! - -html: - - - -Optionally pass a supported doctype name: - - !!! strict - -html: - - - -currently supported doctypes, which can be -extended simply by adding values to to _haml.doctypes_. - - '5': '', - 'xml': '', - 'default': '', - 'strict': '', - 'frameset': '', - '1.1': '', - 'basic': '', - 'mobile': '' - - -## :cdata - - %script - :cdata - foo - -html: - - - -## :javascript - - %head - :javascript - if (foo) - if (bar) - alert('baz') - -html: - - - - - -## Extending Haml - -### Adding Filters - - var haml = require('haml') - haml.filters.my_filter = function(str) { - return doSomethingWith(str) - } - -by registering the filter function _my_filter_ we can now -utilize it within our Haml templates as shown below: - %p - :my_filter - some text - here yay - whoop awesome - -### Adding Doctypes - - var haml = require('haml') - haml.doctypes.foo = '' - -Will now allow you to: - !!! foo - -## Running Benchmarks - -To run benchmarks against [haml-js](http://github.com/creationix/haml-js) -simply execute: - - $ git submodule update --init - $ node benchmarks/run.js - -## More Information - - * View _spec/fixtures_ for more examples - * Official [Haml](http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html) reference - * JavaScript [Sass](http://github.com/visionmedia/sass.js) implementation - -## 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/node_modules/jade/benchmarks/haml/benchmarks/page.haml b/node/node_modules/jade/benchmarks/haml/benchmarks/page.haml deleted file mode 100644 index 98b40fb..0000000 --- a/node/node_modules/jade/benchmarks/haml/benchmarks/page.haml +++ /dev/null @@ -1,30 +0,0 @@ -!!! -%html - %head - %title Welcome - %script{ src: 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js', type: 'javascript' } - -# javascript filter (and others) - -# support arbitrary whitespace - :javascript - $(function(){ - alert('yay!') - }) - %meta{ name: 'keywords', content: 'foo bar baz' } - %body - %h1 Title - %ul - %li one - %li two - %li - %ol - %li one - %li two - %li three - %li four - %ul - %li five - %li six - %li - %ol - %li seven - %li eight \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/benchmarks/run.js b/node/node_modules/jade/benchmarks/haml/benchmarks/run.js deleted file mode 100644 index 190aec8..0000000 --- a/node/node_modules/jade/benchmarks/haml/benchmarks/run.js +++ /dev/null @@ -1,25 +0,0 @@ - -var fs = require('fs'), - haml = require('../lib/haml'), - hamlJS = require('./haml-js/lib/haml'), - page = fs.readFileSync('benchmarks/page.haml') - -var js = hamlJS.compile(page) - -exports.compare = { - 'haml.js': function(){ - haml.render(page) - }, - 'haml.js cached': function(){ - haml.render(page, { cache: true, filename: 'page.haml' }) - }, - 'haml-js': function(){ - hamlJS.render(page) - }, - 'haml-js cached': function(){ - hamlJS.execute(js) - }, - 'haml-js cached / optimized': function(){ - hamlJS.execute(js) - } -} diff --git a/node/node_modules/jade/benchmarks/haml/examples/example.js b/node/node_modules/jade/benchmarks/haml/examples/example.js deleted file mode 100644 index b3e7816..0000000 --- a/node/node_modules/jade/benchmarks/haml/examples/example.js +++ /dev/null @@ -1,15 +0,0 @@ - -var sys = require('sys'), - fs = require('fs'), - haml = require('../lib/haml') - -var options = { - filename: 'page.haml', - locals: { - title: 'Welcome', - body: 'wahoo', - usersOnline: 15 - } -} - -sys.puts(haml.render(fs.readFileSync('examples/page.haml'), options)) \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/examples/page.haml b/node/node_modules/jade/benchmarks/haml/examples/page.haml deleted file mode 100644 index ffb69ef..0000000 --- a/node/node_modules/jade/benchmarks/haml/examples/page.haml +++ /dev/null @@ -1,22 +0,0 @@ -%html - %head - %title= title - - %script{ src: 'jquery.js' } - - %script{ src: 'jquery.ui.js' } - - %body - %h1 Welcome - - %ul#menu - %li.first one - %li two - %li.last three - %li - %ul - %li nested - - #content - = body - #usersOnline= usersOnline diff --git a/node/node_modules/jade/benchmarks/haml/index.js b/node/node_modules/jade/benchmarks/haml/index.js deleted file mode 120000 index 55a170f..0000000 --- a/node/node_modules/jade/benchmarks/haml/index.js +++ /dev/null @@ -1 +0,0 @@ -lib/haml.js \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/lib/haml.js b/node/node_modules/jade/benchmarks/haml/lib/haml.js deleted file mode 100644 index 8da6ba3..0000000 --- a/node/node_modules/jade/benchmarks/haml/lib/haml.js +++ /dev/null @@ -1,666 +0,0 @@ - -// Haml - Copyright TJ Holowaychuk (MIT Licensed) - -/** - * Module dependencies. - */ - -var sys = require('sys') - -/** - * Version. - */ - -exports.version = '0.4.5' - -/** - * Haml template cache. - */ - -exports.cache = {} - -/** - * Default error context length. - */ - -exports.errorContextLength = 15 - -/** - * Self closing tags. - */ - -exports.selfClosing = [ - 'meta', - 'img', - 'link', - 'br', - 'hr', - 'input', - 'area', - 'base' - ] - -/** - * Default supported doctypes. - */ - -exports.doctypes = { - '5': '', - 'xml': '', - 'default': '', - 'strict': '', - 'frameset': '', - '1.1': '', - 'basic': '', - 'mobile': '' -} - -/** - * Default filters. - */ - -exports.filters = { - - /** - * Return plain string. - */ - - plain: function(str) { - return str - }, - - /** - * Wrap with CDATA tags. - */ - - cdata: function(str) { - return '' - }, - - /** - * Wrap with ' - } -} - -/** - * Function templates. - */ - -exports.templates = { - - /** - * Execute __code__. - */ - - code: (function(){ - __code__; - return "" - }).toString(), - - /** - * Execute __code__ followed by buffering __block__. - */ - - codeBlock: (function(){ - var buf = []; - __code__ - buf.push(__block__); - return buf.join("") - }).toString(), - - /** - * Iterate __vals__ as __val__ while buffering __block__. - */ - - iterate: (function(){ - var buf = []; - if (__vals__ instanceof Array) { - for (var i = 0, len = __vals__.length; i < len; ++i) { - var __key__ = i; - var __val__ = __vals__[i]; - buf.push(__block__); - } - } else if (__vals__) { - var keys = Object.keys(__vals__); - for (var i = 0, len = keys.length; i < len; ++i) { - var __key__ = keys[i]; - var __val__ = __vals__[__key__]; - buf.push(__block__); - } - } - return buf.join("") - }).toString() -} - -/** - * HamlError. - */ - -var HamlError = exports.HamlError = function(msg) { - this.name = 'HamlError' - this.message = msg - Error.captureStackTrace(this, exports.render) -} -sys.inherits(HamlError, Error) - -/** - * Lexing rules. - */ - -var rules = { - indent: /^\n( *)(?! *-#)/, - conditionalComment: /^\/(\[[^\n]+\])/, - comment: /^\n? *\/ */, - silentComment: /^\n? *-#([^\n]*)/, - doctype: /^!!! *([^\n]*)/, - escape: /^\\(.)/, - filter: /^:(\w+) */, - each: /^\- *each *(\w+)(?: *, *(\w+))? * in ([^\n]+)/, - code: /^\-([^\n]+)/, - outputCode: /^!=([^\n]+)/, - escapeCode: /^=([^\n]+)/, - attrs: /^\{(.*?)\}/, - tag: /^%([-a-zA-Z][-a-zA-Z0-9:]*)/, - class: /^\.([\w\-]+)/, - id: /^\#([\w\-]+)/, - text: /^([^\n]+)/ -} - -/** - * Return error context _str_. - * - * @param {string} str - * @return {string} - * @api private - */ - -function context(str) { - return String(str) - .substr(0, exports.errorContextLength) - .replace(/\n/g, '\\n') -} - -/** - * Tokenize _str_. - * - * @param {string} str - * @return {array} - * @api private - */ - -function tokenize(str) { - var captures, - token, - tokens = [], - line = 1, - lastIndents = 0, - str = String(str).trim().replace(/\r\n|\r/g, '\n') - function error(msg){ throw new HamlError('(Haml):' + line + ' ' + msg) } - while (str.length) { - for (var type in rules) - if (captures = rules[type].exec(str)) { - token = { - type: type, - line: line, - match: captures[0], - val: captures.length > 2 - ? captures.slice(1) - : captures[1] - } - str = str.substr(captures[0].length) - if (type === 'newline' || - type === 'indent') ++line - if (type !== 'indent') break - var indents = token.val.length / 2 - if (indents % 1) - error('invalid indentation; got ' + token.val.length + ' spaces, should be multiple of 2') - else if (indents - 1 > lastIndents) - error('invalid indentation; got ' + indents + ', when previous was ' + lastIndents) - else if (lastIndents > indents) - while (lastIndents-- > indents) - tokens.push({ type: 'outdent', line: line }) - else if (lastIndents !== indents) - tokens.push({ type: 'indent', line: line }) - else - tokens.push({ type: 'newline', line: line }) - lastIndents = indents - } - if (token) { - if (token.type !== 'silentComment') - tokens.push(token) - token = null - } else - error('near "' + context(str) + '"') - } - return tokens.concat({ type: 'eof' }) -} - -/** - * Render template _name_ with the given placeholder _vals_. - * - * @param {string} name - * @param {object} vals - * @return {string} - * @api private - */ - -function template(name, vals) { - var buf = '(' + exports.templates[name] + ').call(this)' - for (var key in vals) - buf = buf.replace(new RegExp(key, 'g'), vals[key]) - return buf -} - -// --- Parser - -/** - * Initialize parser with _str_ and _options_. - */ - -function Parser(str, options) { - options = options || {} - this.tokens = tokenize(str) - this.xml = options.xml -} - -Parser.prototype = { - - /** - * Lookahead a single token. - * - * @return {object} - * @api private - */ - - get peek() { - return this.tokens[0] - }, - - /** - * Advance a single token. - * - * @return {object} - * @api private - */ - - get advance() { - return this.current = this.tokens.shift() - }, - - /** - * outdent - * | eof - */ - - get outdent() { - switch (this.peek.type) { - case 'eof': - return - case 'outdent': - return this.advance - default: - throw new HamlError('expected outdent, got ' + this.peek.type) - } - }, - - /** - * text - */ - - get text() { - return '"' + this.advance.val.trim() + '"' - }, - - /** - * indent expr outdent - */ - - get block() { - var buf = [] - this.advance - while (this.peek.type !== 'outdent' && - this.peek.type !== 'eof') - buf.push(this.expr) - this.outdent - return buf.join(' + ') - }, - - /** - * indent expr - */ - - get textBlock() { - var token, - indents = 1, - buf = [] - this.advance - while (this.peek.type !== 'eof' && indents) - switch((token = this.advance).type) { - case 'newline': - buf.push('"\\n' + Array(indents).join(' ') + '"') - break - case 'indent': - ++indents - buf.push('"\\n' + Array(indents).join(' ') + '"') - break - case 'outdent': - --indents - if (indents === 1) buf.push('"\\n"') - break - default: - buf.push('"' + token.match.replace(/"/g, '\\\"') + '"') - } - return buf.join(' + ') - }, - - /** - * ( attrs | class | id )* - */ - - get attrs() { - var attrs = ['attrs', 'class', 'id'], - classes = [], - buf = [] - while (attrs.indexOf(this.peek.type) !== -1) - switch (this.peek.type) { - case 'id': - buf.push('id: "' + this.advance.val + '"') - break - case 'class': - classes.push(this.advance.val) - break - case 'attrs': - buf.push(this.advance.val.replace(/(for) *:/gi, '"$1":')) - } - if (classes.length) - buf.push('"class": "' + classes.join(' ') + '"') - return buf.length - ? ' " + attrs({' + buf.join() + '}) + "' - : '' - }, - - /** - * tag - * | tag text - * | tag conditionalComment - * | tag comment - * | tag outputCode - * | tag escapeCode - * | tag block - */ - - get tag() { - var tag = this.advance.val, - selfClosing = !this.xml && exports.selfClosing.indexOf(tag) !== -1, - buf = ['"\\n<' + tag + this.attrs + (selfClosing ? '/>"' : '>"')] - switch (this.peek.type) { - case 'text': - buf.push(this.text) - break - case 'conditionalComment': - buf.push(this.conditionalComment) - break; - case 'comment': - buf.push(this.comment) - break - case 'outputCode': - buf.push(this.outputCode) - break - case 'escapeCode': - buf.push(this.escapeCode) - break - case 'indent': - buf.push(this.block) - } - if (!selfClosing) buf.push('""') - return buf.join(' + ') - }, - - /** - * outputCode - */ - - get outputCode() { - return this.advance.val - }, - - /** - * escapeCode - */ - - get escapeCode() { - return 'escape(' + this.advance.val + ')' - }, - - /** - * doctype - */ - - get doctype() { - var doctype = this.advance.val.trim().toLowerCase() || 'default' - if (doctype in exports.doctypes) - return '"' + exports.doctypes[doctype].replace(/"/g, '\\"') + '"' - else - throw new HamlError("doctype `" + doctype + "' does not exist") - }, - - /** - * conditional comment expr - */ - - get conditionalComment() { - var condition= this.advance.val - var buf = this.peek.type === 'indent' - ? this.block - : this.expr - return '""' - }, - - /** - * comment expr - */ - - get comment() { - this.advance - var buf = this.peek.type === 'indent' - ? this.block - : this.expr - return '""' - }, - - /** - * code - * | code block - */ - - get code() { - var code = this.advance.val - if (this.peek.type === 'indent') - return template('codeBlock', { __code__: code, __block__: this.block }) - return template('code', { __code__: code }) - }, - - /** - * filter textBlock - */ - - get filter() { - var filter = this.advance.val - if (!(filter in exports.filters)) - throw new HamlError("filter `" + filter + "' does not exist") - if (this.peek.type !== 'indent') - throw new HamlError("filter `" + filter + "' expects a text block") - return 'exports.filters.' + filter + '(' + this.textBlock + ')' - }, - - /** - * each block - */ - - get iterate() { - var each = this.advance - if (this.peek.type !== 'indent') - throw new HamlError("'- each' expects a block, but got " + this.peek.type) - return template('iterate', { - __key__: each.val[1], - __vals__: each.val[2], - __val__: each.val[0], - __block__: this.block - }) - }, - - /** - * eof - * | tag - * | text* - * | each - * | code - * | escape - * | doctype - * | filter - * | comment - * | conditionalComment - * | escapeCode - * | outputCode - */ - - get expr() { - switch (this.peek.type) { - case 'id': - case 'class': - this.tokens.unshift({ type: 'tag', val: 'div' }) - return this.tag - case 'tag': - return this.tag - case 'text': - var buf = [] - while (this.peek.type === 'text') { - buf.push(this.advance.val.trim()) - if (this.peek.type === 'newline') - this.advance - } - return '"' + buf.join(' ') + '"' - case 'each': - return this.iterate - case 'code': - return this.code - case 'escape': - return '"' + this.advance.val + '"' - case 'doctype': - return this.doctype - case 'filter': - return this.filter - case 'conditionalComment': - return this.conditionalComment - case 'comment': - return this.comment - case 'escapeCode': - return this.escapeCode - case 'outputCode': - return this.outputCode - case 'newline': - case 'indent': - case 'outdent': - this.advance - return this.expr - default: - throw new HamlError('unexpected ' + this.peek.type) - } - }, - - /** - * expr* - */ - - get js() { - var buf = [] - while (this.peek.type !== 'eof') - buf.push(this.expr) - return buf.join(' + ') - } -} - -/** - * Escape html entities in _str_. - * - * @param {string} str - * @return {string} - * @api private - */ - -function escape(str) { - return String(str) - .replace(/&/g, '&') - .replace(/>/g, '>') - .replace(/", - "version": "0.4.5", - "directories": { - "lib": "." - } -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/seed.yml b/node/node_modules/jade/benchmarks/haml/seed.yml deleted file mode 100644 index 9fdfe3b..0000000 --- a/node/node_modules/jade/benchmarks/haml/seed.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- - name: Haml - description: Faster, harder, better HAML template engine - tags: haml html template engine - version: 0.4.5 diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.haml deleted file mode 100644 index f11f685..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.haml +++ /dev/null @@ -1 +0,0 @@ -.users \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.html deleted file mode 100644 index 4dc2d12..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/class.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.haml deleted file mode 100644 index dc250ce..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.haml +++ /dev/null @@ -1 +0,0 @@ -.foo.bar.baz_is-awesome \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.html deleted file mode 100644 index 94bf993..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/classes.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.haml deleted file mode 100644 index 9dbc82e..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.haml +++ /dev/null @@ -1,3 +0,0 @@ -%ul - - each item in items - %li= item \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.html deleted file mode 100644 index bfdb0cd..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -
  • one
  • -
  • two
  • -
  • three
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.haml deleted file mode 100644 index bfaf81f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.haml +++ /dev/null @@ -1,3 +0,0 @@ -%ul - - each item, index in items - %li= item + '(' + index + ')' \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.html deleted file mode 100644 index b449d4b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.index.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -
  • one(0)
  • -
  • two(1)
  • -
  • three(2)
\ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.haml deleted file mode 100644 index bfaf81f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.haml +++ /dev/null @@ -1,3 +0,0 @@ -%ul - - each item, index in items - %li= item + '(' + index + ')' \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.html deleted file mode 100644 index e2d1b04..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.each.non-enumerable.html +++ /dev/null @@ -1 +0,0 @@ -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.haml deleted file mode 100644 index aacec56..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.haml +++ /dev/null @@ -1 +0,0 @@ -= "" \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.html deleted file mode 100644 index a18ba70..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.escape.html +++ /dev/null @@ -1 +0,0 @@ -<br/> \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.haml deleted file mode 100644 index 4236fe0..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.haml +++ /dev/null @@ -1 +0,0 @@ -!= "foo" + "bar" \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.html deleted file mode 100644 index f6ea049..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.html +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.haml deleted file mode 100644 index 6731782..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.haml +++ /dev/null @@ -1,3 +0,0 @@ -- name = "tj" -- if (name === 'tj') - %p You are logged in \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.html deleted file mode 100644 index 07c3d71..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.if.html +++ /dev/null @@ -1 +0,0 @@ -

    You are logged in

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.haml deleted file mode 100644 index a86a44f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.haml +++ /dev/null @@ -1,5 +0,0 @@ -- if (true) - - if (false) - %p nope - - if (true) - %p yay \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.html deleted file mode 100644 index 26c4fe1..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/code.nested.html +++ /dev/null @@ -1 +0,0 @@ -

    yay

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.haml deleted file mode 100644 index 213e9a9..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.haml +++ /dev/null @@ -1,9 +0,0 @@ -/[if IE] - %a{ 'href' : 'http://www.mozilla.com/en-US/firefox/' } - %h1 Get Firefox -/[if IE] - %a{ 'href' : 'http://www.mozilla.com/en-US/firefox/' } - /[if IE 6] - %h1 Get Firefox (IE6 user) - /[if IE 7] - %h1 Get Firefox (IE7 user) \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.html deleted file mode 100644 index f0020fa..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.conditional.html +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.haml deleted file mode 100644 index 39041ea..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.haml +++ /dev/null @@ -1,5 +0,0 @@ -/ - %ul - %li nope - %li nope - %li nope \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.html deleted file mode 100644 index cfbdcb7..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.block.html +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.haml deleted file mode 100644 index 92d8988..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.haml +++ /dev/null @@ -1,3 +0,0 @@ --# nothing -%p yay - -# whatever you want \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.html deleted file mode 100644 index 26c4fe1..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.html +++ /dev/null @@ -1 +0,0 @@ -

    yay

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.haml deleted file mode 100644 index 880db37..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.haml +++ /dev/null @@ -1 +0,0 @@ - / %p foo \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.html deleted file mode 100644 index 1fde28f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.tag.html +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.haml deleted file mode 100644 index 187cb4f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.haml +++ /dev/null @@ -1,7 +0,0 @@ -%ul - %li one - / first item - %li two - / second item - %ul - %li three \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.html deleted file mode 100644 index 301aaf7..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.complex.html +++ /dev/null @@ -1,5 +0,0 @@ -
      -
    • one
    • -
    • two
    • -
        -
      • three
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.haml deleted file mode 100644 index 4dfe18d..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.haml +++ /dev/null @@ -1,2 +0,0 @@ -%p - / foo bar baz \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.html deleted file mode 100644 index 0d5b7c9..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/comment.text.html +++ /dev/null @@ -1 +0,0 @@ -

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.haml deleted file mode 100644 index a22be1c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.haml +++ /dev/null @@ -1 +0,0 @@ -%p= this \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.html deleted file mode 100644 index 26c4fe1..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/context.html +++ /dev/null @@ -1 +0,0 @@ -

    yay

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.haml deleted file mode 100644 index a492ae1..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.haml +++ /dev/null @@ -1 +0,0 @@ -#foo .bar \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.html deleted file mode 100644 index 65e61f7..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/cr.html +++ /dev/null @@ -1,3 +0,0 @@ -
    -
    -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.haml deleted file mode 100644 index 7263f27..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.haml +++ /dev/null @@ -1,2 +0,0 @@ -#foo - .bar \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.html deleted file mode 100644 index 65e61f7..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/crlf.html +++ /dev/null @@ -1,3 +0,0 @@ -
    -
    -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.haml deleted file mode 100644 index 08faabd..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.haml +++ /dev/null @@ -1 +0,0 @@ -!!! \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.html deleted file mode 100644 index f38b71c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.haml deleted file mode 100644 index 57e66ca..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.haml +++ /dev/null @@ -1 +0,0 @@ -!!! xml \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.html deleted file mode 100644 index 3297f54..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.case.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.haml deleted file mode 100644 index 3f0fe33..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.haml +++ /dev/null @@ -1 +0,0 @@ -!!! XML \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.html deleted file mode 100644 index 3297f54..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/doctype.xml.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/error.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/error.haml deleted file mode 100644 index c5b0877..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/error.haml +++ /dev/null @@ -1,3 +0,0 @@ -%html - %body - %p \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.haml deleted file mode 100644 index d226974..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.haml +++ /dev/null @@ -1,2 +0,0 @@ -%p - \.foo \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.html deleted file mode 100644 index a919d0c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/escape.html +++ /dev/null @@ -1 +0,0 @@ -

    .foo

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.haml deleted file mode 100644 index bc4b080..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.haml +++ /dev/null @@ -1,11 +0,0 @@ -!!! xml -%rss{ version: '2.0' } - %channel - %title ExpressJS - %link http://expressjs.com - %description Is super cool - %language en-us - %item - %title Creating Routes - %description Some stuff - %link http://expressjs.com/routes \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.xml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.xml deleted file mode 100644 index 6e0633d..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/feed.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - -ExpressJS -http://expressjs.com -Is super cool -en-us - -Creating Routes -Some stuff -http://expressjs.com/routes \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.haml deleted file mode 100644 index ede8c5b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.haml +++ /dev/null @@ -1,3 +0,0 @@ -%script - :cdata - foo \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.html deleted file mode 100644 index 8cefa09..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.html +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.haml deleted file mode 100644 index 30db588..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.haml +++ /dev/null @@ -1,7 +0,0 @@ -%script - :cdata - $(function(){ - if (foo) - if (bar) - alert('yay') - }) \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.html deleted file mode 100644 index c09bdd9..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.cdata.whitespace.html +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.haml deleted file mode 100644 index 6a4fb39..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.haml +++ /dev/null @@ -1,8 +0,0 @@ -%head - :javascript - if (foo) - if (bar) - alert("baz") - foo() - bar() - %title Yay \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.html deleted file mode 100644 index 62eefe2..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.javascript.html +++ /dev/null @@ -1,9 +0,0 @@ - -Yay \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.haml deleted file mode 100644 index 3d70c5d..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.haml +++ /dev/null @@ -1,5 +0,0 @@ -%body - :plain - .foo - bar - = baz \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.html deleted file mode 100644 index d2b9084..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/filter.plain.html +++ /dev/null @@ -1,3 +0,0 @@ -.foo -bar -= baz \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.haml deleted file mode 100644 index a516e3c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.haml +++ /dev/null @@ -1,2 +0,0 @@ -%div -

    literal

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.html deleted file mode 100644 index cf23b5b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/html.html +++ /dev/null @@ -1 +0,0 @@ -

    literal

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.haml deleted file mode 100644 index f2c7c82..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.haml +++ /dev/null @@ -1 +0,0 @@ -#users \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.html deleted file mode 100644 index c0171e2..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/id.html +++ /dev/null @@ -1 +0,0 @@ -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.haml deleted file mode 100644 index d6a16e3..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.haml +++ /dev/null @@ -1 +0,0 @@ -%label{ for: "forsomething"} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.html deleted file mode 100644 index c3e1e61..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#10.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.haml deleted file mode 100644 index 6611716..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.haml +++ /dev/null @@ -1,4 +0,0 @@ -%ul - - each item in items - %li= item -%p= "Total: " + items.length \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.html deleted file mode 100644 index b0d3442..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/issue.#8.html +++ /dev/null @@ -1,5 +0,0 @@ -
      -
    • foo
    • -
    • bar
    • -
    • baz
    -

    Total: 3

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.haml deleted file mode 100644 index 8ddd574..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.haml +++ /dev/null @@ -1 +0,0 @@ -%p= user \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.html deleted file mode 100644 index ab8d4e5..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/literals.html +++ /dev/null @@ -1 +0,0 @@ -

    tj

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.haml deleted file mode 100644 index 45fbdb6..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.haml +++ /dev/null @@ -1 +0,0 @@ -%h:table{ 'xmlns:h': 'http://www.w3.org/1999/xhtml' } \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.haml deleted file mode 100644 index ab6f9b2..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.haml +++ /dev/null @@ -1,5 +0,0 @@ -%body - %fb:test.a - %fb:bar - %fb:foo{ title: 'home' } - %fb:login-button diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.html deleted file mode 100644 index a5db0c0..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.tag.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.xml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.xml deleted file mode 100644 index 8d1888a..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/namespace.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.haml deleted file mode 100644 index b3bc8cc..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.haml +++ /dev/null @@ -1,6 +0,0 @@ -%html - %head - %title Page Title - %body - %h1 Title - %p some stuff \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.html deleted file mode 100644 index b6eb8b5..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.complex.html +++ /dev/null @@ -1,6 +0,0 @@ - - -Page Title - -

    Title

    -

    some stuff

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.haml deleted file mode 100644 index 7a91ed3..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.haml +++ /dev/null @@ -1,6 +0,0 @@ -%ul - %li one - %li two - %li - %ul - %li three \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.html deleted file mode 100644 index 50544e2..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/nesting.simple.html +++ /dev/null @@ -1,6 +0,0 @@ -
      -
    • one
    • -
    • two
    • -
    • -
        -
      • three
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.haml deleted file mode 100644 index b087e44..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.haml +++ /dev/null @@ -1,12 +0,0 @@ -%ul - %li one - %li two - %li three - %li - %ul - %li four - -%p foo -%p - bar - baz \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.html deleted file mode 100644 index 5beb1f9..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/newlines.html +++ /dev/null @@ -1,9 +0,0 @@ -
      -
    • one
    • -
    • two
    • -
    • three
    • -
    • -
        -
      • four
    -

    foo

    -

    bar baz

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.haml deleted file mode 100644 index 7e0dc4f..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.haml +++ /dev/null @@ -1 +0,0 @@ -%input{ type: 'checkbox', checked: true } \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.html deleted file mode 100644 index 84416da..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.bools.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.haml deleted file mode 100644 index b9f40e1..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.haml +++ /dev/null @@ -1 +0,0 @@ -%option{ value: '' } \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.html deleted file mode 100644 index a958f38..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.escape.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.haml deleted file mode 100644 index 84d2729..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.haml +++ /dev/null @@ -1 +0,0 @@ -%a{ href: '/', title: 'home' } \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.html deleted file mode 100644 index 2f8ca31..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.attrs.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.haml deleted file mode 100644 index 66dbc04..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.haml +++ /dev/null @@ -1 +0,0 @@ -%h1.title \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.html deleted file mode 100644 index 101bb29..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.class.html +++ /dev/null @@ -1 +0,0 @@ -

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.haml deleted file mode 100644 index 61a79a6..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.haml +++ /dev/null @@ -1 +0,0 @@ -%body.front-page.editing-user \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.html deleted file mode 100644 index 173556e..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.classes.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.haml deleted file mode 100644 index 679e61c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.haml +++ /dev/null @@ -1 +0,0 @@ -%div= "yay" \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.html deleted file mode 100644 index b3d55fc..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.html +++ /dev/null @@ -1 +0,0 @@ -
    yay
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.haml deleted file mode 100644 index f092e67..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.haml +++ /dev/null @@ -1 +0,0 @@ -%div!= "
    " \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.html deleted file mode 100644 index 2c2ec7a..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.code.no-escape.html +++ /dev/null @@ -1 +0,0 @@ -

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.haml deleted file mode 100644 index 307f672..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.haml +++ /dev/null @@ -1 +0,0 @@ -%a#delete-user.first.button{ href: '/', title: 'Click to delete' }= "Delete " + "tj" \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.html deleted file mode 100644 index 4ddee81..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.complex.html +++ /dev/null @@ -1 +0,0 @@ -Delete tj \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.haml deleted file mode 100644 index fdfb6cb..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.haml +++ /dev/null @@ -1,7 +0,0 @@ -%body - %div.a - %div.b - .c - .d - #e - #f \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.html deleted file mode 100644 index ddc05d3..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.empty.html +++ /dev/null @@ -1,7 +0,0 @@ - -
    -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.haml deleted file mode 100644 index d33a301..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.haml +++ /dev/null @@ -1 +0,0 @@ -%div= "
    " \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.html deleted file mode 100644 index 5b703e7..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.escape.html +++ /dev/null @@ -1 +0,0 @@ -
    <br/>
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.haml deleted file mode 100644 index 63096c9..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.haml +++ /dev/null @@ -1 +0,0 @@ -%br \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.html deleted file mode 100644 index 4bbea23..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.self-close.html +++ /dev/null @@ -1 +0,0 @@ -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.haml deleted file mode 100644 index 20d531e..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.haml +++ /dev/null @@ -1 +0,0 @@ -%div \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.html deleted file mode 100644 index 281c686..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.simple.html +++ /dev/null @@ -1 +0,0 @@ -
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.haml deleted file mode 100644 index cc55e16..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.haml +++ /dev/null @@ -1,5 +0,0 @@ -%p - Visit - %a{ href: 'http://vision-media.ca' } Vision Media - because im amazing, - yes... \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.html deleted file mode 100644 index 07c2b6b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.complex.html +++ /dev/null @@ -1,2 +0,0 @@ -

    Visit -Vision Mediabecause im amazing, yes...

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.haml deleted file mode 100644 index 20c5bcf..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.haml +++ /dev/null @@ -1,5 +0,0 @@ -%p - some text - and more text - and even more text! - OMG \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.html deleted file mode 100644 index e02ce19..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.block.html +++ /dev/null @@ -1 +0,0 @@ -

    some text and more text and even more text! OMG

    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.haml deleted file mode 100644 index 8718f9a..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.haml +++ /dev/null @@ -1 +0,0 @@ -%div some text \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.html deleted file mode 100644 index e64083b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/tag.text.html +++ /dev/null @@ -1 +0,0 @@ -
    some text
    \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.haml b/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.haml deleted file mode 100644 index 1e118cd..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.haml +++ /dev/null @@ -1,4 +0,0 @@ -%a - %b - - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.html b/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.html deleted file mode 100644 index 094e68b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/fixtures/trailing-indent.html +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/bg.png b/node/node_modules/jade/benchmarks/haml/spec/lib/images/bg.png deleted file mode 100644 index 947804f..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/bg.png and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/hr.png b/node/node_modules/jade/benchmarks/haml/spec/lib/images/hr.png deleted file mode 100644 index 4a94d12..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/hr.png and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/loading.gif b/node/node_modules/jade/benchmarks/haml/spec/lib/images/loading.gif deleted file mode 100644 index c69e937..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/loading.gif and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.bg.png b/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.bg.png deleted file mode 100644 index dc8790f..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.bg.png and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.png b/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.png deleted file mode 100644 index 010b98e..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/sprites.png and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/images/vr.png b/node/node_modules/jade/benchmarks/haml/spec/lib/images/vr.png deleted file mode 100644 index b2e7617..0000000 Binary files a/node/node_modules/jade/benchmarks/haml/spec/lib/images/vr.png and /dev/null differ diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.css b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.css deleted file mode 100644 index 629d41c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.css +++ /dev/null @@ -1,149 +0,0 @@ -body.jspec { - margin: 45px 0; - font: 12px "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; - background: #efefef url(images/bg.png) top left repeat-x; - text-align: center; -} -#jspec { - margin: 0 auto; - padding-top: 30px; - width: 1008px; - background: url(images/vr.png) top left repeat-y; - text-align: left; -} -#jspec-top { - position: relative; - margin: 0 auto; - width: 1008px; - height: 40px; - background: url(images/sprites.bg.png) top left no-repeat; -} -#jspec-bottom { - margin: 0 auto; - width: 1008px; - height: 15px; - background: url(images/sprites.bg.png) bottom left no-repeat; -} -#jspec .loading { - margin-top: -45px; - width: 1008px; - height: 80px; - background: url(images/loading.gif) 50% 50% no-repeat; -} -#jspec-title { - position: absolute; - top: 15px; - left: 20px; - width: 160px; - font-size: 22px; - font-weight: normal; - background: url(images/sprites.png) 0 -126px no-repeat; - text-align: center; -} -#jspec-title em { - font-size: 10px; - font-style: normal; - color: #BCC8D1; -} -#jspec-report * { - margin: 0; - padding: 0; - background: none; - border: none; -} -#jspec-report { - padding: 15px 40px; - font: 11px "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; - color: #7B8D9B; -} -#jspec-report.has-failures { - padding-bottom: 30px; -} -#jspec-report .hidden { - display: none; -} -#jspec-report .heading { - margin-bottom: 15px; -} -#jspec-report .heading span { - padding-right: 10px; -} -#jspec-report .heading .passes em { - color: #0ea0eb; -} -#jspec-report .heading .failures em { - color: #FA1616; -} -#jspec-report table { - font-size: 11px; - border-collapse: collapse; -} -#jspec-report td { - padding: 8px; - text-indent: 30px; - color: #7B8D9B; -} -#jspec-report tr.body { - display: none; -} -#jspec-report tr.body pre { - margin: 0; - padding: 0 0 5px 25px; -} -#jspec-report tr.even:hover + tr.body, -#jspec-report tr.odd:hover + tr.body { - display: block; -} -#jspec-report tr td:first-child em { - display: block; - clear: both; - font-style: normal; - font-weight: normal; - color: #7B8D9B; -} -#jspec-report tr.even:hover, -#jspec-report tr.odd:hover { - text-shadow: 1px 1px 1px #fff; - background: #F2F5F7; -} -#jspec-report td + td { - padding-right: 0; - width: 15px; -} -#jspec-report td.pass { - background: url(images/sprites.png) 3px -7px no-repeat; -} -#jspec-report td.fail { - background: url(images/sprites.png) 3px -158px no-repeat; - font-weight: bold; - color: #FC0D0D; -} -#jspec-report td.requires-implementation { - background: url(images/sprites.png) 3px -333px no-repeat; -} -#jspec-report tr.description td { - margin-top: 25px; - padding-top: 25px; - font-size: 12px; - font-weight: bold; - text-indent: 0; - color: #1a1a1a; -} -#jspec-report tr.description:first-child td { - border-top: none; -} -#jspec-report .assertion { - display: block; - float: left; - margin: 0 0 0 1px; - padding: 0; - width: 1px; - height: 5px; - background: #7B8D9B; -} -#jspec-report .assertion.failed { - background: red; -} -.jspec-sandbox { - display: none; -} \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.growl.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.growl.js deleted file mode 100644 index a150257..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.growl.js +++ /dev/null @@ -1,115 +0,0 @@ - -// JSpec - Growl - Copyright TJ Holowaychuk (MIT Licensed) - -;(function(){ - - Growl = { - - // --- Version - - version: '1.0.0', - - /** - * Execute the given _cmd_, returning an array of lines from stdout. - * - * Examples: - * - * Growl.exec('growlnotify', '-m', msg) - * - * @param {string ...} cmd - * @return {array} - * @api public - */ - - exec: function(cmd) { - var lines = [], line - with (JavaImporter(java.lang, java.io)) { - var proccess = Runtime.getRuntime().exec(Array.prototype.slice.call(arguments)) - var stream = new DataInputStream(proccess.getInputStream()) - while (line = stream.readLine()) - lines.push(line + '') - stream.close() - } - return lines - }, - - /** - * Return the extension of the given _path_ or null. - * - * @param {string} path - * @return {string} - * @api private - */ - - extname: function(path) { - return path.lastIndexOf('.') != -1 ? - path.slice(path.lastIndexOf('.') + 1, path.length) : - null - }, - - /** - * Version of the 'growlnotify' binary. - * - * @return {string} - * @api private - */ - - binVersion: function() { - try { return this.exec('growlnotify', '-v')[0].split(' ')[1] } catch (e) {} - }, - - /** - * Send growl notification _msg_ with _options_. - * - * Options: - * - * - title Notification title - * - sticky Make the notification stick (defaults to false) - * - 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.notify('New email') - * Growl.notify('5 new emails', { title: 'Thunderbird' }) - * - * @param {string} msg - * @param {options} hash - * @api public - */ - - notify: function(msg, options) { - options = options || {} - var args = ['growlnotify', '-m', msg] - if (!this.binVersion()) throw new Error('growlnotify executable is required') - if (image = options.image) { - var flag, ext = this.extname(image) - 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) - } - if (options.sticky) args.push('--sticky') - if (options.name) args.push('--name', options.name) - if (options.title) args.push(options.title) - this.exec.apply(this, args) - } - } - - JSpec.include({ - name: 'Growl', - reporting: function(options){ - var stats = JSpec.stats - if (stats.failures) Growl.notify('failed ' + stats.failures + ' assertions', { title: 'JSpec'}) - else Growl.notify('passed ' + stats.passes + ' assertions', { title: 'JSpec' }) - } - }) - -})() \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.jquery.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.jquery.js deleted file mode 100644 index 46422ec..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.jquery.js +++ /dev/null @@ -1,79 +0,0 @@ - -// JSpec - jQuery - Copyright TJ Holowaychuk (MIT Licensed) - -JSpec -.requires('jQuery', 'when using jspec.jquery.js') -.include({ - name: 'jQuery', - - // --- Initialize - - init : function() { - jQuery.ajaxSetup({ async: false }) - }, - - // --- Utilities - - utilities : { - element: jQuery, - elements: jQuery, - sandbox : function() { - return jQuery('
    ') - } - }, - - // --- Matchers - - matchers : { - have_tag : "jQuery(expected, actual).length === 1", - have_one : "alias have_tag", - have_tags : "jQuery(expected, actual).length > 1", - have_many : "alias have_tags", - have_any : "alias have_tags", - have_child : "jQuery(actual).children(expected).length === 1", - have_children : "jQuery(actual).children(expected).length > 1", - have_text : "jQuery(actual).text() === expected", - have_value : "jQuery(actual).val() === expected", - be_enabled : "!jQuery(actual).attr('disabled')", - have_class : "jQuery(actual).hasClass(expected)", - be_animated : "jQuery(actual).queue().length > 0", - - be_visible : function(actual) { - return jQuery(actual).css('display') != 'none' && - jQuery(actual).css('visibility') != 'hidden' && - jQuery(actual).attr('type') != 'hidden' - }, - - be_hidden : function(actual) { - return !JSpec.does(actual, 'be_visible') - }, - - have_classes : function(actual) { - return !JSpec.any(JSpec.toArray(arguments, 1), function(arg){ - return !JSpec.does(actual, 'have_class', arg) - }) - }, - - have_attr : function(actual, attr, value) { - return value ? jQuery(actual).attr(attr) == value: - jQuery(actual).attr(attr) - }, - - have_event_handlers : function(actual, expected) { - return jQuery(actual).data('events') ? - jQuery(actual).data('events').hasOwnProperty(expected) : - false - }, - - 'be disabled selected checked' : function(attr) { - return 'jQuery(actual).attr("' + attr + '")' - }, - - 'have type id title alt href src sel rev name target' : function(attr) { - return function(actual, value) { - return JSpec.does(actual, 'have_attr', attr, value) - } - } - } -}) - diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.js deleted file mode 100644 index 131c745..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.js +++ /dev/null @@ -1,1893 +0,0 @@ - -// JSpec - Core - Copyright TJ Holowaychuk (MIT Licensed) - -;(function(){ - - JSpec = { - version : '4.3.2', - assert : true, - cache : {}, - suites : [], - modules : [], - allSuites : [], - sharedBehaviors: [], - matchers : {}, - stubbed : [], - options : {}, - request : 'XMLHttpRequest' in this ? XMLHttpRequest : null, - stats : { specs: 0, assertions: 0, failures: 0, passes: 0, specsFinished: 0, suitesFinished: 0 }, - - /** - * Default context in which bodies are evaluated. - * - * Replace context simply by setting JSpec.context - * to your own like below: - * - * JSpec.context = { foo : 'bar' } - * - * Contexts can be changed within any body, this can be useful - * in order to provide specific helper methods to specific suites. - * - * To reset (usually in after hook) simply set to null like below: - * - * JSpec.context = null - * - */ - - defaultContext : { - - /** - * Return an object used for proxy assertions. - * This object is used to indicate that an object - * should be an instance of _object_, not the constructor - * itself. - * - * @param {function} constructor - * @return {hash} - * @api public - */ - - an_instance_of : function(constructor) { - return { an_instance_of : constructor } - }, - - /** - * Load fixture at _path_. - * - * Fixtures are resolved as: - * - * - - * - .html - * - * @param {string} path - * @return {string} - * @api public - */ - - fixture : function(path) { - if (JSpec.cache[path]) return JSpec.cache[path] - return JSpec.cache[path] = - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) || - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.html') - }, - - /** - * Load json fixture at _path_. - * - * JSON fixtures are resolved as: - * - * - - * - .json - * - * @param {string} path - * @return {object} - * @api public - */ - - json_fixture: function(path) { - if (!JSpec.cache['json:' + path]) - JSpec.cache['json:' + path] = - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) || - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.json') - try { - return eval('(' + JSpec.cache['json:' + path] + ')') - } catch (e) { - throw 'json_fixture("' + path + '"): ' + e - } - } - }, - - // --- Objects - - reporters : { - - /** - * Report to server. - * - * Options: - * - uri specific uri to report to. - * - verbose weither or not to output messages - * - failuresOnly output failure messages only - * - * @api public - */ - - Server : function(results, options) { - var uri = options.uri || 'http://' + window.location.host + '/results' - JSpec.post(uri, { - stats: JSpec.stats, - options: options, - results: map(results.allSuites, function(suite) { - if (suite.isExecutable()) - return { - description: suite.description, - specs: map(suite.specs, function(spec) { - return { - description: spec.description, - message: !spec.passed() ? spec.failure().message : null, - status: spec.requiresImplementation() ? 'pending' : - spec.passed() ? 'pass' : - 'fail', - assertions: map(spec.assertions, function(assertion){ - return { - passed: assertion.passed - } - }) - } - }) - } - }) - }) - if ('close' in main) main.close() - }, - - /** - * Default reporter, outputting to the DOM. - * - * Options: - * - reportToId id of element to output reports to, defaults to 'jspec' - * - failuresOnly displays only suites with failing specs - * - * @api public - */ - - DOM : function(results, options) { - var id = option('reportToId') || 'jspec', - report = document.getElementById(id), - failuresOnly = option('failuresOnly'), - classes = results.stats.failures ? 'has-failures' : '' - if (!report) throw 'JSpec requires the element #' + id + ' to output its reports' - - function bodyContents(body) { - return JSpec. - escape(JSpec.contentsOf(body)). - replace(/^ */gm, function(a){ return (new Array(Math.round(a.length / 3))).join(' ') }). - replace(/\r\n|\r|\n/gm, '
    ') - } - - report.innerHTML = '
    \ - Passes: ' + results.stats.passes + ' \ - Failures: ' + results.stats.failures + ' \ - Duration: ' + results.duration + ' ms \ -
    ' + map(results.allSuites, function(suite) { - var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran - if (displaySuite && suite.isExecutable()) - return '' + - map(suite.specs, function(i, spec) { - return '' + - (spec.requiresImplementation() ? - '' : - (spec.passed() && !failuresOnly) ? - '' : - !spec.passed() ? - '' : - '') + - '' - }).join('') + '' - }).join('') + '
    ' + escape(suite.description) + '
    ' + escape(spec.description) + '' + escape(spec.description)+ '' + spec.assertionsGraph() + '' + escape(spec.description) + - map(spec.failures(), function(a){ return '' + escape(a.message) + '' }).join('') + - '' + spec.assertionsGraph() + '
    ' + bodyContents(spec.body) + '
    ' - }, - - /** - * Terminal reporter. - * - * @api public - */ - - Terminal : function(results, options) { - var failuresOnly = option('failuresOnly') - print(color("\n Passes: ", 'bold') + color(results.stats.passes, 'green') + - color(" Failures: ", 'bold') + color(results.stats.failures, 'red') + - color(" Duration: ", 'bold') + color(results.duration, 'green') + " ms \n") - - function indent(string) { - return string.replace(/^(.)/gm, ' $1') - } - - each(results.allSuites, function(suite) { - var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran - if (displaySuite && suite.isExecutable()) { - print(color(' ' + suite.description, 'bold')) - each(suite.specs, function(spec){ - var assertionsGraph = inject(spec.assertions, '', function(graph, assertion){ - return graph + color('.', assertion.passed ? 'green' : 'red') - }) - if (spec.requiresImplementation()) - print(color(' ' + spec.description, 'blue') + assertionsGraph) - else if (spec.passed() && !failuresOnly) - print(color(' ' + spec.description, 'green') + assertionsGraph) - else if (!spec.passed()) - print(color(' ' + spec.description, 'red') + assertionsGraph + - "\n" + indent(map(spec.failures(), function(a){ return a.message }).join("\n")) + "\n") - }) - print("") - } - }) - - quit(results.stats.failures) - } - }, - - Assertion : function(matcher, actual, expected, negate) { - extend(this, { - message: '', - passed: false, - actual: actual, - negate: negate, - matcher: matcher, - expected: expected, - - // Report assertion results - - report : function() { - if (JSpec.assert) - this.passed ? JSpec.stats.passes++ : JSpec.stats.failures++ - return this - }, - - // Run the assertion - - run : function() { - // TODO: remove unshifting - expected.unshift(actual) - this.result = matcher.match.apply(this, expected) - this.passed = negate ? !this.result : this.result - if (!this.passed) this.message = matcher.message.call(this, actual, expected, negate, matcher.name) - return this - } - }) - }, - - ProxyAssertion : function(object, method, times, negate) { - var self = this, - old = object[method] - - // Proxy - - object[method] = function(){ - var args = toArray(arguments), - result = old.apply(object, args) - self.calls.push({ args : args, result : result }) - return result - } - - // Times - - this.times = { - once : 1, - twice : 2 - }[times] || times || 1 - - extend(this, { - calls: [], - message: '', - defer: true, - passed: false, - negate: negate, - object: object, - method: method, - - // Proxy return value - - and_return : function(result) { - this.expectedResult = result - return this - }, - - // Proxy arguments passed - - with_args : function() { - this.expectedArgs = toArray(arguments) - return this - }, - - // Check if any calls have failing results - - anyResultsFail : function() { - return any(this.calls, function(call){ - return self.expectedResult.an_instance_of ? - call.result.constructor != self.expectedResult.an_instance_of: - !equal(self.expectedResult, call.result) - }) - }, - - // Check if any calls have passing results - - anyResultsPass : function() { - return any(this.calls, function(call){ - return self.expectedResult.an_instance_of ? - call.result.constructor == self.expectedResult.an_instance_of: - equal(self.expectedResult, call.result) - }) - }, - - // Return the passing result - - passingResult : function() { - return this.anyResultsPass().result - }, - - // Return the failing result - - failingResult : function() { - return this.anyResultsFail().result - }, - - // Check if any arguments fail - - anyArgsFail : function() { - return any(this.calls, function(call){ - return any(self.expectedArgs, function(i, arg){ - if (arg == null) return call.args[i] == null - return arg.an_instance_of ? - call.args[i].constructor != arg.an_instance_of: - !equal(arg, call.args[i]) - - }) - }) - }, - - // Check if any arguments pass - - anyArgsPass : function() { - return any(this.calls, function(call){ - return any(self.expectedArgs, function(i, arg){ - return arg.an_instance_of ? - call.args[i].constructor == arg.an_instance_of: - equal(arg, call.args[i]) - - }) - }) - }, - - // Return the passing args - - passingArgs : function() { - return this.anyArgsPass().args - }, - - // Return the failing args - - failingArgs : function() { - return this.anyArgsFail().args - }, - - // Report assertion results - - report : function() { - if (JSpec.assert) - this.passed ? ++JSpec.stats.passes : ++JSpec.stats.failures - return this - }, - - // Run the assertion - - run : function() { - var methodString = 'expected ' + object.toString() + '.' + method + '()' + (negate ? ' not' : '' ) - - function times(n) { - return n > 2 ? n + ' times' : { 1: 'once', 2: 'twice' }[n] - } - - if (this.expectedResult != null && (negate ? this.anyResultsPass() : this.anyResultsFail())) - this.message = methodString + ' to return ' + puts(this.expectedResult) + - ' but ' + (negate ? 'it did' : 'got ' + puts(this.failingResult())) - - if (this.expectedArgs && (negate ? !this.expectedResult && this.anyArgsPass() : this.anyArgsFail())) - this.message = methodString + ' to be called with ' + puts.apply(this, this.expectedArgs) + - ' but was' + (negate ? '' : ' called with ' + puts.apply(this, this.failingArgs())) - - if (negate ? !this.expectedResult && !this.expectedArgs && this.calls.length >= this.times : this.calls.length != this.times) - this.message = methodString + ' to be called ' + times(this.times) + - ', but ' + (this.calls.length == 0 ? ' was not called' : ' was called ' + times(this.calls.length)) - - if (!this.message.length) - this.passed = true - - return this - } - }) - }, - - /** - * Specification Suite block object. - * - * @param {string} description - * @param {function} body - * @api private - */ - - Suite : function(description, body, isShared) { - var self = this - extend(this, { - body: body, - description: description, - suites: [], - sharedBehaviors: [], - specs: [], - ran: false, - shared: isShared, - hooks: { 'before' : [], 'after' : [], - 'before_each' : [], 'after_each' : [], - 'before_nested' : [], 'after_nested' : []}, - - // Add a spec to the suite - - addSpec : function(description, body) { - var spec = new JSpec.Spec(description, body) - this.specs.push(spec) - JSpec.stats.specs++ // TODO: abstract - spec.suite = this - }, - - // Add a before hook to the suite - - addBefore : function(options, body) { - body.options = options || {} - this.befores.push(body) - }, - - // Add an after hook to the suite - - addAfter : function(options, body) { - body.options = options || {} - this.afters.unshift(body) - }, - - // Add a hook to the suite - - addHook : function(hook, body) { - this.hooks[hook].push(body) - }, - - // Add a nested suite - - addSuite : function(description, body, isShared) { - var suite = new JSpec.Suite(description, body, isShared) - JSpec.allSuites.push(suite) - suite.name = suite.description - suite.description = this.description + ' ' + suite.description - this.suites.push(suite) - suite.suite = this - }, - - // Invoke a hook in context to this suite - - hook : function(hook) { - if (hook != 'before' && hook != 'after') - if (this.suite) this.suite.hook(hook) - - each(this.hooks[hook], function(body) { - JSpec.evalBody(body, "Error in hook '" + hook + "', suite '" + self.description + "': ") - }) - }, - - // Check if nested suites are present - - hasSuites : function() { - return this.suites.length - }, - - // Check if this suite has specs - - hasSpecs : function() { - return this.specs.length - }, - - // Check if the entire suite passed - - passed : function() { - return !any(this.specs, function(spec){ - return !spec.passed() - }) - }, - - isShared : function(){ - return this.shared - }, - - isExecutable : function() { - return !this.isShared() && this.hasSpecs() - } - }) - }, - - /** - * Specification block object. - * - * @param {string} description - * @param {function} body - * @api private - */ - - Spec : function(description, body) { - extend(this, { - body: body, - description: description, - assertions: [], - - // Add passing assertion - - pass : function(message) { - this.assertions.push({ passed: true, message: message }) - if (JSpec.assert) ++JSpec.stats.passes - }, - - // Add failing assertion - - fail : function(message) { - this.assertions.push({ passed: false, message: message }) - if (JSpec.assert) ++JSpec.stats.failures - }, - - // Run deferred assertions - - runDeferredAssertions : function() { - each(this.assertions, function(assertion){ - if (assertion.defer) assertion.run().report(), hook('afterAssertion', assertion) - }) - }, - - // Find first failing assertion - - failure : function() { - return find(this.assertions, function(assertion){ - return !assertion.passed - }) - }, - - // Find all failing assertions - - failures : function() { - return select(this.assertions, function(assertion){ - return !assertion.passed - }) - }, - - // Weither or not the spec passed - - passed : function() { - return !this.failure() - }, - - // Weither or not the spec requires implementation (no assertions) - - requiresImplementation : function() { - return this.assertions.length == 0 - }, - - // Sprite based assertions graph - - assertionsGraph : function() { - return map(this.assertions, function(assertion){ - return '' - }).join('') - } - }) - }, - - Module : function(methods) { - extend(this, methods) - }, - - JSON : { - - /** - * Generic sequences. - */ - - meta : { - '\b' : '\\b', - '\t' : '\\t', - '\n' : '\\n', - '\f' : '\\f', - '\r' : '\\r', - '"' : '\\"', - '\\' : '\\\\' - }, - - /** - * Escapable sequences. - */ - - escapable : /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - - /** - * JSON encode _object_. - * - * @param {mixed} object - * @return {string} - * @api private - */ - - encode : function(object) { - var self = this - if (object == undefined || object == null) return 'null' - if (object === true) return 'true' - if (object === false) return 'false' - switch (typeof object) { - case 'number': return object - case 'string': return this.escapable.test(object) ? - '"' + object.replace(this.escapable, function (a) { - return typeof self.meta[a] === 'string' ? self.meta[a] : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4) - }) + '"' : - '"' + object + '"' - case 'object': - if (object.constructor == Array) - return '[' + map(object, function(val){ - return self.encode(val) - }).join(', ') + ']' - else if (object) - return '{' + map(object, function(key, val){ - return self.encode(key) + ':' + self.encode(val) - }).join(', ') + '}' - } - return 'null' - } - }, - - // --- DSLs - - DSLs : { - snake : { - expect : function(actual){ - return JSpec.expect(actual) - }, - - describe : function(description, body) { - return JSpec.currentSuite.addSuite(description, body, false) - }, - - it : function(description, body) { - return JSpec.currentSuite.addSpec(description, body) - }, - - before : function(body) { - return JSpec.currentSuite.addHook('before', body) - }, - - after : function(body) { - return JSpec.currentSuite.addHook('after', body) - }, - - before_each : function(body) { - return JSpec.currentSuite.addHook('before_each', body) - }, - - after_each : function(body) { - return JSpec.currentSuite.addHook('after_each', body) - }, - - before_nested : function(body) { - return JSpec.currentSuite.addHook('before_nested', body) - }, - - after_nested : function(body){ - return JSpec.currentSuite.addhook('after_nested', body) - }, - - shared_behaviors_for : function(description, body){ - return JSpec.currentSuite.addSuite(description, body, true) - }, - - should_behave_like : function(description) { - return JSpec.shareBehaviorsOf(description) - } - } - }, - - // --- Methods - - /** - * Check if _value_ is 'stop'. For use as a - * utility callback function. - * - * @param {mixed} value - * @return {bool} - * @api public - */ - - haveStopped : function(value) { - return value === 'stop' - }, - - /** - * Include _object_ which may be a hash or Module instance. - * - * @param {hash, Module} object - * @return {JSpec} - * @api public - */ - - include : function(object) { - var module = object.constructor == JSpec.Module ? object : new JSpec.Module(object) - this.modules.push(module) - if ('init' in module) module.init() - if ('utilities' in module) extend(this.defaultContext, module.utilities) - if ('matchers' in module) this.addMatchers(module.matchers) - if ('reporters' in module) extend(this.reporters, module.reporters) - if ('DSLs' in module) - each(module.DSLs, function(name, methods){ - JSpec.DSLs[name] = JSpec.DSLs[name] || {} - extend(JSpec.DSLs[name], methods) - }) - return this - }, - - /** - * Add a module hook _name_, which is immediately - * called per module with the _args_ given. An array of - * hook return values is returned. - * - * @param {name} string - * @param {...} args - * @return {array} - * @api private - */ - - hook : function(name, args) { - args = toArray(arguments, 1) - return inject(JSpec.modules, [], function(results, module){ - if (typeof module[name] == 'function') - results.push(JSpec.evalHook(module, name, args)) - }) - }, - - /** - * Eval _module_ hook _name_ with _args_. Evaluates in context - * to the module itself, JSpec, and JSpec.context. - * - * @param {Module} module - * @param {string} name - * @param {array} args - * @return {mixed} - * @api private - */ - - evalHook : function(module, name, args) { - hook('evaluatingHookBody', module, name) - return module[name].apply(module, args) - }, - - /** - * Same as hook() however accepts only one _arg_ which is - * considered immutable. This function passes the arg - * to the first module, then passes the return value of the last - * module called, to the following module. - * - * @param {string} name - * @param {mixed} arg - * @return {mixed} - * @api private - */ - - hookImmutable : function(name, arg) { - return inject(JSpec.modules, arg, function(result, module){ - if (typeof module[name] == 'function') - return JSpec.evalHook(module, name, [result]) - }) - }, - - /** - * Find a shared example suite by its description or name. - * First searches parent tree of suites for shared behavior - * before falling back to global scoped nested behaviors. - * - * @param {string} description - * @return {Suite} - * @api private - */ - - findSharedBehavior : function(description) { - var behavior - return (behavior = JSpec.findLocalSharedBehavior(description)) - ? behavior - : JSpec.findGlobalSharedBehavior(description) - }, - - /** - * Find a shared example suite within the current suite's - * parent tree by its description or name. - * - * @param {string} description - * @return {Suite} - * @api private - */ - - findLocalSharedBehavior : function(description) { - var behavior, - currentSuite = JSpec.currentSuite.suite - while (currentSuite) - if (behavior = find(currentSuite.suites, JSpec.suiteDescriptionPredicate(description))) - return behavior - else - currentSuite = currentSuite.suite - }, - - /** - * Find a shared example suite within the global - * scope by its description or name. - * - * @param {string} description - * @return {Suite} - * @api private - */ - - findGlobalSharedBehavior : function(description) { - return find(JSpec.suites, JSpec.suiteDescriptionPredicate(description)) - }, - - /** - * Build a predicate that will match a suite based on name or description - * - * @param {string} description - * @return {function} - * @api private - */ - - suiteDescriptionPredicate : function(description) { - return function(suite){ - return suite.name === description || - suite.description === description - } - }, - - /** - * Share behaviors (specs) of the given suite with - * the current suite. - * - * @param {string} description - * @api public - */ - - shareBehaviorsOf : function(description) { - var suite = JSpec.findSharedBehavior(description) - if (suite) - JSpec.evalBody(suite.body) - else - throw new Error("failed to find shared behaviors named `" + description + "'") - }, - - - /** - * Convert arguments to an array. - * - * @param {object} arguments - * @param {int} offset - * @return {array} - * @api public - */ - - toArray : function(arguments, offset) { - return Array.prototype.slice.call(arguments, offset || 0) - }, - - /** - * Return ANSI-escaped colored string. - * - * @param {string} string - * @param {string} color - * @return {string} - * @api public - */ - - color : function(string, color) { - if (option('disableColors')) { - return string - } else { - return "\u001B[" + { - bold : 1, - black : 30, - red : 31, - green : 32, - yellow : 33, - blue : 34, - magenta : 35, - cyan : 36, - white : 37 - }[color] + 'm' + string + "\u001B[0m" - } - }, - - /** - * Default matcher message callback. - * - * @api private - */ - - defaultMatcherMessage : function(actual, expected, negate, name) { - return 'expected ' + puts(actual) + ' to ' + - (negate ? 'not ' : '') + - name.replace(/_/g, ' ') + - ' ' + (expected.length > 1 ? - puts.apply(this, expected.slice(1)) : - '') - }, - - /** - * Normalize a matcher message. - * - * When no messge callback is present the defaultMatcherMessage - * will be assigned, will suffice for most matchers. - * - * @param {hash} matcher - * @return {hash} - * @api public - */ - - normalizeMatcherMessage : function(matcher) { - if (typeof matcher.message != 'function') - matcher.message = this.defaultMatcherMessage - return matcher - }, - - /** - * Normalize a matcher body - * - * This process allows the following conversions until - * the matcher is in its final normalized hash state. - * - * - '==' becomes 'actual == expected' - * - 'actual == expected' becomes 'return actual == expected' - * - function(actual, expected) { return actual == expected } becomes - * { match : function(actual, expected) { return actual == expected }} - * - * @param {mixed} body - * @return {hash} - * @api public - */ - - normalizeMatcherBody : function(body) { - var captures - switch (body.constructor) { - case String: - if (captures = body.match(/^alias (\w+)/)) return JSpec.matchers[last(captures)] - if (body.length < 4) body = 'actual ' + body + ' expected' - return { match: function(actual, expected) { return eval(body) }} - - case Function: - return { match: body } - - default: - return body - } - }, - - /** - * Get option value. This method first checks if - * the option key has been set via the query string, - * otherwise returning the options hash value. - * - * @param {string} key - * @return {mixed} - * @api public - */ - - option : function(key) { - return (value = query(key)) !== null ? value : - JSpec.options[key] || null - }, - - /** - * Check if object _a_, is equal to object _b_. - * - * @param {object} a - * @param {object} b - * @return {bool} - * @api private - */ - - equal: function(a, b) { - if (typeof a != typeof b) return - if (a === b) return true - if (a instanceof RegExp) - return a.toString() === b.toString() - if (a instanceof Date) - return Number(a) === Number(b) - if (typeof a != 'object') return - if (a.length !== undefined) - if (a.length !== b.length) return - else - for (var i = 0, len = a.length; i < len; ++i) - if (!equal(a[i], b[i])) - return - for (var key in a) - if (!equal(a[key], b[key])) - return - return true - }, - - /** - * Return last element of an array. - * - * @param {array} array - * @return {object} - * @api public - */ - - last : function(array) { - return array[array.length - 1] - }, - - /** - * Convert object(s) to a print-friend string. - * - * @param {...} object - * @return {string} - * @api public - */ - - puts : function(object) { - if (arguments.length > 1) - return map(toArray(arguments), function(arg){ - return puts(arg) - }).join(', ') - if (object === undefined) return 'undefined' - if (object === null) return 'null' - if (object === true) return 'true' - if (object === false) return 'false' - if (object.an_instance_of) return 'an instance of ' + object.an_instance_of.name - if (object.jquery && object.selector.length > 0) return 'selector ' + puts(object.selector) - if (object.jquery) return object.get(0).outerHTML - if (object.nodeName) return object.outerHTML - switch (object.constructor) { - case Function: return object.name || object - case String: - return '"' + object - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\t/g, '\\t') - + '"' - case Array: - return inject(object, '[', function(b, v){ - return b + ', ' + puts(v) - }).replace('[,', '[') + ' ]' - case Object: - object.__hit__ = true - return inject(object, '{', function(b, k, v) { - if (k == '__hit__') return b - return b + ', ' + k + ': ' + (v && v.__hit__ ? '' : puts(v)) - }).replace('{,', '{') + ' }' - default: - return object.toString() - } - }, - - /** - * Parse an XML String and return a 'document'. - * - * @param {string} text - * @return {document} - * @api public - */ - - parseXML : function(text) { - var xmlDoc - if (window.DOMParser) - xmlDoc = (new DOMParser()).parseFromString(text, "text/xml") - else { - xmlDoc = new ActiveXObject("Microsoft.XMLDOM") - xmlDoc.async = "false" - xmlDoc.loadXML(text) - } - return xmlDoc - }, - - /** - * Escape HTML. - * - * @param {string} html - * @return {string} - * @api public - */ - - escape : function(html) { - return html.toString() - .replace(/&/gmi, '&') - .replace(/"/gmi, '"') - .replace(/>/gmi, '>') - .replace(/ current) while (++current <= end) values.push(current) - else while (--current >= end) values.push(current) - return '[' + values + ']' - }, - - /** - * Report on the results. - * - * @api public - */ - - report : function() { - this.duration = Number(new Date) - this.start - hook('reporting', JSpec.options) - new (JSpec.options.reporter || JSpec.reporters.DOM)(JSpec, JSpec.options) - }, - - /** - * Run the spec suites. Options are merged - * with JSpec options when present. - * - * @param {hash} options - * @return {JSpec} - * @api public - */ - - run : function(options) { - if (any(hook('running'), haveStopped)) return this - if (options) extend(this.options, options) - this.start = Number(new Date) - each(this.suites, function(suite) { JSpec.runSuite(suite) }) - return this - }, - - /** - * Run a suite. - * - * @param {Suite} suite - * @api public - */ - - runSuite : function(suite) { - if (!suite.isShared()) - { - this.currentSuite = suite - this.evalBody(suite.body) - suite.ran = true - hook('beforeSuite', suite), suite.hook('before'), suite.hook('before_nested') - each(suite.specs, function(spec) { - hook('beforeSpec', spec) - suite.hook('before_each') - JSpec.runSpec(spec) - hook('afterSpec', spec) - suite.hook('after_each') - }) - if (suite.hasSuites()) { - each(suite.suites, function(suite) { - JSpec.runSuite(suite) - }) - } - hook('afterSuite', suite), suite.hook('after_nested'), suite.hook('after') - this.stats.suitesFinished++ - } - }, - - /** - * Report a failure for the current spec. - * - * @param {string} message - * @api public - */ - - fail : function(message) { - JSpec.currentSpec.fail(message) - }, - - /** - * Report a passing assertion for the current spec. - * - * @param {string} message - * @api public - */ - - pass : function(message) { - JSpec.currentSpec.pass(message) - }, - - /** - * Run a spec. - * - * @param {Spec} spec - * @api public - */ - - runSpec : function(spec) { - this.currentSpec = spec - try { this.evalBody(spec.body) } - catch (e) { fail(e) } - spec.runDeferredAssertions() - destub() - this.stats.specsFinished++ - this.stats.assertions += spec.assertions.length - }, - - /** - * Require a dependency, with optional message. - * - * @param {string} dependency - * @param {string} message (optional) - * @return {JSpec} - * @api public - */ - - requires : function(dependency, message) { - hook('requiring', dependency, message) - try { eval(dependency) } - catch (e) { throw 'JSpec depends on ' + dependency + ' ' + message } - return this - }, - - /** - * Query against the current query strings keys - * or the queryString specified. - * - * @param {string} key - * @param {string} queryString - * @return {string, null} - * @api private - */ - - query : function(key, queryString) { - var queryString = (queryString || (main.location ? main.location.search : null) || '').substring(1) - return inject(queryString.split('&'), null, function(value, pair){ - parts = pair.split('=') - return parts[0] == key ? parts[1].replace(/%20|\+/gmi, ' ') : value - }) - }, - - /** - * Ad-hoc POST request for JSpec server usage. - * - * @param {string} uri - * @param {string} data - * @api private - */ - - post : function(uri, data) { - if (any(hook('posting', uri, data), haveStopped)) return - var request = this.xhr() - request.open('POST', uri, false) - request.setRequestHeader('Content-Type', 'application/json') - request.send(JSpec.JSON.encode(data)) - }, - - /** - * Instantiate an XMLHttpRequest. - * - * Here we utilize IE's lame ActiveXObjects first which - * allow IE access serve files via the file: protocol, otherwise - * we then default to XMLHttpRequest. - * - * @return {XMLHttpRequest, ActiveXObject} - * @api private - */ - - xhr : function() { - return this.ieXhr() || new JSpec.request - }, - - /** - * Return Microsoft piece of crap ActiveXObject. - * - * @return {ActiveXObject} - * @api public - */ - - ieXhr : function() { - function object(str) { - try { return new ActiveXObject(str) } catch(e) {} - } - return object('Msxml2.XMLHTTP.6.0') || - object('Msxml2.XMLHTTP.3.0') || - object('Msxml2.XMLHTTP') || - object('Microsoft.XMLHTTP') - }, - - /** - * Check for HTTP request support. - * - * @return {bool} - * @api private - */ - - hasXhr : function() { - return JSpec.request || 'ActiveXObject' in main - }, - - /** - * Try loading _file_ returning the contents - * string or null. Chain to locate / read a file. - * - * @param {string} file - * @return {string} - * @api public - */ - - tryLoading : function(file) { - try { return JSpec.load(file) } catch (e) {} - }, - - /** - * Load a _file_'s contents. - * - * @param {string} file - * @param {function} callback - * @return {string} - * @api public - */ - - load : function(file, callback) { - if (any(hook('loading', file), haveStopped)) return - if ('readFile' in main) - return readFile(file) - else if (this.hasXhr()) { - var request = this.xhr() - request.open('GET', file, false) - request.send(null) - if (request.readyState == 4 && - (request.status == 0 || - request.status.toString().charAt(0) == 2)) - return request.responseText - } - else - throw new Error("failed to load `" + file + "'") - }, - - /** - * Load, pre-process, and evaluate a file. - * - * @param {string} file - * @param {JSpec} - * @api public - */ - - exec : function(file) { - if (any(hook('executing', file), haveStopped)) return this - eval('with (JSpec){' + this.preprocess(this.load(file)) + '}') - return this - } - } - - // --- Node.js support - - if (typeof GLOBAL === 'object' && typeof exports === 'object') { - var fs = require('fs') - quit = process.exit - print = require('sys').puts - readFile = function(file){ - return fs.readFileSync(file).toString('utf8') - } - } - - // --- Utility functions - - var main = this, - find = JSpec.any, - utils = 'haveStopped stub hookImmutable hook destub map any last pass fail range each option inject select \ - error escape extend puts query strip color does addMatchers callIterator toArray equal'.split(/\s+/) - while (utils.length) eval('var ' + utils[0] + ' = JSpec.' + utils.shift()) - if (!main.setTimeout) main.setTimeout = function(callback){ callback() } - - // --- Matchers - - addMatchers({ - equal : "===", - eql : "equal(actual, expected)", - be : "alias equal", - be_greater_than : ">", - be_less_than : "<", - be_at_least : ">=", - be_at_most : "<=", - be_a : "actual.constructor == expected", - be_an : "alias be_a", - be_an_instance_of : "actual instanceof expected", - be_null : "actual == null", - be_true : "actual == true", - be_false : "actual == false", - be_undefined : "typeof actual == 'undefined'", - be_type : "typeof actual == expected", - match : "typeof actual == 'string' ? actual.match(expected) : false", - respond_to : "typeof actual[expected] == 'function'", - have_length : "actual.length == expected", - be_within : "actual >= expected[0] && actual <= last(expected)", - have_length_within : "actual.length >= expected[0] && actual.length <= last(expected)", - - receive : { defer : true, match : function(actual, method, times) { - var proxy = new JSpec.ProxyAssertion(actual, method, times, this.negate) - JSpec.currentSpec.assertions.push(proxy) - return proxy - }}, - - be_empty : function(actual) { - if (actual.constructor == Object && actual.length == undefined) - for (var key in actual) - return false; - return !actual.length - }, - - include : function(actual) { - for (var state = true, i = 1; i < arguments.length; i++) { - var arg = arguments[i] - switch (actual.constructor) { - case String: - case Number: - case RegExp: - case Function: - state = actual.toString().indexOf(arg) !== -1 - break - - case Object: - state = arg in actual - break - - case Array: - state = any(actual, function(value){ return equal(value, arg) }) - break - } - if (!state) return false - } - return true - }, - - throw_error : { match : function(actual, expected, message) { - try { actual() } - catch (e) { - this.e = e - var assert = function(arg) { - switch (arg.constructor) { - case RegExp : return arg.test(e.message || e.toString()) - case String : return arg == (e.message || e.toString()) - case Function : return e instanceof arg || e.name == arg.name - } - } - return message ? assert(expected) && assert(message) : - expected ? assert(expected) : - true - } - }, message : function(actual, expected, negate) { - // TODO: refactor when actual is not in expected [0] - var message_for = function(i) { - if (expected[i] == undefined) return 'exception' - switch (expected[i].constructor) { - case RegExp : return 'exception matching ' + puts(expected[i]) - case String : return 'exception of ' + puts(expected[i]) - case Function : return expected[i].name || 'Error' - } - } - var exception = message_for(1) + (expected[2] ? ' and ' + message_for(2) : '') - return 'expected ' + exception + (negate ? ' not ' : '' ) + - ' to be thrown, but ' + (this.e ? 'got ' + puts(this.e) : 'nothing was') - }}, - - have : function(actual, length, property) { - return actual[property] == null ? false : actual[property].length == length - }, - - have_at_least : function(actual, length, property) { - return actual[property] == null ? (length === 0) : actual[property].length >= length - }, - - have_at_most :function(actual, length, property) { - return actual[property] == null || actual[property].length <= length - }, - - have_within : function(actual, range, property) { - var length = actual[property] == undefined ? 0 : actual[property].length - return length >= range.shift() && length <= range.pop() - }, - - have_prop : function(actual, property, value) { - var actualVal = actual[property], actualType = typeof actualVal - return (actualType == 'function' || actualType == 'undefined') ? false : - typeof value === 'undefined' || - does(actual[property],'eql',value) - }, - - have_property : function(actual, property, value) { - var actualVal = actual[property], actualType = typeof actualVal - return (actualType == 'function' || actualType == 'undefined') ? false : - typeof value === 'undefined' || - value === actualVal - } - }) - -})() diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.nodejs.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.nodejs.js deleted file mode 100644 index 6765273..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.nodejs.js +++ /dev/null @@ -1,18 +0,0 @@ - -// JSpec - node - Copyright TJ Holowaychuk (MIT Licensed) - -JSpec -.include({ - name: 'node', - - // --- Matchers - - matchers : { - have_enumerable_property: 'actual.propertyIsEnumerable(expected)', - have_writable_property: 'Object.getOwnPropertyDescriptor(actual, expected).writable === true', - have_configurable_property: 'Object.getOwnPropertyDescriptor(actual, expected).configurable === true', - have_keys: 'does(Object.keys(actual), "eql", expected)', - have_prototype: 'Object.getPrototypeOf(actual) === expected' - } -}) - diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.shell.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.shell.js deleted file mode 100644 index cb19c69..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.shell.js +++ /dev/null @@ -1,39 +0,0 @@ - -// JSpec - Shell - Copyright TJ Holowaychuk (MIT Licensed) - -;(function(){ - - var _quit = quit - - Shell = { - - // --- Global - - main: this, - - // --- Commands - - commands: { - quit: ['Terminate the shell', function(){ _quit() }], - exit: ['Terminate the shell', function(){ _quit() }], - p: ['Inspect an object', function(o){ return o.toSource() }] - }, - - /** - * Start the interactive shell. - * - * @api public - */ - - start : function() { - for (var name in this.commands) - if (this.commands.hasOwnProperty(name)) - this.commands[name][1].length ? - this.main[name] = this.commands[name][1] : - this.main.__defineGetter__(name, this.commands[name][1]) - } - } - - Shell.start() - -})() \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.timers.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.timers.js deleted file mode 100644 index c88d10b..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.timers.js +++ /dev/null @@ -1,90 +0,0 @@ - -// JSpec - Mock Timers - Copyright TJ Holowaychuk (MIT Licensed) - -;(function(){ - - /** - * Version. - */ - - mockTimersVersion = '1.0.2' - - /** - * Localized timer stack. - */ - - var timers = [] - - /** - * Set mock timeout with _callback_ and timeout of _ms_. - * - * @param {function} callback - * @param {int} ms - * @return {int} - * @api public - */ - - setTimeout = function(callback, ms) { - var id - return id = setInterval(function(){ - callback() - clearInterval(id) - }, ms) - } - - /** - * Set mock interval with _callback_ and interval of _ms_. - * - * @param {function} callback - * @param {int} ms - * @return {int} - * @api public - */ - - setInterval = function(callback, ms) { - callback.step = ms, callback.current = callback.last = 0 - return timers[timers.length] = callback, timers.length - } - - /** - * Destroy timer with _id_. - * - * @param {int} id - * @return {bool} - * @api public - */ - - clearInterval = clearTimeout = function(id) { - return delete timers[--id] - } - - /** - * Reset timers. - * - * @return {array} - * @api public - */ - - resetTimers = function() { - return timers = [] - } - - /** - * Increment each timers internal clock by _ms_. - * - * @param {int} ms - * @api public - */ - - tick = function(ms) { - for (var i = 0, len = timers.length; i < len; ++i) - if (timers[i] && (timers[i].current += ms)) - if (timers[i].current - timers[i].last >= timers[i].step) { - var times = Math.floor((timers[i].current - timers[i].last) / timers[i].step) - var remainder = (timers[i].current - timers[i].last) % timers[i].step - timers[i].last = timers[i].current - remainder - while (times-- && timers[i]) timers[i]() - } - } - -})() \ No newline at end of file diff --git a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.xhr.js b/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.xhr.js deleted file mode 100644 index 3b96310..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/lib/jspec.xhr.js +++ /dev/null @@ -1,210 +0,0 @@ - -// JSpec - XHR - Copyright TJ Holowaychuk (MIT Licensed) - -(function(){ - - var lastRequest - - // --- Original XMLHttpRequest - - var OriginalXMLHttpRequest = 'XMLHttpRequest' in this ? - XMLHttpRequest : - function(){} - var OriginalActiveXObject = 'ActiveXObject' in this ? - ActiveXObject : - undefined - - // --- MockXMLHttpRequest - - var MockXMLHttpRequest = function() { - this.requestHeaders = {} - } - - MockXMLHttpRequest.prototype = { - status: 0, - async: true, - readyState: 0, - responseXML: null, - responseText: '', - abort: function(){}, - onreadystatechange: function(){}, - - /** - * Return response headers hash. - */ - - getAllResponseHeaders : function(){ - return JSpec.inject(this.responseHeaders, '', function(buf, key, val){ - return buf + key + ': ' + val + '\r\n' - }) - }, - - /** - * Return case-insensitive value for header _name_. - */ - - getResponseHeader : function(name) { - return this.responseHeaders[name.toLowerCase()] - }, - - /** - * Set case-insensitive _value_ for header _name_. - */ - - setRequestHeader : function(name, value) { - this.requestHeaders[name.toLowerCase()] = value - }, - - /** - * Open mock request. - */ - - open : function(method, url, async, user, password) { - this.user = user - this.password = password - this.url = url - this.readyState = 1 - this.method = method.toUpperCase() - if (async != undefined) this.async = async - if (this.async) this.onreadystatechange() - }, - - /** - * Send request _data_. - */ - - send : function(data) { - var self = this - this.data = data - this.readyState = 4 - if (this.method == 'HEAD') this.responseText = null - this.responseHeaders['content-length'] = (this.responseText || '').length - if(this.async) this.onreadystatechange() - this.populateResponseXML() - lastRequest = function(){ - return self - } - }, - - /** - * Parse request body and populate responseXML if response-type is xml - * Based on the standard specification : http://www.w3.org/TR/XMLHttpRequest/ - */ - populateResponseXML: function() { - var type = this.getResponseHeader("content-type") - if (!type || !this.responseText || !type.match(/(text\/xml|application\/xml|\+xml$)/g)) - return - this.responseXML = JSpec.parseXML(this.responseText) - } - } - - // --- Response status codes - - JSpec.statusCodes = { - 100: 'Continue', - 101: 'Switching Protocols', - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - 300: 'Multiple Choice', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 307: 'Temporary Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Failed', - 413: 'Request Entity Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 422: 'Unprocessable Entity', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported' - } - - /** - * Mock XMLHttpRequest requests. - * - * mockRequest().and_return('some data', 'text/plain', 200, { 'X-SomeHeader' : 'somevalue' }) - * - * @return {hash} - * @api public - */ - - function mockRequest() { - return { and_return : function(body, type, status, headers) { - XMLHttpRequest = MockXMLHttpRequest - ActiveXObject = false - status = status || 200 - headers = headers || {} - headers['content-type'] = type - JSpec.extend(XMLHttpRequest.prototype, { - responseText: body, - responseHeaders: headers, - status: status, - statusText: JSpec.statusCodes[status] - }) - }} - } - - /** - * Unmock XMLHttpRequest requests. - * - * @api public - */ - - function unmockRequest() { - XMLHttpRequest = OriginalXMLHttpRequest - ActiveXObject = OriginalActiveXObject - } - - JSpec.include({ - name: 'Mock XHR', - - // --- Utilities - - utilities : { - mockRequest: mockRequest, - unmockRequest: unmockRequest - }, - - // --- Hooks - - afterSpec : function() { - unmockRequest() - }, - - // --- DSLs - - DSLs : { - snake : { - mock_request: mockRequest, - unmock_request: unmockRequest, - last_request: function(){ return lastRequest() } - } - } - - }) -})() diff --git a/node/node_modules/jade/benchmarks/haml/spec/node.js b/node/node_modules/jade/benchmarks/haml/spec/node.js deleted file mode 100644 index c96429c..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/node.js +++ /dev/null @@ -1,10 +0,0 @@ - -require.paths.unshift('spec', './spec/lib', 'lib') -require('jspec') -require('unit/spec.helper') -haml = require('haml') - -JSpec - .exec('spec/unit/spec.js') - .run({ reporter: JSpec.reporters.Terminal, fixturePath: 'spec/fixtures', failuresOnly: true }) - .report() diff --git a/node/node_modules/jade/benchmarks/haml/spec/unit/spec.helper.js b/node/node_modules/jade/benchmarks/haml/spec/unit/spec.helper.js deleted file mode 100644 index e69de29..0000000 diff --git a/node/node_modules/jade/benchmarks/haml/spec/unit/spec.js b/node/node_modules/jade/benchmarks/haml/spec/unit/spec.js deleted file mode 100644 index 4e1e69d..0000000 --- a/node/node_modules/jade/benchmarks/haml/spec/unit/spec.js +++ /dev/null @@ -1,316 +0,0 @@ - -describe 'haml' - describe '.version' - it 'should be a triplet' - haml.version.should.match(/^\d+\.\d+\.\d+$/) - end - end - - describe '.render()' - before - assertAs = function(name, type, options) { - var str = fixture(name + '.haml') - try { - var html = haml.render(str, options).trim(), - expected = fixture(name + '.' + type).trim() - if (html === expected) - pass() - else - fail('got:\n' + html + '\n\nexpected:\n' + expected) - } catch (err) { - if (err instanceof haml.HamlError) { - throw err - } else { - fail('\n:' + err.stack + '\n') - } - } - } - assert = function(name, options) { - assertAs(name, 'html', options, 'CRLF', '\r\n') - } - assertXML = function(name, options) { - assertAs(name, 'xml', options, 'CRLF', '\r\n') - } - end - - it 'should allow passing of a context object' - assert('context', { context: 'yay' }) - end - - it 'should allow passing of literals' - assert('literals', { locals: { user: 'tj' }}) - end - - it 'should not fail on trailing indents' - assert('trailing-indent') - end - - it 'should add xml support via the "xml" option' - assertXML('feed', { xml: true }) - end - - it 'should support xml namespaces' - assertXML('namespace') - end - - it 'should utilize "filename" option when an error is thrown' - try { assert('error', { filename: 'error.haml' }) } - catch (err) { - err.message.should.eql '(error.haml):3 invalid indentation; got 3, when previous was 1' - } - end - - it 'should default filename to "Haml" when an error is thrown' - try { assert('error') } - catch (err) { - err.message.should.eql '(Haml):3 invalid indentation; got 3, when previous was 1' - } - end - - it 'should bitch when "cache" is true without a filename given' - // -{ assert('tag.simple', { cache: true }) }.should.throw_error - end - - it 'should pre-compiled and cache when "cache" is true' - assert('tag.simple', { cache: true, filename: 'tag.simple.haml' }) - assert('tag.simple', { cache: true, filename: 'tag.simple.haml' }) - end - - it 'should support blank lines' - assert('newlines') - end - - describe '.class' - it 'should output a div with the given class' - assert('class') - end - - it 'should work with several classes' - assert('classes') - end - end - - describe '#id' - it 'should output a div with the given id' - assert('id') - end - end - - describe '%tag' - it 'should work with no text or block' - assert('tag.simple') - end - - it 'should work with text' - assert('tag.text') - end - - it 'should work with block text' - assert('tag.text.block') - end - - it 'should work with blocks of text and tags' - assert('tag.text.block.complex') - end - - it 'should work with many classes / ids / attrs' - assert('tag.complex') - end - - it 'should allow empty tags' - assert('tag.empty') - end - end - - describe '%tag.class' - it 'should output tag with a class' - assert('tag.class') - end - - it 'should work with several classes' - assert('tag.classes') - end - - it 'should support self-closing tags' - assert('tag.self-close') - end - end - - describe '%tag!=' - it 'should output the evaluated code' - assert('tag.code') - end - - it 'should not escape output' - assert('tag.code.no-escape') - end - end - - describe '%tag=' - it 'should escape the evaluated code' - assert('tag.escape') - end - end - - describe '%namespace:tag' - it 'should output a tag with a namespace prefix' - assert('namespace.tag') - end - end - - describe '{...}' - it 'should be mapped as html attributes' - assert('tag.attrs') - end - - it 'should escape values' - assert('tag.attrs.escape') - end - - it 'should allow booleans' - assert('tag.attrs.bools') - end - end - - describe '!!!' - it 'should default the doctype to 1.0 transitional' - assert('doctype') - end - end - - describe '!!! NAME' - it 'should output a specific doctype' - assert('doctype.xml') - end - - it 'should be case-insensitive' - assert('doctype.xml.case') - end - end - - describe 'nesting' - it 'should work when nested downwards' - assert('nesting.simple') - end - - it 'should work when blocks outdent' - assert('nesting.complex') - end - end - - describe '- code' - it 'should work with if statements' - assert('code.if') - end - - it 'should work when nested' - assert('code.nested') - end - end - - describe '- each' - it 'should iterate' - assert('code.each', { locals: { items: ['one', 'two', 'three'] }}) - assert('code.each.non-enumerable', { locals: { items: null }}) - end - - it 'should iterate objects' - assert('code.each', { locals: { items: { 0: 'one', 1: 'two', 2: 'three' }}}) - assert('code.each.index', { locals: { items: { 0: 'one', 1: 'two', 2: 'three' }}}) - end - - it 'should iterate with index' - assert('code.each.index', { locals: { items: ['one', 'two', 'three'] }}) - end - end - - describe '= code' - it 'should output evaluation' - assert('code') - end - end - - describe '&= code' - it 'should output evaluation while escaping html entities' - assert('code.escape') - end - end - - describe '' - it 'should remain intact' - assert('html') - end - end - - describe '\\char' - it 'should escape the character' - assert('escape') - end - end - - describe '-#' - it 'should become a silent comment' - assert('comment') - end - end - - describe '/' - it 'should comment out tags' - assert('comment.tag') - end - - it 'should comment out blocks' - assert('comment.block') - end - - it 'should comment out text' - assert('comment.text') - end - - it 'should work in blocks' - assert('comment.text.complex') - end - end - - describe '/[]' - it 'should insert conditional comment blocks' - assert('comment.block.conditional') - end - end - - describe ':filter' - describe 'plain' - it 'should ignore haml specific characters' - assert('filter.plain') - end - end - - describe 'cdata' - it 'should wrap with CDATA tags' - assert('filter.cdata') - end - - it 'should retain whitespace' - assert('filter.cdata.whitespace') - end - end - - describe 'javascript' - it 'should wrap with "}}}),require.register("jade.js",function(module,exports,require){var Parser=require("./parser"),Compiler=require("./compiler");exports.version="0.12.1";var cache=exports.cache={};exports.selfClosing=require("./self-closing"),exports.doctypes=require("./doctypes"),exports.filters=require("./filters"),exports.utils=require("./utils"),exports.Compiler=Compiler,exports.Parser=Parser,exports.nodes=require("./nodes");function attrs(obj){var buf=[],terse=obj.terse;delete obj.terse;var keys=Object.keys(obj),len=keys.length;if(len){buf.push("");for(var i=0;i/g,">").replace(/"/g,""")}function rethrow(err,str,filename,lineno){var context=3,lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}function parse(str,options){var filename=options.filename;try{var parser=new Parser(str,filename);options.debug&&parser.debug();var compiler=new(options.compiler||Compiler)(parser.parse(),options),js=compiler.compile();options.debug&&console.log("\nCompiled Function:\n\n%s",js.replace(/^/gm," "));try{return""+attrs.toString()+"\n\n"+escape.toString()+"\n\n"+"var buf = [];\n"+(options.self?"var self = locals || {}, __ = __ || locals.__;\n"+js:"with (locals || {}) {"+js+"}")+'return buf.join("");'}catch(err){process.compile(js,filename||"Jade");return}}catch(err){rethrow(err,str,filename,parser.lexer.lineno)}}exports.compile=function(str,options){var options=options||{},input=JSON.stringify(str),filename=options.filename?JSON.stringify(options.filename):"undefined",fn=["var __ = { lineno: 1, input: "+input+", filename: "+filename+" };",rethrow.toString(),"try {",parse(String(str),options||{}),"} catch (err) {"," rethrow(err, __.input, __.filename, __.lineno);","}"].join("\n");return new Function("locals",fn)},exports.render=function(str,options){var fn,options=options||{},filename=options.filename;str=String(str);if(options.cache)if(filename)cache[filename]?fn=cache[filename]:fn=cache[filename]=new Function("locals",parse(str,options));else throw new Error("filename is required when using the cache option");else fn=new Function("locals",parse(str,options));try{var locals=options.locals||{},meta={lineno:1};locals.__=meta;return fn.call(options.scope,locals)}catch(err){rethrow(err,str,filename,meta.lineno)}},exports.renderFile=function(path,options,fn){var ret;typeof options=="function"&&(fn=options,options={}),options.filename=path;if(options.cache&&cache[path]){try{ret=exports.render("",options)}catch(err){return fn(err)}fn(null,ret)}else fs.readFile(path,"utf8",function(err,str){if(err)return fn(err);try{ret=exports.render(str,options)}catch(err){return fn(err)}fn(null,ret)})}}),require.register("lexer.js",function(module,exports,require){var Lexer=module.exports=function Lexer(str){this.input=str.replace(/\r\n|\r/g,"\n"),this.deferredTokens=[],this.lastIndents=0,this.lineno=1,this.stash=[],this.indentStack=[],this.indentRe=null,this.pipeless=!1};Lexer.prototype={tok:function(type,val){return{type:type,line:this.lineno,val:val}},consume:function(len){this.input=this.input.substr(len)},scan:function(regexp,type){var captures;if(captures=regexp.exec(this.input)){this.consume(captures[0].length);return this.tok(type,captures[1])}},defer:function(tok){this.deferredTokens.push(tok)},lookahead:function(n){var fetch=n-this.stash.length;while(fetch-->0)this.stash.push(this.next());return this.stash[--n]},indexOfDelimiters:function(start,end){var str=this.input,nstart=0,nend=0,pos=0;for(var i=0,len=str.length;iindents)this.stash.push(this.tok("outdent")),this.indentStack.shift();tok=this.stash.pop()}else indents&&indents!=this.indentStack[0]?(this.indentStack.unshift(indents),tok=this.tok("indent",indents)):tok=this.tok("newline");return tok}},pipelessText:function(){if(this.pipeless){if("\n"==this.input[0])return;var i=this.input.indexOf("\n");-1==i&&(i=this.input.length);var str=this.input.substr(0,i);this.consume(str.length);return this.tok("text",str)}},colon:function(){return this.scan(/^: */,":")},advance:function(){return this.stashed()||this.next()},next:function(){return this.deferred()||this.eos()||this.pipelessText()||this.doctype()||this.tag()||this.filter()||this.each()||this.code()||this.id()||this.className()||this.attrs()||this.indent()||this.comment()||this.blockComment()||this.colon()||this.text()}}}),require.register("nodes/block-comment.js",function(module,exports,require){var Node=require("./node"),BlockComment=module.exports=function BlockComment(val,block){this.block=block,this.val=val};BlockComment.prototype=new Node,BlockComment.prototype.constructor=BlockComment}),require.register("nodes/block.js",function(module,exports,require){var Node=require("./node"),Block=module.exports=function Block(node){this.nodes=[],node&&this.push(node)};Block.prototype=new Node,Block.prototype.constructor=Block,Block.prototype.push=function(node){return this.nodes.push(node)},Block.prototype.unshift=function(node){return this.nodes.unshift(node)}}),require.register("nodes/code.js",function(module,exports,require){var Node=require("./node"),Code=module.exports=function Code(val,buffer,escape){this.val=val,this.buffer=buffer,this.escape=escape,/^ *else/.test(val)&&(this.instrumentLineNumber=!1)};Code.prototype=new Node,Code.prototype.constructor=Code}),require.register("nodes/comment.js",function(module,exports,require){var Node=require("./node"),Comment=module.exports=function Comment(val,buffer){this.val=val,this.buffer=buffer};Comment.prototype=new Node,Comment.prototype.constructor=Comment}),require.register("nodes/doctype.js",function(module,exports,require){var Node=require("./node"),Doctype=module.exports=function Doctype(val){this.val=val};Doctype.prototype=new Node,Doctype.prototype.constructor=Doctype}),require.register("nodes/each.js",function(module,exports,require){var Node=require("./node"),Each=module.exports=function Each(obj,val,key,block){this.obj=obj,this.val=val,this.key=key,this.block=block};Each.prototype=new Node,Each.prototype.constructor=Each}),require.register("nodes/filter.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Filter=module.exports=function Filter(name,block,attrs){this.name=name,this.block=block,this.attrs=attrs,this.isASTFilter=block instanceof Block};Filter.prototype=new Node,Filter.prototype.constructor=Filter}),require.register("nodes/index.js",function(module,exports,require){exports.Node=require("./node"),exports.Tag=require("./tag"),exports.Code=require("./code"),exports.Each=require("./each"),exports.Text=require("./text"),exports.Block=require("./block"),exports.Filter=require("./filter"),exports.Comment=require("./comment"),exports.BlockComment=require("./block-comment"),exports.Doctype=require("./doctype")}),require.register("nodes/node.js",function(module,exports,require){var Node=module.exports=function(){}}),require.register("nodes/tag.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Tag=module.exports=function Tag(name,block){this.name=name,this.attrs=[],this.block=block||new Block};Tag.prototype=new Node,Tag.prototype.constructor=Tag,Tag.prototype.setAttribute=function(name,val){this.attrs.push({name:name,val:val});return this},Tag.prototype.removeAttribute=function(name){for(var i=0,len=this.attrs.length;i"):this.buffer("/>")):(tag.attrs.length?(this.buffer("<"+name),tag.attrs.length&&this.visitAttributes(tag.attrs),this.buffer(">")):this.buffer("<"+name+">"),tag.code&&this.visitCode(tag.code),tag.text&&this.buffer(utils.text(tag.text.nodes[0].trimLeft())),this.escape="pre"==tag.name,this.visit(tag.block),this.pp&&!~inlineTags.indexOf(name)&&!tag.textOnly&&this.buffer("\\n"+Array(this.indents).join(" ")),this.buffer("")),this.indents--},visitFilter:function(filter){var fn=filters[filter.name];if(!fn)throw filter.isASTFilter?new Error('unknown ast filter "'+filter.name+':"'):new Error('unknown filter ":'+filter.name+'"');if(filter.isASTFilter)this.buf.push(fn(filter.block,this,filter.attrs));else{var text=filter.block.nodes.join("");this.buffer(utils.text(fn(text,filter.attrs)))}},visitText:function(text){text=utils.text(text.nodes.join("")),this.escape&&(text=escape(text)),this.buffer(text),this.buffer("\\n")},visitComment:function(comment){!comment.buffer||(this.pp&&this.buffer("\\n"+Array(this.indents+1).join(" ")),this.buffer(""))},visitBlockComment:function(comment){!comment.buffer||(0==comment.val.indexOf("if")?(this.buffer("")):(this.buffer("")))},visitCode:function(code){if(code.buffer){var val=code.val.trimLeft();this.buf.push("var __val__ = "+val),val='null == __val__ ? "" : __val__',code.escape&&(val="escape("+val+")"),this.buf.push("buf.push("+val+");")}else this.buf.push(code.val);code.block&&(code.buffer||this.buf.push("{"),this.visit(code.block),code.buffer||this.buf.push("}"))},visitEach:function(each){this.buf.push("// iterate "+each.obj+"\n"+"(function(){\n"+" if ('number' == typeof "+each.obj+".length) {\n"+" for (var "+each.key+" = 0, $$l = "+each.obj+".length; "+each.key+" < $$l; "+each.key+"++) {\n"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n } else {\n for (var "+each.key+" in "+each.obj+") {\n"+" if ("+each.obj+".hasOwnProperty("+each.key+")){"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n"),this.buf.push(" }\n }\n}).call(this);\n")},visitAttributes:function(attrs){var buf=[],classes=[];this.terse&&buf.push("terse: true"),attrs.forEach(function(attr){if(attr.name=="class")classes.push("("+attr.val+")");else{var pair="'"+attr.name+"':("+attr.val+")";buf.push(pair)}}),classes.length&&(classes=classes.join(" + ' ' + "),buf.push("class: "+classes)),buf=buf.join(", ").replace("class:",'"class":'),this.buf.push("buf.push(attrs({ "+buf+" }));")}};function escape(html){return String(html).replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}}),require.register("doctypes.js",function(module,exports,require){module.exports={5:"",html:"",xml:'',"default":'',transitional:'',strict:'',frameset:'',1.1:'',basic:'',mobile:''}}),require.register("filters.js",function(module,exports,require){module.exports={cdata:function(str){return""},sass:function(str){str=str.replace(/\\n/g,"\n");var sass=require("sass").render(str).replace(/\n/g,"\\n");return""},stylus:function(str,options){var ret;str=str.replace(/\\n/g,"\n");var stylus=require("stylus");stylus(str,options).render(function(err,css){if(err)throw err;ret=css.replace(/\n/g,"\\n")});return""},less:function(str){var ret;str=str.replace(/\\n/g,"\n"),require("less").render(str,function(err,css){if(err)throw err;ret=""});return ret},markdown:function(str){var md;try{md=require("markdown")}catch(err){try{md=require("discount")}catch(err){try{md=require("markdown-js")}catch(err){throw new Error("Cannot find markdown library, install markdown or discount")}}}str=str.replace(/\\n/g,"\n");return md.parse(str).replace(/\n/g,"\\n").replace(/'/g,"'")},coffeescript:function(str){str=str.replace(/\\n/g,"\n");var js=require("coffee-script").compile(str).replace(/\n/g,"\\n");return'"}}}),require.register("inline-tags.js",function(module,exports,require){module.exports=["a","abbr","acronym","b","br","code","em","font","i","img","ins","kbd","map","samp","small","span","strong","sub","sup"]}),require.register("jade.js",function(module,exports,require){var Parser=require("./parser"),Compiler=require("./compiler"),runtime=require("./runtime");exports.version="0.15.4";var cache=exports.cache={};exports.selfClosing=require("./self-closing"),exports.doctypes=require("./doctypes"),exports.filters=require("./filters"),exports.utils=require("./utils"),exports.Compiler=Compiler,exports.Parser=Parser,exports.nodes=require("./nodes"),exports.runtime=runtime;function parse(str,options){var filename=options.filename;try{var parser=new Parser(str,filename,options),compiler=new(options.compiler||Compiler)(parser.parse(),options),js=compiler.compile();options.debug&&console.log("\nCompiled Function:\n\n%s",js.replace(/^/gm," "));try{return"var buf = [];\n"+(options.self?"var self = locals || {};\n"+js:"with (locals || {}) {\n"+js+"\n}\n")+'return buf.join("");'}catch(err){process.compile(js,filename||"Jade");return}}catch(err){runtime.rethrow(err,str,filename,parser.lexer.lineno)}}exports.compile=function(str,options){var options=options||{},input=JSON.stringify(str),client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined",fn;options.compileDebug!==!1?fn=["var __ = { lineno: 1, input: "+input+", filename: "+filename+" };","try {",parse(String(str),options||{}),"} catch (err) {"," rethrow(err, __.input, __.filename, __.lineno);","}"].join("\n"):fn=parse(String(str),options||{}),client&&(fn="var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;\n"+fn),fn=new Function("locals, attrs, escape, rethrow",fn);if(client)return fn;return function(locals){return fn(locals,runtime.attrs,runtime.escape,runtime.rethrow)}}}),require.register("lexer.js",function(module,exports,require){var Lexer=module.exports=function Lexer(str,options){options=options||{},this.input=str.replace(/\r\n|\r/g,"\n"),this.colons=options.colons,this.deferredTokens=[],this.lastIndents=0,this.lineno=1,this.stash=[],this.indentStack=[],this.indentRe=null,this.pipeless=!1};Lexer.prototype={tok:function(type,val){return{type:type,line:this.lineno,val:val}},consume:function(len){this.input=this.input.substr(len)},scan:function(regexp,type){var captures;if(captures=regexp.exec(this.input)){this.consume(captures[0].length);return this.tok(type,captures[1])}},defer:function(tok){this.deferredTokens.push(tok)},lookahead:function(n){var fetch=n-this.stash.length;while(fetch-->0)this.stash.push(this.next());return this.stash[--n]},indexOfDelimiters:function(start,end){var str=this.input,nstart=0,nend=0,pos=0;for(var i=0,len=str.length;iindents)this.stash.push(this.tok("outdent")),this.indentStack.shift();tok=this.stash.pop()}else indents&&indents!=this.indentStack[0]?(this.indentStack.unshift(indents),tok=this.tok("indent",indents)):tok=this.tok("newline");return tok}},pipelessText:function(){if(this.pipeless){if("\n"==this.input[0])return;var i=this.input.indexOf("\n");-1==i&&(i=this.input.length);var str=this.input.substr(0,i);this.consume(str.length);return this.tok("text",str)}},colon:function(){return this.scan(/^: */,":")},advance:function(){return this.stashed()||this.next()},next:function(){return this.deferred()||this.eos()||this.pipelessText()||this.doctype()||this.include()||this.mixin()||this.conditional()||this.each()||this.tag()||this.filter()||this.code()||this.id()||this.className()||this.attrs()||this.indent()||this.comment()||this.colon()||this.text()}}}),require.register("nodes/block-comment.js",function(module,exports,require){var Node=require("./node"),BlockComment=module.exports=function BlockComment(val,block,buffer){this.block=block,this.val=val,this.buffer=buffer};BlockComment.prototype=new Node,BlockComment.prototype.constructor=BlockComment}),require.register("nodes/block.js",function(module,exports,require){var Node=require("./node"),Block=module.exports=function Block(node){this.nodes=[],node&&this.push(node)};Block.prototype=new Node,Block.prototype.constructor=Block,Block.prototype.push=function(node){return this.nodes.push(node)},Block.prototype.unshift=function(node){return this.nodes.unshift(node)}}),require.register("nodes/code.js",function(module,exports,require){var Node=require("./node"),Code=module.exports=function Code(val,buffer,escape){this.val=val,this.buffer=buffer,this.escape=escape,/^ *else/.test(val)&&(this.instrumentLineNumber=!1)};Code.prototype=new Node,Code.prototype.constructor=Code}),require.register("nodes/comment.js",function(module,exports,require){var Node=require("./node"),Comment=module.exports=function Comment(val,buffer){this.val=val,this.buffer=buffer};Comment.prototype=new Node,Comment.prototype.constructor=Comment}),require.register("nodes/doctype.js",function(module,exports,require){var Node=require("./node"),Doctype=module.exports=function Doctype(val){this.val=val};Doctype.prototype=new Node,Doctype.prototype.constructor=Doctype}),require.register("nodes/each.js",function(module,exports,require){var Node=require("./node"),Each=module.exports=function Each(obj,val,key,block){this.obj=obj,this.val=val,this.key=key,this.block=block};Each.prototype=new Node,Each.prototype.constructor=Each}),require.register("nodes/filter.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Filter=module.exports=function Filter(name,block,attrs){this.name=name,this.block=block,this.attrs=attrs,this.isASTFilter=block instanceof Block};Filter.prototype=new Node,Filter.prototype.constructor=Filter}),require.register("nodes/index.js",function(module,exports,require){exports.Node=require("./node"),exports.Tag=require("./tag"),exports.Code=require("./code"),exports.Each=require("./each"),exports.Text=require("./text"),exports.Block=require("./block"),exports.Mixin=require("./mixin"),exports.Filter=require("./filter"),exports.Comment=require("./comment"),exports.Literal=require("./literal"),exports.BlockComment=require("./block-comment"),exports.Doctype=require("./doctype")}),require.register("nodes/literal.js",function(module,exports,require){var Node=require("./node"),Literal=module.exports=function Literal(str){this.str=str};Literal.prototype=new Node,Literal.prototype.constructor=Literal}),require.register("nodes/mixin.js",function(module,exports,require){var Node=require("./node"),Mixin=module.exports=function Mixin(name,args,block){this.name=name,this.args=args,this.block=block};Mixin.prototype=new Node,Mixin.prototype.constructor=Mixin}),require.register("nodes/node.js",function(module,exports,require){var Node=module.exports=function(){}}),require.register("nodes/tag.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Tag=module.exports=function Tag(name,block){this.name=name,this.attrs=[],this.block=block||new Block};Tag.prototype=new Node,Tag.prototype.constructor=Tag,Tag.prototype.setAttribute=function(name,val){this.attrs.push({name:name,val:val});return this},Tag.prototype.removeAttribute=function(name){for(var i=0,len=this.attrs.length;i/g,">").replace(/"/g,""")},exports.rethrow=function(err,str,filename,lineno){var context=3,lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}}),require.register("self-closing.js",function(module,exports,require){module.exports=["meta","img","link","input","area","base","col","br","hr"]}),require.register("utils.js",function(module,exports,require){var interpolate=exports.interpolate=function(str){return str.replace(/(\\)?([#!]){(.*?)}/g,function(str,escape,flag,code){return escape?str:"' + "+("!"==flag?"":"escape")+"((interp = "+code.replace(/\\'/g,"'")+") == null ? '' : interp) + '"})},escape=exports.escape=function(str){return str.replace(/'/g,"\\'")};exports.text=function(str){return interpolate(escape(str))}}) \ No newline at end of file diff --git a/node/node_modules/jade/lib/compiler.js b/node/node_modules/jade/lib/compiler.js index 15f0dd8..342e1f4 100644 --- a/node/node_modules/jade/lib/compiler.js +++ b/node/node_modules/jade/lib/compiler.js @@ -53,6 +53,7 @@ var Compiler = module.exports = function Compiler(node, options) { this.hasCompiledDoctype = false; this.hasCompiledTag = false; this.pp = options.pretty || false; + this.debug = false !== options.compileDebug; this.indents = 0; if (options.doctype) this.setDoctype(options.doctype); }; @@ -70,7 +71,8 @@ Compiler.prototype = { */ compile: function(){ - this.buf = []; + this.buf = ['var interp;']; + this.lastBufferedIdx = -1 this.visit(this.node); return this.buf.join('\n'); }, @@ -102,7 +104,15 @@ Compiler.prototype = { buffer: function(str, esc){ if (esc) str = utils.escape(str); - this.buf.push("buf.push('" + str + "');"); + + if (this.lastBufferedIdx == this.buf.length) { + this.lastBuffered += str; + this.buf[this.lastBufferedIdx - 1] = "buf.push('" + this.lastBuffered + "');" + } else { + this.buf.push("buf.push('" + str + "');"); + this.lastBuffered = str; + this.lastBufferedIdx = this.buf.length; + } }, /** @@ -113,7 +123,7 @@ Compiler.prototype = { */ line: function(node){ - if (node.instrumentLineNumber === false) return; + if (false === node.instrumentLineNumber) return; this.buf.push('__.lineno = ' + node.line + ';'); }, @@ -125,7 +135,7 @@ Compiler.prototype = { */ visit: function(node){ - this.line(node); + if (this.debug) this.line(node); return this.visitNode(node); }, @@ -141,7 +151,19 @@ Compiler.prototype = { || node.constructor.toString().match(/function ([^(\s]+)()/)[1]; return this['visit' + name](node); }, - + + /** + * Visit literal `node`. + * + * @param {Literal} node + * @api public + */ + + visitLiteral: function(node){ + var str = node.str.replace(/\n/g, '\\\\n'); + this.buffer(str); + }, + /** * Visit all nodes in `block`. * @@ -150,7 +172,7 @@ Compiler.prototype = { */ visitBlock: function(block){ - var len = len = block.nodes.length; + var len = block.nodes.length; for (var i = 0; i < len; ++i) { this.visit(block.nodes[i]); } diff --git a/node/node_modules/jade/lib/jade.js b/node/node_modules/jade/lib/jade.js index 25fafef..b210255 100644 --- a/node/node_modules/jade/lib/jade.js +++ b/node/node_modules/jade/lib/jade.js @@ -11,6 +11,7 @@ var Parser = require('./parser') , Compiler = require('./compiler') + , runtime = require('./runtime') // if node , fs = require('fs'); // end @@ -19,7 +20,7 @@ var Parser = require('./parser') * Library version. */ -exports.version = '0.13.0'; +exports.version = '0.15.4'; /** * Intermediate JavaScript cache. @@ -70,88 +71,10 @@ exports.Parser = Parser; exports.nodes = require('./nodes'); /** - * Render the given attributes object. - * - * @param {Object} obj - * @return {String} - * @api private - */ - -function attrs(obj){ - var buf = [] - , terse = obj.terse; - delete obj.terse; - var keys = Object.keys(obj) - , len = keys.length; - if (len) { - buf.push(''); - for (var i = 0; i < len; ++i) { - var key = keys[i] - , val = obj[key]; - if ('boolean' == typeof val || null == val) { - if (val) { - terse - ? buf.push(key) - : buf.push(key + '="' + key + '"'); - } - } else if ('class' == key && Array.isArray(val)) { - buf.push(key + '="' + escape(val.join(' ')) + '"'); - } else { - buf.push(key + '="' + escape(val) + '"'); - } - } - } - return buf.join(' '); -} - -/** - * Escape the given string of `html`. - * - * @param {String} html - * @return {String} - * @api private + * Jade runtime helpers. */ -function escape(html){ - return String(html) - .replace(/&(?!\w+;)/g, '&') - .replace(//g, '>') - .replace(/"/g, '"'); -} - -/** - * Re-throw the given `err` in context to the - * `str` of jade, `filename`, and `lineno`. - * - * @param {Error} err - * @param {String} str - * @param {String} filename - * @param {String} lineno - * @api private - */ - -function rethrow(err, str, filename, lineno){ - var context = 3 - , lines = str.split('\n') - , start = Math.max(lineno - context, 0) - , end = Math.min(lines.length, lineno + context); - - // 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 || 'Jade') + ':' + lineno - + '\n' + context + '\n\n' + err.message; - throw err; -} +exports.runtime = runtime; /** * Parse the given `str` of jade and return a function body. @@ -164,10 +87,10 @@ function rethrow(err, str, filename, lineno){ function parse(str, options){ var filename = options.filename; + try { // Parse - var parser = new Parser(str, filename); - if (options.debug) parser.debug(); + var parser = new Parser(str, filename, options); // Compile var compiler = new (options.compiler || Compiler)(parser.parse(), options) @@ -180,25 +103,30 @@ function parse(str, options){ try { return '' - + attrs.toString() + '\n\n' - + escape.toString() + '\n\n' + 'var buf = [];\n' + (options.self - ? 'var self = locals || {}, __ = __ || locals.__;\n' + js - : 'with (locals || {}) {' + js + '}') + ? 'var self = locals || {};\n' + js + : 'with (locals || {}) {\n' + js + '\n}\n') + 'return buf.join("");'; + } catch (err) { process.compile(js, filename || 'Jade'); return; } } catch (err) { - rethrow(err, str, filename, parser.lexer.lineno); + runtime.rethrow(err, str, filename, parser.lexer.lineno); } } /** * Compile a `Function` representation of the given jade `str`. * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * * @param {String} str * @param {Options} options * @return {Function} @@ -208,111 +136,34 @@ function parse(str, options){ exports.compile = function(str, options){ var options = options || {} , input = JSON.stringify(str) + , client = options.client , filename = options.filename ? JSON.stringify(options.filename) - : 'undefined'; - - // Reduce closure madness by injecting some locals - var fn = [ - 'var __ = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };' - , rethrow.toString() - , 'try {' - , parse(String(str), options || {}) - , '} catch (err) {' - , ' rethrow(err, __.input, __.filename, __.lineno);' - , '}' - ].join('\n'); - - return new Function('locals', fn); -}; - -/** - * Render the given `str` of jade. - * - * Options: - * - * - `scope` Evaluation scope (`this`) - * - `locals` Local variable object - * - `filename` Used in exceptions, and required by `cache` - * - `cache` Cache intermediate JavaScript in memory keyed by `filename` - * - `compiler` Compiler to replade jade's default - * - `doctype` Specify the default doctype - * - * @param {String|Buffer} str - * @param {Object} options - * @return {String} - * @api public - */ - -exports.render = function(str, options){ - var fn - , options = options || {} - , filename = options.filename; - - // Accept Buffers - str = String(str); - - // Cache support - if (options.cache) { - if (filename) { - if (cache[filename]) { - fn = cache[filename]; - } else { - fn = cache[filename] = new Function('locals', parse(str, options)); - } - } else { - throw new Error('filename is required when using the cache option'); - } + : 'undefined' + , fn; + + if (options.compileDebug !== false) { + fn = [ + 'var __ = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };' + , 'try {' + , parse(String(str), options || {}) + , '} catch (err) {' + , ' rethrow(err, __.input, __.filename, __.lineno);' + , '}' + ].join('\n'); } else { - fn = new Function('locals', parse(str, options)); + fn = parse(String(str), options || {}); } - // Render the template - try { - var locals = options.locals || {} - , meta = { lineno: 1 }; - locals.__ = meta; - return fn.call(options.scope, locals); - } catch (err) { - rethrow(err, str, filename, meta.lineno); + if (client) { + fn = 'var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;\n' + fn; } -}; -/** - * Render jade template at the given `path`. - * - * @param {String} path - * @param {Object} options - * @param {Function} fn - * @api public - */ + fn = new Function('locals, attrs, escape, rethrow', fn); -exports.renderFile = function(path, options, fn){ - var ret; + if (client) return fn; - if (typeof options === 'function') { - fn = options; - options = {}; - } - options.filename = path; - - // Primed cache - if (options.cache && cache[path]) { - try { - ret = exports.render('', options); - } catch (err) { - return fn(err); - } - fn(null, ret); - } else { - fs.readFile(path, 'utf8', function(err, str){ - if (err) return fn(err); - try { - ret = exports.render(str, options); - } catch (err) { - return fn(err); - } - fn(null, ret); - }); - } + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow); + }; }; diff --git a/node/node_modules/jade/lib/lexer.js b/node/node_modules/jade/lib/lexer.js index 641eae5..fb4d7c3 100644 --- a/node/node_modules/jade/lib/lexer.js +++ b/node/node_modules/jade/lib/lexer.js @@ -8,12 +8,19 @@ /** * Initialize `Lexer` with the given `str`. * + * Options: + * + * - `colons` allow colons for attr delimiters + * * @param {String} str + * @param {Object} options * @api private */ -var Lexer = module.exports = function Lexer(str) { +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; this.deferredTokens = []; this.lastIndents = 0; this.lineno = 1; @@ -255,13 +262,35 @@ Lexer.prototype = { } }, + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + /** * Each. */ each: function() { var captures; - if (captures = /^- *each *(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { + if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { this.consume(captures[0].length); var tok = this.tok('each', captures[1]); tok.key = captures[2] || 'index'; @@ -297,6 +326,7 @@ Lexer.prototype = { , str = this.input.substr(1, index-1) , tok = this.tok('attrs') , len = str.length + , colons = this.colons , states = ['key'] , key = '' , val = '' @@ -317,6 +347,9 @@ Lexer.prototype = { tok.attrs = {}; function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; switch (c) { case ',': case '\n': @@ -341,14 +374,14 @@ Lexer.prototype = { case '=': switch (state()) { case 'key char': - key += c; + key += real; break; case 'val': case 'expr': case 'array': case 'string': case 'object': - val += c; + val += real; break; default: states.push('val'); @@ -532,9 +565,10 @@ Lexer.prototype = { || this.doctype() || this.include() || this.mixin() + || this.conditional() + || this.each() || this.tag() || this.filter() - || this.each() || this.code() || this.id() || this.className() diff --git a/node/node_modules/jade/lib/nodes/index.js b/node/node_modules/jade/lib/nodes/index.js index 4ac5816..869d01a 100644 --- a/node/node_modules/jade/lib/nodes/index.js +++ b/node/node_modules/jade/lib/nodes/index.js @@ -14,5 +14,6 @@ exports.Block = require('./block'); exports.Mixin = require('./mixin'); exports.Filter = require('./filter'); exports.Comment = require('./comment'); +exports.Literal = require('./literal'); exports.BlockComment = require('./block-comment'); exports.Doctype = require('./doctype'); diff --git a/node/node_modules/jade/lib/nodes/literal.js b/node/node_modules/jade/lib/nodes/literal.js new file mode 100644 index 0000000..a8a02a2 --- /dev/null +++ b/node/node_modules/jade/lib/nodes/literal.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str; +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype.__proto__ = Node.prototype; diff --git a/node/node_modules/jade/lib/parser.js b/node/node_modules/jade/lib/parser.js index 9edb5e3..25f1601 100644 --- a/node/node_modules/jade/lib/parser.js +++ b/node/node_modules/jade/lib/parser.js @@ -10,23 +10,20 @@ */ var Lexer = require('./lexer') - , nodes = require('./nodes') - , path = require('path') - , dirname = path.dirname - , join = path.join - , fs = require('fs'); + , nodes = require('./nodes'); /** * Initialize `Parser` with the given input `str` and `filename`. * * @param {String} str * @param {String} filename + * @param {Object} options * @api public */ -var Parser = exports = module.exports = function Parser(str, filename){ +var Parser = exports = module.exports = function Parser(str, filename, options){ this.input = str; - this.lexer = new Lexer(str); + this.lexer = new Lexer(str, options); this.filename = filename; }; @@ -42,20 +39,6 @@ var textOnly = exports.textOnly = ['code', 'script', 'textarea', 'style', 'title Parser.prototype = { - /** - * Output parse tree to stdout. - * - * @api public - */ - - debug: function(){ - var lexer = new Lexer(this.input) - , tree = require('sys').inspect(this.parse(), false, 12, true); - console.log('\n\x1b[1mParse Tree\x1b[0m:\n'); - console.log(tree); - this.lexer = lexer; - }, - /** * Return the next token object. * @@ -66,6 +49,17 @@ Parser.prototype = { advance: function(){ return this.lexer.advance(); }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, /** * Single token lookahead. @@ -211,9 +205,14 @@ Parser.prototype = { parseCode: function(){ var tok = this.expect('code') - , node = new nodes.Code(tok.val, tok.buffer, tok.escape); + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , i = 1; node.line = this.line(); - if ('indent' == this.peek().type) { + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); node.block = this.parseBlock(); } return node; @@ -299,14 +298,27 @@ Parser.prototype = { */ parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + if (!this.filename) throw new Error('the "filename" option is required to use includes'); var path = name = this.expect('include').val.trim() - , dir = dirname(this.filename) - , path = join(dir, path + '.jade'); + , dir = dirname(this.filename); + + // non-jade + if (~basename(path).indexOf('.')) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } - var str = fs.readFileSync(path, 'utf8') + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') , parser = new Parser(str, path) , ast = parser.parse(); @@ -394,7 +406,8 @@ Parser.prototype = { } var name = this.advance().val - , tag = new nodes.Tag(name); + , tag = new nodes.Tag(name) + , dot; tag.line = this.line(); @@ -423,7 +436,7 @@ Parser.prototype = { // check immediate '.' if ('.' == this.peek().val) { - tag.textOnly = true; + dot = tag.textOnly = true; this.advance(); } @@ -450,7 +463,7 @@ Parser.prototype = { // script special-case if ('script' == tag.name) { var type = tag.getAttribute('type'); - if (type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { tag.textOnly = false; } } diff --git a/node/node_modules/jade/lib/runtime.js b/node/node_modules/jade/lib/runtime.js new file mode 100644 index 0000000..b826252 --- /dev/null +++ b/node/node_modules/jade/lib/runtime.js @@ -0,0 +1,116 @@ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(obj); + } + } + return arr; + } +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj){ + var buf = [] + , terse = obj.terse; + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else { + buf.push(key + '="' + exports.escape(val) + '"'); + } + } + } + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of jade, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, str, filename, lineno){ + var context = 3 + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // 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 || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; diff --git a/node/node_modules/jade/package.json b/node/node_modules/jade/package.json index cbfe661..2dedf7b 100644 --- a/node/node_modules/jade/package.json +++ b/node/node_modules/jade/package.json @@ -1,18 +1,23 @@ { "name": "jade", "description": "Jade template engine", - "version": "0.13.0", + "version": "0.15.4", "author": "TJ Holowaychuk ", "repository": "git://github.com/visionmedia/jade", "main": "./index.js", "bin": { "jade": "./bin/jade" }, + "dependencies": { + "commander": "0.1.0", + "mkdirp": "0.0.6" + }, "devDependencies": { "expresso": "0.6.4", "coffee-script": ">= 0.0.1", "sass": ">= 0.0.1", "less": ">= 0.0.1", "markdown": ">= 0.0.1", - "stylus": ">= 0.0.1" + "stylus": ">= 0.0.1", + "uubench": "0.0.1" }, "scripts" : { "prepublish" : "npm prune" }, "engines": { "node": ">= 0.1.98" } diff --git a/node/node_modules/jade/runtime.js b/node/node_modules/jade/runtime.js new file mode 100644 index 0000000..b7f5fba --- /dev/null +++ b/node/node_modules/jade/runtime.js @@ -0,0 +1,121 @@ + +var jade = (function(exports){ +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(obj); + } + } + return arr; + } +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj){ + var buf = [] + , terse = obj.terse; + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else { + buf.push(key + '="' + exports.escape(val) + '"'); + } + } + } + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * `str` of jade, `filename`, and `lineno`. + * + * @param {Error} err + * @param {String} str + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, str, filename, lineno){ + var context = 3 + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // 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 || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; + + return exports; + +})({}); \ No newline at end of file diff --git a/node/node_modules/jade/runtime.min.js b/node/node_modules/jade/runtime.min.js new file mode 100644 index 0000000..6e1efc9 --- /dev/null +++ b/node/node_modules/jade/runtime.min.js @@ -0,0 +1 @@ +var jade=function(exports){Array.isArray||(Array.isArray=function(arr){return"[object Array]"==toString.call(arr)}),Object.keys||(Object.keys=function(obj){var arr=[];for(var key in obj)obj.hasOwnProperty(key)&&arr.push(obj);return arr}),exports.attrs=function(obj){var buf=[],terse=obj.terse;delete obj.terse;var keys=Object.keys(obj),len=keys.length;if(len){buf.push("");for(var i=0;i/g,">").replace(/"/g,""")},exports.rethrow=function(err,str,filename,lineno){var context=3,lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err};return exports}({}) \ No newline at end of file diff --git a/node/node_modules/jade/support/benchmark.js b/node/node_modules/jade/support/benchmark.js new file mode 100644 index 0000000..85c2f3f --- /dev/null +++ b/node/node_modules/jade/support/benchmark.js @@ -0,0 +1,62 @@ + +/** + * Module dependencies. + */ + +var uubench = require('uubench') + , jade = require('../'); + + +var suite = new uubench.Suite({ + min: 200, + result: function(name, stats){ + var persec = 1000 / stats.elapsed + , ops = stats.iterations * persec; + console.log('%s: %d', name, ops | 0); + } +}); + +var str = 'html\n body\n h1 Title' + , fn = jade.compile(str); + +suite.bench('tiny', function(next){ + fn(); + next(); +}); + +str = '\ +html\n\ + body\n\ + h1 Title\n\ + ul#menu\n\ + li: a(href="#") Home\n\ + li: a(href="#") About Us\n\ + li: a(href="#") Store\n\ + li: a(href="#") FAQ\n\ + li: a(href="#") Contact\n\ +'; + +var fn2 = jade.compile(str); + +suite.bench('small', function(next){ + fn2(); + next(); +}); + +str = '\ +html\n\ + body\n\ + h1 #{title}\n\ + ul#menu\n\ + - each link in links\r\n\ + li: a(href="#")= link\r\n\ +'; + +var fn3 = jade.compile(str); + +suite.bench('small locals', function(next){ + fn3({ title: 'Title', links: ['Home', 'About Us', 'Store', 'FAQ', 'Contact'] }); + next(); +}); + +suite.run(); \ No newline at end of file diff --git a/node/node_modules/jade/support/foot.js b/node/node_modules/jade/support/foot.js new file mode 100644 index 0000000..92f4251 --- /dev/null +++ b/node/node_modules/jade/support/foot.js @@ -0,0 +1,4 @@ + + return exports; + +})({}); \ No newline at end of file diff --git a/node/node_modules/jade/support/head.js b/node/node_modules/jade/support/head.js new file mode 100644 index 0000000..83775aa --- /dev/null +++ b/node/node_modules/jade/support/head.js @@ -0,0 +1,2 @@ + +var jade = (function(exports){ \ No newline at end of file diff --git a/node/node_modules/jade/test/filters.test.js b/node/node_modules/jade/test/filters.test.js index 8f157f5..1d8ffac 100644 --- a/node/node_modules/jade/test/filters.test.js +++ b/node/node_modules/jade/test/filters.test.js @@ -3,10 +3,16 @@ * Module dependencies. */ -var jade = require('../'), - Compiler = jade.Compiler, - render = jade.render, - nodes = jade.nodes; +var jade = require('../') + , Compiler = jade.Compiler + , nodes = jade.nodes; + +// Shortcut + +var render = function(str, options){ + var fn = jade.compile(str, options); + return fn(options); +}; jade.filters.conditionals = function(block, compiler){ return new Visitor(block).compile(); @@ -19,21 +25,13 @@ function Visitor(node) { Visitor.prototype.__proto__ = Compiler.prototype; Visitor.prototype.visit = function(node){ - if (node.name != 'else') this.line(node); + if (node.name != 'or') this.line(node); this.visitNode(node); }; Visitor.prototype.visitTag = function(node){ switch (node.name) { - case 'if': - // First text -> line - var condition = node.text[0] - , block = node.block; - node = new nodes.Code('if (' + condition + ')'); - node.block = block; - this.visit(node); - break; - case 'else': + case 'or': var block = node.block; node = new nodes.Code('else'); node.block = block; @@ -46,108 +44,108 @@ Visitor.prototype.visitTag = function(node){ }; module.exports = { - 'test :cdata filter': function(assert){ - assert.equal('', render(':cdata\n foo')); - assert.equal('', render(':cdata\n foo\n bar')); - assert.equal('

    something else

    ', render(':cdata\n foo\n bar\np something else')); - }, - - 'test :markdown filter': function(assert){ - assert.equal( - '

    foo

    \n\n
    • bar
    • baz
    ', - render(':markdown\n #foo\n - bar\n - baz\n')) - }, - - 'test :stylus filter': function(assert){ - assert.equal( - '', - render(':stylus\n body\n color #c00')); - }, - - 'test :stylus filter with options': function(assert){ - assert.equal( - '', - render(':stylus(compress=true)\n body\n color #c00')); - }, - - 'test :less filter': function(assert){ - assert.equal( - '', - render(':less\n .class { width: 10px * 2 }\n')); - }, - - 'test :coffeescript filter': function(assert){ - var coffee, js; - coffee = [ - ':coffeescript', - ' square = (x) ->', - ' x * x' - ].join('\n'); - js = [ - '' - ].join('\n'); - - assert.equal(js, render(coffee)); - - coffee = [ - ':coffeescript', - ' $ ->', - ' $("#flash").fadeIn ->', - ' console.log("first line")', - ' console.log("second line")' - ].join('\n'); - js = [ - '' - ].join('\n'); - - assert.equal(js, render(coffee)); - }, - - 'test parse tree': function(assert){ - var str = [ - 'conditionals:', - ' if false', - ' | oh noes', - ' else', - ' if null == false', - ' p doh', - ' else', - ' p amazing!' - ].join('\n'); - - var html = [ - '

    amazing!

    ' - ].join(''); - - assert.equal(html, render(str)); - }, - - 'test filter attrs': function(assert){ - jade.filters.testing = function(str, attrs){ - return str + ' ' + attrs.stuff; - }; - - var str = [ - ':testing(stuff)', - ' foo bar', - ].join('\n'); - - assert.equal('foo bar true', render(str)); - } + 'test :cdata filter': function(assert){ + assert.equal('', render(':cdata\n foo')); + assert.equal('', render(':cdata\n foo\n bar')); + assert.equal('

    something else

    ', render(':cdata\n foo\n bar\np something else')); + }, + + 'test :markdown filter': function(assert){ + assert.equal( + '

    foo

    \n\n
    • bar
    • baz
    ', + render(':markdown\n #foo\n - bar\n - baz\n')) + }, + + 'test :stylus filter': function(assert){ + assert.equal( + '', + render(':stylus\n body\n color #c00')); + }, + + 'test :stylus filter with options': function(assert){ + assert.equal( + '', + render(':stylus(compress=true)\n body\n color #c00')); + }, + + 'test :less filter': function(assert){ + assert.equal( + '', + render(':less\n .class { width: 10px * 2 }\n')); + }, + + 'test :coffeescript filter': function(assert){ + var coffee, js; + coffee = [ + ':coffeescript', + ' square = (x) ->', + ' x * x' + ].join('\n'); + js = [ + '' + ].join('\n'); + + assert.equal(js, render(coffee)); + + coffee = [ + ':coffeescript', + ' $ ->', + ' $("#flash").fadeIn ->', + ' console.log("first line")', + ' console.log("second line")' + ].join('\n'); + js = [ + '' + ].join('\n'); + + assert.equal(js, render(coffee)); + }, + + 'test parse tree': function(assert){ + var str = [ + 'conditionals:', + ' if false', + ' | oh noes', + ' or', + ' if null == false', + ' p doh', + ' or', + ' p amazing!' + ].join('\n'); + + var html = [ + '

    amazing!

    ' + ].join(''); + + assert.equal(html, render(str)); + }, + + 'test filter attrs': function(assert){ + jade.filters.testing = function(str, attrs){ + return str + ' ' + attrs.stuff; + }; + + var str = [ + ':testing(stuff)', + ' foo bar', + ].join('\n'); + + assert.equal('foo bar true', render(str)); + } }; \ No newline at end of file diff --git a/node/node_modules/jade/test/jade.test.js b/node/node_modules/jade/test/jade.test.js index bfb375e..89f1ce3 100644 --- a/node/node_modules/jade/test/jade.test.js +++ b/node/node_modules/jade/test/jade.test.js @@ -3,877 +3,918 @@ * Module dependencies. */ -var jade = require('../') - , ENOENT; - -// COMPAT: - -try { - ENOENT = require('constants').ENOENT; -} catch (err) { - ENOENT = process.ENOENT; -} +var jade = require('../'); // Shortcut -var render = jade.render; +var render = function(str, options){ + var fn = jade.compile(str, options); + return fn(options); +}; module.exports = { - 'test .version': function(assert){ - assert.ok(/^\d+\.\d+\.\d+$/.test(jade.version), "Invalid version format"); - }, - - 'test exports': function(assert){ - assert.equal('object', typeof jade.selfClosing, 'exports.selfClosing missing'); - assert.equal('object', typeof jade.doctypes, 'exports.doctypes missing'); - assert.equal('object', typeof jade.filters, 'exports.filters missing'); - assert.equal('object', typeof jade.utils, 'exports.utils missing'); - assert.equal('function', typeof jade.Compiler, 'exports.Compiler missing'); - }, - - 'test doctypes': function(assert){ - assert.equal('', render('!!! xml')); - assert.equal('', render('doctype html')); - assert.equal('', render('doctype HTML')); - assert.equal('', render('!!! 5')); - assert.equal('', render('!!!', { doctype:'html' })); - assert.equal('', render('!!! html', { doctype:'xml' })); - assert.equal('', render('html')); - assert.equal('', render('html', { doctype:'html' })); - }, - - 'test Buffers': function(assert){ - assert.equal('

    foo

    ', render(new Buffer('p foo'))); - }, - - 'test line endings': function(assert){ - var str = [ - 'p', - 'div', - 'img' - ].join('\r\n'); - - var html = [ - '

    ', - '
    ', - '' - ].join(''); - - assert.equal(html, render(str)); - - var str = [ - 'p', - 'div', - 'img' - ].join('\r'); - - var html = [ - '

    ', - '
    ', - '' - ].join(''); - - assert.equal(html, render(str)); - - var str = [ - 'p', - 'div', - 'img' - ].join('\r\n'); - - var html = [ - '

    ', - '
    ', - '' - ].join(''); - - assert.equal(html, render(str, { doctype:'html' })); - }, - - 'test single quotes': function(assert){ - assert.equal("

    'foo'

    ", render("p 'foo'")); - assert.equal("

    'foo'\n

    ", render("p\n | 'foo'")); - assert.equal('', render("- var path = 'foo';\na(href='/' + path)")); - }, - - 'test block-expansion': function(assert){ - assert.equal("
  • foo
  • bar
  • baz
  • ", render("li: a foo\nli: a bar\nli: a baz")); - assert.equal("
  • foo
  • bar
  • baz
  • ", render("li.first: a foo\nli: a bar\nli: a baz")); - }, - - 'test tags': function(assert){ - var str = [ - 'p', - 'div', - 'img' - ].join('\n'); - - var html = [ - '

    ', - '
    ', - '' - ].join(''); - - assert.equal(html, render(str), 'Test basic tags'); - assert.equal('', render('fb:foo-bar'), 'Test hyphens'); - assert.equal('
    ', render('div.something'), 'Test classes'); - assert.equal('
    ', render('div#something'), 'Test ids'); - assert.equal('
    ', render('.something'), 'Test stand-alone classes'); - assert.equal('
    ', render('#something'), 'Test stand-alone ids'); - assert.equal('
    ', render('#foo.bar')); - assert.equal('
    ', render('.bar#foo')); - assert.equal('
    ', render('div#foo(class="bar")')); - assert.equal('
    ', render('div(class="bar")#foo')); - assert.equal('
    ', render('div(id="bar").foo')); - assert.equal('
    ', render('div.foo.bar.baz')); - assert.equal('
    ', render('div(class="foo").bar.baz')); - assert.equal('
    ', render('div.foo(class="bar").baz')); - assert.equal('
    ', render('div.foo.bar(class="baz")')); - assert.equal('
    ', render('div.a-b2')); - assert.equal('
    ', render('div.a_b2')); - assert.equal('', render('fb:user')); - assert.equal('', render('fb:user:role')); - assert.equal('', render('colgroup\n col.test')); - }, - - 'test nested tags': function(assert){ - var str = [ - 'ul', - ' li a', - ' li b', - ' li', - ' ul', - ' li c', - ' li d', - ' li e', - ].join('\n'); - - var html = [ - '
      ', - '
    • a
    • ', - '
    • b
    • ', - '
      • c
      • d
    • ', - '
    • e
    • ', - '
    ' - ].join(''); - - assert.equal(html, render(str)); - - var str = [ - 'a(href="#")', - ' | foo ', - ' | bar ', - ' | baz' - ].join('\n'); - - assert.equal('foo \nbar \nbaz\n', render(str)); - - var str = [ - 'ul', - ' li one', - ' ul', - ' | two', - ' li three' - ].join('\n'); - - var html = [ - '
      ', - '
    • one
    • ', - '
        two\n', - '
      • three
      • ', - '
      ', - '
    ' - ].join(''); - - assert.equal(html, render(str)); - }, - - 'test variable length newlines': function(assert){ - var str = [ - 'ul', - ' li a', - ' ', - ' li b', - ' ', - ' ', - ' li', - ' ul', - ' li c', - '', - ' li d', - ' li e', - ].join('\n'); - - var html = [ - '
      ', - '
    • a
    • ', - '
    • b
    • ', - '
      • c
      • d
    • ', - '
    • e
    • ', - '
    ' - ].join(''); - - assert.equal(html, render(str)); - }, - - 'test tab conversion': function(assert){ - var str = [ - 'ul', - '\tli a', - '\t', - '\tli b', - '\t\t', - '\t\t\t\t\t\t', - '\tli', - '\t\tul', - '\t\t\tli c', - '', - '\t\t\tli d', - '\tli e', - ].join('\n'); - - var html = [ - '
      ', - '
    • a
    • ', - '
    • b
    • ', - '
      • c
      • d
    • ', - '
    • e
    • ', - '
    ' - ].join(''); - - assert.equal(html, render(str)); - }, - - 'test newlines': function(assert){ - var str = [ - 'ul', - ' li a', - ' ', - ' ', - '', - ' ', - ' li b', - ' li', - ' ', - ' ', - ' ', - ' ul', - ' ', - ' li c', - ' li d', - ' li e', - ].join('\n'); - - var html = [ - '
      ', - '
    • a
    • ', - '
    • b
    • ', - '
      • c
      • d
    • ', - '
    • e
    • ', - '
    ' - ].join(''); - - assert.equal(html, render(str)); - - var str = [ - 'html', - ' ', - ' head', - ' != "test"', - ' ', - ' ', - ' ', - ' body' - ].join('\n'); - - var html = [ - '', - '', - 'test', - '', - '', - '' - ].join(''); - - assert.equal(html, render(str)); - assert.equal('something', render('foo\n= "something"\nbar')); - assert.equal('somethingelse', render('foo\n= "something"\nbar\n= "else"')); - }, - - 'test cache': function(assert){ - var err; - try { - render('foo', { cache: true }); - } catch (e) { - err = e; - } - assert.equal('filename is required when using the cache option', err.message); - - assert.equal('

    ', render('p', { cache: true, filename: 'foo.jade' })); - assert.equal('

    ', render('p', { cache: true, filename: 'foo.jade' })); - assert.ok(typeof jade.cache['foo.jade'] === 'function', 'Test cache'); - }, - - 'test text': function(assert){ - assert.equal('foo\nbar\nbaz\n', render('| foo\n| bar\n| baz')); - assert.equal('foo \nbar \nbaz\n', render('| foo \n| bar \n| baz')); - assert.equal('(hey)\n', render('| (hey)')); - assert.equal('some random text\n', render('| some random text')); - assert.equal(' foo\n', render('| foo')); - assert.equal(' foo \n', render('| foo ')); - assert.equal(' foo \n bar \n', render('| foo \n| bar ')); - }, - - 'test pipe-less text': function(assert){ - assert.equal('
    foo\n\nbar\n
    ', render('pre\n code\n foo\n\n bar')); - assert.equal('

    foo\n\nbar\n

    ', render('p.\n foo\n\n bar')); - assert.equal('

    foo\n\n\n\nbar\n

    ', render('p.\n foo\n\n\n\n bar')); - assert.equal('

    foo\n bar\nfoo\n

    ', render('p.\n foo\n bar\n foo')); - assert.equal('', render('script\n s.parentNode.insertBefore(g,s)\n')); - assert.equal('', render('script\n s.parentNode.insertBefore(g,s)')); - }, - - 'test tag text': function(assert){ - assert.equal('

    some random text

    ', render('p some random text')); - assert.equal('

    click\nGoogle.\n

    ', render('p\n | click\n a Google\n | .')); - assert.equal('

    (parens)

    ', render('p (parens)')); - assert.equal('

    (parens)

    ', render('p(foo="bar") (parens)')); - assert.equal('', render('option(value="") -- (optional) foo --')); - }, - - 'test tag text block': function(assert){ - assert.equal('

    foo \nbar \nbaz\n

    ', render('p\n | foo \n | bar \n | baz')); - assert.equal('', render('label\n | Password:\n input')); - assert.equal('', render('label Password:\n input')); - }, - - 'test tag text interpolation': function(assert){ - assert.equal('yo, jade is cool\n', render('| yo, #{name} is cool\n', { locals: { name: 'jade' }})); - assert.equal('

    yo, jade is cool

    ', render('p yo, #{name} is cool', { locals: { name: 'jade' }})); - assert.equal('yo, jade is cool\n', render('| yo, #{name || "jade"} is cool', { locals: { name: null }})); - assert.equal('yo, \'jade\' is cool\n', render('| yo, #{name || "\'jade\'"} is cool', { locals: { name: null }})); - assert.equal('foo <script> bar\n', render('| foo #{code} bar', { locals: { code: '', render('script\n s.parentNode.insertBefore(g,s)\n')); + assert.equal('', render('script\n s.parentNode.insertBefore(g,s)')); + }, + + 'test tag text': function(assert){ + assert.equal('

    some random text

    ', render('p some random text')); + assert.equal('

    click\nGoogle.\n

    ', render('p\n | click\n a Google\n | .')); + assert.equal('

    (parens)

    ', render('p (parens)')); + assert.equal('

    (parens)

    ', render('p(foo="bar") (parens)')); + assert.equal('', render('option(value="") -- (optional) foo --')); + }, + + 'test tag text block': function(assert){ + assert.equal('

    foo \nbar \nbaz\n

    ', render('p\n | foo \n | bar \n | baz')); + assert.equal('', render('label\n | Password:\n input')); + assert.equal('', render('label Password:\n input')); + }, + + 'test tag text interpolation': function(assert){ + assert.equal('yo, jade is cool\n', render('| yo, #{name} is cool\n', { name: 'jade' })); + assert.equal('

    yo, jade is cool

    ', render('p yo, #{name} is cool', { name: 'jade' })); + assert.equal('yo, jade is cool\n', render('| yo, #{name || "jade"} is cool', { name: null })); + assert.equal('yo, \'jade\' is cool\n', render('| yo, #{name || "\'jade\'"} is cool', { name: null })); + assert.equal('foo <script> bar\n', render('| foo #{code} bar', { code: '', + '', + '' + ].join(''); + + assert.equal(html, render(str)); + }, + + 'test comments': function(assert){ + // Regular + var str = [ + '//foo', + 'p bar' + ].join('\n'); + + var html = [ + '', + '

    bar

    ' + ].join(''); + + assert.equal(html, render(str)); + + // Arbitrary indentation + + var str = [ + ' //foo', + 'p bar' + ].join('\n'); + + var html = [ + '', + '

    bar

    ' + ].join(''); + + assert.equal(html, render(str)); + + // Between tags + + var str = [ + 'p foo', + '// bar ', + 'p baz' + ].join('\n'); + + var html = [ + '

    foo

    ', + '', + '

    baz

    ' + ].join(''); + + assert.equal(html, render(str)); + + // Quotes + + var str = "", + js = "// script(src: '/js/validate.js') "; + assert.equal(str, render(js)); + }, + + 'test unbuffered comments': function(assert){ + var str = [ + '//- foo', + 'p bar' + ].join('\n'); + + var html = [ + '

    bar

    ' + ].join(''); + + assert.equal(html, render(str)); + + var str = [ + 'p foo', + '//- bar ', + 'p baz' + ].join('\n'); + + var html = [ + '

    foo

    ', + '

    baz

    ' + ].join(''); + + assert.equal(html, render(str)); + }, + + 'test literal html': function(assert){ + assert.equal('\n', render('')); + }, + + 'test code': function(assert){ + assert.equal('test', render('!= "test"')); + assert.equal('test', render('= "test"')); + assert.equal('test', render('- var foo = "test"\n=foo')); + assert.equal('foo\ntestbar\n', render('- var foo = "test"\n| foo\nem= foo\n| bar')); + assert.equal('test

    something

    ', render('!= "test"\nh2 something')); + + var str = [ + '- var foo = "' + , initial = '' + + '' + + new Array(174).join(' ') + +HTMLFile.prototype.data = function (path, opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + opts.buffer = false; + + return this.request(path, opts, function (res) { + var buf = '' + , messages = 0 + , state = 0; + + res.on('data', function (chunk) { + buf += chunk; + + function parse () { + switch (state) { + case 0: + if (buf.indexOf(initial) === 0) { + buf = buf.substr(initial.length); + state = 1; + } else { + break; + } + + case 1: + if (buf.indexOf(head) === 0) { + buf = buf.substr(head.length); + state = 2; + } else { + break; + } + + case 2: + if (buf.indexOf(foot) != -1) { + var data = buf.slice(0, buf.indexOf(foot)) + , obj = JSON.parse(data); + + fn(obj === '' ? obj : parser.decodePayload(obj), ++messages); + + buf = buf.substr(data.length + foot.length); + state = 1; + + parse(); + } + }; + }; + + parse(); + }); + }); +}; + +/** + * Create client for this transport. + * + * @api public + */ + +function client (port) { + return new HTMLFile(port); +}; + +/** + * Tests. + */ + +module.exports = { + + 'test that not responding to a heartbeat drops client': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , beat = false; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + beat.should.be.true; + reason.should.eql('heartbeat timeout'); + + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) { + switch (i) { + case 1: + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + msgs[0].endpoint.should.eql(''); + break; + + case 2: + msgs.should.have.length(1); + msgs[0].type.should.eql('heartbeat'); + beat = true; + }; + }); + }); + }, + + 'test that responding to a heartbeat maintains session': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , heartbeats = 0; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + heartbeats.should.eql(2); + reason.should.eql('heartbeat timeout'); + + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) { + switch (i) { + case 1: + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + msgs[0].endpoint.should.eql(''); + break; + + default: + msgs.should.have.length(1); + msgs[0].type.should.eql('heartbeat'); + + heartbeats++; + + if (heartbeats == 1) { + cl.post('/socket.io/{protocol}/htmlfile/' + sid, parser.encodePacket({ + type: 'heartbeat' + })); + } + } + }); + }); + }, + + 'test sending undeliverable volatile messages': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function () { }); + + setTimeout(function () { + cl.end(); + + setTimeout(function () { + s.volatile.send('wooooot'); + cl = client(port); + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs) { + if (msgs && msgs.length) + messaged = true; + }); + + setTimeout(function () { + cl.end(); + }, 20); + }, 20); + }, 20); + }); + }, + + 'test sending undeliverable volatile json': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function () { }); + + setTimeout(function () { + cl.end(); + + setTimeout(function () { + s.volatile.json.send(123); + + cl = client(port); + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs) { + if (msgs && msgs.length) + messaged = true; + }); + + setTimeout(function () { + cl.end(); + }, 20); + }, 20); + }, 20); + }); + }, + + 'test sending undeliverable volatile events': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function () { }); + + setTimeout(function () { + cl.end(); + + setTimeout(function () { + s.volatile.emit('tobi'); + + cl = client(port); + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs) { + if (msgs && msgs.length) + messaged = true; + }); + + setTimeout(function () { + cl.end(); + }, 20); + }, 20); + }, 20); + }); + }, + + 'test sending deliverable volatile messages': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.send('woot'); + + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) { + switch (i) { + case 1: + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + msgs[0].endpoint.should.eql(''); + break; + + case 2: + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'message' + , data: 'woot' + , endpoint: '' + }); + cl.end(); + } + }); + }); + }, + + 'test sending deliverable volatile json': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.json.send(['woot']); + + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) { + switch (i) { + case 1: + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + msgs[0].endpoint.should.eql(''); + break; + + case 2: + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'json' + , data: ['woot'] + , endpoint: '' + }); + cl.end(); + } + }); + }); + }, + + 'test sending deliverable volatile events': function (done) { + var port = ++ports + , cl = client(port) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.emit('aaa'); + + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.data('/socket.io/{protocol}/htmlfile/' + sid, function (msgs, i) { + switch (i) { + case 1: + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + msgs[0].endpoint.should.eql(''); + break; + + case 2: + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'aaa' + , endpoint: '' + , args: [] + }); + cl.end(); + } + }); + }); + } + +}; diff --git a/node/node_modules/socket.io/test/transports.jsonp-polling.test.js b/node/node_modules/socket.io/test/transports.jsonp-polling.test.js new file mode 100644 index 0000000..c087d33 --- /dev/null +++ b/node/node_modules/socket.io/test/transports.jsonp-polling.test.js @@ -0,0 +1,770 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Test dependencies. + */ + +var sio = require('socket.io') + , should = require('./common') + , qs = require('querystring') + , HTTPClient = should.HTTPClient + , parser = sio.parser + , ports = 15500; + +/** + * HTTPClient for jsonp-polling transport. + */ + +function JSONPPolling (port) { + HTTPClient.call(this, port); +}; + +/** + * Inhertis from HTTPClient. + */ + +JSONPPolling.prototype.__proto__ = HTTPClient.prototype; + +/** + * Performs a json-p (cross domain) handshake + * + * @api public + */ + +JSONPPolling.prototype.handshake = function (opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + var self = this; + + return this.get( + '/socket.io/{protocol}?jsonp=0' + , opts + , function (res, data) { + var head = 'io.j[0](' + , foot = ');'; + + data.substr(0, head.length).should.eql(head); + data.substr(-foot.length).should.eql(foot); + data = data.slice(head.length, data.length - foot.length); + + var parts = JSON.parse(data).split(':'); + + if (opts.ignoreConnect) { + return fn && fn.apply(null, parts); + } + + // expect connect packet right after handshake + self.get( + '/socket.io/{protocol}/jsonp-polling/' + parts[0] + , function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'connect', endpoint: '', qs: '' }); + + fn && fn.apply(null, parts); + } + ); + } + ); +}; + +/** + * Override GET requests. + * + * @api public + */ + +JSONPPolling.prototype.get = function (path, opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + opts = opts || {}; + + opts.parse = function (data) { + var head = 'io.j[0](' + , foot = ');'; + + if (~path.indexOf('?i=1')) { + head = 'io.j[1]('; + } + + data.substr(0, head.length).should.eql(head); + data.substr(-foot.length).should.eql(foot); + + data = data.substr(head.length, data.length - head.length - foot.length); + + return JSON.parse(data); + }; + + return HTTPClient.prototype.get.call(this, path, opts, fn); +}; + +/** + * Issue an encoded POST request + * + * @api private + */ + +JSONPPolling.prototype.post = function (path, data, opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + opts = opts || {}; + opts.method = 'POST'; + opts.data = qs.stringify({ d: data }); + + return this.request(path, opts, fn); +}; + +/** + * Create client for this transport. + * + * @api public + */ + +function client (port) { + return new JSONPPolling(port); +}; + +/** + * Test. + */ + +module.exports = { + + 'test jsonp handshake': function (done) { + var cl = client(++ports) + , io = create(cl); + + io.configure(function () { + io.set('close timeout', .05); + io.set('polling duration', 0); + }); + + function finish () { + cl.end(); + io.server.close(); + done(); + }; + + cl.handshake(function (sid) { + var total = 2; + + cl.get('/socket.io/{protocol}/jsonp-polling/tobi', function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'error' + , reason: 'client not handshaken' + , endpoint: '' + , advice: 'reconnect' + }); + + --total || finish(); + }); + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + --total || finish(); + }); + }); + }, + + 'test the connection event': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.id.should.eql(sid); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test the disconnection event after a close timeout': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.id.should.eql(sid); + + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + + setTimeout(function () { + cl.end(); + }, 10); + }); + }); + }, + + 'test the disconnection event when the client sends ?disconnect req': + function (done) { + var cl = client(++ports) + , io = create(cl) + , disconnected = false + , sid; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + disconnected = true; + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'disconnect', endpoint: '' }); + disconnected.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid + '/?disconnect'); + }); + }); + }, + + 'test the disconnection event booting a client': function (done) { + var cl = client(++ports) + , io = create(cl) + , forced = false; + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + + cl.end(); + socket.disconnect(); + forced = true; + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'disconnect', endpoint: '' }); + + forced.should.be.true; + }); + }); + }, + + 'test the disconnection event with client disconnect packet': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.sockets.on('connection', function (client) { + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'disconnect' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + client.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test sending back data': function (done) { + var cl = client(++ports) + , io = create(cl); + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.send('woot'); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, packs) { + packs.should.have.length(1); + packs[0].type.should.eql('message'); + packs[0].data.should.eql('woot'); + }); + }); + }, + + 'test sending a batch of messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + var messages = 0; + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePayload([ + parser.encodePacket({ type: 'message', data: 'a' }) + , parser.encodePacket({ type: 'message', data: 'b' }) + , parser.encodePacket({ type: 'disconnect' }) + ]) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + socket.on('message', function (data) { + messages++; + + if (messages == 1) + data.should.eql('a'); + + if (messages == 2) + data.should.eql('b'); + }); + + socket.on('disconnect', function () { + messages.should.eql(2); + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test message buffering between a response and a request': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = false + , tobi; + + io.configure(function () { + io.set('polling duration', .1); + io.set('close timeout', .2); + }); + + io.sockets.on('connection', function (socket) { + tobi = function () { + socket.send('a'); + socket.send('b'); + socket.send('c'); + }; + + socket.on('disconnect', function () { + messages.should.be.true; + + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + tobi(); + + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + msgs.should.have.length(3); + msgs[0].should.eql({ type: 'message', endpoint: '', data: 'a' }); + msgs[1].should.eql({ type: 'message', endpoint: '', data: 'b' }); + msgs[2].should.eql({ type: 'message', endpoint: '', data: 'c' }); + messages = true; + }); + }) + }); + }, + + 'test connecting to a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , connectMessage = false + , sid; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/woot').on('connection', function (socket) { + connectMessage.should.be.true; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, data) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid); + + connectMessage = true; + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }); + }, + + 'test that connecting doesnt connect to defined endpoints': function (done) { + var cl = client(++ports) + , io = create(cl) + , tobiConnected = false + , mainConnected = false + , sid; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + mainConnected = true; + + socket.on('disconnect', function () { + tobiConnected.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/tobi').on('connection', function () { + tobiConnected = true; + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid); + }); + }, + + 'test disconnecting a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , wootDisconnected = false + , mainDisconnected = false + , checked = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (data) { + data.should.eql('ferret'); + mainDisconnected.should.be.false; + wootDisconnected.should.be.true; + checked = true; + }); + + socket.on('disconnect', function () { + mainDisconnected = true; + checked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/woot').on('connection', function (socket) { + socket.on('disconnect', function () { + wootDisconnected = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function () { + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'disconnect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'message', data: 'ferret' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + } + ); + }); + }); + }, + + 'test that disconnecting disconnects all endpoints': function (done) { + var cl = client(++ports) + , io = create(cl) + , aDisconnected = false + , bDisconnected = false; + + io.configure(function () { + io.set('polling duration', .2); + io.set('close timeout', .2); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + setTimeout(function () { + aDisconnected.should.be.true; + bDisconnected.should.be.true; + cl.end(); + io.server.close(); + done(); + }, 50); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('disconnect', function (msg) { + aDisconnected = true; + }); + }); + + io.of('/b').on('connection', function (socket) { + socket.on('disconnect', function (msg) { + bDisconnected = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }); + }, + + 'test messaging a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = true + , aMessaged = false + , bMessaged = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql(''); + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.true; + aMessaged.should.be.true; + bMessaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('a'); + aMessaged = true; + }); + }); + + io.of('/b').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('b'); + bMessaged = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/jsonp-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'message', data: '' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'message', endpoint: '/a', data: 'a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/jsonp-polling/' + sid + , parser.encodePacket({ type: 'message', endpoint: '/b', data: 'b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + }); + }); + } + +}; diff --git a/node/node_modules/socket.io/test/transports.websocket.hybi07-12.parser.test.js b/node/node_modules/socket.io/test/transports.websocket.hybi07-12.parser.test.js new file mode 100644 index 0000000..94efaa6 --- /dev/null +++ b/node/node_modules/socket.io/test/transports.websocket.hybi07-12.parser.test.js @@ -0,0 +1,271 @@ +/** + * Test dependencies. + */ + +var assert = require('assert'); +var Parser = require('../lib/transports/websocket/hybi-07-12.js').Parser; + +/** + * Returns a Buffer from a "ff 00 ff"-type hex string. + */ + +function makeBufferFromHexString(byteStr) { + var bytes = byteStr.split(' '); + var buf = new Buffer(bytes.length); + for (var i = 0; i < bytes.length; ++i) { + buf[i] = parseInt(bytes[i], 16); + } + return buf; +} + +/** + * Splits a buffer in two parts. + */ + +function splitBuffer(buffer) { + var b1 = new Buffer(Math.ceil(buffer.length / 2)); + buffer.copy(b1, 0, 0, b1.length); + var b2 = new Buffer(Math.floor(buffer.length / 2)); + buffer.copy(b2, 0, b1.length, b1.length + b2.length); + return [b1, b2]; +} + +/** + * Performs hybi07+ type masking on a hex string. + */ + +function mask(str, maskString) { + var buf = new Buffer(str); + var mask = makeBufferFromHexString(maskString || '34 83 a8 68'); + for (var i = 0; i < buf.length; ++i) { + buf[i] ^= mask[i % 4]; + } + return buf; +} + +/** + * Unpacks a Buffer into a number. + */ + +function unpack(buffer) { + var n = 0; + for (var i = 0; i < buffer.length; ++i) { + n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; + } + return n; +} + +/** + * Returns a hex string, representing a specific byte count 'length', from a number. + */ + +function pack(length, number) { + return padl(number.toString(16), length, '0').replace(/(\d\d)/g, '$1 ').trim(); +} + +/** + * Left pads the string 's' to a total length of 'n' with char 'c'. + */ + +function padl(s, n, c) { + return new Array(1 + n - s.length).join(c) + s; +} + +/** + * Returns a hex string from a Buffer. + */ + +function dump(data) { + var s = ''; + for (var i = 0; i < data.length; ++i) { + s += padl(data[i].toString(16), 2, '0') + ' '; + } + return s.trim(); +} + +/** + * Tests. + */ + +module.exports = { + 'can parse unmasked text message': function() { + var p = new Parser(); + var packet = '81 05 48 65 6c 6c 6f'; + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal('Hello', data); + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotData); + }, + 'can parse close message': function() { + var p = new Parser(); + var packet = '88 00'; + + var gotClose = false; + p.on('close', function(data) { + gotClose = true; + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotClose); + }, + 'can parse masked text message': function() { + var p = new Parser(); + var packet = '81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'; + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal('5:::{"name":"echo"}', data); + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotData); + }, + 'can parse a masked text message longer than 125 bytes': function() { + var p = new Parser(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var packet = '81 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + dump(mask(message, '34 83 a8 68')); + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal(message, data); + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotData); + }, + 'can parse a really long masked text message': function() { + var p = new Parser(); + var message = 'A'; + for (var i = 0; i < 64*1024; ++i) message += (i % 5).toString(); + var packet = '81 FF ' + pack(16, message.length) + ' 34 83 a8 68 ' + dump(mask(message, '34 83 a8 68')); + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal(message, data); + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotData); + }, + 'can parse a fragmented masked text message of 300 bytes': function() { + var p = new Parser(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + var msgpiece1 = message.substr(0, 150); + var msgpiece2 = message.substr(150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece1, '34 83 a8 68')); + var packet2 = '81 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal(message, data); + }); + + p.add(makeBufferFromHexString(packet1)); + p.add(makeBufferFromHexString(packet2)); + assert.ok(gotData); + }, + 'can parse a ping message': function() { + var p = new Parser(); + var message = 'Hello'; + var packet = '89 FE ' + pack(4, message.length) + ' 34 83 a8 68 ' + dump(mask(message, '34 83 a8 68')); + + var gotPing = false; + p.on('ping', function(data) { + gotPing = true; + assert.equal(message, data); + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotPing); + }, + 'can parse a ping with no data': function() { + var p = new Parser(); + var packet = '89 00'; + + var gotPing = false; + p.on('ping', function(data) { + gotPing = true; + }); + + p.add(makeBufferFromHexString(packet)); + assert.ok(gotPing); + }, + 'can parse a fragmented masked text message of 300 bytes with a ping in the middle': function() { + var p = new Parser(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + dump(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '81 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal(message, data); + }); + var gotPing = false; + p.on('ping', function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }); + + p.add(makeBufferFromHexString(packet1)); + p.add(makeBufferFromHexString(pingPacket)); + p.add(makeBufferFromHexString(packet2)); + assert.ok(gotData); + assert.ok(gotPing); + }, + 'can parse a fragmented masked text message of 300 bytes with a ping in the middle, which is delievered over sevaral tcp packets': function() { + var p = new Parser(); + var message = 'A'; + for (var i = 0; i < 300; ++i) message += (i % 5).toString(); + + var msgpiece1 = message.substr(0, 150); + var packet1 = '01 FE ' + pack(4, msgpiece1.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece1, '34 83 a8 68')); + + var pingMessage = 'Hello'; + var pingPacket = '89 FE ' + pack(4, pingMessage.length) + ' 34 83 a8 68 ' + dump(mask(pingMessage, '34 83 a8 68')); + + var msgpiece2 = message.substr(150); + var packet2 = '81 FE ' + pack(4, msgpiece2.length) + ' 34 83 a8 68 ' + dump(mask(msgpiece2, '34 83 a8 68')); + + var gotData = false; + p.on('data', function(data) { + gotData = true; + assert.equal(message, data); + }); + var gotPing = false; + p.on('ping', function(data) { + gotPing = true; + assert.equal(pingMessage, data); + }); + + var buffers = []; + buffers = buffers.concat(splitBuffer(makeBufferFromHexString(packet1))); + buffers = buffers.concat(splitBuffer(makeBufferFromHexString(pingPacket))); + buffers = buffers.concat(splitBuffer(makeBufferFromHexString(packet2))); + for (var i = 0; i < buffers.length; ++i) { + p.add(buffers[i]); + } + assert.ok(gotData); + assert.ok(gotPing); + }, +}; + diff --git a/node/node_modules/socket.io/test/transports.websocket.test.js b/node/node_modules/socket.io/test/transports.websocket.test.js new file mode 100644 index 0000000..4b9ff61 --- /dev/null +++ b/node/node_modules/socket.io/test/transports.websocket.test.js @@ -0,0 +1,1771 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Test dependencies. + */ + +var sio = require('socket.io') + , should = require('./common') + , parser = sio.parser + , ports = 15800; + +/** + * Tests. + */ + +module.exports = { + + 'test that not responding to a heartbeat drops client': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , ws; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + beat.should.be.true; + reason.should.eql('heartbeat timeout'); + + cl.end(); + ws.finishClose(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (packet) { + if (++messages == 1) { + packet.type.should.eql('connect'); + } else { + packet.type.should.eql('heartbeat'); + beat = true; + } + }); + }); + }, + + 'test that responding to a heartbeat maintains session': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , heartbeats = 0 + , ws; + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function (reason) { + heartbeats.should.eql(2); + reason.should.eql('heartbeat timeout'); + + cl.end(); + ws.finishClose(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (packet) { + if (++messages == 1) { + packet.type.should.eql('connect'); + } else { + packet.type.should.eql('heartbeat'); + heartbeats++; + + if (heartbeats == 1) { + ws.packet({ type: 'heartbeat' }); + } + } + }); + }); + }, + + 'test sending undeliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + msg.type.should.eql('connect'); + ws.finishClose(); + + setTimeout(function () { + s.volatile.send('ah wha wha'); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending undeliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function () { + ws.finishClose(); + + setTimeout(function () { + s.volatile.json.send({ a: 'b' }); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending undeliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , s; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + messaged.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function () { + ws.finishClose(); + + setTimeout(function () { + s.volatile.emit({ a: 'b' }); + + ws = websocket(cl, sid); + ws.on('message', function () { + messaged = true; + }); + + setTimeout(function () { + ws.finishClose(); + }, 10); + }, 10); + }); + }); + }, + + 'test sending deliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.send('tobi'); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (++messages == 1) { + msg.type.should.eql('connect'); + } else { + msg.should.eql({ + type: 'message' + , data: 'tobi' + , endpoint: '' + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending deliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.json.send([1, 2, 3]); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending deliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.volatile.emit('tobi'); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + var ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , endpoint: '' + , args: [] + }); + messaged = true; + ws.finishClose(); + } + }); + }); + }, + + 'test sending to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.send('yup'); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'yup' + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'yup' + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test sending json to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.json.send({ a: 'b' }); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { a: 'b' } + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { a: 'b' } + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test emitting to all clients in a namespace': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 2) { + io.sockets.emit('tobi', 'rapture'); + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 2) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , args: ['rapture'] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'tobi' + , args: ['rapture'] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + }, + + 'test sending to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').send('hahaha'); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'hahaha' + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test sending json to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').json.send(123); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: 123 + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test emitting to all clients in a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , joins = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections != 3) { + socket.join('woot'); + joins++; + + if (joins == 2) { + setTimeout(function () { + connections.should.eql(3); + io.sockets.in('woot').emit('locki'); + }, 20); + } + } + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws1.finishClose(); + }, 50); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws2.finishClose(); + }, 50); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'locki' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + }, + + 'test leaving a room': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , joins = 0 + , disconnects = 0; + + io.set('close timeout', 0); + + io.sockets.on('connection', function (socket) { + socket.join('foo'); + io.sockets.clients('foo').should.have.length(++joins); + + socket.on('disconnect', function () { + socket.leave('foo'); + socket.leave('foo'); + socket.leave('foo'); + + io.sockets.clients('foo').should.have.length(--joins); + + if (++disconnects == 2) { + io.server.close(); + cl1.end(); + cl2.end(); + done(); + } + }) + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + ws2.finishClose(); + } + }); + }); + }, + + 'test message with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.send('boom'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test json with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.json.send([1, 2, 3]); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: [1, 2, 3] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test event with broadcast flag': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + socket.on('trigger broadcast', function () { + socket.broadcast.emit('hey', 'arnold'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(2); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'hey' + , args: ['arnold'] + , endpoint: '' + }); + + messages++; + ws1.finishClose(); + } + }); + }); + + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'hey' + , args: ['arnold'] + , endpoint: '' + }); + + messages++; + ws2.finishClose(); + } + }); + }); + + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }, + + 'test message with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.to('losers').send('boom'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'message' + , data: 'boom' + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + } + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test json with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.json.to('losers').send({ hello: 'world' }); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'json' + , data: { hello: 'world' } + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + } + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test event with broadcast flag and to()': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , cl3 = client(port) + , io = create(cl1) + , messages = 0 + , connections = 0 + , disconnections = 0; + + io.configure(function () { + io.set('close timeout', 0); + }); + + io.sockets.on('connection', function (socket) { + connections++; + + if (connections == 1) { + socket.join('losers'); + } + + socket.on('trigger broadcast', function () { + socket.broadcast.to('losers').emit('victory'); + }); + + socket.on('disconnect', function () { + disconnections++; + + if (disconnections == 3) { + messages.should.eql(1); + cl1.end(); + cl2.end(); + cl3.end(); + io.server.close(); + done(); + } + }); + }); + + cl1.handshake(function (sid) { + var ws1 = websocket(cl1, sid); + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + } else { + msg.should.eql({ + type: 'event' + , name: 'victory' + , args: [] + , endpoint: '' + }); + + messages++; + } + }); + + ws1.on('open', function () { + cl2.handshake(function (sid) { + var ws2 = websocket(cl2, sid); + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + } else { + throw new Error('This socket shouldnt get a message'); + }; + }); + + ws2.on('open', function () { + cl3.handshake(function (sid) { + var ws3 = websocket(cl3, sid); + ws3.on('open', function () { + ws3.packet({ + type: 'event' + , name: 'trigger broadcast' + , endpoint: '' + }); + + setTimeout(function () { + ws1.finishClose(); + ws2.finishClose(); + ws3.finishClose(); + }, 50); + }); + + ws3.on('message', function (msg) { + if (!ws3.connected) { + msg.type.should.eql('connect'); + ws3.connected = true; + } else { + throw new Error('we shouldnt get a message here'); + } + }); + }); + }); + }); + }); + }); + }, + + 'test accessing handshake data from sockets': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + (!!socket.handshake.address.address).should.be.true; + (!!socket.handshake.address.port).should.be.true; + socket.handshake.headers.host.should.equal('localhost'); + socket.handshake.headers.connection.should.equal('keep-alive'); + socket.handshake.time.should.match(/GMT/); + + socket.on('disconnect', function () { + setTimeout(function () { + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + + 'test accessing the array of clients': function (done) { + var port = ++ports + , cl1 = client(port) + , cl2 = client(port) + , io = create(cl1) + , total = 2 + , ws1, ws2; + + io.sockets.on('connection', function (socket) { + socket.on('join ferrets', function () { + socket.join('ferrets'); + socket.send('done'); + }); + }); + + function check() { + io.sockets.clients('ferrets').should.have.length(1); + io.sockets.clients('ferrets')[0].should.be.an.instanceof(sio.Socket); + io.sockets.clients('ferrets')[0].id.should.equal(ws1.sid); + io.sockets.clients().should.have.length(2); + io.sockets.clients()[0].should.be.an.instanceof(sio.Socket); + io.sockets.clients()[0].id.should.equal(ws1.sid); + io.sockets.clients()[1].should.be.an.instanceof(sio.Socket); + io.sockets.clients()[1].id.should.equal(ws2.sid); + + ws1.finishClose(); + ws2.finishClose(); + cl1.end(); + cl2.end(); + io.server.close(); + done(); + }; + + cl1.handshake(function (sid) { + ws1 = websocket(cl1, sid); + ws1.sid = sid; + ws1.on('message', function (msg) { + if (!ws1.connected) { + msg.type.should.eql('connect'); + ws1.connected = true; + ws1.packet({ + type: 'event' + , name: 'join ferrets' + , endpoint: '' + }); + } else { + cl2.handshake(function (sid) { + ws2 = websocket(cl2, sid); + ws2.sid = sid; + ws2.on('message', function (msg) { + if (!ws2.connected) { + msg.type.should.eql('connect'); + ws2.connected = true; + check(); + } + }); + }); + } + }); + }); + }, + + 'test accessing handshake data from sockets on disconnect': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + + (!!socket.handshake.address.address).should.be.true; + (!!socket.handshake.address.port).should.be.true; + socket.handshake.headers.host.should.equal('localhost'); + socket.handshake.headers.connection.should.equal('keep-alive'); + socket.handshake.time.should.match(/GMT/); + + setTimeout(function () { + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + + 'test for intentional and unintentional disconnects': function (done) { + var cl = client(++ports) + , io = create(cl) + , calls = 0 + , ws; + + function close () { + cl.end(); + io.server.close(); + ws.finishClose(); + done(); + } + + io.configure(function () { + io.set('heartbeat interval', .05); + io.set('heartbeat timeout', .05); + io.set('close timeout', 0); + }); + + io.of('/foo').on('connection', function (socket) { + socket.on('disconnect', function (reason) { + reason.should.equal('packet'); + + if (++calls == 2) close(); + }); + }); + + io.of('/bar').on('connection', function (socket) { + socket.on('disconnect', function (reason) { + reason.should.equal('socket end'); + + if (++calls == 2) close(); + }); + }); + + cl.handshake(function (sid) { + var messages = 0; + ws = websocket(cl, sid); + ws.on('open', function () { + ws.packet({ + type: 'connect' + , endpoint: '/foo' + }); + ws.packet({ + type: 'connect' + , endpoint: '/bar' + }); + }); + + ws.on('message', function (packet) { + if (packet.type == 'connect') { + if (++messages === 3) { + ws.packet({ type: 'disconnect', endpoint:'/foo' }); + ws.finishClose(); + } + } + }); + }); + }, + + 'test socket clean up': function (done) { + var cl = client(++ports) + , io = create(cl) + , ws; + + io.sockets.on('connection', function (socket) { + var self = this + , id = socket.id; + + socket.on('disconnect', function () { + setTimeout(function () { + var available = !!self.sockets[id]; + + available.should.be.false; + ws.finishClose(); + cl.end(); + io.server.close(); + done(); + }, 10); + }); + + socket.disconnect(); + }); + + cl.handshake(function (sid) { + ws = websocket(cl, sid); + ws.on('message', function (msg) { + if (!ws.connected) { + msg.type.should.eql('connect'); + ws.connected = true; + } + }); + }); + }, + +}; diff --git a/node/node_modules/socket.io/test/transports.xhr-polling.test.js b/node/node_modules/socket.io/test/transports.xhr-polling.test.js new file mode 100644 index 0000000..fb039ab --- /dev/null +++ b/node/node_modules/socket.io/test/transports.xhr-polling.test.js @@ -0,0 +1,2754 @@ + +/*! + * socket.io-node + * Copyright(c) 2011 LearnBoost + * MIT Licensed + */ + +/** + * Test dependencies. + */ + +var sio = require('socket.io') + , should = require('./common') + , HTTPClient = should.HTTPClient + , parser = sio.parser + , ports = 15200; + +/** + * HTTPClient for xhr-polling transport. + */ + +function XHRPolling (port) { + HTTPClient.call(this, port); +}; + +/** + * Inhertis from HTTPClient. + */ + +XHRPolling.prototype.__proto__ = HTTPClient.prototype; + +/** + * Performs the handshake and expects the connect echo packet. + * + * @api public + */ + +XHRPolling.prototype.handshake = function (opts, fn) { + if ('function' == typeof opts) { + fn = opts; + opts = {}; + } + + var self = this; + + return this.get('/socket.io/{protocol}', opts, function (res, data) { + var parts = data.split(':'); + + if (opts.ignoreConnect) { + return fn && fn.apply(null, parts); + } + + // expect connect packet right after handshake + self.get( + '/socket.io/{protocol}/xhr-polling/' + parts[0] + , function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'connect', endpoint: '', qs: '' }); + + fn && fn.apply(null, parts); + } + ); + }); +}; + +/** + * Create client for this transport. + * + * @api public + */ + +function client (port) { + return new XHRPolling(port); +}; + +/** + * Test. + */ + +module.exports = { + + 'test handshake': function (done) { + var cl = client(++ports) + , io = create(cl); + + io.configure(function () { + io.set('close timeout', .05); + io.set('polling duration', 0); + }); + + function finish () { + cl.end(); + io.server.close(); + done(); + }; + + cl.handshake(function (sid) { + var total = 2; + + cl.get('/socket.io/{protocol}/xhr-polling/tobi', function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'error' + , reason: 'client not handshaken' + , endpoint: '' + , advice: 'reconnect' + }); + + --total || finish(); + }); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + --total || finish(); + }); + }); + }, + + 'test the connection event': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.id.should.eql(sid); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test the disconnection event after a close timeout': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.id.should.eql(sid); + + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + + setTimeout(function () { + cl.end(); + }, 10); + }); + }); + }, + + 'test the disconnection event when the client sends ?disconnect req': + function (done) { + var cl = client(++ports) + , io = create(cl) + , disconnected = false + , sid; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + disconnected = true; + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'disconnect', endpoint: '' }); + disconnected.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid + '/?disconnect'); + }); + }); + }, + + 'test the disconnection event booting a client': function (done) { + var cl = client(++ports) + , io = create(cl) + , forced = false; + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + io.server.close(); + done(); + }); + + cl.end(); + socket.disconnect(); + forced = true; + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'disconnect', endpoint: '' }); + + forced.should.be.true; + }); + }); + }, + + 'test the disconnection event with client disconnect packet': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.sockets.on('connection', function (client) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'disconnect' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + client.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test sending back data': function (done) { + var cl = client(++ports) + , io = create(cl); + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.send('woot'); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, packs) { + packs.should.have.length(1); + packs[0].type.should.eql('message'); + packs[0].data.should.eql('woot'); + }); + }); + }, + + 'test sending a batch of messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , sid; + + io.configure(function () { + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + var messages = 0; + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePayload([ + parser.encodePacket({ type: 'message', data: 'a' }) + , parser.encodePacket({ type: 'message', data: 'b' }) + , parser.encodePacket({ type: 'disconnect' }) + ]) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + socket.on('message', function (data) { + messages++; + + if (messages == 1) + data.should.eql('a'); + + if (messages == 2) + data.should.eql('b'); + }); + + socket.on('disconnect', function () { + messages.should.eql(2); + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake({ ignoreConnect: true }, function (sessid) { + sid = sessid; + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].type.should.eql('connect'); + }); + }); + }, + + 'test message buffering between a response and a request': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = false + , tobi; + + io.configure(function () { + io.set('polling duration', .1); + io.set('close timeout', .2); + }); + + io.sockets.on('connection', function (socket) { + tobi = function () { + socket.send('a'); + socket.send('b'); + socket.send('c'); + }; + + socket.on('disconnect', function () { + messages.should.be.true; + + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + tobi(); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + msgs.should.have.length(3); + msgs[0].should.eql({ type: 'message', endpoint: '', data: 'a' }); + msgs[1].should.eql({ type: 'message', endpoint: '', data: 'b' }); + msgs[2].should.eql({ type: 'message', endpoint: '', data: 'c' }); + messages = true; + }); + }) + }); + }, + + 'test connecting to a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , connectMessage = false + , sid; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/woot').on('connection', function (socket) { + connectMessage.should.be.true; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid); + + connectMessage = true; + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }); + }, + + 'test that connecting doesnt connect to defined endpoints': function (done) { + var cl = client(++ports) + , io = create(cl) + , tobiConnected = false + , mainConnected = false + , sid; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + mainConnected = true; + + socket.on('disconnect', function () { + tobiConnected.should.be.false; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/tobi').on('connection', function () { + tobiConnected = true; + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid); + }); + }, + + 'test disconnecting a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , wootDisconnected = false + , mainDisconnected = false + , checked = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (data) { + data.should.eql('ferret'); + mainDisconnected.should.be.false; + wootDisconnected.should.be.true; + checked = true; + }); + + socket.on('disconnect', function () { + mainDisconnected = true; + checked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/woot').on('connection', function (socket) { + socket.on('disconnect', function () { + wootDisconnected = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function () { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'disconnect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'message', data: 'ferret' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + } + ); + }); + }); + }, + + 'test that disconnecting disconnects all endpoints': function (done) { + var cl = client(++ports) + , io = create(cl) + , aDisconnected = false + , bDisconnected = false; + + io.configure(function () { + io.set('polling duration', .2); + io.set('close timeout', .2); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + setTimeout(function () { + aDisconnected.should.be.true; + bDisconnected.should.be.true; + cl.end(); + io.server.close(); + done(); + }, 50); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('disconnect', function (msg) { + aDisconnected = true; + }); + }); + + io.of('/b').on('connection', function (socket) { + socket.on('disconnect', function (msg) { + bDisconnected = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }); + }, + + 'test messaging a specific endpoint': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = true + , aMessaged = false + , bMessaged = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql(''); + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.true; + aMessaged.should.be.true; + bMessaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('a'); + aMessaged = true; + }); + }); + + io.of('/b').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('b'); + bMessaged = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'message', data: '' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'message', endpoint: '/a', data: 'a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'message', endpoint: '/b', data: 'b' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + }); + }); + }, + + 'test sending json from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0 + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.json.send(['a', 'b', 'c']); + s.json.send({ + a: 'b' + , c: 'd' + }); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'json' + , data: ['a', 'b', 'c'] + , endpoint: '' + }); + msgs[1].should.eql({ + type: 'json' + , data: { + a: 'b' + , c: 'd' + } + , endpoint: '' + }); + }); + }) + }); + }, + + 'test sending json to the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messages = 0; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .1); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + messages++; + + if (messages == 1) { + msg.should.eql({ tobi: 'rocks' }); + } else if (messages == 2) { + msg.should.eql(5000); + } + }); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'json' + , data: { tobi: 'rocks' } + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.equal('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'json' + , data: 5000 + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.equal('1'); + } + ); + } + ); + }); + }); + }, + + 'test emitting an event from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.emit('tobi is playing'); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'tobi is playing' + , endpoint: '' + , args: [] + }); + }); + }); + }); + }, + + 'test emitting an event with data from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.emit('edwald', { woot: 'woot' }, [1, 2, 3]); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'edwald' + , endpoint: '' + , args: [{ woot: 'woot' }, [1, 2, 3]] + }); + }); + }); + }); + }, + + 'test emitting an event to the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('jane', function (a, b, c) { + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , name: 'jane' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.equal('1'); + } + ); + }); + }); + }, + + 'test that emitting an error event doesnt throw': function (done) { + var cl = client(++ports) + , io = create(cl) + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , name: 'error' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.equal('1'); + } + ); + }); + }); + }, + + 'test emitting an event to the server with data': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('woot', function (a, b, c) { + a.should.eql('a'); + b.should.eql(2); + c.should.eql([1, 2]); + + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , name: 'woot' + , args: ['a', 2, [1, 2]] + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.equal('1'); + } + ); + }); + }); + }, + + 'test sending undeliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.volatile.send('woooot'); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + }); + }); + }); + }, + + 'test sending undeliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.volatile.json.send('woooot'); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + }); + }); + }); + }, + + 'test sending undeliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + s.volatile.emit('woooot'); + + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + }); + }); + }); + }, + + 'test sending deliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'message' + , data: 'woooot' + , endpoint: '' + }); + }); + + setTimeout(function () { + s.volatile.send('woooot'); + }, 10); + }); + }, + + 'test sending deliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'json' + , data: 5 + , endpoint: '' + }); + }); + + setTimeout(function () { + s.volatile.json.send(5); + }, 10); + }); + }, + + 'test sending deliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'tobi' + , args: [] + , endpoint: '' + }); + }); + + setTimeout(function () { + s.volatile.json.emit('tobi'); + }, 10); + }); + }, + + 'test automatic acknowledgements sent from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('woot'); + received = true; + }); + + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'message' + , data: 'woot' + , id: 1 + , endpoint: '' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'ack' + , ackId: 1 + , endpoint: '' + , args: [] + }); + } + ); + } + ); + }); + + }); + }, + + 'test manual data acknowledgement sent from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , acknowledged = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (data, fn) { + data.should.eql('tobi'); + fn('woot'); + acknowledged = true; + }); + + socket.on('disconnect', function () { + acknowledged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'ack' + , args: ['woot'] + , endpoint: '' + , ackId: '3' + }); + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'message' + , data: 'tobi' + , ack: 'data' + , id: '3' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }, + + 'test automatic acknowledgements sent from the client': function (done) { + var cl = client(++ports) + , io = create(cl) + , acknowledged = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.send('aaaa', function () { + acknowledged = true; + }); + + socket.on('disconnect', function () { + acknowledged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'message' + , id: '1' + , data: 'aaaa' + , ack: true + , endpoint: '' + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'ack' + , ackId: '1' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + }); + }); + }, + + 'test automatic ack with event sent from the client': function (done) { + var cl = client(++ports) + , io = create(cl) + , acked = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.emit('woot', 1, 2, '3', function () { + acked = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'woot' + , args: [1, 2, '3'] + , id: '1' + , ack: true + , endpoint: '' + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'ack' + , ackId: '1' + , args: [] + , endpoint: '' + }) + ); + }); + }); + }, + + 'test manual data ack with event sent from the client': function (done) { + var cl = client(++ports) + , io = create(cl) + , acked = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.emit('woot', 1, 2, '3', function (a) { + a.should.eql('1'); + acked = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'woot' + , args: [1, 2, '3'] + , id: '1' + , ack: 'data' + , endpoint: '' + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'ack' + , ackId: '1' + , args: ['1'] + , endpoint: '' + }) + ); + }); + }); + }, + + 'test endpoint sending json from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false;; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/chrislee').on('connection', function (socket) { + socket.json.send([1, 2, { 3: 4 }]); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + msgs[1].should.eql({ + type: 'json' + , data: [1, 2, { 3: 4 }] + , endpoint: '/chrislee' + }); + + received = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending json to the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , subMessaged = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.false; + subMessaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql(['a', 'b', { c: 'd' }]); + subMessaged = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'json' + , endpoint: '/a' + , data: ['a', 'b', { c: 'd' }] + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + }); + }); + }, + + 'test endpoint emitting an event from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false;; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/chrislee').on('connection', function (socket) { + socket.emit('tj'); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + msgs[1].should.eql({ + type: 'event' + , name: 'tj' + , args: [] + , endpoint: '/chrislee' + }); + + received = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint emitting an event with data from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false;; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/chrislee').on('connection', function (socket) { + socket.emit('tj', 1, 2, 3, 4); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + msgs[1].should.eql({ + type: 'event' + , name: 'tj' + , args: [1, 2, 3, 4] + , endpoint: '/chrislee' + }); + + received = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint emitting an event to the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , subMessaged = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.false; + subMessaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('tj', function () { + subMessaged = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , name: 'tj' + , endpoint: '/a' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + }); + }); + }, + + 'test endpoint emitting an event to the server with data': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , subMessaged = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.on('message', function (msg) { + messaged = true; + }); + + socket.on('disconnect', function () { + messaged.should.be.false; + subMessaged.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + io.of('/a').on('connection', function (socket) { + socket.on('tj', function (ferret, age) { + ferret.should.eql('tobi'); + age.should.eql(23); + subMessaged = true; + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/a' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , name: 'tj' + , endpoint: '/a' + , args: ['tobi', 23] + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending undeliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , empty = false + , s; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + empty.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + s.volatile.send('woot'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.length.should.eql(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + empty = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending undeliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , empty = false + , s; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + empty.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + s.volatile.json.send(15); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.length.should.eql(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + empty = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending undeliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , empty = false + , s; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + empty.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + s.volatile.json.emit('woot'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.length.should.eql(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + empty = true; + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending deliverable volatile messages': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'message' + , data: 'edwald' + , endpoint: '/chrislee' + }); + + received = true; + } + ); + + setTimeout(function () { + s.volatile.send('edwald'); + }, 20); + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending deliverable volatile json': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'json' + , data: 152 + , endpoint: '/chrislee' + }); + + received = true; + } + ); + + setTimeout(function () { + s.volatile.json.send(152); + }, 20); + } + ); + } + ); + }); + }); + }, + + 'test endpoint sending deliverable volatile events': function (done) { + var cl = client(++ports) + , io = create(cl) + , received = false + , s; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.of('/chrislee').on('connection', function (socket) { + s = socket; + + socket.on('disconnect', function () { + received.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/chrislee' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/chrislee' + , qs: '' + }); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + msgs.should.have.length(1); + msgs[0].should.eql({ + type: 'event' + , name: 'woooo' + , args: [[1, 2]] + , endpoint: '/chrislee' + }); + + received = true; + } + ); + + setTimeout(function () { + s.volatile.emit('woooo', [1, 2]); + }, 20); + } + ); + } + ); + }); + }); + }, + + 'test endpoint automatic acks sent from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , acked = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/tobi').on('connection', function (socket) { + socket.on('message', function (msg) { + msg.should.eql('woot'); + messaged = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/tobi' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'message' + , id: '3' + , data: 'woot' + , endpoint: '/tobi' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/tobi' + , qs: '' + }); + msgs[1].should.eql({ + type: 'ack' + , ackId: '3' + , endpoint: '/tobi' + , args: [] + }); + + acked = true; + } + ); + } + ); + } + ); + }); + }); + }, + + 'test endpoint manual data ack sent from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , acked = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/tobi').on('connection', function (socket) { + socket.on('message', function (msg, fn) { + msg.should.eql('woot'); + fn(); + messaged = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/tobi' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'message' + , id: '3' + , data: 'woot' + , ack: 'data' + , endpoint: '/tobi' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/tobi' + , qs: '' + }); + msgs[1].should.eql({ + type: 'ack' + , ackId: '3' + , args: [] + , endpoint: '/tobi' + }); + + acked = true; + } + ); + } + ); + } + ); + }); + }); + }, + + 'test endpoint manual data event ack sent from the server': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false + , acked = false; + + io.configure(function () { + io.set('polling duration', 0); + io.set('close timeout', .05); + }); + + io.of('/tobi').on('connection', function (socket) { + socket.on('woot', function (msg, fn) { + msg.should.eql(1); + fn('aaaa'); + messaged = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, data) { + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/tobi' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'event' + , id: '3' + , name: 'woot' + , ack: 'data' + , args: [1] + , endpoint: '/tobi' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/tobi' + , qs: '' + }); + msgs[1].should.eql({ + type: 'ack' + , ackId: '3' + , args: ['aaaa'] + , endpoint: '/tobi' + }); + + acked = true; + } + ); + } + ); + } + ); + }); + }); + }, + + 'test endpoint acknowledgements sent from the client': function (done) { + var cl = client(++ports) + , io = create(cl) + , acked = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.of('/woot').on('connection', function (socket) { + socket.send('aaa', function () { + acked = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.eql(200); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/woot' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/woot' + , qs: '' + }); + msgs[1].should.eql({ + type: 'message' + , data: 'aaa' + , endpoint: '/woot' + , id: '1' + , ack: true + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'ack' + , ackId: '1' + , endpoint: '/woot' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + } + ); + }); + }); + }, + + 'test endpoint manual data event acks sent from the client': function (done) { + var cl = client(++ports) + , io = create(cl) + , acked = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.of('/rapture').on('connection', function (socket) { + socket.emit('woot', 'a', function (a, b, c) { + a.should.eql(5); + b.should.eql('hello'); + c.should.eql([1, 2, 3]); + + acked = true; + }); + + socket.on('disconnect', function () { + acked.should.be.true; + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, msgs) { + res.statusCode.should.equal(200); + msgs.should.have.length(1); + msgs[0].should.eql({ type: 'noop', endpoint: '' }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ type: 'connect', endpoint: '/rapture' }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, msgs) { + res.statusCode.should.eql(200); + msgs.should.have.length(2); + msgs[0].should.eql({ + type: 'connect' + , endpoint: '/rapture' + , qs: '' + }); + msgs[1].should.eql({ + type: 'event' + , id: '1' + , name: 'woot' + , args: ['a'] + , ack: 'data' + , endpoint: '/rapture' + }); + + cl.post( + '/socket.io/{protocol}/xhr-polling/' + sid + , parser.encodePacket({ + type: 'ack' + , ackId: '1' + , args: [5, 'hello', [1, 2, 3]] + , endpoint: '/rapture' + }) + , function (res, data) { + res.statusCode.should.eql(200); + data.should.eql('1'); + } + ); + } + ); + } + ); + }); + }); + }, + + 'test CORS': function (done) { + var cl = client(++ports) + , io = create(cl) + , messaged = false; + + io.configure(function () { + io.set('polling duration', .05); + io.set('close timeout', .05); + }); + + io.sockets.on('connection', function (socket) { + socket.send('woot'); + + socket.on('message', function (msg) { + msg.should.equal('woot'); + messaged = true; + }); + + socket.on('disconnect', function () { + cl.end(); + io.server.close(); + done(); + }); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, { + headers: { + Origin: 'http://localhost:3500' + } + }, function (res, packs) { + var headers = res.headers; + + headers['access-control-allow-origin'].should.equal('*'); + should.strictEqual(headers['access-control-allow-credentials'], undefined); + + packs.should.have.length(1); + packs[0].type.should.eql('message'); + packs[0].data.should.eql('woot'); + + cl.post('/socket.io/{protocol}/xhr-polling/' + sid, parser.encodePacket({ + type: 'message' + , data: 'woot' + }), { + headers: { + Origin: 'http://localhost:3500' + , Cookie: 'woot=woot' + } + }, function (res, data) { + var headers = res.headers; + headers['access-control-allow-origin'].should.equal('*'); + headers['access-control-allow-credentials'].should.equal('true'); + + data.should.equal('1'); + }); + }); + }); + }, + + 'test emitting to closed clients': function (done) { + var cl = client(++ports) + , cl2 = client(ports) + , io = create(cl) + , connections = 0; + + io.configure(function () { + io.set('close timeout', .1); + }); + + io.sockets.on('connection', function (socket) { + socket.send('a'); + }); + + cl.handshake(function (sid) { + cl.get('/socket.io/{protocol}/xhr-polling/' + sid, function (res, packs) { + res.statusCode.should.equal(200); + packs.should.have.length(1); + packs[0].should.eql({ type: 'message', endpoint: '', data: 'a' }); + + cl2.handshake(function (sid2) { + cl2.get( + '/socket.io/{protocol}/xhr-polling/' + sid2 + , function (res, packs) { + res.statusCode.should.equal(200); + packs.should.have.length(1); + packs[0].should.eql({ type: 'message', endpoint: '', data: 'a' }); + + io.sockets.emit('woot', 'b'); + + var total = 2; + + cl.get( + '/socket.io/{protocol}/xhr-polling/' + sid + , function (res, packs) { + res.statusCode.should.equal(200); + packs.should.have.length(1); + packs[0].should.eql({ + type: 'event' + , endpoint: '' + , name: 'woot' + , args: ['b'] + }); + + --total || finish(); + } + ); + + cl2.get( + '/socket.io/{protocol}/xhr-polling/' + sid2 + , function (res, packs) { + res.statusCode.should.equal(200); + packs.should.have.length(1); + packs[0].should.eql({ + type: 'event' + , endpoint: '' + , name: 'woot' + , args: ['b'] + }); + + --total || finish(); + } + ); + + function finish () { + cl.end(); + cl2.end(); + io.server.close(); + done(); + }; + } + ); + }); + + }); + }); + } + +}; diff --git a/node/node_modules/uglify-js/README.html b/node/node_modules/uglify-js/README.html index 8bc5da6..bd69e63 100644 --- a/node/node_modules/uglify-js/README.html +++ b/node/node_modules/uglify-js/README.html @@ -7,7 +7,7 @@ lang="en" xml:lang="en"> UglifyJS -- a JavaScript parser/compressor/beautifier - + @@ -85,6 +85,7 @@ lang="en" xml:lang="en">
  • 1.1 Unsafe transformations
  • 1.2 Install (NPM)
  • @@ -224,16 +225,9 @@ function/variable declarations).

    -UglifyJS tries its best to achieve great compression while leaving the -semantics of the code intact. In general, if your code logic is broken by -UglifyJS then it's a bug in UglifyJS and you should report it and I should -fix it. :-) -

    -

    -However, I opted to include the following potentially unsafe transformations -as default behavior. Discussion is welcome, if you have ideas of how to -handle this better, or any objections to these optimizations, please let me -know. +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.

    @@ -249,10 +243,10 @@ The following transformations occur: -
    new Array(1, 2, 3, 4)  => [1,2,3,4]
    +
    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)
    +new Array(5)           => Array(5)
    +new Array(a)           => Array(a)
     
    @@ -270,42 +264,51 @@ following cases UglifyJS doesn't touch calls or instantiations of Array: -
    // case 1.  globally declared variable
    -  var Array;
    -  new Array(1, 2, 3);
    +
    // 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 declared later)
    +  new Array(1, 2, 3);
    +  var Array;
     
    -  // or (can be a function)
    -  new Array(1, 2, 3);
    -  function 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);
    +// case 2.  declared in a function
    +  (function(){
    +    a = new Array(1, 2, 3);
         b = Array(5, 6);
    -    var Array;
    +    var Array;
       })();
     
    -  // or
    -  (function(Array){
    -    return Array(5, 6, 7);
    +  // or
    +  (function(Array){
    +    return Array(5, 6, 7);
       })();
     
    -  // or
    -  (function(){
    -    return new Array(1, 2, 3, 4);
    -    function Array() { ... }
    +  // or
    +  (function(){
    +    return new Array(1, 2, 3, 4);
    +    function Array() { ... }
       })();
     
    -  // etc.
    +  // etc.
     
    + + + + +
    +

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

    +
    + +
    @@ -332,21 +335,21 @@ the job. -
    ## clone the repository
    +
    ## clone the repository
     mkdir -p /where/you/wanna/put/it
    -cd /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
    +## make the module available to Node
     mkdir -p ~/.node_libraries/
    -cd ~/.node_libraries/
    +cd ~/.node_libraries/
     ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
     
    -## and if you want the CLI script too:
    +## and if you want the CLI script too:
     mkdir -p ~/bin
    -cd ~/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)
    +  # (then add ~/bin to your $PATH if it's not there already)
     
    @@ -461,12 +464,6 @@ internals. -v or --verbose — output some notes on STDERR (for now just how long each operation takes). - -
  • ---extra — enable additional optimizations that have not yet been -extensively tested. These might, or might not, break your code. If you -find a bug using this option, please report a test case. -
  • --unsafe — enable other additional optimizations that are known to be @@ -498,6 +495,30 @@ 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. +
    • +
  • @@ -517,14 +538,14 @@ NodeJS): -
    var jsp = require("uglify-js").parser;
    -var pro = require("uglify-js").uglify;
    +
    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
    +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
     
    @@ -549,6 +570,68 @@ 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: @@ -654,63 +737,30 @@ the processing stages.

      -(XXX: this is somewhat outdated. On the jQuery source code we beat Closure -by 168 bytes (560 after gzip) and by many seconds.) -

      -

      -There are a few popular JS minifiers nowadays – the two most well known -being the GoogleClosure (GCL) compiler and the YUI compressor. For some -reason they are both written in Java. I didn't really hope to beat any of -them, but finally I did – UglifyJS compresses better than the YUI -compressor, and safer than GoogleClosure. -

      -

      -I tested it on two big libraries. DynarchLIB is my own, and it's big enough -to contain probably all the JavaScript tricks known to mankind. jQuery is -definitely the most popular JavaScript library (to some people, it's a -synonym to JavaScript itself). -

      -

      -I cannot swear that there are no bugs in the generated codes, but they -appear to work fine. +Here are updated statistics. (I also updated my Google Closure and YUI +installations).

      -Compression results: +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.

      -+ - + - - + + + +
      LibraryOrig. sizeUglifyJSYUIGCL
      FileUglifyJSUglifyJS+gzipClosureClosure+gzipYUIYUI+gzip
      DynarchLIB636896241441246452 (+5011)240439 (-1002) (buggy)
      jQuery1638557200679702 (+7696)71858 (-148)
      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
      -

      -UglifyJS is the fastest to run. On my laptop UglifyJS takes 1.35s for -DynarchLIB, while YUI takes 2.7s and GCL takes 6.5s. -

      -

      -GoogleClosure does a lot of smart ass optimizations. I had to strive really -hard to get close to it. It should be possible to even beat it, but then -again, GCL has a gazillion lines of code and runs terribly slow, so I'm not -sure it worths spending the effort to save a few bytes. Also, GCL doesn't -cope with eval() or with{} – it just dumps a warning and proceeds to -mangle names anyway; my DynarchLIB compiled with it is buggy because of -this. -

      -

      -UglifyJS consists of ~1100 lines of code for the tokenizer/parser, and ~1100 -lines for the compressor and code generator. That should make it very -maintainable and easily extensible, so I would say it has a good place in -this field and it's bound to become the de-facto standard JS minifier. And -I shall rule the world. :-) Use it, and spread the word! -

      @@ -748,6 +798,9 @@ I'd love to hear about them (u
      • +Twitter: @UglifyJS +
      • +
      • Project at GitHub: http://github.com/mishoo/UglifyJS
      • @@ -827,7 +880,7 @@ SUCH DAMAGE.

        Author: Mihai Bazon

        -

        Date: 2011-07-14 12:50:31 EEST

        +

        Date: 2011-08-20 10:08:28 EEST

        HTML generated by org-mode 7.01trans in emacs 23

        diff --git a/node/node_modules/uglify-js/README.org b/node/node_modules/uglify-js/README.org index f0ae354..93b1195 100644 --- a/node/node_modules/uglify-js/README.org +++ b/node/node_modules/uglify-js/README.org @@ -72,15 +72,9 @@ manipulates the AST generated by the parser to provide the following: ** <> -UglifyJS tries its best to achieve great compression while leaving the -semantics of the code intact. In general, if your code logic is broken by -UglifyJS then it's a bug in UglifyJS and you should report it and I should -fix it. :-) - -However, I opted to include the following potentially unsafe transformations -as default behavior. Discussion is welcome, if you have ideas of how to -handle this better, or any objections to these optimizations, please let me -know. +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 @@ -136,6 +130,8 @@ following cases UglifyJS *doesn't touch* calls or instantiations of Array: // etc. #+END_SRC +*** =obj.toString()= ==> =obj+“”= + ** Install (NPM) UglifyJS is now available through NPM --- =npm install uglify-js= should do @@ -227,10 +223,6 @@ Supported options: - =-v= or =--verbose= --- output some notes on STDERR (for now just how long each operation takes). -- =--extra= --- enable additional optimizations that have not yet been - extensively tested. These might, or might not, break your code. If you - find a bug using this option, please report a test case. - - =--unsafe= --- enable other additional optimizations that are known to be unsafe in some contrived situations, but could still be generally useful. For now only this: @@ -251,6 +243,16 @@ Supported options: HTML =