Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed problems with colon character #363

Closed
wants to merge 12 commits into from
20 changes: 18 additions & 2 deletions js/lib/beautify-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,15 @@
indentSize = parseInt(indentSize, 10);
}


// tokenizer
var whiteRe = /^\s+$/;
var wordRe = /[\w$\-_]/;

// clean content inside tags and selectors that support custom user contents (ex: not() and content)
source_text_safe = source_text.replace(new RegExp("('|\").*('|\")", "gm"), function ($0) {
return (new Array($0.length + 1).join("-"));
});

var pos = -1,
ch;

Expand Down Expand Up @@ -233,7 +237,19 @@
insideRule = false;
} else if (ch === ":") {
eatWhitespace();
output.push(ch, " ");

var text_after_pos = source_text_safe.substr(pos - 1) + ";",
semicolon = text_after_pos.substr(0, text_after_pos.indexOf(';')).length,
closed_brace = text_after_pos.substr(0, text_after_pos.indexOf('}')).length,
open_brace = text_after_pos.substr(0, text_after_pos.indexOf('{')).length,
test1 = (semicolon > closed_brace) ? closed_brace : semicolon;

if ((test1 > open_brace && open_brace !== 0) || peek() == ":") {
output.push(ch);
} else {
output.push(ch, " ");
}

insideRule = true;
} else if (ch === '"' || ch === '\'') {
output.push(eatString(ch));
Expand Down
8 changes: 8 additions & 0 deletions js/test/beautify-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,7 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
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 screen {.tab,.bat:hover {color:red}}", "@media screen {\n .tab, .bat:hover {\n color: red\n }\n}\n");

// comments
btc("/* test */", "/* test */\n");
Expand Down Expand Up @@ -1761,6 +1762,13 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
btc("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}\n");
btc("@media print {.tab{}}", "@media print {\n .tab {}\n}\n");
btc("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n");

// colon character
btc("#foo : hover{color:purple}","#foo:hover {\n color: purple\n}\n");
btc(": : selection {\ncolor: #ff0000;}", "::selection {\n color: #ff0000;\n}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These inputs are somewhat nonsensical, as they don't represent valid CSS syntax. It would be clearer if you just asserted properly formatted input (and then omit the second parameter, because it defaults to the first).

btc("#foo:hover {\n  color: purple\n}\n");
btc("::selection {\n  color: #ff0000;\n}\n");

Note that the second test has an added \n, which fixes one breaking test. The #foo:hover case is still breaking.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that the first parameter was the not formatted input and the second one the formatted one. Isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the input and output are expected to be identical, all the test methods support simply passing one argument.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My input and output was not identical.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I said initially, they should be. Who in their right mind writes invalid CSS syntax and then expects it to magically work?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get what you mean, but if the beautifier can even remove extra spaces and make the syntax valid I can't see the problem. I didn't added extra code to do it, it's just a side effect of my patch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, yes, I want to take a part in this bikeshed as well!

The tests by themselves are ok — we have weird corner cases and some broken-code-formatting checks in the jsbeautifier code as well. The strong uneasiness I myself feel is that the tests need to clearly cover the proper input first, but currently there are no tests that make sure that the beautifier formats a clean, proper css code as well.

I.e something like this would make the tests much more structured and clear:

// selector support
btc("#foo :hover {...}", "#foo :hover {...}");
...
// handle some garbage as well, just because we can
btc(" : : selection", "::selection")

...and then we might have a separate discussion WHY would we ever want to test the garbage cases and what do we achieve by that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. Although, for the purposes of this bugfix, #foo :hover is not valid CSS syntax. Pseudo-classes must always be attached to other selectors (some pseudo-elements (doubled colons), however, can be distinct).


// 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}");

return sanitytest;
}
Expand Down