mirror of
https://github.com/beautifier/js-beautify.git
synced 2024-11-27 06:30:32 +00:00
Merge upstream changes into node-package
This commit is contained in:
commit
a42a7a0a01
@ -77,12 +77,13 @@ unescape_strings = %s
|
||||
|
||||
class BeautifierFlags:
|
||||
def __init__(self, mode):
|
||||
self.previous_mode = 'BLOCK'
|
||||
self.previous_mode = MODE.BlockStatement
|
||||
self.mode = mode
|
||||
self.var_line = False
|
||||
self.var_line_tainted = False
|
||||
self.var_line_reindented = False
|
||||
self.in_html_comment = False
|
||||
self.multiline_array = False
|
||||
self.if_block = False
|
||||
self.do_block = False
|
||||
self.do_while = False
|
||||
@ -158,7 +159,9 @@ Rarely needed options:
|
||||
|
||||
|
||||
|
||||
|
||||
class MODE:
|
||||
BlockStatement, Statement, ObjectLiteral, ArrayLiteral, \
|
||||
ForInitializer, Conditional, Expression = range(7)
|
||||
|
||||
class Beautifier:
|
||||
|
||||
@ -170,7 +173,7 @@ class Beautifier:
|
||||
def blank_state(self):
|
||||
|
||||
# internal flags
|
||||
self.flags = BeautifierFlags('BLOCK')
|
||||
self.flags = BeautifierFlags(MODE.BlockStatement)
|
||||
self.flag_store = []
|
||||
self.wanted_newline = False
|
||||
|
||||
@ -201,7 +204,8 @@ class Beautifier:
|
||||
|
||||
# Words which always should start on a new line
|
||||
self.line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',')
|
||||
self.set_mode('BLOCK')
|
||||
|
||||
self.set_mode(MODE.BlockStatement)
|
||||
|
||||
self.parser_pos = 0
|
||||
|
||||
@ -296,11 +300,11 @@ class Beautifier:
|
||||
return s in ['case', 'return', 'do', 'if', 'throw', 'else']
|
||||
|
||||
def is_array(self, mode):
|
||||
return mode in ['[EXPRESSION]', '[INDENTED-EXPRESSION]']
|
||||
return mode == MODE.ArrayLiteral
|
||||
|
||||
|
||||
def is_expression(self, mode):
|
||||
return mode in ['[EXPRESSION]', '[INDENTED-EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']
|
||||
return mode in [MODE.ArrayLiteral, MODE.Expression, MODE.ForInitializer, MODE.Conditional]
|
||||
|
||||
def just_added_newline(self):
|
||||
return len(self.output) and self.output[-1] == '\n'
|
||||
@ -342,9 +346,13 @@ class Beautifier:
|
||||
|
||||
if not preserve_statement_flags:
|
||||
if self.last_text != ';':
|
||||
while self.flags.mode == 'STATEMENT' and not self.flags.if_block:
|
||||
while self.flags.mode == MODE.Statement and not self.flags.if_block:
|
||||
self.restore_mode();
|
||||
|
||||
if self.flags.mode == MODE.ArrayLiteral:
|
||||
self.flags.multiline_array = True
|
||||
|
||||
|
||||
if len(self.output) == 0:
|
||||
# no newline on start of file
|
||||
return
|
||||
@ -398,7 +406,7 @@ class Beautifier:
|
||||
|
||||
def set_mode(self, mode):
|
||||
|
||||
prev = BeautifierFlags('BLOCK')
|
||||
prev = BeautifierFlags(MODE.BlockStatement)
|
||||
|
||||
if self.flags:
|
||||
self.flag_store.append(self.flags)
|
||||
@ -423,9 +431,9 @@ class Beautifier:
|
||||
def start_of_statement(self):
|
||||
if (self.last_text == 'do' \
|
||||
or (self.last_text == 'else' and self.token_text != 'if' ) \
|
||||
or (self.last_type == 'TK_END_EXPR' and (self.flags.previous_mode == '(FOR-EXPRESSION)' or self.flags.previous_mode == '(COND-EXPRESSION)'))):
|
||||
or (self.last_type == 'TK_END_EXPR' and (self.flags.previous_mode == MODE.ForInitializer or self.flags.previous_mode == MODE.Conditional))):
|
||||
self.allow_wrap_or_preserved_newline(self.token_text)
|
||||
self.set_mode('STATEMENT')
|
||||
self.set_mode(MODE.Statement)
|
||||
self.indent()
|
||||
self.output_wrapped = False
|
||||
return True
|
||||
@ -550,7 +558,7 @@ class Beautifier:
|
||||
|
||||
if c == "'" or c == '"' or \
|
||||
(c == '/' and ((self.last_type == 'TK_WORD' and self.is_special_word(self.last_text)) or \
|
||||
(self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in ['(FOR-EXPRESSION)', '(COND-EXPRESSION)']) or \
|
||||
(self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in [MODE.ForInitializer, MODE.Conditional]) or \
|
||||
(self.last_type in ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK', 'TK_END_BLOCK', 'TK_OPERATOR',
|
||||
'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA']))):
|
||||
sep = c
|
||||
@ -700,40 +708,23 @@ class Beautifier:
|
||||
if self.last_type == 'TK_WORD' or self.last_text == ')':
|
||||
if self.last_text in self.line_starters:
|
||||
self.output_space_before_token = True
|
||||
self.set_mode('(EXPRESSION)')
|
||||
self.set_mode(MODE.Expression)
|
||||
self.append_token(token_text)
|
||||
return
|
||||
|
||||
if self.flags.mode in ['[EXPRESSION]', '[INDENTED-EXPRESSION]']:
|
||||
if self.last_last_text == ']' and self.last_text == ',':
|
||||
if self.is_array(self.flags.mode):
|
||||
if self.last_text == '[' or (self.last_last_text == ']' and self.last_text == ','):
|
||||
# ], [ goes to a new line
|
||||
if self.flags.mode == '[EXPRESSION]':
|
||||
self.flags.mode = '[INDENTED-EXPRESSION]'
|
||||
if not self.opts.keep_array_indentation:
|
||||
self.indent()
|
||||
self.set_mode('[EXPRESSION]')
|
||||
if not self.opts.keep_array_indentation:
|
||||
self.append_newline()
|
||||
elif self.last_text == '[':
|
||||
if self.flags.mode == '[EXPRESSION]':
|
||||
self.flags.mode = '[INDENTED-EXPRESSION]'
|
||||
if not self.opts.keep_array_indentation:
|
||||
self.indent()
|
||||
self.set_mode('[EXPRESSION]')
|
||||
|
||||
if not self.opts.keep_array_indentation:
|
||||
self.append_newline()
|
||||
else:
|
||||
self.set_mode('[EXPRESSION]')
|
||||
else:
|
||||
self.set_mode('[EXPRESSION]')
|
||||
else:
|
||||
if self.last_text == 'for':
|
||||
self.set_mode('(FOR-EXPRESSION)')
|
||||
self.set_mode(MODE.ForInitializer)
|
||||
elif self.last_text in ['if', 'while']:
|
||||
self.set_mode('(COND-EXPRESSION)')
|
||||
self.set_mode(MODE.Conditional)
|
||||
else:
|
||||
self.set_mode('(EXPRESSION)')
|
||||
self.set_mode(MODE.Expression)
|
||||
|
||||
|
||||
if self.last_text == ';' or self.last_type == 'TK_START_BLOCK':
|
||||
@ -760,28 +751,32 @@ class Beautifier:
|
||||
self.allow_wrap_or_preserved_newline(token_text)
|
||||
|
||||
self.append_token(token_text)
|
||||
if self.token_text == '[':
|
||||
self.set_mode(MODE.ArrayLiteral)
|
||||
self.indent()
|
||||
|
||||
|
||||
|
||||
def handle_end_expr(self, token_text):
|
||||
if token_text == ']':
|
||||
if not self.opts.keep_array_indentation:
|
||||
if self.flags.mode == '[INDENTED-EXPRESSION]':
|
||||
if self.last_text == ']':
|
||||
self.restore_mode()
|
||||
self.append_newline()
|
||||
self.append_token(token_text)
|
||||
return
|
||||
# statements inside expressions are not valid syntax, but...
|
||||
# statements must all be closed when their container closes
|
||||
while self.flags.mode == MODE.Statement:
|
||||
self.restore_mode()
|
||||
|
||||
if self.token_text == ']' and self.is_array(self.flags.mode) and self.flags.multiline_array and not self.opts.keep_array_indentation:
|
||||
self.append_newline()
|
||||
|
||||
self.restore_mode()
|
||||
self.append_token(token_text)
|
||||
|
||||
# do {} while () // no statement required after
|
||||
if self.flags.do_while and self.flags.previous_mode == '(COND-EXPRESSION)':
|
||||
self.flags.previous_mode = '(EXPRESSION)'
|
||||
if self.flags.do_while and self.flags.previous_mode == MODE.Conditional:
|
||||
self.flags.previous_mode = MODE.Expression
|
||||
self.flags.do_block = False
|
||||
self.flags.do_while = False
|
||||
|
||||
def handle_start_block(self, token_text):
|
||||
self.set_mode('BLOCK')
|
||||
self.set_mode(MODE.BlockStatement)
|
||||
|
||||
empty_braces = self.is_next('}')
|
||||
if self.opts.brace_style == 'expand-strict':
|
||||
@ -812,6 +807,10 @@ class Beautifier:
|
||||
|
||||
|
||||
def handle_end_block(self, token_text):
|
||||
# statements must all be closed when their container closes
|
||||
while self.flags.mode == MODE.Statement:
|
||||
self.restore_mode()
|
||||
|
||||
self.restore_mode()
|
||||
if self.opts.brace_style == 'expand' or self.opts.brace_style == 'expand-strict':
|
||||
if self.last_text != '{':
|
||||
@ -858,7 +857,7 @@ class Beautifier:
|
||||
# Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();
|
||||
if self.flags.if_block:
|
||||
if token_text != 'else':
|
||||
while self.flags.mode == 'STATEMENT':
|
||||
while self.flags.mode == MODE.Statement:
|
||||
self.restore_mode()
|
||||
|
||||
self.flags.if_block = False;
|
||||
@ -917,7 +916,7 @@ class Beautifier:
|
||||
else:
|
||||
prefix = 'SPACE'
|
||||
self.output_space_before_token = True
|
||||
elif self.last_type == 'TK_SEMICOLON' and self.flags.mode in 'BLOCK':
|
||||
elif self.last_type == 'TK_SEMICOLON' and self.flags.mode == MODE.BlockStatement:
|
||||
# TODO: Should this be for STATEMENT as well?
|
||||
prefix = 'NEWLINE'
|
||||
elif self.last_type == 'TK_SEMICOLON' and self.is_expression(self.flags.mode):
|
||||
@ -992,7 +991,7 @@ class Beautifier:
|
||||
|
||||
|
||||
def handle_semicolon(self, token_text):
|
||||
while self.flags.mode == 'STATEMENT' and not self.flags.if_block:
|
||||
while self.flags.mode == MODE.Statement and not self.flags.if_block:
|
||||
self.restore_mode()
|
||||
|
||||
self.append_token(token_text)
|
||||
@ -1000,7 +999,7 @@ class Beautifier:
|
||||
self.flags.var_line_reindented = False
|
||||
if self.flags.mode == 'OBJECT':
|
||||
# OBJECT mode is weird and doesn't get reset too well.
|
||||
self.flags.mode = 'BLOCK'
|
||||
self.flags.mode = MODE.BlockStatement
|
||||
|
||||
|
||||
def handle_string(self, token_text):
|
||||
@ -1010,7 +1009,7 @@ class Beautifier:
|
||||
self.output_space_before_token = True
|
||||
elif self.last_type == 'TK_WORD':
|
||||
self.output_space_before_token = True
|
||||
elif self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in ['(COND-EXPRESSION)', '(FOR-EXPRESSION)']:
|
||||
elif self.last_type == 'TK_END_EXPR' and self.flags.previous_mode in [MODE.Conditional, MODE.ForInitializer]:
|
||||
self.output_space_before_token = True
|
||||
elif self.last_type in ['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']:
|
||||
if self.flags.mode != 'OBJECT':
|
||||
@ -1050,7 +1049,7 @@ class Beautifier:
|
||||
|
||||
return
|
||||
|
||||
if self.last_type == 'TK_END_BLOCK' and self.flags.mode != '(EXPRESSION)':
|
||||
if self.last_type == 'TK_END_BLOCK' and self.flags.mode != MODE.Expression:
|
||||
self.append_token(token_text)
|
||||
if self.flags.mode == 'OBJECT' and self.last_text == '}':
|
||||
self.append_newline()
|
||||
@ -1112,14 +1111,14 @@ class Beautifier:
|
||||
if self.last_type == 'TK_WORD' and self.last_text in self.line_starters:
|
||||
space_before = True
|
||||
|
||||
if self.flags.mode == 'BLOCK' and self.last_text in ['{', ';']:
|
||||
if self.flags.mode == MODE.BlockStatement and self.last_text in ['{', ';']:
|
||||
# { foo: --i }
|
||||
# foo(): --bar
|
||||
self.append_newline()
|
||||
|
||||
elif token_text == ':':
|
||||
if self.flags.ternary_depth == 0:
|
||||
if self.flags.mode == 'BLOCK':
|
||||
if self.flags.mode == MODE.BlockStatement:
|
||||
self.flags.mode = 'OBJECT'
|
||||
space_before = False
|
||||
else:
|
||||
|
@ -129,7 +129,13 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
bt("a = 1;\n // comment", "a = 1;\n// comment");
|
||||
bt('a = [-1, -1, -1]');
|
||||
|
||||
bt('o = [{a:b},{c:d}]', 'o = [{\n a: b\n}, {\n c: d\n}]');
|
||||
# The exact formatting these should have is open for discussion, but they are at least reasonable
|
||||
bt('a = [ // comment\n -1, -1, -1\n]');
|
||||
bt('var a = [ // comment\n -1, -1, -1\n]');
|
||||
bt('a = [ // comment\n -1, // comment\n -1, -1\n]');
|
||||
bt('var a = [ // comment\n -1, // comment\n -1, -1\n]');
|
||||
|
||||
bt('o = [{a:b},{c:d}]', 'o = [{\n a: b\n }, {\n c: d\n }\n]');
|
||||
|
||||
bt("if (a) {\n do();\n}"); # was: extra space appended
|
||||
|
||||
@ -183,7 +189,7 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
test_fragment('/incomplete-regex');
|
||||
|
||||
test_fragment('{a:1},{a:2}', '{\n a: 1\n}, {\n a: 2\n}');
|
||||
test_fragment('var ary=[{a:1}, {a:2}];', 'var ary = [{\n a: 1\n}, {\n a: 2\n}];');
|
||||
test_fragment('var ary=[{a:1}, {a:2}];', 'var ary = [{\n a: 1\n }, {\n a: 2\n }\n];');
|
||||
|
||||
test_fragment('{a:#1', '{\n a: #1'); # incomplete
|
||||
test_fragment('{a:#', '{\n a: #'); # incomplete
|
||||
@ -295,7 +301,7 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
bt("var a2, b2, c2, d2 = 0, c = function() {},\nd = '';", "var a2, b2, c2, d2 = 0,\n c = function() {},\n d = '';");
|
||||
bt('var o2=$.extend(a);function(){alert(x);}', 'var o2 = $.extend(a);\n\nfunction() {\n alert(x);\n}');
|
||||
|
||||
bt('{"x":[{"a":1,"b":3},7,8,8,8,8,{"b":99},{"a":11}]}', '{\n "x": [{\n "a": 1,\n "b": 3\n },\n 7, 8, 8, 8, 8, {\n "b": 99\n }, {\n "a": 11\n }]\n}');
|
||||
bt('{"x":[{"a":1,"b":3},7,8,8,8,8,{"b":99},{"a":11}]}', '{\n "x": [{\n "a": 1,\n "b": 3\n },\n 7, 8, 8, 8, 8, {\n "b": 99\n }, {\n "a": 11\n }\n ]\n}');
|
||||
|
||||
bt('{"1":{"1a":"1b"},"2"}', '{\n "1": {\n "1a": "1b"\n },\n "2"\n}');
|
||||
bt('{a:{a:b},c}', '{\n a: {\n a: b\n },\n c\n}');
|
||||
@ -353,12 +359,12 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
|
||||
|
||||
bt('var x = [{}\n]', 'var x = [{}\n]');
|
||||
bt('var x = [{foo:bar}\n]', 'var x = [{\n foo: bar\n}\n]');
|
||||
bt("a = ['something',\n'completely',\n'different'];\nif (x);");
|
||||
bt('var x = [{foo:bar}\n]', 'var x = [{\n foo: bar\n }\n]');
|
||||
bt("a = ['something',\n 'completely',\n 'different'];\nif (x);");
|
||||
bt("a = ['a','b','c']", "a = ['a', 'b', 'c']");
|
||||
bt("a = ['a', 'b','c']", "a = ['a', 'b', 'c']");
|
||||
|
||||
bt("x = [{'a':0}]", "x = [{\n 'a': 0\n}]");
|
||||
bt("x = [{'a':0}]", "x = [{\n 'a': 0\n }]");
|
||||
|
||||
bt('{a([[a1]], {b;});}', '{\n a([[a1]], {\n b;\n });\n}');
|
||||
|
||||
@ -673,6 +679,20 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
|
||||
bt('if (foo) if (bar) if (baz) whee();\na();');
|
||||
bt('if (foo) a()\nif (bar) if (baz) whee();\na();');
|
||||
bt('if (options)\n' +
|
||||
' for (var p in options)\n' +
|
||||
' this[p] = options[p];',
|
||||
'if (options) for (var p in options) this[p] = options[p];');
|
||||
|
||||
bt('function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
|
||||
'function f(a, b) {\n if (a) b()\n}\nfunction g(a, b) {\n if (!a) b()\n}');
|
||||
bt('function f(a,b) {if(a) b()}\n\n\n\nfunction g(a,b) {if(!a) b()}',
|
||||
'function f(a, b) {\n if (a) b()\n}\n\nfunction g(a, b) {\n if (!a) b()\n}');
|
||||
# This is not valid syntax, but still want to behave reasonably and not side-effect
|
||||
bt('(if(a) b())(if(a) b())',
|
||||
'(\nif (a) b())(\nif (a) b())');
|
||||
bt('(if(a) b())\n\n\n(if(a) b())',
|
||||
'(\nif (a) b())\n(\nif (a) b())');
|
||||
|
||||
bt("if\n(a)\nb();", "if (a) b();");
|
||||
bt('var a =\nfoo', 'var a = foo');
|
||||
@ -700,6 +720,20 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
|
||||
bt('if (foo) if (bar) if (baz) whee();\na();');
|
||||
bt('if (foo) a()\nif (bar) if (baz) whee();\na();');
|
||||
bt('if (options)\n' +
|
||||
' for (var p in options)\n' +
|
||||
' this[p] = options[p];');
|
||||
|
||||
bt('function f(a,b) {if(a) b()}function g(a,b) {if(!a) b()}',
|
||||
'function f(a, b) {\n if (a) b()\n}\nfunction g(a, b) {\n if (!a) b()\n}');
|
||||
bt('function f(a,b) {if(a) b()}\n\n\n\nfunction g(a,b) {if(!a) b()}',
|
||||
'function f(a, b) {\n if (a) b()\n}\n\n\n\nfunction g(a, b) {\n if (!a) b()\n}');
|
||||
# This is not valid syntax, but still want to behave reasonably and not side-effect
|
||||
bt('(if(a) b())(if(a) b())',
|
||||
'(\nif (a) b())(\nif (a) b())');
|
||||
bt('(if(a) b())\n\n\n(if(a) b())',
|
||||
'(\nif (a) b())\n\n\n(\nif (a) b())');
|
||||
|
||||
|
||||
bt("if\n(a)\nb();", "if (a)\n b();");
|
||||
bt('var a =\nfoo', 'var a =\n foo');
|
||||
|
Loading…
Reference in New Issue
Block a user