diff --git a/CHANGELOG.md b/CHANGELOG.md index 5386d6e9bf1f..12fe2a0bb908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,10 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b ### Formatter +### Bug fixes + +- Fix [#4121](https://github.com/biomejs/biome/issues/4326), don't ident a CSS selector when has leading comments. Contributed by @fireairforce + ### JavaScript APIs ### Linter diff --git a/crates/biome_css_formatter/src/css/lists/relative_selector_list.rs b/crates/biome_css_formatter/src/css/lists/relative_selector_list.rs index 566e6e53982a..0561cc0dbb30 100644 --- a/crates/biome_css_formatter/src/css/lists/relative_selector_list.rs +++ b/crates/biome_css_formatter/src/css/lists/relative_selector_list.rs @@ -13,17 +13,36 @@ impl FormatRule for FormatCssRelativeSelectorList { let mut joiner = f.join_with(&separator); for formatted in node.format_separated(",") { - // Each selector gets `indent` added in case it breaks over multiple - // lines. The break is added here rather than in each selector both - // for simplicity and to avoid recursively adding indents when - // selectors are nested within other rules. The group is then added - // around the indent to ensure that it tries using a flat layout - // first and only expands when the single selector can't fit the line. - // - // For example, a selector like `div span a` is structured like - // `[div, [span, [a]]]`, so `a` would end up double-indented if it - // was handled by the selector rather than here. - joiner.entry(&group(&indent(&formatted))); + let mut has_comments_before = false; + if let Some(relative_selector) = formatted.node()?.as_css_relative_selector() { + if let Some(computed_selector) = + relative_selector.selector()?.as_css_compound_selector() + { + if let Some(simple_selector) = computed_selector.simple_selector() { + if let Some(type_selector) = simple_selector.as_css_type_selector() { + has_comments_before = + type_selector.ident()?.value_token()?.has_leading_comments(); + } + } + } + } + + if has_comments_before { + // Computed Selector which contains a leading comments should be formatted without indent. + joiner.entry(&group(&formatted)); + } else { + // Each selector gets `indent` added in case it breaks over multiple + // lines. The break is added here rather than in each selector both + // for simplicity and to avoid recursively adding indents when + // selectors are nested within other rules. The group is then added + // around the indent to ensure that it tries using a flat layout + // first and only expands when the single selector can't fit the line. + // + // For example, a selector like `div span a` is structured like + // `[div, [span, [a]]]`, so `a` would end up double-indented if it + // was handled by the selector rather than here. + joiner.entry(&group(&indent(&formatted))); + } } joiner.finish() diff --git a/crates/biome_css_formatter/tests/specs/css/declaration_list.css b/crates/biome_css_formatter/tests/specs/css/declaration_list.css index 2d9252e42926..780622ef405b 100644 --- a/crates/biome_css_formatter/tests/specs/css/declaration_list.css +++ b/crates/biome_css_formatter/tests/specs/css/declaration_list.css @@ -34,4 +34,20 @@ a { a { color: red;;;; +} + +.with-comments { + /* hello */ + a, + /* world */ + button { + color: blue; + } +} + +.without-comments { + a, + button { + color: blue; + } } \ No newline at end of file diff --git a/crates/biome_css_formatter/tests/specs/css/declaration_list.css.snap b/crates/biome_css_formatter/tests/specs/css/declaration_list.css.snap index e168c99e2562..9db6650632b6 100644 --- a/crates/biome_css_formatter/tests/specs/css/declaration_list.css.snap +++ b/crates/biome_css_formatter/tests/specs/css/declaration_list.css.snap @@ -42,6 +42,22 @@ a { a { color: red;;;; } + +.with-comments { + /* hello */ + a, + /* world */ + button { + color: blue; + } +} + +.without-comments { + a, + button { + color: blue; + } +} ``` @@ -103,4 +119,20 @@ a { a { color: red; } + +.with-comments { + /* hello */ + a, + /* world */ + button { + color: blue; + } +} + +.without-comments { + a, + button { + color: blue; + } +} ```