js-beautify 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +4 -0
  3. data/Gemfile +13 -0
  4. data/Gemfile.lock +27 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +13 -0
  7. data/Rakefile +29 -0
  8. data/VERSION +1 -0
  9. data/bin/js-beautify +5 -0
  10. data/init.sh +3 -0
  11. data/js-beautify-copy/.gitmodules +3 -0
  12. data/js-beautify-copy/Makefile +71 -0
  13. data/js-beautify-copy/README.md +39 -0
  14. data/js-beautify-copy/attic/beautify-cl/beautify-cl.js +142 -0
  15. data/js-beautify-copy/attic/bin/beautify_js +80 -0
  16. data/js-beautify-copy/attic/opera-userscript/beautifier.js +1087 -0
  17. data/js-beautify-copy/attic/opera-userscript/make_opera_userscript.sh +42 -0
  18. data/js-beautify-copy/attic/qtscript/jsbeautify.cpp +121 -0
  19. data/js-beautify-copy/attic/qtscript/jsbeautify.pro +5 -0
  20. data/js-beautify-copy/attic/qtscript/jsbeautify.qrc +6 -0
  21. data/js-beautify-copy/attic/qtscript/readme.txt +28 -0
  22. data/js-beautify-copy/attic/readme.txt +2 -0
  23. data/js-beautify-copy/attic/unmaintained/bbedit/jsBeautify_BBED.scpt +522 -0
  24. data/js-beautify-copy/attic/unmaintained/c-sharp/JSBeautify.cs +801 -0
  25. data/js-beautify-copy/attic/v8/README.txt +40 -0
  26. data/js-beautify-copy/attic/v8/beautify.h +2390 -0
  27. data/js-beautify-copy/attic/v8/jsbeautify.cpp +215 -0
  28. data/js-beautify-copy/beautify-css.js +198 -0
  29. data/js-beautify-copy/beautify-html.js +514 -0
  30. data/js-beautify-copy/beautify.js +1293 -0
  31. data/js-beautify-copy/favicon.png +0 -0
  32. data/js-beautify-copy/index.html +401 -0
  33. data/js-beautify-copy/jquery/jquery.cookie.js +96 -0
  34. data/js-beautify-copy/jquery/jquery.js +167 -0
  35. data/js-beautify-copy/license.txt +24 -0
  36. data/js-beautify-copy/php/jsbeautifier.php +1599 -0
  37. data/js-beautify-copy/php/test.php +476 -0
  38. data/js-beautify-copy/python/MANIFEST.in +2 -0
  39. data/js-beautify-copy/python/js-beautify +7 -0
  40. data/js-beautify-copy/python/js-beautify-profile +16 -0
  41. data/js-beautify-copy/python/js-beautify-test +10 -0
  42. data/js-beautify-copy/python/jsbeautifier/__init__.py +1166 -0
  43. data/js-beautify-copy/python/jsbeautifier/tests/__init__.py +1 -0
  44. data/js-beautify-copy/python/jsbeautifier/tests/testindentation.py +43 -0
  45. data/js-beautify-copy/python/jsbeautifier/tests/testjsbeautifier.py +464 -0
  46. data/js-beautify-copy/python/jsbeautifier/unpackers/README.specs.mkd +25 -0
  47. data/js-beautify-copy/python/jsbeautifier/unpackers/__init__.py +67 -0
  48. data/js-beautify-copy/python/jsbeautifier/unpackers/evalbased.py +39 -0
  49. data/js-beautify-copy/python/jsbeautifier/unpackers/javascriptobfuscator.py +58 -0
  50. data/js-beautify-copy/python/jsbeautifier/unpackers/myobfuscate.py +86 -0
  51. data/js-beautify-copy/python/jsbeautifier/unpackers/packer.py +104 -0
  52. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/__init__.py +2 -0
  53. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-myobfuscate-input.js +1 -0
  54. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-myobfuscate-output.js +65 -0
  55. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-packer-62-input.js +1 -0
  56. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-packer-non62-input.js +1 -0
  57. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testjavascriptobfuscator.py +46 -0
  58. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testmyobfuscate.py +40 -0
  59. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testpacker.py +34 -0
  60. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testurlencode.py +36 -0
  61. data/js-beautify-copy/python/jsbeautifier/unpackers/urlencode.py +34 -0
  62. data/js-beautify-copy/python/setup.py +17 -0
  63. data/js-beautify-copy/tests/beautify-tests.js +489 -0
  64. data/js-beautify-copy/tests/run-tests +17 -0
  65. data/js-beautify-copy/tests/sanitytest.js +128 -0
  66. data/js-beautify-copy/unpackers/javascriptobfuscator_unpacker.js +103 -0
  67. data/js-beautify-copy/unpackers/myobfuscate_unpacker.js +81 -0
  68. data/js-beautify-copy/unpackers/p_a_c_k_e_r_unpacker.js +61 -0
  69. data/js-beautify-copy/unpackers/urlencode_unpacker.js +51 -0
  70. data/lib/js-beautify.rb +0 -0
  71. data/test/helper.rb +18 -0
  72. data/test/test_js-beautify.rb +7 -0
  73. data/update.sh +23 -0
  74. metadata +173 -0
@@ -0,0 +1,2 @@
1
+ include js-beautify
2
+ include js-beautify-test
@@ -0,0 +1,7 @@
1
+ #! /usr/bin/env python
2
+ #
3
+ # Stub script to run jsbeautifier
4
+ #
5
+
6
+ from jsbeautifier import main
7
+ main()
@@ -0,0 +1,16 @@
1
+ #! /usr/bin/env python
2
+
3
+ import sys
4
+ import unittest
5
+
6
+ #Speedup things...
7
+ try:
8
+ import cProfile as profile
9
+ except ImportError:
10
+ import profile
11
+
12
+ def run():
13
+ sys.argv.append('discover')
14
+ unittest.main()
15
+
16
+ profile.run('run()')
@@ -0,0 +1,10 @@
1
+ #! /bin/sh
2
+ #
3
+ # Test suite launcher
4
+ #
5
+
6
+ if [ -z $PYTHON ]; then
7
+ env python -m unittest discover "$@"
8
+ else
9
+ env $PYTHON -m unittest discover "$@"
10
+ fi
@@ -0,0 +1,1166 @@
1
+ import sys
2
+ import getopt
3
+ import re
4
+ import string
5
+
6
+ #
7
+ # Originally written by Einar Lielmanis et al.,
8
+ # Conversion to python by Einar Lielmanis, einar@jsbeautifier.org,
9
+ # MIT licence, enjoy.
10
+ #
11
+ # Python is not my native language, feel free to push things around.
12
+ #
13
+ # Use either from command line (script displays its usage when run
14
+ # without any parameters),
15
+ #
16
+ #
17
+ # or, alternatively, use it as a module:
18
+ #
19
+ # import jsbeautifier
20
+ # res = jsbeautifier.beautify('your javascript string')
21
+ # res = jsbeautifier.beautify_file('some_file.js')
22
+ #
23
+ # you may specify some options:
24
+ #
25
+ # opts = jsbeautifier.default_options()
26
+ # opts.indent_size = 2
27
+ # res = jsbeautifier.beautify('some javascript', opts)
28
+ #
29
+ #
30
+ # Here are the available options: (read source)
31
+
32
+
33
+ class BeautifierOptions:
34
+ def __init__(self):
35
+ self.indent_size = 4
36
+ self.indent_char = ' '
37
+ self.indent_with_tabs = False
38
+ self.preserve_newlines = True
39
+ self.max_preserve_newlines = 10.
40
+ self.jslint_happy = False
41
+ self.brace_style = 'collapse'
42
+ self.keep_array_indentation = False
43
+ self.keep_function_indentation = False
44
+ self.eval_code = False
45
+
46
+
47
+
48
+ def __repr__(self):
49
+ return \
50
+ """indent_size = %d
51
+ indent_char = [%s]
52
+ preserve_newlines = %s
53
+ max_preserve_newlines = %d
54
+ jslint_happy = %s
55
+ indent_with_tabs = %s
56
+ brace_style = %s
57
+ keep_array_indentation = %s
58
+ eval_code = %s
59
+ """ % ( self.indent_size,
60
+ self.indent_char,
61
+ self.preserve_newlines,
62
+ self.max_preserve_newlines,
63
+ self.jslint_happy,
64
+ self.indent_with_tabs,
65
+ self.brace_style,
66
+ self.keep_array_indentation,
67
+ self.eval_code,
68
+ )
69
+
70
+
71
+ class BeautifierFlags:
72
+ def __init__(self, mode):
73
+ self.previous_mode = 'BLOCK'
74
+ self.mode = mode
75
+ self.var_line = False
76
+ self.var_line_tainted = False
77
+ self.var_line_reindented = False
78
+ self.in_html_comment = False
79
+ self.if_line = False
80
+ self.in_case = False
81
+ self.in_case_statement = False
82
+ self.eat_next_space = False
83
+ self.indentation_baseline = -1
84
+ self.indentation_level = 0
85
+ self.ternary_depth = 0
86
+
87
+
88
+ def default_options():
89
+ return BeautifierOptions()
90
+
91
+
92
+ def beautify(string, opts = default_options() ):
93
+ b = Beautifier()
94
+ return b.beautify(string, opts)
95
+
96
+ def beautify_file(file_name, opts = default_options() ):
97
+
98
+ if file_name == '-': # stdin
99
+ f = sys.stdin
100
+ else:
101
+ try:
102
+ f = open(file_name)
103
+ except Exception as ex:
104
+ return 'The file could not be opened'
105
+
106
+ b = Beautifier()
107
+ return b.beautify(''.join(f.readlines()), opts)
108
+
109
+
110
+ def usage():
111
+
112
+ print("""Javascript beautifier (http://jsbeautifier.org/)
113
+
114
+ Usage: jsbeautifier.py [options] <infile>
115
+
116
+ <infile> can be "-", which means stdin.
117
+ <outfile> defaults to stdout
118
+
119
+ Input options:
120
+
121
+ -i, --stdin read input from stdin
122
+
123
+ Output options:
124
+
125
+ -s, --indent-size=NUMBER indentation size. (default 4).
126
+ -c, --indent-char=CHAR character to indent with. (default space).
127
+ -t, --indent-with-tabs Indent with tabs, overrides -s and -c
128
+ -d, --disable-preserve-newlines do not preserve existing line breaks.
129
+ -j, --jslint-happy more jslint-compatible output
130
+ -b, --brace-style=collapse brace style (collapse, expand, end-expand)
131
+ -k, --keep-array-indentation keep array indentation.
132
+ -o, --outfile=FILE specify a file to output to (default stdout)
133
+ -f, --keep-function-indentation Do not re-indent function bodies defined in var lines.
134
+
135
+ Rarely needed options:
136
+
137
+ --eval-code evaluate code if a JS interpreter is
138
+ installed. May be useful with some obfuscated
139
+ script but poses a potential security issue.
140
+
141
+ -l, --indent-level=NUMBER initial indentation level. (default 0).
142
+
143
+ -h, --help, --usage prints this help statement.
144
+
145
+ """)
146
+
147
+
148
+
149
+
150
+
151
+
152
+ class Beautifier:
153
+
154
+ def __init__(self, opts = default_options() ):
155
+
156
+ self.opts = opts
157
+ self.blank_state()
158
+
159
+ def blank_state(self):
160
+
161
+ # internal flags
162
+ self.flags = BeautifierFlags('BLOCK')
163
+ self.flag_store = []
164
+ self.wanted_newline = False
165
+ self.just_added_newline = False
166
+ self.do_block_just_closed = False
167
+
168
+ if self.opts.indent_with_tabs:
169
+ self.indent_string = "\t"
170
+ else:
171
+ self.indent_string = self.opts.indent_char * self.opts.indent_size
172
+
173
+ self.preindent_string = ''
174
+ self.last_word = '' # last TK_WORD seen
175
+ self.last_type = 'TK_START_EXPR' # last token type
176
+ self.last_text = '' # last token text
177
+ self.last_last_text = '' # pre-last token text
178
+
179
+ self.input = None
180
+ self.output = [] # formatted javascript gets built here
181
+
182
+ self.whitespace = ["\n", "\r", "\t", " "]
183
+ self.wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'
184
+ self.digits = '0123456789'
185
+ self.punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::'
186
+ self.punct += ' <?= <? ?> <%= <% %>'
187
+ self.punct = self.punct.split(' ')
188
+
189
+
190
+ # Words which always should start on a new line
191
+ self.line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',')
192
+ self.set_mode('BLOCK')
193
+
194
+ global parser_pos
195
+ parser_pos = 0
196
+
197
+
198
+ def beautify(self, s, opts = None ):
199
+
200
+ if opts != None:
201
+ self.opts = opts
202
+
203
+
204
+ if self.opts.brace_style not in ['expand', 'collapse', 'end-expand']:
205
+ raise(Exception('opts.brace_style must be "expand", "collapse" or "end-expand".'))
206
+
207
+ self.blank_state()
208
+
209
+ while s and s[0] in [' ', '\t']:
210
+ self.preindent_string += s[0]
211
+ s = s[1:]
212
+
213
+ self.input = self.unpack(s, opts.eval_code)
214
+
215
+ parser_pos = 0
216
+ while True:
217
+ token_text, token_type = self.get_next_token()
218
+ #print (token_text, token_type, self.flags.mode)
219
+ if token_type == 'TK_EOF':
220
+ break
221
+
222
+ handlers = {
223
+ 'TK_START_EXPR': self.handle_start_expr,
224
+ 'TK_END_EXPR': self.handle_end_expr,
225
+ 'TK_START_BLOCK': self.handle_start_block,
226
+ 'TK_END_BLOCK': self.handle_end_block,
227
+ 'TK_WORD': self.handle_word,
228
+ 'TK_SEMICOLON': self.handle_semicolon,
229
+ 'TK_STRING': self.handle_string,
230
+ 'TK_EQUALS': self.handle_equals,
231
+ 'TK_OPERATOR': self.handle_operator,
232
+ 'TK_BLOCK_COMMENT': self.handle_block_comment,
233
+ 'TK_INLINE_COMMENT': self.handle_inline_comment,
234
+ 'TK_COMMENT': self.handle_comment,
235
+ 'TK_UNKNOWN': self.handle_unknown,
236
+ }
237
+
238
+ handlers[token_type](token_text)
239
+
240
+ self.last_last_text = self.last_text
241
+ self.last_type = token_type
242
+ self.last_text = token_text
243
+
244
+ sweet_code = self.preindent_string + re.sub('[\n ]+$', '', ''.join(self.output))
245
+ return sweet_code
246
+
247
+ def unpack(self, source, evalcode=False):
248
+ import jsbeautifier.unpackers as unpackers
249
+ try:
250
+ return unpackers.run(source, evalcode)
251
+ except unpackers.UnpackingError as error:
252
+ print('error:', error)
253
+ return ''
254
+
255
+ def trim_output(self, eat_newlines = False):
256
+ while len(self.output) \
257
+ and (
258
+ self.output[-1] == ' '\
259
+ or self.output[-1] == self.indent_string \
260
+ or self.output[-1] == self.preindent_string \
261
+ or (eat_newlines and self.output[-1] in ['\n', '\r'])):
262
+ self.output.pop()
263
+
264
+ def is_special_word(self, s):
265
+ return s in ['case', 'return', 'do', 'if', 'throw', 'else'];
266
+
267
+ def is_array(self, mode):
268
+ return mode in ['[EXPRESSION]', '[INDENDED-EXPRESSION]']
269
+
270
+
271
+ def is_expression(self, mode):
272
+ return mode in ['[EXPRESSION]', '[INDENDED-EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']
273
+
274
+
275
+ def append_newline_forced(self):
276
+ old_array_indentation = self.opts.keep_array_indentation
277
+ self.opts.keep_array_indentation = False
278
+ self.append_newline()
279
+ self.opts.keep_array_indentation = old_array_indentation
280
+
281
+ def append_newline(self, ignore_repeated = True):
282
+
283
+ self.flags.eat_next_space = False
284
+
285
+ if self.opts.keep_array_indentation and self.is_array(self.flags.mode):
286
+ return
287
+
288
+ self.flags.if_line = False
289
+ self.trim_output()
290
+
291
+ if len(self.output) == 0:
292
+ # no newline on start of file
293
+ return
294
+
295
+ if self.output[-1] != '\n' or not ignore_repeated:
296
+ self.just_added_newline = True
297
+ self.output.append('\n')
298
+
299
+ if self.preindent_string:
300
+ self.output.append(self.preindent_string)
301
+
302
+ for i in range(self.flags.indentation_level):
303
+ self.output.append(self.indent_string)
304
+
305
+ if self.flags.var_line and self.flags.var_line_reindented:
306
+ self.output.append(self.indent_string)
307
+
308
+
309
+ def append(self, s):
310
+ if s == ' ':
311
+ # do not add just a single space after the // comment, ever
312
+ if self.last_type == 'TK_COMMENT':
313
+ return self.append_newline()
314
+
315
+ # make sure only single space gets drawn
316
+ if self.flags.eat_next_space:
317
+ self.flags.eat_next_space = False
318
+ elif len(self.output) and self.output[-1] not in [' ', '\n', self.indent_string]:
319
+ self.output.append(' ')
320
+ else:
321
+ self.just_added_newline = False
322
+ self.flags.eat_next_space = False
323
+ self.output.append(s)
324
+
325
+
326
+ def indent(self):
327
+ self.flags.indentation_level = self.flags.indentation_level + 1
328
+
329
+
330
+ def remove_indent(self):
331
+ if len(self.output) and self.output[-1] in [self.indent_string, self.preindent_string]:
332
+ self.output.pop()
333
+
334
+
335
+ def set_mode(self, mode):
336
+
337
+ prev = BeautifierFlags('BLOCK')
338
+
339
+ if self.flags:
340
+ self.flag_store.append(self.flags)
341
+ prev = self.flags
342
+
343
+ self.flags = BeautifierFlags(mode)
344
+
345
+ if len(self.flag_store) == 1:
346
+ self.flags.indentation_level = 0
347
+ else:
348
+ self.flags.indentation_level = prev.indentation_level
349
+ if prev.var_line and prev.var_line_reindented:
350
+ self.flags.indentation_level = self.flags.indentation_level + 1
351
+ self.flags.previous_mode = prev.mode
352
+
353
+
354
+ def restore_mode(self):
355
+ self.do_block_just_closed = self.flags.mode == 'DO_BLOCK'
356
+ if len(self.flag_store) > 0:
357
+ mode = self.flags.mode
358
+ self.flags = self.flag_store.pop()
359
+ self.flags.previous_mode = mode
360
+
361
+
362
+ def get_next_token(self):
363
+
364
+ global parser_pos
365
+
366
+ self.n_newlines = 0
367
+
368
+ if parser_pos >= len(self.input):
369
+ return '', 'TK_EOF'
370
+
371
+ self.wanted_newline = False
372
+ c = self.input[parser_pos]
373
+ parser_pos += 1
374
+
375
+ keep_whitespace = self.opts.keep_array_indentation and self.is_array(self.flags.mode)
376
+
377
+ if keep_whitespace:
378
+ # slight mess to allow nice preservation of array indentation and reindent that correctly
379
+ # first time when we get to the arrays:
380
+ # var a = [
381
+ # ....'something'
382
+ # we make note of whitespace_count = 4 into flags.indentation_baseline
383
+ # so we know that 4 whitespaces in original source match indent_level of reindented source
384
+ #
385
+ # and afterwards, when we get to
386
+ # 'something,
387
+ # .......'something else'
388
+ # we know that this should be indented to indent_level + (7 - indentation_baseline) spaces
389
+
390
+ whitespace_count = 0
391
+ while c in self.whitespace:
392
+ if c == '\n':
393
+ self.trim_output()
394
+ self.output.append('\n')
395
+ self.just_added_newline = True
396
+ whitespace_count = 0
397
+ elif c == '\t':
398
+ whitespace_count += 4
399
+ elif c == '\r':
400
+ pass
401
+ else:
402
+ whitespace_count += 1
403
+
404
+ if parser_pos >= len(self.input):
405
+ return '', 'TK_EOF'
406
+
407
+ c = self.input[parser_pos]
408
+ parser_pos += 1
409
+
410
+ if self.flags.indentation_baseline == -1:
411
+
412
+ self.flags.indentation_baseline = whitespace_count
413
+
414
+ if self.just_added_newline:
415
+ for i in range(self.flags.indentation_level + 1):
416
+ self.output.append(self.indent_string)
417
+
418
+ if self.flags.indentation_baseline != -1:
419
+ for i in range(whitespace_count - self.flags.indentation_baseline):
420
+ self.output.append(' ')
421
+
422
+ else: # not keep_whitespace
423
+ while c in self.whitespace:
424
+ if c == '\n':
425
+ if self.opts.max_preserve_newlines == 0 or self.opts.max_preserve_newlines > self.n_newlines:
426
+ self.n_newlines += 1
427
+
428
+ if parser_pos >= len(self.input):
429
+ return '', 'TK_EOF'
430
+
431
+ c = self.input[parser_pos]
432
+ parser_pos += 1
433
+
434
+ if self.opts.preserve_newlines and self.n_newlines > 1:
435
+ for i in range(self.n_newlines):
436
+ self.append_newline(i == 0)
437
+ self.just_added_newline = True
438
+
439
+ self.wanted_newline = self.n_newlines > 0
440
+
441
+
442
+ if c in self.wordchar:
443
+ if parser_pos < len(self.input):
444
+ while self.input[parser_pos] in self.wordchar:
445
+ c = c + self.input[parser_pos]
446
+ parser_pos += 1
447
+ if parser_pos == len(self.input):
448
+ break
449
+
450
+ # small and surprisingly unugly hack for 1E-10 representation
451
+ if parser_pos != len(self.input) and self.input[parser_pos] in '+-' \
452
+ and re.match('^[0-9]+[Ee]$', c):
453
+
454
+ sign = self.input[parser_pos]
455
+ parser_pos += 1
456
+ t = self.get_next_token()
457
+ c += sign + t[0]
458
+ return c, 'TK_WORD'
459
+
460
+ if c == 'in': # in is an operator, need to hack
461
+ return c, 'TK_OPERATOR'
462
+
463
+ if self.wanted_newline and \
464
+ self.last_type != 'TK_OPERATOR' and\
465
+ self.last_type != 'TK_EQUALS' and\
466
+ not self.flags.if_line and \
467
+ (self.opts.preserve_newlines or self.last_text != 'var'):
468
+ self.append_newline()
469
+
470
+ return c, 'TK_WORD'
471
+
472
+ if c in '([':
473
+ return c, 'TK_START_EXPR'
474
+
475
+ if c in ')]':
476
+ return c, 'TK_END_EXPR'
477
+
478
+ if c == '{':
479
+ return c, 'TK_START_BLOCK'
480
+
481
+ if c == '}':
482
+ return c, 'TK_END_BLOCK'
483
+
484
+ if c == ';':
485
+ return c, 'TK_SEMICOLON'
486
+
487
+ if c == '/':
488
+ comment = ''
489
+ inline_comment = True
490
+ comment_mode = 'TK_INLINE_COMMENT'
491
+ if self.input[parser_pos] == '*': # peek /* .. */ comment
492
+ parser_pos += 1
493
+ if parser_pos < len(self.input):
494
+ while not (self.input[parser_pos] == '*' and \
495
+ parser_pos + 1 < len(self.input) and \
496
+ self.input[parser_pos + 1] == '/')\
497
+ and parser_pos < len(self.input):
498
+ c = self.input[parser_pos]
499
+ comment += c
500
+ if c in '\r\n':
501
+ comment_mode = 'TK_BLOCK_COMMENT'
502
+ parser_pos += 1
503
+ if parser_pos >= len(self.input):
504
+ break
505
+ parser_pos += 2
506
+ return '/*' + comment + '*/', comment_mode
507
+ if self.input[parser_pos] == '/': # peek // comment
508
+ comment = c
509
+ while self.input[parser_pos] not in '\r\n':
510
+ comment += self.input[parser_pos]
511
+ parser_pos += 1
512
+ if parser_pos >= len(self.input):
513
+ break
514
+ parser_pos += 1
515
+ if self.wanted_newline:
516
+ self.append_newline()
517
+ return comment, 'TK_COMMENT'
518
+
519
+
520
+
521
+ if c == "'" or c == '"' or \
522
+ (c == '/' and ((self.last_type == 'TK_WORD' and self.is_special_word(self.last_text)) or \
523
+ (self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in ['(FOR-EXPRESSION)', '(COND-EXPRESSION)']) or \
524
+ (self.last_type in ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK', 'TK_END_BLOCK', 'TK_OPERATOR',
525
+ 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON']))):
526
+ sep = c
527
+ esc = False
528
+ resulting_string = c
529
+ in_char_class = False
530
+
531
+ if parser_pos < len(self.input):
532
+ if sep == '/':
533
+ # handle regexp
534
+ in_char_class = False
535
+ while esc or in_char_class or self.input[parser_pos] != sep:
536
+ resulting_string += self.input[parser_pos]
537
+ if not esc:
538
+ esc = self.input[parser_pos] == '\\'
539
+ if self.input[parser_pos] == '[':
540
+ in_char_class = True
541
+ elif self.input[parser_pos] == ']':
542
+ in_char_class = False
543
+ else:
544
+ esc = False
545
+ parser_pos += 1
546
+ if parser_pos >= len(self.input):
547
+ # incomplete regex when end-of-file reached
548
+ # bail out with what has received so far
549
+ return resulting_string, 'TK_STRING'
550
+ else:
551
+ # handle string
552
+ while esc or self.input[parser_pos] != sep:
553
+ resulting_string += self.input[parser_pos]
554
+ if not esc:
555
+ esc = self.input[parser_pos] == '\\'
556
+ else:
557
+ esc = False
558
+ parser_pos += 1
559
+ if parser_pos >= len(self.input):
560
+ # incomplete string when end-of-file reached
561
+ # bail out with what has received so far
562
+ return resulting_string, 'TK_STRING'
563
+
564
+
565
+ parser_pos += 1
566
+ resulting_string += sep
567
+ if sep == '/':
568
+ # regexps may have modifiers /regexp/MOD, so fetch those too
569
+ while parser_pos < len(self.input) and self.input[parser_pos] in self.wordchar:
570
+ resulting_string += self.input[parser_pos]
571
+ parser_pos += 1
572
+ return resulting_string, 'TK_STRING'
573
+
574
+ if c == '#':
575
+
576
+ # she-bang
577
+ if len(self.output) == 0 and len(self.input) > 1 and self.input[parser_pos] == '!':
578
+ resulting_string = c
579
+ while parser_pos < len(self.input) and c != '\n':
580
+ c = self.input[parser_pos]
581
+ resulting_string += c
582
+ parser_pos += 1
583
+ self.output.append(resulting_string.strip() + "\n")
584
+ self.append_newline()
585
+ return self.get_next_token()
586
+
587
+
588
+ # Spidermonkey-specific sharp variables for circular references
589
+ # https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
590
+ # http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
591
+ sharp = '#'
592
+ if parser_pos < len(self.input) and self.input[parser_pos] in self.digits:
593
+ while True:
594
+ c = self.input[parser_pos]
595
+ sharp += c
596
+ parser_pos += 1
597
+ if parser_pos >= len(self.input) or c == '#' or c == '=':
598
+ break
599
+ if c == '#' or parser_pos >= len(self.input):
600
+ pass
601
+ elif self.input[parser_pos] == '[' and self.input[parser_pos + 1] == ']':
602
+ sharp += '[]'
603
+ parser_pos += 2
604
+ elif self.input[parser_pos] == '{' and self.input[parser_pos + 1] == '}':
605
+ sharp += '{}'
606
+ parser_pos += 2
607
+ return sharp, 'TK_WORD'
608
+
609
+ if c == '<' and self.input[parser_pos - 1 : parser_pos + 3] == '<!--':
610
+ parser_pos += 3
611
+ c = '<!--'
612
+ while parser_pos < len(self.input) and self.input[parser_pos] != '\n':
613
+ c += self.input[parser_pos]
614
+ parser_pos += 1
615
+ self.flags.in_html_comment = True
616
+ return c, 'TK_COMMENT'
617
+
618
+ if c == '-' and self.flags.in_html_comment and self.input[parser_pos - 1 : parser_pos + 2] == '-->':
619
+ self.flags.in_html_comment = False
620
+ parser_pos += 2
621
+ if self.wanted_newline:
622
+ self.append_newline()
623
+ return '-->', 'TK_COMMENT'
624
+
625
+ if c in self.punct:
626
+ while parser_pos < len(self.input) and c + self.input[parser_pos] in self.punct:
627
+ c += self.input[parser_pos]
628
+ parser_pos += 1
629
+ if parser_pos >= len(self.input):
630
+ break
631
+ if c == '=':
632
+ return c, 'TK_EQUALS'
633
+ else:
634
+ return c, 'TK_OPERATOR'
635
+ return c, 'TK_UNKNOWN'
636
+
637
+
638
+
639
+ def handle_start_expr(self, token_text):
640
+ if token_text == '[':
641
+ if self.last_type == 'TK_WORD' or self.last_text == ')':
642
+ if self.last_text in self.line_starters:
643
+ self.append(' ')
644
+ self.set_mode('(EXPRESSION)')
645
+ self.append(token_text)
646
+ return
647
+
648
+ if self.flags.mode in ['[EXPRESSION]', '[INDENTED-EXPRESSION]']:
649
+ if self.last_last_text == ']' and self.last_text == ',':
650
+ # ], [ goes to a new line
651
+ if self.flags.mode == '[EXPRESSION]':
652
+ self.flags.mode = '[INDENTED-EXPRESSION]'
653
+ if not self.opts.keep_array_indentation:
654
+ self.indent()
655
+ self.set_mode('[EXPRESSION]')
656
+ if not self.opts.keep_array_indentation:
657
+ self.append_newline()
658
+ elif self.last_text == '[':
659
+ if self.flags.mode == '[EXPRESSION]':
660
+ self.flags.mode = '[INDENTED-EXPRESSION]'
661
+ if not self.opts.keep_array_indentation:
662
+ self.indent()
663
+ self.set_mode('[EXPRESSION]')
664
+
665
+ if not self.opts.keep_array_indentation:
666
+ self.append_newline()
667
+ else:
668
+ self.set_mode('[EXPRESSION]')
669
+ else:
670
+ self.set_mode('[EXPRESSION]')
671
+ else:
672
+ if self.last_text == 'for':
673
+ self.set_mode('(FOR-EXPRESSION)')
674
+ elif self.last_text in ['if', 'while']:
675
+ self.set_mode('(COND-EXPRESSION)')
676
+ else:
677
+ self.set_mode('(EXPRESSION)')
678
+
679
+
680
+ if self.last_text == ';' or self.last_type == 'TK_START_BLOCK':
681
+ self.append_newline()
682
+ elif self.last_type in ['TK_END_EXPR', 'TK_START_EXPR', 'TK_END_BLOCK'] or self.last_text == '.':
683
+ # do nothing on (( and )( and ][ and ]( and .(
684
+ if self.wanted_newline:
685
+ self.append_newline();
686
+ elif self.last_type not in ['TK_WORD', 'TK_OPERATOR']:
687
+ self.append(' ')
688
+ elif self.last_word == 'function' or self.last_word == 'typeof':
689
+ # function() vs function (), typeof() vs typeof ()
690
+ if self.opts.jslint_happy:
691
+ self.append(' ')
692
+ elif self.last_text in self.line_starters or self.last_text == 'catch':
693
+ self.append(' ')
694
+
695
+ self.append(token_text)
696
+
697
+
698
+ def handle_end_expr(self, token_text):
699
+ if token_text == ']':
700
+ if self.opts.keep_array_indentation:
701
+ if self.last_text == '}':
702
+ self.remove_indent()
703
+ self.append(token_text)
704
+ self.restore_mode()
705
+ return
706
+ else:
707
+ if self.flags.mode == '[INDENTED-EXPRESSION]':
708
+ if self.last_text == ']':
709
+ self.restore_mode()
710
+ self.append_newline()
711
+ self.append(token_text)
712
+ return
713
+ self.restore_mode()
714
+ self.append(token_text)
715
+
716
+
717
+ def handle_start_block(self, token_text):
718
+ if self.last_word == 'do':
719
+ self.set_mode('DO_BLOCK')
720
+ else:
721
+ self.set_mode('BLOCK')
722
+
723
+ if self.opts.brace_style == 'expand':
724
+ if self.last_type != 'TK_OPERATOR':
725
+ if self.last_text == '=' or (self.is_special_word(self.last_text) and self.last_text != 'else'):
726
+ self.append(' ')
727
+ else:
728
+ self.append_newline(True)
729
+
730
+ self.append(token_text)
731
+ self.indent()
732
+ else:
733
+ if self.last_type not in ['TK_OPERATOR', 'TK_START_EXPR']:
734
+ if self.last_type == 'TK_START_BLOCK':
735
+ self.append_newline()
736
+ else:
737
+ self.append(' ')
738
+ else:
739
+ # if TK_OPERATOR or TK_START_EXPR
740
+ if self.is_array(self.flags.previous_mode) and self.last_text == ',':
741
+ if self.last_last_text == '}':
742
+ self.append(' ')
743
+ else:
744
+ self.append_newline()
745
+ self.indent()
746
+ self.append(token_text)
747
+
748
+
749
+ def handle_end_block(self, token_text):
750
+ self.restore_mode()
751
+ if self.opts.brace_style == 'expand':
752
+ if self.last_text != '{':
753
+ self.append_newline()
754
+ else:
755
+ if self.last_type == 'TK_START_BLOCK':
756
+ if self.just_added_newline:
757
+ self.remove_indent()
758
+ else:
759
+ # {}
760
+ self.trim_output()
761
+ else:
762
+ if self.is_array(self.flags.mode) and self.opts.keep_array_indentation:
763
+ self.opts.keep_array_indentation = False
764
+ self.append_newline()
765
+ self.opts.keep_array_indentation = True
766
+ else:
767
+ self.append_newline()
768
+
769
+ self.append(token_text)
770
+
771
+
772
+ def handle_word(self, token_text):
773
+ if self.do_block_just_closed:
774
+ self.append(' ')
775
+ self.append(token_text)
776
+ self.append(' ')
777
+ self.do_block_just_closed = False
778
+ return
779
+
780
+ if token_text == 'function':
781
+
782
+ if self.flags.var_line:
783
+ self.flags.var_line_reindented = not self.opts.keep_function_indentation
784
+ if (self.just_added_newline or self.last_text == ';') and self.last_text != '{':
785
+ # make sure there is a nice clean space of at least one blank line
786
+ # before a new function definition
787
+ have_newlines = self.n_newlines
788
+ if not self.just_added_newline:
789
+ have_newlines = 0
790
+ if not self.opts.preserve_newlines:
791
+ have_newlines = 1
792
+ for i in range(2 - have_newlines):
793
+ self.append_newline(False)
794
+
795
+ if token_text == 'case' or (token_text == 'default' and self.flags.in_case_statement):
796
+ if self.last_text == ':':
797
+ self.remove_indent()
798
+ else:
799
+ self.flags.indentation_level -= 1
800
+ self.append_newline()
801
+ self.flags.indentation_level += 1
802
+ self.append(token_text)
803
+ self.flags.in_case = True
804
+ self.flags.in_case_statement = True
805
+ return
806
+
807
+ prefix = 'NONE'
808
+
809
+ if self.last_type == 'TK_END_BLOCK':
810
+ if token_text not in ['else', 'catch', 'finally']:
811
+ prefix = 'NEWLINE'
812
+ else:
813
+ if self.opts.brace_style in ['expand', 'end-expand']:
814
+ prefix = 'NEWLINE'
815
+ else:
816
+ prefix = 'SPACE'
817
+ self.append(' ')
818
+ elif self.last_type == 'TK_SEMICOLON' and self.flags.mode in ['BLOCK', 'DO_BLOCK']:
819
+ prefix = 'NEWLINE'
820
+ elif self.last_type == 'TK_SEMICOLON' and self.is_expression(self.flags.mode):
821
+ prefix = 'SPACE'
822
+ elif self.last_type == 'TK_STRING':
823
+ prefix = 'NEWLINE'
824
+ elif self.last_type == 'TK_WORD':
825
+ if self.last_text == 'else':
826
+ # eat newlines between ...else *** some_op...
827
+ # won't preserve extra newlines in this place (if any), but don't care that much
828
+ self.trim_output(True)
829
+ prefix = 'SPACE'
830
+ elif self.last_type == 'TK_START_BLOCK':
831
+ prefix = 'NEWLINE'
832
+ elif self.last_type == 'TK_END_EXPR':
833
+ self.append(' ')
834
+ prefix = 'NEWLINE'
835
+
836
+ if self.flags.if_line and self.last_type == 'TK_END_EXPR':
837
+ self.flags.if_line = False
838
+
839
+ if token_text in self.line_starters:
840
+ if self.last_text == 'else':
841
+ prefix = 'SPACE'
842
+ else:
843
+ prefix = 'NEWLINE'
844
+
845
+ if token_text == 'function' and self.last_text in ['get', 'set']:
846
+ prefix = 'SPACE'
847
+
848
+ if token_text in ['else', 'catch', 'finally']:
849
+ if self.last_type != 'TK_END_BLOCK' \
850
+ or self.opts.brace_style == 'expand' \
851
+ or self.opts.brace_style == 'end-expand':
852
+ self.append_newline()
853
+ else:
854
+ self.trim_output(True)
855
+ self.append(' ')
856
+ elif prefix == 'NEWLINE':
857
+ if token_text == 'function' and (self.last_type == 'TK_START_EXPR' or self.last_text in '=,'):
858
+ # no need to force newline on "function" -
859
+ # (function...
860
+ pass
861
+ elif token_text == 'function' and self.last_text == 'new':
862
+ self.append(' ')
863
+ elif self.is_special_word(self.last_text):
864
+ # no newline between return nnn
865
+ self.append(' ')
866
+ elif self.last_type != 'TK_END_EXPR':
867
+ if (self.last_type != 'TK_START_EXPR' or token_text != 'var') and self.last_text != ':':
868
+ # no need to force newline on VAR -
869
+ # for (var x = 0...
870
+ if token_text == 'if' and self.last_word == 'else' and self.last_text != '{':
871
+ self.append(' ')
872
+ else:
873
+ self.flags.var_line = False
874
+ self.flags.var_line_reindented = False
875
+ self.append_newline()
876
+ elif token_text in self.line_starters and self.last_text != ')':
877
+ self.flags.var_line = False
878
+ self.flags.var_line_reindented = False
879
+ self.append_newline()
880
+ elif self.is_array(self.flags.mode) and self.last_text == ',' and self.last_last_text == '}':
881
+ self.append_newline() # }, in lists get a newline
882
+ elif prefix == 'SPACE':
883
+ self.append(' ')
884
+
885
+
886
+ self.append(token_text)
887
+ self.last_word = token_text
888
+
889
+ if token_text == 'var':
890
+ self.flags.var_line = True
891
+ self.flags.var_line_reindented = False
892
+ self.flags.var_line_tainted = False
893
+
894
+
895
+ if token_text == 'if':
896
+ self.flags.if_line = True
897
+
898
+ if token_text == 'else':
899
+ self.flags.if_line = False
900
+
901
+
902
+ def handle_semicolon(self, token_text):
903
+ self.append(token_text)
904
+ self.flags.var_line = False
905
+ self.flags.var_line_reindented = False
906
+ if self.flags.mode == 'OBJECT':
907
+ # OBJECT mode is weird and doesn't get reset too well.
908
+ self.flags.mode = 'BLOCK'
909
+
910
+
911
+ def handle_string(self, token_text):
912
+ if self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in ['(COND-EXPRESSION)', '(FOR-EXPRESSION)']:
913
+ self.append(' ')
914
+ if self.last_type in ['TK_STRING', 'TK_START_BLOCK', 'TK_END_BLOCK', 'TK_SEMICOLON']:
915
+ self.append_newline()
916
+ elif self.last_type == 'TK_WORD':
917
+ self.append(' ')
918
+
919
+ # Try to replace readable \x-encoded characters with their equivalent,
920
+ # if it is possible (e.g. '\x41\x42\x43\x01' becomes 'ABC\x01').
921
+ def unescape(match):
922
+ block, code = match.group(0, 1)
923
+ char = chr(int(code, 16))
924
+ if block.count('\\') == 1 and char in string.printable:
925
+ return char
926
+ return block
927
+
928
+ token_text = re.sub(r'\\{1,2}x([a-fA-F0-9]{2})', unescape, token_text)
929
+
930
+ self.append(token_text)
931
+
932
+ def handle_equals(self, token_text):
933
+ if self.flags.var_line:
934
+ # just got an '=' in a var-line, different line breaking rules will apply
935
+ self.flags.var_line_tainted = True
936
+
937
+ self.append(' ')
938
+ self.append(token_text)
939
+ self.append(' ')
940
+
941
+
942
+ def handle_operator(self, token_text):
943
+ space_before = True
944
+ space_after = True
945
+
946
+ if self.flags.var_line and token_text == ',' and self.is_expression(self.flags.mode):
947
+ # do not break on comma, for ( var a = 1, b = 2
948
+ self.flags.var_line_tainted = False
949
+
950
+ if self.flags.var_line and token_text == ',':
951
+ if self.flags.var_line_tainted:
952
+ self.append(token_text)
953
+ self.flags.var_line_reindented = True
954
+ self.flags.var_line_tainted = False
955
+ self.append_newline()
956
+ return
957
+ else:
958
+ self.flags.var_line_tainted = False
959
+
960
+ if self.is_special_word(self.last_text):
961
+ # return had a special handling in TK_WORD
962
+ self.append(' ')
963
+ self.append(token_text)
964
+ return
965
+
966
+ # hack for actionscript's import .*;
967
+ if token_text == '*' and self.last_type == 'TK_UNKNOWN' and not self.last_last_text.isdigit():
968
+ self.append(token_text)
969
+ return
970
+
971
+
972
+ if token_text == ':' and self.flags.in_case:
973
+ self.append(token_text)
974
+ self.append_newline()
975
+ self.flags.in_case = False
976
+ return
977
+
978
+ if token_text == '::':
979
+ # no spaces around the exotic namespacing syntax operator
980
+ self.append(token_text)
981
+ return
982
+
983
+
984
+ if token_text == ',':
985
+ if self.flags.var_line:
986
+ if self.flags.var_line_tainted:
987
+ # This never happens, as it's handled previously, right?
988
+ self.append(token_text)
989
+ self.append_newline()
990
+ self.flags.var_line_tainted = False
991
+ else:
992
+ self.append(token_text)
993
+ self.append(' ')
994
+ elif self.last_type == 'TK_END_BLOCK' and self.flags.mode != '(EXPRESSION)':
995
+ self.append(token_text)
996
+ if self.flags.mode == 'OBJECT' and self.last_text == '}':
997
+ self.append_newline()
998
+ else:
999
+ self.append(' ')
1000
+ else:
1001
+ if self.flags.mode == 'OBJECT':
1002
+ self.append(token_text)
1003
+ self.append_newline()
1004
+ else:
1005
+ # EXPR or DO_BLOCK
1006
+ self.append(token_text)
1007
+ self.append(' ')
1008
+ # comma handled
1009
+ return
1010
+ elif token_text in ['--', '++', '!'] \
1011
+ or (token_text in ['+', '-'] \
1012
+ and (self.last_type in ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR'] \
1013
+ or self.last_text in self.line_starters)):
1014
+
1015
+ space_before = False
1016
+ space_after = False
1017
+
1018
+ if self.last_text == ';' and self.is_expression(self.flags.mode):
1019
+ # for (;; ++i)
1020
+ # ^^
1021
+ space_before = True
1022
+
1023
+ if self.last_type == 'TK_WORD' and self.last_text in self.line_starters:
1024
+ space_before = True
1025
+
1026
+ if self.flags.mode == 'BLOCK' and self.last_text in ['{', ';']:
1027
+ # { foo: --i }
1028
+ # foo(): --bar
1029
+ self.append_newline()
1030
+
1031
+ elif token_text == '.':
1032
+ # decimal digits or object.property
1033
+ space_before = False
1034
+
1035
+ elif token_text == ':':
1036
+ if self.flags.ternary_depth == 0:
1037
+ if self.flags.mode == 'BLOCK':
1038
+ self.flags.mode = 'OBJECT'
1039
+ space_before = False
1040
+ else:
1041
+ self.flags.ternary_depth -= 1
1042
+ elif token_text == '?':
1043
+ self.flags.ternary_depth += 1
1044
+
1045
+ if space_before:
1046
+ self.append(' ')
1047
+
1048
+ self.append(token_text)
1049
+
1050
+ if space_after:
1051
+ self.append(' ')
1052
+
1053
+
1054
+
1055
+ def handle_block_comment(self, token_text):
1056
+
1057
+ lines = token_text.replace('\x0d', '').split('\x0a')
1058
+ # all lines start with an asterisk? that's a proper box comment
1059
+ if not any(l for l in lines[1:] if ( l.strip() == '' or (l.lstrip())[0] != '*')):
1060
+ self.append_newline()
1061
+ self.append(lines[0])
1062
+ for line in lines[1:]:
1063
+ self.append_newline()
1064
+ self.append(' ' + line.strip())
1065
+ else:
1066
+ # simple block comment: leave intact
1067
+ if len(lines) > 1:
1068
+ # multiline comment starts on a new line
1069
+ self.append_newline()
1070
+ else:
1071
+ # single line /* ... */ comment stays on the same line
1072
+ self.append(' ')
1073
+ for line in lines:
1074
+ self.append(line)
1075
+ self.append('\n')
1076
+ self.append_newline()
1077
+
1078
+
1079
+ def handle_inline_comment(self, token_text):
1080
+ self.append(' ')
1081
+ self.append(token_text)
1082
+ if self.is_expression(self.flags.mode):
1083
+ self.append(' ')
1084
+ else:
1085
+ self.append_newline_forced()
1086
+
1087
+
1088
+ def handle_comment(self, token_text):
1089
+ if self.last_type == 'TK_COMMENT':
1090
+ self.append_newline()
1091
+ if self.wanted_newline:
1092
+ self.append_newline(False)
1093
+ else:
1094
+ if self.wanted_newline:
1095
+ self.append_newline()
1096
+ else:
1097
+ self.append(' ')
1098
+
1099
+ self.append(token_text)
1100
+ self.append_newline_forced()
1101
+
1102
+
1103
+ def handle_unknown(self, token_text):
1104
+ if self.last_text in ['return', 'throw']:
1105
+ self.append(' ')
1106
+
1107
+ self.append(token_text)
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+ def main():
1114
+
1115
+ argv = sys.argv[1:]
1116
+
1117
+ try:
1118
+ opts, args = getopt.getopt(argv, "s:c:o:djbkil:htf", ['indent-size=','indent-char=','outfile=', 'disable-preserve-newlines',
1119
+ 'jslint-happy', 'brace-style=',
1120
+ 'keep-array-indentation', 'indent-level=', 'help',
1121
+ 'usage', 'stdin', 'eval-code', 'indent-with-tabs', 'keep-function-indentation'])
1122
+ except getopt.GetoptError:
1123
+ return usage()
1124
+
1125
+ js_options = default_options()
1126
+
1127
+ file = None
1128
+ outfile = 'stdout'
1129
+ if len(args) == 1:
1130
+ file = args[0]
1131
+
1132
+ for opt, arg in opts:
1133
+ if opt in ('--keep-array-indentation', '-k'):
1134
+ js_options.keep_array_indentation = True
1135
+ if opt in ('--keep-function-indentation','-f'):
1136
+ js_options.keep_function_indentation = True
1137
+ elif opt in ('--outfile', '-o'):
1138
+ outfile = arg
1139
+ elif opt in ('--indent-size', '-s'):
1140
+ js_options.indent_size = int(arg)
1141
+ elif opt in ('--indent-char', '-c'):
1142
+ js_options.indent_char = arg
1143
+ elif opt in ('--indent-with-tabs', '-t'):
1144
+ js_options.indent_with_tabs = True
1145
+ elif opt in ('--disable-preserve_newlines', '-d'):
1146
+ js_options.preserve_newlines = False
1147
+ elif opt in ('--jslint-happy', '-j'):
1148
+ js_options.jslint_happy = True
1149
+ elif opt in ('--eval-code'):
1150
+ js_options.eval_code = True
1151
+ elif opt in ('--brace-style', '-b'):
1152
+ js_options.brace_style = arg
1153
+ elif opt in ('--stdin', '-i'):
1154
+ file = '-'
1155
+ elif opt in ('--help', '--usage', '-h'):
1156
+ return usage()
1157
+
1158
+ if not file:
1159
+ return usage()
1160
+ else:
1161
+ if outfile == 'stdout':
1162
+ print(beautify_file(file, js_options))
1163
+ else:
1164
+ with open(outfile, 'w') as f:
1165
+ f.write(beautify_file(file, js_options) + '\n')
1166
+