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

feat(css_parser): allow multiple semicolons after declaration #4315

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

Contributed by @fireairforce

- Fix [#3836](https://github.com/biomejs/biome/issues/3836), css parser allow multiple semicolons after a declaration, the following example will now parsed correctly:

```css
.foo {
color: red;;
}
```

Contributed by @fireairforce


## v1.9.4 (2024-10-17)

### Analyzer
Expand Down
6 changes: 6 additions & 0 deletions crates/biome_css_factory/src/generated/node_factory.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions crates/biome_css_factory/src/generated/syntax_factory.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ impl FormatRule<AnyCssDeclarationOrRule> for FormatAnyCssDeclarationOrRule {
AnyCssDeclarationOrRule::AnyCssRule(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssBogus(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssDeclarationWithSemicolon(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssEmptyDeclaration(node) => node.format().fmt(f),
AnyCssDeclarationOrRule::CssMetavariable(node) => node.format().fmt(f),
}
}
Expand Down
21 changes: 21 additions & 0 deletions crates/biome_css_formatter/src/css/auxiliary/empty_declaration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::prelude::*;
use biome_css_syntax::{CssEmptyDeclaration, CssEmptyDeclarationFields, CssSyntaxKind};
use biome_formatter::write;
use biome_rowan::{AstNode, SyntaxNodeOptionExt};
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatCssEmptyDeclaration;
impl FormatNodeRule<CssEmptyDeclaration> for FormatCssEmptyDeclaration {
fn fmt_fields(&self, node: &CssEmptyDeclaration, f: &mut CssFormatter) -> FormatResult<()> {
let CssEmptyDeclarationFields { semicolon_token } = node.as_fields();
let parent_kind = node.syntax().parent().kind();

if matches!(
parent_kind,
Some(CssSyntaxKind::CSS_DECLARATION_WITH_SEMICOLON,)
) {
write!(f, [semicolon_token.format()])
} else {
write!(f, [format_removed(&semicolon_token?)])
}
}
}
1 change: 1 addition & 0 deletions crates/biome_css_formatter/src/css/auxiliary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(crate) mod declaration_or_at_rule_block;
pub(crate) mod declaration_or_rule_block;
pub(crate) mod declaration_with_semicolon;
pub(crate) mod document_custom_matcher;
pub(crate) mod empty_declaration;
pub(crate) mod font_family_name;
pub(crate) mod font_feature_values_block;
pub(crate) mod font_feature_values_item;
Expand Down
40 changes: 40 additions & 0 deletions crates/biome_css_formatter/src/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,46 @@ impl IntoFormat<CssFormatContext> for biome_css_syntax::CssDocumentCustomMatcher
)
}
}
impl FormatRule<biome_css_syntax::CssEmptyDeclaration>
for crate::css::auxiliary::empty_declaration::FormatCssEmptyDeclaration
{
type Context = CssFormatContext;
#[inline(always)]
fn fmt(
&self,
node: &biome_css_syntax::CssEmptyDeclaration,
f: &mut CssFormatter,
) -> FormatResult<()> {
FormatNodeRule::<biome_css_syntax::CssEmptyDeclaration>::fmt(self, node, f)
}
}
impl AsFormat<CssFormatContext> for biome_css_syntax::CssEmptyDeclaration {
type Format<'a> = FormatRefWithRule<
'a,
biome_css_syntax::CssEmptyDeclaration,
crate::css::auxiliary::empty_declaration::FormatCssEmptyDeclaration,
>;
fn format(&self) -> Self::Format<'_> {
#![allow(clippy::default_constructed_unit_structs)]
FormatRefWithRule::new(
self,
crate::css::auxiliary::empty_declaration::FormatCssEmptyDeclaration::default(),
)
}
}
impl IntoFormat<CssFormatContext> for biome_css_syntax::CssEmptyDeclaration {
type Format = FormatOwnedWithRule<
biome_css_syntax::CssEmptyDeclaration,
crate::css::auxiliary::empty_declaration::FormatCssEmptyDeclaration,
>;
fn into_format(self) -> Self::Format {
#![allow(clippy::default_constructed_unit_structs)]
FormatOwnedWithRule::new(
self,
crate::css::auxiliary::empty_declaration::FormatCssEmptyDeclaration::default(),
)
}
}
impl FormatRule<biome_css_syntax::CssFontFaceAtRule>
for crate::css::statements::font_face_at_rule::FormatCssFontFaceAtRule
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ a {
--bs-font-monospace: sfmono-regular , menlo , monaco , consolas ,
'Liberation Mono' , 'Courier New' , monospace;
}

a {
color: red;;;;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ a {
'Liberation Mono' , 'Courier New' , monospace;
}

a {
color: red;;;;
}
```


Expand Down Expand Up @@ -96,4 +99,8 @@ a {
--bs-font-monospace: sfmono-regular, menlo, monaco, consolas,
"Liberation Mono", "Courier New", monospace;
}

a {
color: red;
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ font-size: 12px;
```diff
--- Prettier
+++ Biome
@@ -1,13 +1,14 @@
@@ -1,13 +1,13 @@
/* comment 1 */
:root {
/* comment 2 */
Expand All @@ -41,7 +41,6 @@ font-size: 12px;
/* comment 9 */
- };
+ }
+ ;
/* comment 10 */
}
/* comment 11 */
Expand All @@ -60,7 +59,6 @@ font-size: 12px;
font-size: 12px;
/* comment 9 */
}
;
/* comment 10 */
}
/* comment 11 */
Expand Down Expand Up @@ -127,25 +125,5 @@ custom-properties.css:4:12 parse ━━━━━━━━━━━━━━━
- past
- future

custom-properties.css:10:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Expected a declaration, or an at rule but instead found ';'.

8 │ font-size: 12px;
9 │ /* comment 9 */
> 10 │ };
│ ^
11 │ /* comment 10 */
12 │ }

i Expected a declaration, or an at rule here.

8 │ font-size: 12px;
9 │ /* comment 9 */
> 10 │ };
│ ^
11 │ /* comment 10 */
12 │ }


```
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ input:not(/* comment 125 */[/* comment 126 */disabled/* comment 127 */]/* commen
/* comment 161 */
} /* comment 162 */
/* comment 163 */
@@ -201,30 +188,35 @@
@@ -201,30 +188,34 @@
/* comment 165 */
} /* comment 166 */

Expand Down Expand Up @@ -482,7 +482,6 @@ input:not(/* comment 125 */[/* comment 126 */disabled/* comment 127 */]/* commen
justify-content: center;
- };
+ }
+ ;
}
```

Expand Down Expand Up @@ -709,7 +708,6 @@ input:not(
align-items: center;
justify-content: center;
}
;
}
```

Expand Down Expand Up @@ -854,26 +852,6 @@ selectors.css:152:75 parse ━━━━━━━━━━━━━━━━━
- past
- future

selectors.css:156:6 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Expected a declaration, or an at rule but instead found ';'.

154 │ align-items: center;
155 │ justify-content: center;
> 156 │ };
│ ^
157 │ }
158 │

i Expected a declaration, or an at rule here.

154 │ align-items: center;
155 │ justify-content: center;
> 156 │ };
│ ^
157 │ }
158 │


```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ a {
```diff
--- Prettier
+++ Biome
@@ -13,17 +13,19 @@
@@ -13,16 +13,17 @@
content: url(https://example.com/\)\).jpg);
content: url(https://example.com/\(\(.jpg);
content: url(https://example.com/\ \ .jpg);
Expand All @@ -69,8 +69,6 @@ a {
no-repeat url(foo.ttf?query=foo,bar,),
no-repeat url(foo.woff2?foo=rgb\(255,255,0\))
no-repeat url(RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf);
+ ;
}
```

# Output
Expand Down Expand Up @@ -105,7 +103,6 @@ a {
no-repeat url(foo.ttf?query=foo,bar,),
no-repeat url(foo.woff2?foo=rgb\(255,255,0\))
no-repeat url(RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf);
;
}
```

Expand Down Expand Up @@ -165,26 +162,6 @@ url.css:3:33 parse ━━━━━━━━━━━━━━━━━━━━
- custom property
- function

url.css:30:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

× Expected a declaration, or an at rule but instead found ';'.

28 │ no-repeat url(foo.woff2?foo=rgb\(255,255,0\))
29 │ no-repeat url(RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf);
> 30 │ ;
│ ^
31 │ }
32 │

i Expected a declaration, or an at rule here.

28 │ no-repeat url(foo.woff2?foo=rgb\(255,255,0\))
29 │ no-repeat url(RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf);
> 30 │ ;
│ ^
31 │ }
32 │


```

Expand Down
Loading
Loading