mirror of
https://github.com/beautifier/js-beautify.git
synced 2024-11-23 04:40:06 +00:00
Add "end_with_newline" option throughout and make consistent
-n, --end_with_newline added to all beautifiers This changes to the way the command-line produces output. Piped output and file output is now the same, and by default will not add a newline at the end. Ending with newline is respected when passed via html beautifier to css or js beautifier. Fixing this also exposed a number of holes tests and test framework. Fixes #492
This commit is contained in:
parent
5b2736f096
commit
d030e1cbed
@ -170,6 +170,7 @@
|
||||
$('#wrap-line-length').val(any($.cookie('wrap-line-length'), '0'));
|
||||
$('#unescape-strings').prop('checked', $.cookie('unescape-strings') === 'on');
|
||||
$('#jslint-happy').prop('checked', $.cookie('jslint-happy') === 'on');
|
||||
$('#end-with-newline').prop('checked', $.cookie('end-with-newline') === 'on');
|
||||
}
|
||||
|
||||
function store_settings_to_cookie() {
|
||||
@ -185,7 +186,8 @@
|
||||
$.cookie('space-before-conditional', $('#space-before-conditional').prop('checked') ? 'on' : 'off',
|
||||
opts);
|
||||
$.cookie('unescape-strings', $('#unescape-strings').prop('checked') ? 'on' : 'off', opts);
|
||||
$.cookie('jslint-happy', $('jslint-happy').prop('checked') ? 'on' : 'off', opts);
|
||||
$.cookie('jslint-happy', $('#jslint-happy').prop('checked') ? 'on' : 'off', opts);
|
||||
$.cookie('end-with-newline', $('#end-with-newline').prop('checked') ? 'on' : 'off', opts);
|
||||
$.cookie('wrap-line-length', $('#wrap-line-length').val(), opts);
|
||||
$.cookie('indent-scripts', $('#indent-scripts').val(), opts);
|
||||
}
|
||||
@ -248,6 +250,7 @@
|
||||
opts.space_before_conditional = $('#space-before-conditional').prop('checked');
|
||||
opts.unescape_strings = $('#unescape-strings').prop('checked');
|
||||
opts.jslint_happy = $('#jslint-happy').prop('checked');
|
||||
opts.end_with_newline = $('#end-with-newline').prop('checked');
|
||||
opts.wrap_line_length = $('#wrap-line-length').val();
|
||||
opts.space_after_anon_function = true;
|
||||
|
||||
@ -340,7 +343,9 @@
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<input class="checkbox" type="checkbox" id="end-with-newline">
|
||||
<label for="end-with-newline">End script and style with newline?</label>
|
||||
<br>
|
||||
<input class="checkbox" type="checkbox" id="detect-packers">
|
||||
<label for="detect-packers">Detect packers and obfuscators?</label>
|
||||
<br>
|
||||
|
@ -64,7 +64,7 @@
|
||||
var indentSize = options.indent_size || 4;
|
||||
var indentCharacter = options.indent_char || ' ';
|
||||
var selectorSeparatorNewline = (options.selector_separator_newline === undefined) ? true : options.selector_separator_newline;
|
||||
var endWithNewline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
|
||||
var end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
|
||||
|
||||
// compatibility
|
||||
if (typeof indentSize === "string") {
|
||||
@ -336,8 +336,7 @@
|
||||
var sweetCode = output.join('').replace(/[\r\n\t ]+$/, '');
|
||||
|
||||
// establish end_with_newline
|
||||
var should = endWithNewline;
|
||||
if (should) {
|
||||
if (end_with_newline) {
|
||||
sweetCode += "\n";
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,8 @@
|
||||
Only works before elements, not inside tags or for text.
|
||||
max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk
|
||||
indent_handlebars (default false) - format and indent {{#foo}} and {{/foo}}
|
||||
end_with_newline (false) - end with a newline
|
||||
|
||||
|
||||
e.g.
|
||||
|
||||
@ -90,7 +92,8 @@
|
||||
unformatted,
|
||||
preserve_newlines,
|
||||
max_preserve_newlines,
|
||||
indent_handlebars;
|
||||
indent_handlebars,
|
||||
end_with_newline;
|
||||
|
||||
options = options || {};
|
||||
|
||||
@ -111,6 +114,7 @@
|
||||
(isNaN(parseInt(options.max_preserve_newlines, 10)) ? 32786 : parseInt(options.max_preserve_newlines, 10))
|
||||
: 0;
|
||||
indent_handlebars = (options.indent_handlebars === undefined) ? false : options.indent_handlebars;
|
||||
end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
|
||||
|
||||
function Parser() {
|
||||
|
||||
@ -801,8 +805,8 @@
|
||||
.replace(/\s+$/, '');
|
||||
}
|
||||
if (text) {
|
||||
multi_parser.print_token_raw(indentation + trim(text));
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token_raw(text);
|
||||
multi_parser.print_newline(true, multi_parser.output);
|
||||
}
|
||||
}
|
||||
multi_parser.current_mode = 'TAG';
|
||||
@ -811,7 +815,11 @@
|
||||
multi_parser.last_token = multi_parser.token_type;
|
||||
multi_parser.last_text = multi_parser.token_text;
|
||||
}
|
||||
return multi_parser.output.join('');
|
||||
var sweet_code = multi_parser.output.join('').replace(/[\r\n\t ]+$/, '');
|
||||
if (end_with_newline) {
|
||||
sweet_code += '\n';
|
||||
}
|
||||
return sweet_code;
|
||||
}
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
|
@ -72,6 +72,9 @@
|
||||
NOTE: This is not a hard limit. Lines will continue until a point where a newline would
|
||||
be preserved if it were present.
|
||||
|
||||
end_with_newline (default false) - end output with a newline
|
||||
|
||||
|
||||
e.g
|
||||
|
||||
js_beautify(js_source_text, {
|
||||
@ -267,6 +270,8 @@
|
||||
opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;
|
||||
opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);
|
||||
opt.e4x = (options.e4x === undefined) ? false : options.e4x;
|
||||
opt.end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
|
||||
|
||||
|
||||
// force opt.space_after_anon_function to true if opt.jslint_happy
|
||||
if(opt.jslint_happy) {
|
||||
@ -338,6 +343,10 @@
|
||||
}
|
||||
|
||||
sweet_code = output.get_code();
|
||||
if (opt.end_with_newline) {
|
||||
sweet_code += '\n';
|
||||
}
|
||||
|
||||
return sweet_code;
|
||||
};
|
||||
|
||||
@ -1320,7 +1329,7 @@
|
||||
this.add_space_before_token = function() {
|
||||
if (this.space_before_token && this.current_line.get_item_count()) {
|
||||
var last_output = this.current_line.last();
|
||||
if (last_output !== ' ' && last_output !== indent_string) { // prevent occassional duplicate space
|
||||
if (last_output !== ' ' && last_output !== indent_string && last_output !== baseIndentString) { // prevent occassional duplicate space
|
||||
this.current_line.push(' ');
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ var fs = require('fs'),
|
||||
"unescape_strings": Boolean,
|
||||
"wrap_line_length": Number,
|
||||
"e4x": Boolean,
|
||||
"end_with_newline": Boolean,
|
||||
// HTML-only
|
||||
"max_char": Number, // obsolete since 1.3.5
|
||||
"unformatted": [String, Array],
|
||||
@ -96,6 +97,7 @@ var fs = require('fs'),
|
||||
"x": ["--unescape_strings"],
|
||||
"w": ["--wrap_line_length"],
|
||||
"X": ["--e4x"],
|
||||
"n": ["--end_with_newline"],
|
||||
// HTML-only
|
||||
"W": ["--max_char"], // obsolete since 1.3.5
|
||||
"U": ["--unformatted"],
|
||||
@ -222,6 +224,7 @@ function usage(err) {
|
||||
msg.push(' -w, --wrap-line-length Wrap lines at next opportunity after N characters [0]');
|
||||
msg.push(' -X, --e4x Pass E4X xml literals through untouched');
|
||||
msg.push(' --good-stuff Warm the cockles of Crockford\'s heart');
|
||||
msg.push(' -n, --end_with_newline End output with newline');
|
||||
break;
|
||||
case "html":
|
||||
msg.push(' -b, --brace-style [collapse|expand|end-expand] ["collapse"]');
|
||||
@ -281,11 +284,6 @@ function makePretty(code, config, outfile, callback) {
|
||||
var fileType = getOutputType(outfile, config.type);
|
||||
var pretty = beautify[fileType](code, config);
|
||||
|
||||
// ensure newline at end of beautified output
|
||||
if (pretty && pretty.charAt(pretty.length - 1) !== '\n') {
|
||||
pretty += '\n';
|
||||
}
|
||||
|
||||
callback(null, pretty, outfile, config);
|
||||
} catch (ex) {
|
||||
callback(ex);
|
||||
|
@ -13,7 +13,7 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
space_before_conditional: true,
|
||||
break_chained_methods: false,
|
||||
selector_separator: '\n',
|
||||
end_with_newline: true
|
||||
end_with_newline: false
|
||||
};
|
||||
|
||||
function test_js_beautifier(input)
|
||||
@ -37,11 +37,11 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
// does not check the indentation / surroundings as bt() does
|
||||
function test_fragment(input, expected)
|
||||
{
|
||||
expected = expected || input;
|
||||
expected = expected || expected === '' ? expected : input;
|
||||
sanitytest.expect(input, expected);
|
||||
// if the expected is different from input, run it again
|
||||
// expected output should be unchanged when run twice.
|
||||
if (expected != input) {
|
||||
if (expected !== input) {
|
||||
sanitytest.expect(expected, expected);
|
||||
}
|
||||
}
|
||||
@ -54,7 +54,7 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
{
|
||||
var wrapped_input, wrapped_expectation;
|
||||
|
||||
expectation = expectation || input;
|
||||
expectation = expectation || expectation === '' ? expectation : input;
|
||||
sanitytest.test_function(test_js_beautifier, 'js_beautify');
|
||||
test_fragment(input, expectation);
|
||||
|
||||
@ -79,13 +79,16 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
{
|
||||
var wrapped_input, wrapped_expectation, field_input, field_expectation;
|
||||
|
||||
expectation = expectation || input;
|
||||
expectation = expectation || expectation === '' ? expectation : input;
|
||||
sanitytest.test_function(test_html_beautifier, 'html_beautify');
|
||||
test_fragment(input, expectation);
|
||||
|
||||
if (opts.indent_size === 4 && input) {
|
||||
wrapped_input = '<div>\n' + input.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
|
||||
wrapped_expectation = '<div>\n' + expectation.replace(/^(.+)$/mg, ' $1') + '\n <span>inline</span>\n</div>';
|
||||
if (opts.end_with_newline) {
|
||||
wrapped_expectation += '\n';
|
||||
}
|
||||
test_fragment(wrapped_input, wrapped_expectation);
|
||||
}
|
||||
|
||||
@ -114,7 +117,7 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
{
|
||||
var wrapped_input, wrapped_expectation;
|
||||
|
||||
expectation = expectation || input;
|
||||
expectation = expectation || expectation === '' ? expectation : input;
|
||||
sanitytest.test_function(test_css_beautifier, 'css_beautify');
|
||||
test_fragment(input, expectation);
|
||||
}
|
||||
@ -140,15 +143,23 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
opts.keep_array_indentation = false;
|
||||
opts.brace_style = "collapse";
|
||||
|
||||
|
||||
// unicode support
|
||||
bt('var ' + String.fromCharCode(3232) + '_' + String.fromCharCode(3232) + ' = "hi";');
|
||||
bt('var ' + String.fromCharCode(228) + 'x = {\n ' + String.fromCharCode(228) + 'rgerlich: true\n};');
|
||||
|
||||
opts.end_with_newline = true;
|
||||
test_fragment('', '\n');
|
||||
test_fragment(' return .5',' return .5\n');
|
||||
test_fragment(' \n\nreturn .5\n\n\n\n',' return .5\n');
|
||||
test_fragment('\n', '\n');
|
||||
|
||||
opts.end_with_newline = false;
|
||||
bt('');
|
||||
test_fragment('\n', '');
|
||||
bt('return .5');
|
||||
test_fragment(' return .5');
|
||||
test_fragment(' return .5;\n a();');
|
||||
test_fragment(' < div');
|
||||
bt('a = 1', 'a = 1');
|
||||
bt('a=1', 'a = 1');
|
||||
bt("a();\n\nb();", "a();\n\nb();");
|
||||
@ -1786,7 +1797,29 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
'var a = {\n bing: 1\n },\n b = 2,\n c = 3;');
|
||||
Urlencoded.run_tests(sanitytest);
|
||||
|
||||
|
||||
bth('');
|
||||
|
||||
opts.end_with_newline = true;
|
||||
test_fragment('', '\n');
|
||||
test_fragment('<div></div>\n');
|
||||
test_fragment('<div></div>\n\n\n', '<div></div>\n');
|
||||
test_fragment('<head>\n' +
|
||||
' <script>\n' +
|
||||
' mocha.setup("bdd");\n' +
|
||||
'\n' +
|
||||
' </script>\n' +
|
||||
'</head>\n');
|
||||
|
||||
|
||||
opts.end_with_newline = false;
|
||||
test_fragment('<head>\n' +
|
||||
' <script>\n' +
|
||||
' mocha.setup("bdd");\n' +
|
||||
' </script>\n' +
|
||||
'</head>');
|
||||
|
||||
test_fragment('<div></div>\n', '<div></div>');
|
||||
bth('<div></div>');
|
||||
bth('<div>content</div>');
|
||||
bth('<div><div></div></div>',
|
||||
@ -2164,45 +2197,53 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
opts.indent_char = '\t';
|
||||
opts.selector_separator_newline = true;
|
||||
opts.end_with_newline = true;
|
||||
btc('', '\n');
|
||||
btc('\n', '\n');
|
||||
btc(".tabs{}\n", ".tabs {}\n");
|
||||
btc(".tabs{}", ".tabs {}\n");
|
||||
|
||||
opts.end_with_newline = false;
|
||||
btc('', '');
|
||||
btc('\n', '');
|
||||
btc(".tabs{}\n", ".tabs {}");
|
||||
|
||||
// test basic css beautifier
|
||||
btc('', '\n');
|
||||
btc(".tabs{}", ".tabs {}\n");
|
||||
btc(".tabs{color:red;}", ".tabs {\n\tcolor: red;\n}\n");
|
||||
btc(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}\n");
|
||||
btc(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}\n");
|
||||
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n");
|
||||
btc("@media print {.tab{}}", "@media print {\n\t.tab {}\n}\n");
|
||||
btc("@media print {.tab{background-image:url(foo@2x.png)}}", "@media print {\n\t.tab {\n\t\tbackground-image: url(foo@2x.png)\n\t}\n}\n");
|
||||
btc(".tabs {}");
|
||||
btc(".tabs{color:red;}", ".tabs {\n\tcolor: red;\n}");
|
||||
btc(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}");
|
||||
btc(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}");
|
||||
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
|
||||
btc("@media print {.tab{}}", "@media print {\n\t.tab {}\n}");
|
||||
btc("@media print {.tab{background-image:url(foo@2x.png)}}", "@media print {\n\t.tab {\n\t\tbackground-image: url(foo@2x.png)\n\t}\n}");
|
||||
|
||||
//lead-in whitespace determines base-indent.
|
||||
// lead-in newlines are stripped.
|
||||
btc("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");
|
||||
btc(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }\n");
|
||||
btc(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }\n");
|
||||
btc("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");
|
||||
btc("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
|
||||
btc(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }");
|
||||
btc(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }");
|
||||
btc("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
|
||||
|
||||
// comments
|
||||
btc("/* test */", "/* test */\n");
|
||||
btc(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n");
|
||||
btc("/* header */.tabs {}", "/* header */\n\n.tabs {}\n");
|
||||
btc("/* test */", "/* test */");
|
||||
btc(".tabs{/* test */}", ".tabs {\n\t/* test */\n}");
|
||||
btc("/* header */.tabs {}", "/* header */\n\n.tabs {}");
|
||||
|
||||
//single line comment support (less/sass)
|
||||
btc(".tabs{\n// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}\n");
|
||||
btc(".tabs{// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}\n");
|
||||
btc("//comment\n.tabs{width:10px;}", "//comment\n.tabs {\n\twidth: 10px;\n}\n");
|
||||
btc(".tabs{//comment\n//2nd single line comment\nwidth:10px;}", ".tabs {\n\t//comment\n\t//2nd single line comment\n\twidth: 10px;\n}\n");
|
||||
btc(".tabs{width:10px;//end of line comment\n}", ".tabs {\n\twidth: 10px;//end of line comment\n}\n");
|
||||
btc(".tabs{width:10px;//end of line comment\nheight:10px;}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;\n}\n");
|
||||
btc(".tabs{width:10px;//end of line comment\nheight:10px;//another\n}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;//another\n}\n");
|
||||
btc(".tabs{\n// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}");
|
||||
btc(".tabs{// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}");
|
||||
btc("//comment\n.tabs{width:10px;}", "//comment\n.tabs {\n\twidth: 10px;\n}");
|
||||
btc(".tabs{//comment\n//2nd single line comment\nwidth:10px;}", ".tabs {\n\t//comment\n\t//2nd single line comment\n\twidth: 10px;\n}");
|
||||
btc(".tabs{width:10px;//end of line comment\n}", ".tabs {\n\twidth: 10px;//end of line comment\n}");
|
||||
btc(".tabs{width:10px;//end of line comment\nheight:10px;}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;\n}");
|
||||
btc(".tabs{width:10px;//end of line comment\nheight:10px;//another\n}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;//another\n}");
|
||||
|
||||
// separate selectors
|
||||
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n");
|
||||
btc("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");
|
||||
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}");
|
||||
btc("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}");
|
||||
|
||||
// block nesting
|
||||
btc("#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}\n");
|
||||
btc("@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}\n");
|
||||
btc("#foo {\n\tbackground-image: url(foo@2x.png);\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}");
|
||||
btc("@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo@2x.png);\n\t}\n\t@font-face {\n\t\tfont-family: 'Bitstream Vera Serif Bold';\n\t\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n\t}\n}");
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'Bitstream Vera Serif Bold';
|
||||
@ -2222,33 +2263,33 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
|
||||
}
|
||||
}
|
||||
*/
|
||||
btc("@font-face {\n\tfont-family: 'Bitstream Vera Serif Bold';\n\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: 'Helvetica Neue'\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}\n");
|
||||
btc("@font-face {\n\tfont-family: 'Bitstream Vera Serif Bold';\n\tsrc: url('http://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf');\n}\n@media screen {\n\t#foo:hover {\n\t\tbackground-image: url(foo.png);\n\t}\n\t@media screen and (min-device-pixel-ratio: 2) {\n\t\t@font-face {\n\t\t\tfont-family: 'Helvetica Neue'\n\t\t}\n\t\t#foo:hover {\n\t\t\tbackground-image: url(foo@2x.png);\n\t\t}\n\t}\n}");
|
||||
|
||||
// test options
|
||||
opts.indent_size = 2;
|
||||
opts.indent_char = ' ';
|
||||
opts.selector_separator_newline = false;
|
||||
|
||||
btc("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}\n");
|
||||
btc("@media print {.tab{}}", "@media print {\n .tab {}\n}\n");
|
||||
btc("@media print {.tab,.bat{}}", "@media print {\n .tab, .bat {}\n}\n");
|
||||
btc("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n");
|
||||
btc("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}");
|
||||
btc("@media print {.tab{}}", "@media print {\n .tab {}\n}");
|
||||
btc("@media print {.tab,.bat{}}", "@media print {\n .tab, .bat {}\n}");
|
||||
btc("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}");
|
||||
|
||||
// pseudo-classes and pseudo-elements
|
||||
btc("#foo:hover {\n background-image: url(foo@2x.png)\n}\n");
|
||||
btc("#foo *:hover {\n color: purple\n}\n");
|
||||
btc("::selection {\n color: #ff0000;\n}\n");
|
||||
btc("#foo:hover {\n background-image: url(foo@2x.png)\n}");
|
||||
btc("#foo *:hover {\n color: purple\n}");
|
||||
btc("::selection {\n color: #ff0000;\n}");
|
||||
|
||||
// TODO: don't break nested pseduo-classes
|
||||
btc("@media screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}\n");
|
||||
btc("@media screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}");
|
||||
|
||||
// particular edge case with braces and semicolons inside tags that allows custom text
|
||||
btc("a:not(\"foobar\\\";{}omg\"){\ncontent: 'example\\';{} text';\ncontent: \"example\\\";{} text\";}",
|
||||
"a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}\n");
|
||||
"a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}");
|
||||
|
||||
// may not eat the space before "["
|
||||
btc('html.js [data-custom="123"] {\n opacity: 1.00;\n}\n');
|
||||
btc('html.js *[data-custom="123"] {\n opacity: 1.00;\n}\n');
|
||||
btc('html.js [data-custom="123"] {\n opacity: 1.00;\n}');
|
||||
btc('html.js *[data-custom="123"] {\n opacity: 1.00;\n}');
|
||||
|
||||
return sanitytest;
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ test_cli_common()
|
||||
exit 1
|
||||
}
|
||||
|
||||
$CLI_SCRIPT -invalidParameter 2> /dev/null && {
|
||||
echo "[$CLI_SCRIPT_NAME -invalidParameter] Return code should be error."
|
||||
$CLI_SCRIPT -Z 2> /dev/null && {
|
||||
echo "[$CLI_SCRIPT_NAME -Z] Return code for invalid parameter should be error."
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
@ -304,9 +304,8 @@ class Beautifier:
|
||||
sweet_code = re.sub('[\r\n\t ]+$', '', printer.result())
|
||||
|
||||
# establish end_with_newline
|
||||
should = self.opts.end_with_newline
|
||||
if should:
|
||||
sweet_code = sweet_code + "\n"
|
||||
if self.opts.end_with_newline:
|
||||
sweet_code += "\n"
|
||||
|
||||
return sweet_code
|
||||
|
||||
|
@ -9,55 +9,67 @@ class CSSBeautifierTest(unittest.TestCase):
|
||||
self.options.indent_size = 1
|
||||
self.options.indent_char = '\t'
|
||||
self.options.selector_separator_newline = True
|
||||
self.options.end_with_newline = False
|
||||
|
||||
def testNewline(self):
|
||||
self.resetOptions()
|
||||
t = self.decodesto
|
||||
|
||||
self.options.end_with_newline = True
|
||||
t("", "\n")
|
||||
t("\n", "\n")
|
||||
t(".tabs{}\n", ".tabs {}\n")
|
||||
t(".tabs{}", ".tabs {}\n")
|
||||
|
||||
def testBasics(self):
|
||||
self.resetOptions()
|
||||
t = self.decodesto
|
||||
|
||||
t("", "\n")
|
||||
t(".tabs{}", ".tabs {}\n")
|
||||
t(".tabs{color:red}", ".tabs {\n\tcolor: red\n}\n")
|
||||
t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}\n")
|
||||
t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}\n")
|
||||
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n")
|
||||
t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}\n")
|
||||
t("", "")
|
||||
t("\n", "")
|
||||
t(".tabs{}\n", ".tabs {}")
|
||||
t(".tabs{}", ".tabs {}")
|
||||
t(".tabs{color:red}", ".tabs {\n\tcolor: red\n}")
|
||||
t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}")
|
||||
t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}")
|
||||
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}")
|
||||
t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}")
|
||||
|
||||
# may not eat the space before "["
|
||||
t('html.js [data-custom="123"] {\n\topacity: 1.00;\n}\n');
|
||||
t('html.js *[data-custom="123"] {\n\topacity: 1.00;\n}\n');
|
||||
t('html.js [data-custom="123"] {\n\topacity: 1.00;\n}')
|
||||
t('html.js *[data-custom="123"] {\n\topacity: 1.00;\n}')
|
||||
|
||||
# lead-in whitespace determines base-indent.
|
||||
# lead-in newlines are stripped.
|
||||
t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")
|
||||
t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }\n")
|
||||
t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }\n")
|
||||
t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")
|
||||
t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}")
|
||||
t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }")
|
||||
t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }")
|
||||
t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}")
|
||||
|
||||
def testComments(self):
|
||||
self.resetOptions()
|
||||
t = self.decodesto
|
||||
|
||||
t("/* test */", "/* test */\n")
|
||||
t(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n")
|
||||
t("/* header */.tabs {}", "/* header */\n\n.tabs {}\n")
|
||||
t("/* test */", "/* test */")
|
||||
t(".tabs{/* test */}", ".tabs {\n\t/* test */\n}")
|
||||
t("/* header */.tabs {}", "/* header */\n\n.tabs {}")
|
||||
|
||||
#single line comment support (less/sass)
|
||||
t(".tabs{\n// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}\n")
|
||||
t(".tabs{// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}\n")
|
||||
t("//comment\n.tabs{width:10px;}", "//comment\n.tabs {\n\twidth: 10px;\n}\n")
|
||||
t(".tabs{//comment\n//2nd single line comment\nwidth:10px;}", ".tabs {\n\t//comment\n\t//2nd single line comment\n\twidth: 10px;\n}\n")
|
||||
t(".tabs{width:10px;//end of line comment\n}", ".tabs {\n\twidth: 10px;//end of line comment\n}\n")
|
||||
t(".tabs{width:10px;//end of line comment\nheight:10px;}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;\n}\n")
|
||||
t(".tabs{width:10px;//end of line comment\nheight:10px;//another\n}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;//another\n}\n")
|
||||
t(".tabs{\n// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}")
|
||||
t(".tabs{// comment\nwidth:10px;\n}", ".tabs {\n\t// comment\n\twidth: 10px;\n}")
|
||||
t("//comment\n.tabs{width:10px;}", "//comment\n.tabs {\n\twidth: 10px;\n}")
|
||||
t(".tabs{//comment\n//2nd single line comment\nwidth:10px;}", ".tabs {\n\t//comment\n\t//2nd single line comment\n\twidth: 10px;\n}")
|
||||
t(".tabs{width:10px;//end of line comment\n}", ".tabs {\n\twidth: 10px;//end of line comment\n}")
|
||||
t(".tabs{width:10px;//end of line comment\nheight:10px;}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;\n}")
|
||||
t(".tabs{width:10px;//end of line comment\nheight:10px;//another\n}", ".tabs {\n\twidth: 10px;//end of line comment\n\theight: 10px;//another\n}")
|
||||
|
||||
|
||||
def testSeperateSelectors(self):
|
||||
self.resetOptions()
|
||||
t = self.decodesto
|
||||
|
||||
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n")
|
||||
t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")
|
||||
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}")
|
||||
t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}")
|
||||
|
||||
def testOptions(self):
|
||||
self.resetOptions()
|
||||
@ -66,13 +78,22 @@ class CSSBeautifierTest(unittest.TestCase):
|
||||
self.options.selector_separator_newline = False
|
||||
t = self.decodesto
|
||||
|
||||
t("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}\n")
|
||||
t("@media print {.tab{}}", "@media print {\n .tab {}\n}\n")
|
||||
t("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n")
|
||||
t("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}")
|
||||
t("@media print {.tab{}}", "@media print {\n .tab {}\n}")
|
||||
t("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}")
|
||||
|
||||
def decodesto(self, input, expectation=None):
|
||||
if expectation == None:
|
||||
expectation = input
|
||||
|
||||
self.assertMultiLineEqual(
|
||||
cssbeautifier.beautify(input, self.options), expectation or input)
|
||||
cssbeautifier.beautify(input, self.options), expectation)
|
||||
|
||||
# if the expected is different from input, run it again
|
||||
# expected output should be unchanged when run twice.
|
||||
if not expectation == None:
|
||||
self.assertMultiLineEqual(
|
||||
cssbeautifier.beautify(expectation, self.options), expectation)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -78,6 +78,7 @@ class BeautifierOptions:
|
||||
self.unescape_strings = False
|
||||
self.wrap_line_length = 0
|
||||
self.break_chained_methods = False
|
||||
self.end_with_newline = False
|
||||
|
||||
|
||||
|
||||
@ -272,6 +273,7 @@ Output options:
|
||||
-X, --e4x Pass E4X xml literals through untouched
|
||||
-w, --wrap-line-length Attempt to wrap line when it exceeds this length.
|
||||
NOTE: Line continues until next wrap point is found.
|
||||
-n, --end_with_newline End output with newline
|
||||
|
||||
Rarely needed options:
|
||||
|
||||
@ -393,6 +395,9 @@ class Beautifier:
|
||||
|
||||
|
||||
sweet_code = self.output.get_code()
|
||||
if self.opts.end_with_newline:
|
||||
sweet_code += "\n"
|
||||
|
||||
return sweet_code
|
||||
|
||||
def handle_token(self, local_token):
|
||||
@ -1205,7 +1210,7 @@ class Output:
|
||||
for line_index in range(1, len(self.lines)):
|
||||
sweet_code += '\n' + self.lines[line_index].get_output()
|
||||
|
||||
return re.sub('[\n ]+$', '', sweet_code)
|
||||
return re.sub('[\r\n\t ]+$', '', sweet_code)
|
||||
|
||||
def add_indent_string(self, level):
|
||||
if self.baseIndentString != '':
|
||||
@ -1226,7 +1231,7 @@ class Output:
|
||||
def add_space_before_token(self):
|
||||
# make sure only single space gets drawn
|
||||
if self.space_before_token and self.current_line.get_item_count() and \
|
||||
self.current_line.last() not in [' ', self.indent_string]:
|
||||
self.current_line.last() not in [' ', self.indent_string, self.baseIndentString]:
|
||||
self.current_line.push(' ')
|
||||
self.space_before_token = False
|
||||
|
||||
@ -1654,12 +1659,12 @@ def main():
|
||||
argv = sys.argv[1:]
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "s:c:o:dEPjabkil:xhtfvXw:",
|
||||
opts, args = getopt.getopt(argv, "s:c:o:dEPjabkil:xhtfvXnw:",
|
||||
['indent-size=','indent-char=','outfile=', 'disable-preserve-newlines',
|
||||
'space-in-paren', 'space-in-empty-paren', 'jslint-happy', 'space-after-anon-function',
|
||||
'brace-style=', 'keep-array-indentation', 'indent-level=', 'unescape-strings', 'help',
|
||||
'usage', 'stdin', 'eval-code', 'indent-with-tabs', 'keep-function-indentation', 'version',
|
||||
'e4x', 'wrap-line-length'])
|
||||
'e4x', 'end-with-newline','wrap-line-length'])
|
||||
except getopt.GetoptError as ex:
|
||||
print(ex, file=sys.stderr)
|
||||
return usage(sys.stderr)
|
||||
@ -1702,6 +1707,8 @@ def main():
|
||||
js_options.unescape_strings = True
|
||||
elif opt in ('--e4x', '-X'):
|
||||
js_options.e4x = True
|
||||
elif opt in ('--end-with-newline', '-n'):
|
||||
js_options.end_with_newline = True
|
||||
elif opt in ('--wrap-line-length ', '-w'):
|
||||
js_options.wrap_line_length = int(arg)
|
||||
elif opt in ('--stdin', '-i'):
|
||||
@ -1718,11 +1725,11 @@ def main():
|
||||
else:
|
||||
try:
|
||||
if outfile == 'stdout':
|
||||
print(beautify_file(file, js_options))
|
||||
sys.stdout.write(beautify_file(file, js_options))
|
||||
else:
|
||||
mkdir_p(os.path.dirname(outfile))
|
||||
with open(outfile, 'w') as f:
|
||||
f.write(beautify_file(file, js_options) + '\n')
|
||||
f.write(beautify_file(file, js_options))
|
||||
except Exception as ex:
|
||||
print(ex, file=sys.stderr)
|
||||
return 1
|
||||
|
@ -22,8 +22,8 @@ test_cli_common()
|
||||
exit 1
|
||||
}
|
||||
|
||||
$CLI_SCRIPT -invalidParameter 2> /dev/null && {
|
||||
echo "[$CLI_SCRIPT_NAME -invalidParameter] Return code should be error."
|
||||
$CLI_SCRIPT -Z 2> /dev/null && {
|
||||
echo "[$CLI_SCRIPT_NAME -Z] Return code for invalid parameter should be error."
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -68,23 +68,23 @@ test_cli_js_beautify()
|
||||
}
|
||||
|
||||
$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/css-beautify.js > /dev/null || {
|
||||
echo "js-beautify output for $SCRIPT_DIR/../bin/css-beautify.js was expected succeed."
|
||||
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/css-beautify.js was expected succeed."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/js-beautify.js | diff $SCRIPT_DIR/../../../js/bin/js-beautify.js - || {
|
||||
echo "js-beautify output for $SCRIPT_DIR/../bin/js-beautify.js was expected to be unchanged."
|
||||
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/js-beautify.js was expected to be unchanged."
|
||||
exit 1
|
||||
}
|
||||
|
||||
rm -rf /tmp/js-beautify-mkdir
|
||||
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify.js $SCRIPT_DIR/../../../js/bin/js-beautify.js && diff $SCRIPT_DIR/../../../js/bin/js-beautify.js /tmp/js-beautify-mkdir/js-beautify.js || {
|
||||
echo "js-beautify output for $SCRIPT_DIR/../bin/js-beautify.js should have been created in /tmp/js-beautify-mkdir/js-beautify.js."
|
||||
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/js-beautify.js should have been created in /tmp/js-beautify-mkdir/js-beautify.js."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/css-beautify.js | diff -q $SCRIPT_DIR/../../../js/bin/css-beautify.js - && {
|
||||
echo "js-beautify output for $SCRIPT_DIR/../bin/css-beautify.js was expected to be different."
|
||||
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/css-beautify.js was expected to be different."
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
@ -43,9 +43,19 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
bt('var ' + six.unichr(3232) + '_' + six.unichr(3232) + ' = "hi";');
|
||||
bt('var ' + six.unichr(228) + 'x = {\n ' + six.unichr(228) + 'rgerlich: true\n};');
|
||||
|
||||
self.options.end_with_newline = True;
|
||||
test_fragment('', '\n');
|
||||
test_fragment(' return .5',' return .5\n');
|
||||
test_fragment(' \n\nreturn .5\n\n\n\n',' return .5\n');
|
||||
test_fragment('\n', '\n');
|
||||
|
||||
self.options.end_with_newline = False;
|
||||
bt('');
|
||||
test_fragment('\n', '');
|
||||
bt('return .5');
|
||||
test_fragment(' return .5');
|
||||
test_fragment(' return .5;\n a();');
|
||||
test_fragment(' < div');
|
||||
bt('a = 1', 'a = 1');
|
||||
bt('a=1', 'a = 1');
|
||||
bt("a();\n\nb();", "a();\n\nb();");
|
||||
@ -1658,8 +1668,11 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
|
||||
|
||||
def decodesto(self, input, expectation=None):
|
||||
if expectation == None:
|
||||
expectation = input
|
||||
|
||||
self.assertMultiLineEqual(
|
||||
jsbeautifier.beautify(input, self.options), expectation or input)
|
||||
jsbeautifier.beautify(input, self.options), expectation)
|
||||
|
||||
# if the expected is different from input, run it again
|
||||
# expected output should be unchanged when run twice.
|
||||
@ -1671,7 +1684,9 @@ class TestJSBeautifier(unittest.TestCase):
|
||||
return self.wrapregex.sub(' \\1', text)
|
||||
|
||||
def bt(self, input, expectation=None):
|
||||
expectation = expectation or input
|
||||
if expectation == None:
|
||||
expectation = input
|
||||
|
||||
self.decodesto(input, expectation)
|
||||
if self.options.indent_size == 4 and input:
|
||||
wrapped_input = '{\n%s\nfoo=bar;}' % self.wrap(input)
|
||||
|
Loading…
Reference in New Issue
Block a user