Adds jQuery collection to objects that will be used as global events context if provi...
[jquery.git] / build / uglify.js
1 #! /usr/bin/env node
2 // -*- js2 -*-
3
4 global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util");
5 var fs = require("fs"),
6     jsp = require("./lib/parse-js"),
7     pro = require("./lib/process");
8
9 pro.set_logger(function(msg){
10         sys.debug(msg);
11 });
12
13 var options = {
14         ast: false,
15         mangle: true,
16         mangle_toplevel: false,
17         squeeze: true,
18         make_seqs: true,
19         dead_code: true,
20         beautify: false,
21         verbose: false,
22         show_copyright: true,
23         out_same_file: false,
24         extra: false,
25         unsafe: false,            // XXX: extra & unsafe?  but maybe we don't want both, so....
26         beautify_options: {
27                 indent_level: 4,
28                 indent_start: 0,
29                 quote_keys: false,
30                 space_colon: false
31         },
32         output: true            // stdout
33 };
34
35 var args = jsp.slice(process.argv, 2);
36 var filename;
37
38 out: while (args.length > 0) {
39         var v = args.shift();
40         switch (v) {
41             case "-b":
42             case "--beautify":
43                 options.beautify = true;
44                 break;
45             case "-i":
46             case "--indent":
47                 options.beautify_options.indent_level = args.shift();
48                 break;
49             case "-q":
50             case "--quote-keys":
51                 options.beautify_options.quote_keys = true;
52                 break;
53             case "-mt":
54             case "--mangle-toplevel":
55                 options.mangle_toplevel = true;
56                 break;
57             case "--no-mangle":
58             case "-nm":
59                 options.mangle = false;
60                 break;
61             case "--no-squeeze":
62             case "-ns":
63                 options.squeeze = false;
64                 break;
65             case "--no-seqs":
66                 options.make_seqs = false;
67                 break;
68             case "--no-dead-code":
69                 options.dead_code = false;
70                 break;
71             case "--no-copyright":
72             case "-nc":
73                 options.show_copyright = false;
74                 break;
75             case "-o":
76             case "--output":
77                 options.output = args.shift();
78                 break;
79             case "--overwrite":
80                 options.out_same_file = true;
81                 break;
82             case "-v":
83             case "--verbose":
84                 options.verbose = true;
85                 break;
86             case "--ast":
87                 options.ast = true;
88                 break;
89             case "--extra":
90                 options.extra = true;
91                 break;
92             case "--unsafe":
93                 options.unsafe = true;
94                 break;
95             default:
96                 filename = v;
97                 break out;
98         }
99 }
100
101 if (filename) {
102         fs.readFile(filename, "utf8", function(err, text){
103                 if (err) {
104                         throw err;
105                 }
106                 output(squeeze_it(text));
107         });
108 } else {
109         var stdin = process.openStdin();
110         stdin.setEncoding("utf8");
111         var text = "";
112         stdin.on("data", function(chunk){
113                 text += chunk;
114         });
115         stdin.on("end", function() {
116                 output(squeeze_it(text));
117         });
118 }
119
120 function output(text) {
121         var out;
122         if (options.out_same_file && filename)
123                 options.output = filename;
124         if (options.output === true) {
125                 out = process.stdout;
126         } else {
127                 out = fs.createWriteStream(options.output, {
128                         flags: "w",
129                         encoding: "utf8",
130                         mode: 0644
131                 });
132         }
133         out.write(text);
134         out.end();
135 };
136
137 // --------- main ends here.
138
139 function show_copyright(comments) {
140         var ret = "";
141         for (var i = 0; i < comments.length; ++i) {
142                 var c = comments[i];
143                 if (c.type == "comment1") {
144                         ret += "//" + c.value + "\n";
145                 } else {
146                         ret += "/*" + c.value + "*/";
147                 }
148         }
149         return ret;
150 };
151
152 function squeeze_it(code) {
153         var result = "";
154         if (options.show_copyright) {
155                 var initial_comments = [];
156                 // keep first comment
157                 var tok = jsp.tokenizer(code, false), c;
158                 c = tok();
159                 var prev = null;
160                 while (/^comment/.test(c.type) && (!prev || prev == c.type)) {
161                         initial_comments.push(c);
162                         prev = c.type;
163                         c = tok();
164                 }
165                 result += show_copyright(initial_comments);
166         }
167         try {
168                 var ast = time_it("parse", function(){ return jsp.parse(code); });
169                 if (options.mangle)
170                         ast = time_it("mangle", function(){ return pro.ast_mangle(ast, options.mangle_toplevel); });
171                 if (options.squeeze)
172                         ast = time_it("squeeze", function(){
173                                 ast = pro.ast_squeeze(ast, {
174                                         make_seqs : options.make_seqs,
175                                         dead_code : options.dead_code,
176                                         extra     : options.extra
177                                 });
178                                 if (options.unsafe)
179                                         ast = pro.ast_squeeze_more(ast);
180                                 return ast;
181                         });
182                 if (options.ast)
183                         return sys.inspect(ast, null, null);
184                 result += time_it("generate", function(){ return pro.gen_code(ast, options.beautify && options.beautify_options) });
185                 return result;
186         } catch(ex) {
187                 sys.debug(ex.stack);
188                 sys.debug(sys.inspect(ex));
189                 sys.debug(JSON.stringify(ex));
190         }
191 };
192
193 function time_it(name, cont) {
194         if (!options.verbose)
195                 return cont();
196         var t1 = new Date().getTime();
197         try { return cont(); }
198         finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); }
199 };