Merge pull request #182 from bitwiseman/master

Javascript line wrapping option based on expanded newline preservation points
This commit is contained in:
Einar Lielmanis 2013-03-13 02:48:00 -07:00
commit 3db9e37e2d
5 changed files with 487 additions and 43 deletions

View File

@ -46,6 +46,10 @@
unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65"
wrap_line_length (default unlimited) - lines should wrap at next opportunity after this number of characters.
NOTE: This is not a hard limit. Lines will continue until a point where a newline would
be preserved if it were present.
e.g
js_beautify(js_source_text, {
@ -53,7 +57,6 @@
'indent_char': '\t'
});
*/
@ -82,15 +85,16 @@ function js_beautify(js_source_text, options) {
opt_brace_style = options.brace_style ? options.brace_style : (opt_brace_style ? opt_brace_style : "collapse");
var opt_indent_size = options.indent_size ? options.indent_size : 4,
var opt_indent_size = options.indent_size ? parseInt(options.indent_size) : 4,
opt_indent_char = options.indent_char ? options.indent_char : ' ',
opt_preserve_newlines = typeof options.preserve_newlines === 'undefined' ? true : options.preserve_newlines,
opt_break_chained_methods = typeof options.break_chained_methods === 'undefined' ? false : options.break_chained_methods,
opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? false : options.max_preserve_newlines,
opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? 0 : parseInt(options.max_preserve_newlines),
opt_jslint_happy = options.jslint_happy === 'undefined' ? false : options.jslint_happy,
opt_keep_array_indentation = typeof options.keep_array_indentation === 'undefined' ? false : options.keep_array_indentation,
opt_space_before_conditional = typeof options.space_before_conditional === 'undefined' ? true : options.space_before_conditional,
opt_unescape_strings = typeof options.unescape_strings === 'undefined' ? false : options.unescape_strings;
opt_unescape_strings = typeof options.unescape_strings === 'undefined' ? false : options.unescape_strings,
opt_wrap_line_length = typeof options.wrap_line_length === 'undefined' ? 0 : parseInt(options.wrap_line_length);
just_added_newline = false;
@ -130,9 +134,22 @@ function js_beautify(js_source_text, options) {
return out;
}
function print_preserved_newline() {
if(opt_preserve_newlines && wanted_newline && !just_added_newline) {
print_newline(true);
function allow_wrap_or_preserved_newline(force_linewrap) {
force_linewrap = typeof force_linewrap === 'undefined' ? false : force_linewrap;
if (opt_wrap_line_length && !force_linewrap) {
var current_line = '';
var start_line = output.lastIndexOf('\n') + 1;
// never wrap the first token of a line.
if(start_line < output.length) {
current_line = output.slice(start_line).join('');
if(current_line.length + token_text.length >= opt_wrap_line_length) {
force_linewrap = true;
}
}
}
if(!just_added_newline &&
((opt_preserve_newlines && wanted_newline) || force_linewrap)) {
print_newline();
print_indent_string();
wanted_newline = false;
}
@ -792,6 +809,17 @@ function js_beautify(js_source_text, options) {
print_single_space();
}
}
// Support of this kind of newline preservation.
// a = (b &&
// (c || d));
if (token_text === '(') {
if(last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
if (flags.mode !== 'OBJECT') {
allow_wrap_or_preserved_newline();
}
}
}
print_token();
break;
@ -800,11 +828,10 @@ function js_beautify(js_source_text, options) {
if (is_special_word(last_text)) {
print_single_space();
} else if (last_text === ')') {
if (opt_break_chained_methods || wanted_newline) {
print_newline(true /* ignore_repeated */, false /* reset_statement_flags */);
print_indent_string();
}
} else {
// allow preserved newlines before dots in general
// force newlines on dots after close paren when break_chained - for bar().baz()
allow_wrap_or_preserved_newline(last_text === ')' && opt_break_chained_methods);
}
print_token();
@ -1028,7 +1055,7 @@ function js_beautify(js_source_text, options) {
if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
if (flags.mode !== 'OBJECT') {
print_preserved_newline();
allow_wrap_or_preserved_newline();
}
}
@ -1102,7 +1129,7 @@ function js_beautify(js_source_text, options) {
print_single_space();
} else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {
if (flags.mode !== 'OBJECT') {
print_preserved_newline();
allow_wrap_or_preserved_newline();
}
} else {
print_newline();

View File

@ -154,6 +154,7 @@ function read_settings_from_cookie() {
$('#break-chained-methods').attr('checked', $.cookie('break-chained-methods') === 'on');
$('#indent-scripts').val(any($.cookie('indent-scripts'), 'normal'));
$('#space-before-conditional').attr('checked', $.cookie('space-before-conditional') !== 'off');
$('#wrap-line-length').val(any($.cookie('wrap-line-length'), '0'));
$('#unescape-strings').attr('checked', $.cookie('unescape-strings') === 'on');
}
@ -167,6 +168,7 @@ function store_settings_to_cookie() {
$.cookie('break-chained-methods', $('#break-chained-methods').attr('checked') ? 'on' : 'off', opts);
$.cookie('space-before-conditional', $('#space-before-conditional').attr('checked') ? 'on' : 'off', opts);
$.cookie('unescape-strings', $('#unescape-strings').attr('checked') ? 'on' : 'off', opts);
$.cookie('wrap-line-length', $('#wrap-line-length').val(), opts);
$.cookie('indent-scripts', $('#indent-scripts').val(), opts);
}
@ -227,6 +229,7 @@ function beautify()
opts.brace_style = $('#brace-style').val();
opts.space_before_conditional = $('#space-before-conditional').attr('checked');
opts.unescape_strings = $('#unescape-strings').attr('checked');
opts.wrap_line_length = $('#wrap-line-length').val();
opts.space_after_anon_function = true;
if (looks_like_html(source)) {
@ -308,6 +311,16 @@ $(function() {
<option value="8">indent with 8 spaces</option>
</select><br>
<select name="wrap-line-length" id="wrap-line-length">
<option value="0">Do not wrap lines</option>
<option value="40">Wrap lines near 40 characters</option>
<option value="70">Wrap lines near 70 characters</option>
<option value="80">Wrap lines near 80 characters</option>
<option value="110">Wrap lines near 110 characters</option>
<option value="120">Wrap lines near 120 characters</option>
<option value="160">Wrap lines near 160 characters</option>
</select><br>
<select id="brace-style">
<option value="collapse">Braces with control statement</option>
<option value="expand">Braces on own line</option>

View File

@ -43,6 +43,7 @@ class BeautifierOptions:
self.keep_function_indentation = False
self.eval_code = False
self.unescape_strings = False
self.wrap_line_length = 0
self.break_chained_methods = False
@ -58,6 +59,7 @@ indent_with_tabs = %s
brace_style = %s
keep_array_indentation = %s
eval_code = %s
wrap_line_length = %s
unescape_strings = %s
""" % ( self.indent_size,
self.indent_char,
@ -68,6 +70,7 @@ unescape_strings = %s
self.brace_style,
self.keep_array_indentation,
self.eval_code,
self.wrap_line_length,
self.unescape_strings,
)
@ -136,7 +139,9 @@ Output options:
-k, --keep-array-indentation keep array indentation.
-o, --outfile=FILE specify a file to output to (default stdout)
-f, --keep-function-indentation Do not re-indent function bodies defined in var lines.
-x, --unescape-strings Decode printable chars encoded in \\xNN notation.
-x, --unescape-strings Decode printable chars encoded in \\xNN notation.
-w, --wrap-line-length Attempt to wrap line when it exceeds this length.
NOTE: Line continues until next wrap point is found.
Rarely needed options:
@ -288,9 +293,26 @@ class Beautifier:
self.append_newline()
self.opts.keep_array_indentation = old_array_indentation
def append_preserved_newline(self):
if self.opts.preserve_newlines and self.wanted_newline and not self.just_added_newline:
self.append_newline()
def allow_wrap_or_preserved_newline(self, token_text, force_linewrap = False):
if self.opts.wrap_line_length > 0 and not force_linewrap:
start_line = len(self.output) - 1
while start_line >= 0:
if self.output[start_line] == '\n':
break
else:
start_line -= 1
start_line += 1
# never wrap the first token of a line.
if start_line < len(self.output):
current_line = ''.join(self.output[start_line:])
if len(current_line) + len(token_text) >= self.opts.wrap_line_length:
force_linewrap = True;
if not self.just_added_newline and ((self.opts.preserve_newlines and self.wanted_newline) or force_linewrap):
self.append_newline(reset_statement_flags = False)
self.append_indent_string()
self.wanted_newline = False
@ -724,6 +746,13 @@ class Beautifier:
elif self.last_text in self.line_starters or self.last_text == 'catch':
self.append(' ')
# Support of this kind of newline preservation:
# a = (b &&
# (c || d));
if self.last_type in ['TK_EQUALS', 'TK_OPERATOR']:
if self.flags.mode != 'OBJECT':
self.allow_wrap_or_preserved_newline(token_text)
self.append(token_text)
@ -890,7 +919,7 @@ class Beautifier:
if self.last_type in ['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']:
if self.flags.mode != 'OBJECT':
self.append_preserved_newline()
self.allow_wrap_or_preserved_newline(token_text)
if token_text in self.line_starters:
if self.last_text == 'else':
@ -962,7 +991,7 @@ class Beautifier:
self.append(' ')
elif self.last_type in ['TK_COMMA', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']:
if self.flags.mode != 'OBJECT':
self.append_preserved_newline()
self.allow_wrap_or_preserved_newline(token_text)
else:
self.append_newline()
@ -1137,10 +1166,12 @@ class Beautifier:
def handle_dot(self, token_text):
if self.is_special_word(self.last_text):
self.append(' ')
elif self.last_text == ')':
if self.opts.break_chained_methods or self.wanted_newline:
self.flags.chain_extra_indentation = 1;
self.append_newline(True, False)
else:
# allow preserved newlines before dots in general
# force newlines on dots after close paren when break_chained - for bar().baz()
self.allow_wrap_or_preserved_newline(token_text,
self.last_text == ')' and self.opts.break_chained_methods)
self.append(token_text)
def handle_unknown(self, token_text):
@ -1192,6 +1223,8 @@ def main():
js_options.brace_style = arg
elif opt in ('--unescape-strings', '-x'):
js_options.unescape_strings = True
elif opt in ('--wrap-line-length ', '-w'):
js_options.wrap_line_length = int(arg)
elif opt in ('--stdin', '-i'):
file = '-'
elif opt in ('--help', '--usage', '-h'):

View File

@ -480,12 +480,195 @@ class TestJSBeautifier(unittest.TestCase):
bt("var a = \"foo\" +\n \"bar\";");
self.options.break_chained_methods = True
bt('foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)');
bt('foo.bar().baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo.bar().baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something = foo.bar().baz().cucumber(fat)', 'this.something = foo.bar()\n .baz()\n .cucumber(fat)');
self.options.break_chained_methods = False
self.options.preserve_newlines = False
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar().baz().cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()');
self.options.break_chained_methods = False
self.options.preserve_newlines = True
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz().cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()');
self.options.break_chained_methods = True
self.options.preserve_newlines = False
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()');
self.options.break_chained_methods = True
self.options.preserve_newlines = True
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()');
self.options.break_chained_methods = False
self.options.preserve_newlines = False
self.options.preserve_newlines = False
self.options.wrap_line_length = 0
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();')
self.options.wrap_line_length = 70
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();');
self.options.wrap_line_length = 40
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat &&\n' +
' "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();');
self.options.wrap_line_length = 41
# NOTE: wrap is only best effort - line continues until next wrap point is found.
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();');
self.options.wrap_line_length = 45
# NOTE: wrap is only best effort - line continues until next wrap point is found.
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('{\n' +
' foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
'}',
# expected #
'{\n' +
' foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();\n' +
'}');
self.options.preserve_newlines = True
self.options.wrap_line_length = 0
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();');
self.options.wrap_line_length = 70
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();');
self.options.wrap_line_length = 40
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat &&\n' +
' "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();');
self.options.wrap_line_length = 41
# NOTE: wrap is only best effort - line continues until next wrap point is found.
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
# expected #
'foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();');
self.options.wrap_line_length = 45
# NOTE: wrap is only best effort - line continues until next wrap point is found.
#..............---------1---------2---------3---------4---------5---------6---------7
#..............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('{\n' +
' foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
'}',
# expected #
'{\n' +
' foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
'}');
self.options.wrap_line_length = 0
self.options.preserve_newlines = False
bt('var a =\nfoo', 'var a = foo');
@ -495,7 +678,8 @@ class TestJSBeautifier(unittest.TestCase):
bt('var a = /*i*/\n"b";', 'var a = /*i*/ "b";');
bt('var a = /*i*/\nb;', 'var a = /*i*/ b;');
bt('{\n\n\n"x"\n}', '{\n "x"\n}');
bt('if(a && b &&\nc\n&& d && e) e = f', 'if (a && b && c && d && e) e = f');
bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a && b || c || d && e) e = f');
bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a && (b || c || d) && e) e = f');
test_fragment('\n\n"x"', '"x"');
self.options.preserve_newlines = True
bt('var a =\nfoo', 'var a =\n foo');
@ -504,8 +688,9 @@ class TestJSBeautifier(unittest.TestCase):
bt('var a = /*i*/ "b";');
bt('var a = /*i*/\n"b";', 'var a = /*i*/\n "b";');
bt('var a = /*i*/\nb;', 'var a = /*i*/\n b;');
bt('if(a && b &&\nc\n&& d && e) e = f', 'if (a && b &&\n c && d && e) e = f');
bt('{\n\n\n"x"\n}', '{\n\n\n "x"\n}');
bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a &&\n b ||\n c || d &&\n e) e = f');
bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a &&\n (b ||\n c || d) &&\n e) e = f');
test_fragment('\n\n"x"', '"x"');

View File

@ -497,6 +497,8 @@ function run_beautifier_tests(test_obj)
bt('switch (createdAt) {\n case a:\n Date,\n default:\n Date.now\n}');
opts.space_before_conditional = false;
bt('if(a) b()');
opts.space_before_conditional = true;
opts.preserve_newlines = true;
bt('var a = 42; // foo\n\nvar b;');
@ -536,21 +538,203 @@ function run_beautifier_tests(test_obj)
// bt('if (foo) // comment\n (bar());');
// bt('if (foo) // comment\n (bar());');
// bt('if (foo) // comment\n /asdf/;');
bt('if(foo) // comment\nbar();');
bt('if(foo) // comment\n(bar());');
bt('if(foo) // comment\n(bar());');
bt('if(foo) // comment\n/asdf/;');
bt('if (foo) // comment\nbar();');
bt('if (foo) // comment\n(bar());');
bt('if (foo) // comment\n(bar());');
bt('if (foo) // comment\n/asdf/;');
bt('/* foo */\n"x"');
opts.break_chained_methods = true;
bt('foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)');
bt('foo.bar().baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo.bar().baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something = foo.bar().baz().cucumber(fat)', 'this.something = foo.bar()\n .baz()\n .cucumber(fat)');
opts.break_chained_methods = false;
opts.preserve_newlines = false;
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar().baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar().baz().cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()');
opts.break_chained_methods = false;
opts.preserve_newlines = true;
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat);\nfoo.bar().baz().cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz().cucumber(fat)\nfoo.bar().baz().cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz().cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()');
opts.break_chained_methods = true;
opts.preserve_newlines = false;
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo.bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this.something = foo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this.something.xxx = foo.moo.bar()');
opts.break_chained_methods = true;
opts.preserve_newlines = true;
bt('foo\n.bar()\n.baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat); foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat);\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('foo\n.bar()\n.baz().cucumber(fat)\n foo.bar().baz().cucumber(fat)', 'foo\n .bar()\n .baz()\n .cucumber(fat)\nfoo.bar()\n .baz()\n .cucumber(fat)');
bt('this\n.something = foo.bar()\n.baz().cucumber(fat)', 'this\n .something = foo.bar()\n .baz()\n .cucumber(fat)');
bt('this.something.xxx = foo.moo.bar()');
bt('this\n.something\n.xxx = foo.moo\n.bar()', 'this\n .something\n .xxx = foo.moo\n .bar()');
opts.break_chained_methods = false;
opts.preserve_newlines = false;
opts.wrap_line_length = 0;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();');
opts.wrap_line_length = 70;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_.okay();');
opts.wrap_line_length = 40;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat &&\n' +
' "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();');
opts.wrap_line_length = 41;
// NOTE: wrap is only best effort - line continues until next wrap point is found.
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();');
opts.wrap_line_length = 45;
// NOTE: wrap is only best effort - line continues until next wrap point is found.
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('{\n' +
' foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
'}',
/* expected */
'{\n' +
' foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_.okay();\n' +
'}');
opts.preserve_newlines = true;
opts.wrap_line_length = 0;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();');
opts.wrap_line_length = 70;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n' +
' .okay();');
opts.wrap_line_length = 40;
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat &&\n' +
' "sassy") || (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();');
opts.wrap_line_length = 41;
// NOTE: wrap is only best effort - line continues until next wrap point is found.
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
'if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();',
/* expected */
'foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
'Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
'if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();');
opts.wrap_line_length = 45;
// NOTE: wrap is only best effort - line continues until next wrap point is found.
//.............---------1---------2---------3---------4---------5---------6---------7
//.............1234567890123456789012345678901234567890123456789012345678901234567890
test_fragment('{\n' +
' foo.bar().baz().cucumber((fat && "sassy") || (leans\n&& mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n.but_this_can\n' +
' if (wraps_can_occur && inside_an_if_block) that_is_\n.okay();\n' +
'}',
/* expected */
'{\n' +
' foo.bar().baz().cucumber((fat && "sassy") ||\n' +
' (leans && mean));\n' +
' Test_very_long_variable_name_this_should_never_wrap\n' +
' .but_this_can\n' +
' if (wraps_can_occur &&\n' +
' inside_an_if_block) that_is_\n' +
' .okay();\n' +
'}');
opts.wrap_line_length = 0;
opts.space_before_conditional = true;
opts.preserve_newlines = false;
bt('var a =\nfoo', 'var a = foo');
bt('var a = {\n"a":1,\n"b":2}', "var a = {\n \"a\": 1,\n \"b\": 2\n}");
@ -559,7 +743,8 @@ function run_beautifier_tests(test_obj)
bt('var a = /*i*/\n"b";', 'var a = /*i*/ "b";');
bt('var a = /*i*/\nb;', 'var a = /*i*/ b;');
bt('{\n\n\n"x"\n}', '{\n "x"\n}');
bt('if(a && b &&\nc\n&& d && e) e = f', 'if (a && b && c && d && e) e = f');
bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a && b || c || d && e) e = f');
bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a && (b || c || d) && e) e = f');
test_fragment('\n\n"x"', '"x"');
opts.preserve_newlines = true;
@ -570,7 +755,8 @@ function run_beautifier_tests(test_obj)
bt('var a = /*i*/\n"b";', 'var a = /*i*/\n "b";');
bt('var a = /*i*/\nb;', 'var a = /*i*/\n b;');
bt('{\n\n\n"x"\n}', '{\n\n\n "x"\n}');
bt('if (a && b &&\nc\n&& d && e) e = f', 'if (a && b &&\n c && d && e) e = f');
bt('if(a &&\nb\n||\nc\n||d\n&&\ne) e = f', 'if (a &&\n b ||\n c || d &&\n e) e = f');
bt('if(a &&\n(b\n||\nc\n||d)\n&&\ne) e = f', 'if (a &&\n (b ||\n c || d) &&\n e) e = f');
test_fragment('\n\n"x"', '"x"');
Urlencoded.run_tests(sanitytest);