holmes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.md +10 -0
  4. data/Rakefile +1 -0
  5. data/holmes.gemspec +24 -0
  6. data/lib/holmes.rb +38 -0
  7. data/lib/holmes/node_modules/detective/README.markdown +64 -0
  8. data/lib/holmes/node_modules/detective/example/strings.js +6 -0
  9. data/lib/holmes/node_modules/detective/example/strings_src.js +3 -0
  10. data/lib/holmes/node_modules/detective/index.js +65 -0
  11. data/lib/holmes/node_modules/detective/node_modules/burrito/.npmignore +1 -0
  12. data/lib/holmes/node_modules/detective/node_modules/burrito/README.markdown +185 -0
  13. data/lib/holmes/node_modules/detective/node_modules/burrito/browserify.js +4296 -0
  14. data/lib/holmes/node_modules/detective/node_modules/burrito/example/microwave.js +7 -0
  15. data/lib/holmes/node_modules/detective/node_modules/burrito/example/web/bs.js +4832 -0
  16. data/lib/holmes/node_modules/detective/node_modules/burrito/example/web/index.html +14 -0
  17. data/lib/holmes/node_modules/detective/node_modules/burrito/example/web/main.js +17 -0
  18. data/lib/holmes/node_modules/detective/node_modules/burrito/example/web/server.js +12 -0
  19. data/lib/holmes/node_modules/detective/node_modules/burrito/example/wrap.js +7 -0
  20. data/lib/holmes/node_modules/detective/node_modules/burrito/index.html +8 -0
  21. data/lib/holmes/node_modules/detective/node_modules/burrito/index.js +208 -0
  22. data/lib/holmes/node_modules/detective/node_modules/burrito/main.js +11 -0
  23. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/.bin/uglifyjs +317 -0
  24. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/.npmignore +1 -0
  25. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/LICENSE +24 -0
  26. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/README.markdown +237 -0
  27. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/examples/json.js +16 -0
  28. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/examples/leaves.js +15 -0
  29. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/examples/negative.js +8 -0
  30. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/examples/scrub.js +10 -0
  31. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/examples/stringify.js +38 -0
  32. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/index.js +267 -0
  33. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/main.js +10 -0
  34. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/package.json +18 -0
  35. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/circular.js +115 -0
  36. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/date.js +35 -0
  37. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/equal.js +220 -0
  38. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/instance.js +17 -0
  39. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/interface.js +42 -0
  40. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/json.js +47 -0
  41. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/keys.js +29 -0
  42. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/leaves.js +21 -0
  43. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/lib/deep_equal.js +92 -0
  44. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/mutability.js +252 -0
  45. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/negative.js +20 -0
  46. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/obj.js +15 -0
  47. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/siblings.js +35 -0
  48. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/stop.js +41 -0
  49. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/stringify.js +36 -0
  50. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/subexpr.js +34 -0
  51. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/traverse/test/super_deep.js +55 -0
  52. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/.npmignore +4 -0
  53. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/README.html +888 -0
  54. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/README.org +463 -0
  55. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/bin/uglifyjs +317 -0
  56. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/docstyle.css +75 -0
  57. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/lib/object-ast.js +75 -0
  58. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/lib/parse-js.js +1341 -0
  59. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/lib/process.js +1949 -0
  60. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/lib/squeeze-more.js +51 -0
  61. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/package.json +22 -0
  62. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/beautify.js +28 -0
  63. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/testparser.js +402 -0
  64. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/array1.js +1 -0
  65. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/array2.js +1 -0
  66. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/array3.js +1 -0
  67. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/array4.js +1 -0
  68. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/assignment.js +1 -0
  69. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/concatstring.js +1 -0
  70. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/const.js +1 -0
  71. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/empty-blocks.js +1 -0
  72. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/forstatement.js +1 -0
  73. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/if.js +1 -0
  74. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/ifreturn.js +1 -0
  75. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/ifreturn2.js +1 -0
  76. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue10.js +1 -0
  77. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue11.js +1 -0
  78. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue13.js +1 -0
  79. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue14.js +1 -0
  80. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue16.js +1 -0
  81. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue17.js +1 -0
  82. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue20.js +1 -0
  83. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue21.js +1 -0
  84. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue25.js +1 -0
  85. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue27.js +1 -0
  86. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue28.js +1 -0
  87. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue29.js +1 -0
  88. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue30.js +1 -0
  89. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue34.js +1 -0
  90. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue4.js +1 -0
  91. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue48.js +1 -0
  92. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue50.js +1 -0
  93. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue53.js +1 -0
  94. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue54.1.js +1 -0
  95. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue68.js +1 -0
  96. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue69.js +1 -0
  97. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/issue9.js +1 -0
  98. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/mangle.js +1 -0
  99. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/strict-equals.js +1 -0
  100. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/var.js +1 -0
  101. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/expected/with.js +1 -0
  102. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/array1.js +3 -0
  103. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/array2.js +4 -0
  104. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/array3.js +4 -0
  105. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/array4.js +6 -0
  106. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/assignment.js +20 -0
  107. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/concatstring.js +3 -0
  108. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/const.js +5 -0
  109. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/empty-blocks.js +4 -0
  110. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/forstatement.js +10 -0
  111. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/if.js +6 -0
  112. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/ifreturn.js +9 -0
  113. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/ifreturn2.js +16 -0
  114. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue10.js +1 -0
  115. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue11.js +3 -0
  116. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue13.js +1 -0
  117. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue14.js +1 -0
  118. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue16.js +1 -0
  119. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue17.js +4 -0
  120. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue20.js +1 -0
  121. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue21.js +6 -0
  122. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue25.js +7 -0
  123. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue27.js +1 -0
  124. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue28.js +3 -0
  125. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue29.js +1 -0
  126. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue30.js +3 -0
  127. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue34.js +3 -0
  128. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue4.js +3 -0
  129. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue48.js +1 -0
  130. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue50.js +9 -0
  131. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue53.js +1 -0
  132. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue54.1.js +3 -0
  133. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue68.js +5 -0
  134. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue69.js +1 -0
  135. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/issue9.js +4 -0
  136. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/mangle.js +5 -0
  137. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/strict-equals.js +3 -0
  138. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/var.js +3 -0
  139. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/compress/test/with.js +2 -0
  140. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/test/unit/scripts.js +55 -0
  141. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/tmp/hoist.js +33 -0
  142. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/tmp/instrument.js +97 -0
  143. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/tmp/instrument2.js +138 -0
  144. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/tmp/test.js +16 -0
  145. data/lib/holmes/node_modules/detective/node_modules/burrito/node_modules/uglify-js/uglify-js.js +17 -0
  146. data/lib/holmes/node_modules/detective/node_modules/burrito/package.json +43 -0
  147. data/lib/holmes/node_modules/detective/node_modules/burrito/server.js +4 -0
  148. data/lib/holmes/node_modules/detective/node_modules/burrito/test/ast.js +29 -0
  149. data/lib/holmes/node_modules/detective/node_modules/burrito/test/err.js +47 -0
  150. data/lib/holmes/node_modules/detective/node_modules/burrito/test/fail.js +8 -0
  151. data/lib/holmes/node_modules/detective/node_modules/burrito/test/fail/src.js +60 -0
  152. data/lib/holmes/node_modules/detective/node_modules/burrito/test/label.js +110 -0
  153. data/lib/holmes/node_modules/detective/node_modules/burrito/test/microwave.js +33 -0
  154. data/lib/holmes/node_modules/detective/node_modules/burrito/test/parent.js +26 -0
  155. data/lib/holmes/node_modules/detective/node_modules/burrito/test/wrap.js +157 -0
  156. data/lib/holmes/node_modules/detective/package.json +39 -0
  157. data/lib/holmes/node_modules/detective/test/both.js +10 -0
  158. data/lib/holmes/node_modules/detective/test/files/both.js +4 -0
  159. data/lib/holmes/node_modules/detective/test/files/nested.js +22 -0
  160. data/lib/holmes/node_modules/detective/test/files/strings.js +13 -0
  161. data/lib/holmes/node_modules/detective/test/files/word.js +13 -0
  162. data/lib/holmes/node_modules/detective/test/nested.js +8 -0
  163. data/lib/holmes/node_modules/detective/test/strings.js +8 -0
  164. data/lib/holmes/node_modules/detective/test/word.js +11 -0
  165. data/lib/holmes/require.js +5 -0
  166. data/lib/holmes/runner.js +20 -0
  167. data/lib/holmes/version.rb +3 -0
  168. metadata +223 -0
@@ -0,0 +1,463 @@
1
+ #+TITLE: UglifyJS -- a JavaScript parser/compressor/beautifier
2
+ #+KEYWORDS: javascript, js, parser, compiler, compressor, mangle, minify, minifier
3
+ #+DESCRIPTION: a JavaScript parser/compressor/beautifier in JavaScript
4
+ #+STYLE: <link rel="stylesheet" type="text/css" href="docstyle.css" />
5
+ #+AUTHOR: Mihai Bazon
6
+ #+EMAIL: mihai.bazon@gmail.com
7
+
8
+ * UglifyJS --- a JavaScript parser/compressor/beautifier
9
+
10
+ This package implements a general-purpose JavaScript
11
+ parser/compressor/beautifier toolkit. It is developed on [[http://nodejs.org/][NodeJS]], but it
12
+ should work on any JavaScript platform supporting the CommonJS module system
13
+ (and if your platform of choice doesn't support CommonJS, you can easily
14
+ implement it, or discard the =exports.*= lines from UglifyJS sources).
15
+
16
+ The tokenizer/parser generates an abstract syntax tree from JS code. You
17
+ can then traverse the AST to learn more about the code, or do various
18
+ manipulations on it. This part is implemented in [[../lib/parse-js.js][parse-js.js]] and it's a
19
+ port to JavaScript of the excellent [[http://marijn.haverbeke.nl/parse-js/][parse-js]] Common Lisp library from [[http://marijn.haverbeke.nl/][Marijn
20
+ Haverbeke]].
21
+
22
+ ( See [[http://github.com/mishoo/cl-uglify-js][cl-uglify-js]] if you're looking for the Common Lisp version of
23
+ UglifyJS. )
24
+
25
+ The second part of this package, implemented in [[../lib/process.js][process.js]], inspects and
26
+ manipulates the AST generated by the parser to provide the following:
27
+
28
+ - ability to re-generate JavaScript code from the AST. Optionally
29
+ indented---you can use this if you want to “beautify” a program that has
30
+ been compressed, so that you can inspect the source. But you can also run
31
+ our code generator to print out an AST without any whitespace, so you
32
+ achieve compression as well.
33
+
34
+ - shorten variable names (usually to single characters). Our mangler will
35
+ analyze the code and generate proper variable names, depending on scope
36
+ and usage, and is smart enough to deal with globals defined elsewhere, or
37
+ with =eval()= calls or =with{}= statements. In short, if =eval()= or
38
+ =with{}= are used in some scope, then all variables in that scope and any
39
+ variables in the parent scopes will remain unmangled, and any references
40
+ to such variables remain unmangled as well.
41
+
42
+ - various small optimizations that may lead to faster code but certainly
43
+ lead to smaller code. Where possible, we do the following:
44
+
45
+ - foo["bar"] ==> foo.bar
46
+
47
+ - remove block brackets ={}=
48
+
49
+ - join consecutive var declarations:
50
+ var a = 10; var b = 20; ==> var a=10,b=20;
51
+
52
+ - resolve simple constant expressions: 1 +2 * 3 ==> 7. We only do the
53
+ replacement if the result occupies less bytes; for example 1/3 would
54
+ translate to 0.333333333333, so in this case we don't replace it.
55
+
56
+ - consecutive statements in blocks are merged into a sequence; in many
57
+ cases, this leaves blocks with a single statement, so then we can remove
58
+ the block brackets.
59
+
60
+ - various optimizations for IF statements:
61
+
62
+ - if (foo) bar(); else baz(); ==> foo?bar():baz();
63
+ - if (!foo) bar(); else baz(); ==> foo?baz():bar();
64
+ - if (foo) bar(); ==> foo&&bar();
65
+ - if (!foo) bar(); ==> foo||bar();
66
+ - if (foo) return bar(); else return baz(); ==> return foo?bar():baz();
67
+ - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}
68
+
69
+ - remove some unreachable code and warn about it (code that follows a
70
+ =return=, =throw=, =break= or =continue= statement, except
71
+ function/variable declarations).
72
+
73
+ ** <<Unsafe transformations>>
74
+
75
+ The following transformations can in theory break code, although they're
76
+ probably safe in most practical cases. To enable them you need to pass the
77
+ =--unsafe= flag.
78
+
79
+ *** Calls involving the global Array constructor
80
+
81
+ The following transformations occur:
82
+
83
+ #+BEGIN_SRC js
84
+ new Array(1, 2, 3, 4) => [1,2,3,4]
85
+ Array(a, b, c) => [a,b,c]
86
+ new Array(5) => Array(5)
87
+ new Array(a) => Array(a)
88
+ #+END_SRC
89
+
90
+ These are all safe if the Array name isn't redefined. JavaScript does allow
91
+ one to globally redefine Array (and pretty much everything, in fact) but I
92
+ personally don't see why would anyone do that.
93
+
94
+ UglifyJS does handle the case where Array is redefined locally, or even
95
+ globally but with a =function= or =var= declaration. Therefore, in the
96
+ following cases UglifyJS *doesn't touch* calls or instantiations of Array:
97
+
98
+ #+BEGIN_SRC js
99
+ // case 1. globally declared variable
100
+ var Array;
101
+ new Array(1, 2, 3);
102
+ Array(a, b);
103
+
104
+ // or (can be declared later)
105
+ new Array(1, 2, 3);
106
+ var Array;
107
+
108
+ // or (can be a function)
109
+ new Array(1, 2, 3);
110
+ function Array() { ... }
111
+
112
+ // case 2. declared in a function
113
+ (function(){
114
+ a = new Array(1, 2, 3);
115
+ b = Array(5, 6);
116
+ var Array;
117
+ })();
118
+
119
+ // or
120
+ (function(Array){
121
+ return Array(5, 6, 7);
122
+ })();
123
+
124
+ // or
125
+ (function(){
126
+ return new Array(1, 2, 3, 4);
127
+ function Array() { ... }
128
+ })();
129
+
130
+ // etc.
131
+ #+END_SRC
132
+
133
+ *** =obj.toString()= ==> =obj+“”=
134
+
135
+ ** Install (NPM)
136
+
137
+ UglifyJS is now available through NPM --- =npm install uglify-js= should do
138
+ the job.
139
+
140
+ ** Install latest code from GitHub
141
+
142
+ #+BEGIN_SRC sh
143
+ ## clone the repository
144
+ mkdir -p /where/you/wanna/put/it
145
+ cd /where/you/wanna/put/it
146
+ git clone git://github.com/mishoo/UglifyJS.git
147
+
148
+ ## make the module available to Node
149
+ mkdir -p ~/.node_libraries/
150
+ cd ~/.node_libraries/
151
+ ln -s /where/you/wanna/put/it/UglifyJS/uglify-js.js
152
+
153
+ ## and if you want the CLI script too:
154
+ mkdir -p ~/bin
155
+ cd ~/bin
156
+ ln -s /where/you/wanna/put/it/UglifyJS/bin/uglifyjs
157
+ # (then add ~/bin to your $PATH if it's not there already)
158
+ #+END_SRC
159
+
160
+ ** Usage
161
+
162
+ There is a command-line tool that exposes the functionality of this library
163
+ for your shell-scripting needs:
164
+
165
+ #+BEGIN_SRC sh
166
+ uglifyjs [ options... ] [ filename ]
167
+ #+END_SRC
168
+
169
+ =filename= should be the last argument and should name the file from which
170
+ to read the JavaScript code. If you don't specify it, it will read code
171
+ from STDIN.
172
+
173
+ Supported options:
174
+
175
+ - =-b= or =--beautify= --- output indented code; when passed, additional
176
+ options control the beautifier:
177
+
178
+ - =-i N= or =--indent N= --- indentation level (number of spaces)
179
+
180
+ - =-q= or =--quote-keys= --- quote keys in literal objects (by default,
181
+ only keys that cannot be identifier names will be quotes).
182
+
183
+ - =--ascii= --- pass this argument to encode non-ASCII characters as
184
+ =\uXXXX= sequences. By default UglifyJS won't bother to do it and will
185
+ output Unicode characters instead. (the output is always encoded in UTF8,
186
+ but if you pass this option you'll only get ASCII).
187
+
188
+ - =-nm= or =--no-mangle= --- don't mangle variable names
189
+
190
+ - =-ns= or =--no-squeeze= --- don't call =ast_squeeze()= (which does various
191
+ optimizations that result in smaller, less readable code).
192
+
193
+ - =-mt= or =--mangle-toplevel= --- mangle names in the toplevel scope too
194
+ (by default we don't do this).
195
+
196
+ - =--no-seqs= --- when =ast_squeeze()= is called (thus, unless you pass
197
+ =--no-squeeze=) it will reduce consecutive statements in blocks into a
198
+ sequence. For example, "a = 10; b = 20; foo();" will be written as
199
+ "a=10,b=20,foo();". In various occasions, this allows us to discard the
200
+ block brackets (since the block becomes a single statement). This is ON
201
+ by default because it seems safe and saves a few hundred bytes on some
202
+ libs that I tested it on, but pass =--no-seqs= to disable it.
203
+
204
+ - =--no-dead-code= --- by default, UglifyJS will remove code that is
205
+ obviously unreachable (code that follows a =return=, =throw=, =break= or
206
+ =continue= statement and is not a function/variable declaration). Pass
207
+ this option to disable this optimization.
208
+
209
+ - =-nc= or =--no-copyright= --- by default, =uglifyjs= will keep the initial
210
+ comment tokens in the generated code (assumed to be copyright information
211
+ etc.). If you pass this it will discard it.
212
+
213
+ - =-o filename= or =--output filename= --- put the result in =filename=. If
214
+ this isn't given, the result goes to standard output (or see next one).
215
+
216
+ - =--overwrite= --- if the code is read from a file (not from STDIN) and you
217
+ pass =--overwrite= then the output will be written in the same file.
218
+
219
+ - =--ast= --- pass this if you want to get the Abstract Syntax Tree instead
220
+ of JavaScript as output. Useful for debugging or learning more about the
221
+ internals.
222
+
223
+ - =-v= or =--verbose= --- output some notes on STDERR (for now just how long
224
+ each operation takes).
225
+
226
+ - =--unsafe= --- enable other additional optimizations that are known to be
227
+ unsafe in some contrived situations, but could still be generally useful.
228
+ For now only this:
229
+
230
+ - foo.toString() ==> foo+""
231
+
232
+ - =--max-line-len= (default 32K characters) --- add a newline after around
233
+ 32K characters. I've seen both FF and Chrome croak when all the code was
234
+ on a single line of around 670K. Pass --max-line-len 0 to disable this
235
+ safety feature.
236
+
237
+ - =--reserved-names= --- some libraries rely on certain names to be used, as
238
+ pointed out in issue #92 and #81, so this option allow you to exclude such
239
+ names from the mangler. For example, to keep names =require= and =$super=
240
+ intact you'd specify --reserved-names "require,$super".
241
+
242
+ - =--inline-script= -- when you want to include the output literally in an
243
+ HTML =<script>= tag you can use this option to prevent =</script= from
244
+ showing up in the output.
245
+
246
+ - =--lift-vars= -- when you pass this, UglifyJS will apply the following
247
+ transformations (see the notes in API, =ast_lift_variables=):
248
+
249
+ - put all =var= declarations at the start of the scope
250
+ - make sure a variable is declared only once
251
+ - discard unused function arguments
252
+ - discard unused inner (named) functions
253
+ - finally, try to merge assignments into that one =var= declaration, if
254
+ possible.
255
+
256
+ *** API
257
+
258
+ To use the library from JavaScript, you'd do the following (example for
259
+ NodeJS):
260
+
261
+ #+BEGIN_SRC js
262
+ var jsp = require("uglify-js").parser;
263
+ var pro = require("uglify-js").uglify;
264
+
265
+ var orig_code = "... JS code here";
266
+ var ast = jsp.parse(orig_code); // parse code and get the initial AST
267
+ ast = pro.ast_mangle(ast); // get a new AST with mangled names
268
+ ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
269
+ var final_code = pro.gen_code(ast); // compressed code here
270
+ #+END_SRC
271
+
272
+ The above performs the full compression that is possible right now. As you
273
+ can see, there are a sequence of steps which you can apply. For example if
274
+ you want compressed output but for some reason you don't want to mangle
275
+ variable names, you would simply skip the line that calls
276
+ =pro.ast_mangle(ast)=.
277
+
278
+ Some of these functions take optional arguments. Here's a description:
279
+
280
+ - =jsp.parse(code, strict_semicolons)= -- parses JS code and returns an AST.
281
+ =strict_semicolons= is optional and defaults to =false=. If you pass
282
+ =true= then the parser will throw an error when it expects a semicolon and
283
+ it doesn't find it. For most JS code you don't want that, but it's useful
284
+ if you want to strictly sanitize your code.
285
+
286
+ - =pro.ast_lift_variables(ast)= -- merge and move =var= declarations to the
287
+ scop of the scope; discard unused function arguments or variables; discard
288
+ unused (named) inner functions. It also tries to merge assignments
289
+ following the =var= declaration into it.
290
+
291
+ If your code is very hand-optimized concerning =var= declarations, this
292
+ lifting variable declarations might actually increase size. For me it
293
+ helps out. On jQuery it adds 865 bytes (243 after gzip). YMMV. Also
294
+ note that (since it's not enabled by default) this operation isn't yet
295
+ heavily tested (please report if you find issues!).
296
+
297
+ Note that although it might increase the image size (on jQuery it gains
298
+ 865 bytes, 243 after gzip) it's technically more correct: in certain
299
+ situations, dead code removal might drop variable declarations, which
300
+ would not happen if the variables are lifted in advance.
301
+
302
+ Here's an example of what it does:
303
+
304
+ #+BEGIN_SRC js
305
+ function f(a, b, c, d, e) {
306
+ var q;
307
+ var w;
308
+ w = 10;
309
+ q = 20;
310
+ for (var i = 1; i < 10; ++i) {
311
+ var boo = foo(a);
312
+ }
313
+ for (var i = 0; i < 1; ++i) {
314
+ var boo = bar(c);
315
+ }
316
+ function foo(){ ... }
317
+ function bar(){ ... }
318
+ function baz(){ ... }
319
+ }
320
+
321
+ // transforms into ==>
322
+
323
+ function f(a, b, c) {
324
+ var i, boo, w = 10, q = 20;
325
+ for (i = 1; i < 10; ++i) {
326
+ boo = foo(a);
327
+ }
328
+ for (i = 0; i < 1; ++i) {
329
+ boo = bar(c);
330
+ }
331
+ function foo() { ... }
332
+ function bar() { ... }
333
+ }
334
+ #+END_SRC
335
+
336
+ - =pro.ast_mangle(ast, options)= -- generates a new AST containing mangled
337
+ (compressed) variable and function names. It supports the following
338
+ options:
339
+
340
+ - =toplevel= -- mangle toplevel names (by default we don't touch them).
341
+ - =except= -- an array of names to exclude from compression.
342
+
343
+ - =pro.ast_squeeze(ast, options)= -- employs further optimizations designed
344
+ to reduce the size of the code that =gen_code= would generate from the
345
+ AST. Returns a new AST. =options= can be a hash; the supported options
346
+ are:
347
+
348
+ - =make_seqs= (default true) which will cause consecutive statements in a
349
+ block to be merged using the "sequence" (comma) operator
350
+
351
+ - =dead_code= (default true) which will remove unreachable code.
352
+
353
+ - =pro.gen_code(ast, options)= -- generates JS code from the AST. By
354
+ default it's minified, but using the =options= argument you can get nicely
355
+ formatted output. =options= is, well, optional :-) and if you pass it it
356
+ must be an object and supports the following properties (below you can see
357
+ the default values):
358
+
359
+ - =beautify: false= -- pass =true= if you want indented output
360
+ - =indent_start: 0= (only applies when =beautify= is =true=) -- initial
361
+ indentation in spaces
362
+ - =indent_level: 4= (only applies when =beautify= is =true=) --
363
+ indentation level, in spaces (pass an even number)
364
+ - =quote_keys: false= -- if you pass =true= it will quote all keys in
365
+ literal objects
366
+ - =space_colon: false= (only applies when =beautify= is =true=) -- wether
367
+ to put a space before the colon in object literals
368
+ - =ascii_only: false= -- pass =true= if you want to encode non-ASCII
369
+ characters as =\uXXXX=.
370
+ - =inline_script: false= -- pass =true= to escape occurrences of
371
+ =</script= in strings
372
+
373
+ *** Beautifier shortcoming -- no more comments
374
+
375
+ The beautifier can be used as a general purpose indentation tool. It's
376
+ useful when you want to make a minified file readable. One limitation,
377
+ though, is that it discards all comments, so you don't really want to use it
378
+ to reformat your code, unless you don't have, or don't care about, comments.
379
+
380
+ In fact it's not the beautifier who discards comments --- they are dumped at
381
+ the parsing stage, when we build the initial AST. Comments don't really
382
+ make sense in the AST, and while we could add nodes for them, it would be
383
+ inconvenient because we'd have to add special rules to ignore them at all
384
+ the processing stages.
385
+
386
+ ** Compression -- how good is it?
387
+
388
+ Here are updated statistics. (I also updated my Google Closure and YUI
389
+ installations).
390
+
391
+ We're still a lot better than YUI in terms of compression, though slightly
392
+ slower. We're still a lot faster than Closure, and compression after gzip
393
+ is comparable.
394
+
395
+ | File | UglifyJS | UglifyJS+gzip | Closure | Closure+gzip | YUI | YUI+gzip |
396
+ |-----------------------------+------------------+---------------+------------------+--------------+------------------+----------|
397
+ | jquery-1.6.2.js | 91001 (0:01.59) | 31896 | 90678 (0:07.40) | 31979 | 101527 (0:01.82) | 34646 |
398
+ | paper.js | 142023 (0:01.65) | 43334 | 134301 (0:07.42) | 42495 | 173383 (0:01.58) | 48785 |
399
+ | prototype.js | 88544 (0:01.09) | 26680 | 86955 (0:06.97) | 26326 | 92130 (0:00.79) | 28624 |
400
+ | thelib-full.js (DynarchLIB) | 251939 (0:02.55) | 72535 | 249911 (0:09.05) | 72696 | 258869 (0:01.94) | 76584 |
401
+
402
+ ** Bugs?
403
+
404
+ Unfortunately, for the time being there is no automated test suite. But I
405
+ ran the compressor manually on non-trivial code, and then I tested that the
406
+ generated code works as expected. A few hundred times.
407
+
408
+ DynarchLIB was started in times when there was no good JS minifier.
409
+ Therefore I was quite religious about trying to write short code manually,
410
+ and as such DL contains a lot of syntactic hacks[1] such as “foo == bar ? a
411
+ = 10 : b = 20”, though the more readable version would clearly be to use
412
+ “if/else”.
413
+
414
+ Since the parser/compressor runs fine on DL and jQuery, I'm quite confident
415
+ that it's solid enough for production use. If you can identify any bugs,
416
+ I'd love to hear about them ([[http://groups.google.com/group/uglifyjs][use the Google Group]] or email me directly).
417
+
418
+ [1] I even reported a few bugs and suggested some fixes in the original
419
+ [[http://marijn.haverbeke.nl/parse-js/][parse-js]] library, and Marijn pushed fixes literally in minutes.
420
+
421
+ ** Links
422
+
423
+ - Twitter: [[http://twitter.com/UglifyJS][@UglifyJS]]
424
+ - Project at GitHub: [[http://github.com/mishoo/UglifyJS][http://github.com/mishoo/UglifyJS]]
425
+ - Google Group: [[http://groups.google.com/group/uglifyjs][http://groups.google.com/group/uglifyjs]]
426
+ - Common Lisp JS parser: [[http://marijn.haverbeke.nl/parse-js/][http://marijn.haverbeke.nl/parse-js/]]
427
+ - JS-to-Lisp compiler: [[http://github.com/marijnh/js][http://github.com/marijnh/js]]
428
+ - Common Lisp JS uglifier: [[http://github.com/mishoo/cl-uglify-js][http://github.com/mishoo/cl-uglify-js]]
429
+
430
+ ** License
431
+
432
+ UglifyJS is released under the BSD license:
433
+
434
+ #+BEGIN_EXAMPLE
435
+ Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
436
+ Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
437
+
438
+ Redistribution and use in source and binary forms, with or without
439
+ modification, are permitted provided that the following conditions
440
+ are met:
441
+
442
+ * Redistributions of source code must retain the above
443
+ copyright notice, this list of conditions and the following
444
+ disclaimer.
445
+
446
+ * Redistributions in binary form must reproduce the above
447
+ copyright notice, this list of conditions and the following
448
+ disclaimer in the documentation and/or other materials
449
+ provided with the distribution.
450
+
451
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
452
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
453
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
454
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
455
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
456
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
457
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
458
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
459
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
460
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
461
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
462
+ SUCH DAMAGE.
463
+ #+END_EXAMPLE