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

Implement option to support adding spaces between CSS selectors #2029

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,9 @@ CSS Beautifier Options:
-e, --eol Character(s) to use as line terminators. (default newline - "\\n")
-n, --end-with-newline End output with newline
-b, --brace-style [collapse|expand] ["collapse"]
-L, --selector-separator-newline Add a newline between multiple selectors
-N, --newline-between-rules Add a newline between CSS rules
--indent-empty-lines Keep indentation on empty lines
--selector_separator Whitespace between selectors [none|newline|space] [space]

HTML Beautifier Options:
-s, --indent-size Indentation size [4]
Expand Down
6 changes: 4 additions & 2 deletions js/src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ var path = require('path'),
"indent_empty_lines": Boolean,
"templating": [String, Array],
// CSS-only
"selector_separator_newline": Boolean,
"newline_between_rules": Boolean,
"space_around_combinator": Boolean,
"selector_separator": String,
//deprecated - replaced with space_around_combinator, remove in future version
"space_around_selector_separator": Boolean,
"selector_separator_newline": Boolean,
// HTML-only
"max_char": Number, // obsolete since 1.3.5
"inline": [String, Array],
Expand Down Expand Up @@ -180,6 +181,7 @@ var path = require('path'),
// no shorthand for "editorconfig"
// no shorthand for "indent_empty_lines"
// not shorthad for "templating"
// no shorthand for "selector_separator"
});

function verifyExists(fullPath) {
Expand Down Expand Up @@ -392,8 +394,8 @@ function usage(err) {
break;
case "css":
msg.push(' -b, --brace-style [collapse|expand] ["collapse"]');
msg.push(' -L, --selector-separator-newline Add a newline between multiple selectors.');
msg.push(' -N, --newline-between-rules Add a newline between CSS rules.');
msg.push(' --selector_separator Whitespace between selectors [none|newline|space] [space]');
}

if (err) {
Expand Down
9 changes: 8 additions & 1 deletion js/src/css/beautifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,15 @@ Beautifier.prototype.beautify = function() {
} else if (this._ch === ',') {
this.print_string(this._ch);
this.eatWhitespace(true);
if (this._options.selector_separator_newline && (!insidePropertyValue || insideScssMap) && parenLevel === 0 && !insideAtImport && !insideAtExtend) {

var selector_separator = (this._options.selector_separator === "default") ||
(this._options.selector_separator === "newline");

if (this._options.selector_separator_newline && (!insidePropertyValue || insideScssMap) &&
parenLevel === 0 && !insideAtImport && !insideAtExtend && selector_separator) {
this._output.add_new_line();
} else if (this._options.selector_separator === "none") {
this._output.space_before_token = false;
} else {
this._output.space_before_token = true;
}
Expand Down
8 changes: 6 additions & 2 deletions js/src/css/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ function Options(options) {
var space_around_selector_separator = this._get_boolean('space_around_selector_separator');
this.space_around_combinator = this._get_boolean('space_around_combinator') || space_around_selector_separator;

var selector_separator_list = this._get_selection_list('selector_separator', ['', 'none', 'space', 'newline']);
if (!selector_separator_list[0]) {
selector_separator_list = ['default'];
}
this.selector_separator = selector_separator_list[0];

var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']);
this.brace_style = 'collapse';
for (var bs = 0; bs < brace_style_split.length; bs++) {
Expand All @@ -51,6 +57,4 @@ function Options(options) {
}
Options.prototype = new BaseOptions();



module.exports.Options = Options;
3 changes: 3 additions & 0 deletions python/cssbeautifier/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def main():
"disable-newline-between-rules",
"space-around-combinator",
"indent-empty-lines",
"selector-separator",
],
)
except getopt.GetoptError as ex:
Expand Down Expand Up @@ -178,6 +179,8 @@ def main():
css_options.indent_empty_lines = True
elif opt in ("--editorconfig",):
css_options.editorconfig = True
elif opt in ("--selector-separator"):
css_options.selector_separator = True
kcamsanc marked this conversation as resolved.
Show resolved Hide resolved

try:
filepaths, replace = get_filepaths_from_params(filepath_params, replace)
Expand Down
8 changes: 8 additions & 0 deletions python/cssbeautifier/css/beautifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,14 +498,22 @@ def beautify(self):
elif self._ch == ",":
self.print_string(self._ch)
self.eatWhitespace(True)

selector_separator = (
self._options.selector_separator == "default"
) or (self._options.selector_separator == "newline")

if (
self._options.selector_separator_newline
and (not insidePropertyValue or insideScssMap)
and parenLevel == 0
and not insideAtImport
and not insideAtExtend
and selector_separator
):
self._output.add_new_line()
elif self._options.selector_separator == "none":
self._output.space_before_token = False
else:
self._output.space_before_token = True
elif (
Expand Down
8 changes: 8 additions & 0 deletions python/cssbeautifier/css/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ def __init__(self, options=None):
or space_around_selector_separator
)
self.keep_quiet = False

selector_separator_list = self._get_selection_list(
"selector_separator", ["", "none", "space", "newline"]
)
if not selector_separator_list[0]:
selector_separator_list = ["default"]

self.selector_separator = selector_separator_list[0]
30 changes: 29 additions & 1 deletion test/data/css/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1970,7 +1970,35 @@ exports.test_data = {
unchanged: 'p {\n color: blue;\n}'
}]
}, {

name: "Issue #1862 -- selector-separator option adds space between CSS selectors if value is space",
options: [
{ name: "selector_separator", value: "'space'" }
],
description: "",
tests: [{
input: '#main,#section,a {\n color: blue;\n}',
output: '#main, #section, a {\n color: blue;\n}'
}]
}, {
name: "Issue #1862 -- selector-separator option adds newline between CSS selectors if value is newline",
options: [
{ name: "selector_separator", value: "'newline'" }
],
description: "",
tests: [{
input: '#main,#section,a {\n color: blue;\n}',
output: '#main,\n#section,\na {\n color: blue;\n}'
}]
},
{
name: "Issue #1862 -- selector-separator option adds no whitespace between CSS selectors if value is none",
options: [
{ name: "selector_separator", value: "'none'" }
],
description: "",
tests: [{
unchanged: '#main,#section,a {\n color: blue;\n}'
}]
}
]
};