Skip to content

Commit bf1c3eb

Browse files
authored
feat(css_formatter): support for pseudo selectors (#1291)
1 parent 934fa66 commit bf1c3eb

File tree

51 files changed

+1243
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1243
-81
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssNthOffset;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssNthOffset, CssNthOffsetFields};
3+
use biome_formatter::write;
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssNthOffset;
67
impl FormatNodeRule<CssNthOffset> for FormatCssNthOffset {
78
fn fmt_fields(&self, node: &CssNthOffset, f: &mut CssFormatter) -> FormatResult<()> {
8-
format_verbatim_node(node.syntax()).fmt(f)
9+
let CssNthOffsetFields { sign, value } = node.as_fields();
10+
11+
write!(f, [sign.format(), space(), value.format()])
912
}
1013
}

crates/biome_css_formatter/src/css/auxiliary/rule.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ impl FormatNodeRule<CssRule> for FormatCssRule {
77
fn fmt_fields(&self, node: &CssRule, f: &mut CssFormatter) -> FormatResult<()> {
88
let CssRuleFields { prelude, block } = node.as_fields();
99

10-
write!(f, [group(&prelude.format()), space(), &block?.format()])
10+
write!(
11+
f,
12+
[
13+
// The selector list gets expanded so that every selector
14+
// appears on its own line, no matter how long they are.
15+
group(&prelude.format()).should_expand(true),
16+
space(),
17+
&block?.format()
18+
]
19+
)
1120
}
1221
}

crates/biome_css_formatter/src/css/lists/compound_selector_list.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ pub(crate) struct FormatCssCompoundSelectorList;
55
impl FormatRule<CssCompoundSelectorList> for FormatCssCompoundSelectorList {
66
type Context = CssFormatContext;
77
fn fmt(&self, node: &CssCompoundSelectorList, f: &mut CssFormatter) -> FormatResult<()> {
8-
f.join().entries(node.iter().formatted()).finish()
8+
let mut joiner = f.join_nodes_with_soft_line();
9+
10+
for (rule, formatted) in node.elements().zip(node.format_separated(",")) {
11+
// Each selector gets `indent` added in case it breaks over multiple
12+
// lines. The break is added here rather than in each selector both
13+
// for simplicity and to avoid recursively adding indents when
14+
// selectors are nested within other rules. The group is then added
15+
// around the indent to ensure that it tries using a flat layout
16+
// first and only expands when the single selector can't fit the line.
17+
//
18+
// For example, a selector like `div span a` is structured like
19+
// `[div, [span, [a]]]`, so `a` would end up double-indented if it
20+
// was handled by the selector rather than here.
21+
joiner.entry(rule.node()?.syntax(), &group(&indent(&formatted)));
22+
}
23+
24+
joiner.finish()
925
}
1026
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
use crate::prelude::*;
22
use biome_css_syntax::CssPseudoValueList;
3+
34
#[derive(Debug, Clone, Default)]
45
pub(crate) struct FormatCssPseudoValueList;
56
impl FormatRule<CssPseudoValueList> for FormatCssPseudoValueList {
67
type Context = CssFormatContext;
78
fn fmt(&self, node: &CssPseudoValueList, f: &mut CssFormatter) -> FormatResult<()> {
8-
format_verbatim_node(node.syntax()).fmt(f)
9+
let mut joiner = f.join_nodes_with_soft_line();
10+
11+
for (rule, formatted) in node.elements().zip(node.format_separated(",")) {
12+
joiner.entry(rule.node()?.syntax(), &formatted);
13+
}
14+
15+
joiner.finish()
916
}
1017
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
use crate::prelude::*;
22
use biome_css_syntax::CssRelativeSelectorList;
3+
34
#[derive(Debug, Clone, Default)]
45
pub(crate) struct FormatCssRelativeSelectorList;
56
impl FormatRule<CssRelativeSelectorList> for FormatCssRelativeSelectorList {
67
type Context = CssFormatContext;
78
fn fmt(&self, node: &CssRelativeSelectorList, f: &mut CssFormatter) -> FormatResult<()> {
8-
format_verbatim_node(node.syntax()).fmt(f)
9+
let mut joiner = f.join_nodes_with_soft_line();
10+
11+
for (rule, formatted) in node.elements().zip(node.format_separated(",")) {
12+
// Each selector gets `indent` added in case it breaks over multiple
13+
// lines. The break is added here rather than in each selector both
14+
// for simplicity and to avoid recursively adding indents when
15+
// selectors are nested within other rules. The group is then added
16+
// around the indent to ensure that it tries using a flat layout
17+
// first and only expands when the single selector can't fit the line.
18+
//
19+
// For example, a selector like `div span a` is structured like
20+
// `[div, [span, [a]]]`, so `a` would end up double-indented if it
21+
// was handled by the selector rather than here.
22+
joiner.entry(rule.node()?.syntax(), &group(&indent(&formatted)));
23+
}
24+
25+
joiner.finish()
926
}
1027
}

crates/biome_css_formatter/src/css/lists/selector_list.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use crate::prelude::*;
22
use biome_css_syntax::CssSelectorList;
3+
34
#[derive(Debug, Clone, Default)]
45
pub(crate) struct FormatCssSelectorList;
56
impl FormatRule<CssSelectorList> for FormatCssSelectorList {
67
type Context = CssFormatContext;
78
fn fmt(&self, node: &CssSelectorList, f: &mut CssFormatter) -> FormatResult<()> {
8-
let mut joiner = f.join_nodes_with_hardline();
9+
let mut joiner = f.join_nodes_with_soft_line();
910

1011
for (rule, formatted) in node.elements().zip(node.format_separated(",")) {
1112
// Each selector gets `indent` added in case it breaks over multiple
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionCompoundSelectorList;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{
3+
CssPseudoClassFunctionCompoundSelectorList, CssPseudoClassFunctionCompoundSelectorListFields,
4+
};
5+
use biome_formatter::{format_args, write};
6+
47
#[derive(Debug, Clone, Default)]
58
pub(crate) struct FormatCssPseudoClassFunctionCompoundSelectorList;
69
impl FormatNodeRule<CssPseudoClassFunctionCompoundSelectorList>
@@ -11,6 +14,23 @@ impl FormatNodeRule<CssPseudoClassFunctionCompoundSelectorList>
1114
node: &CssPseudoClassFunctionCompoundSelectorList,
1215
f: &mut CssFormatter,
1316
) -> FormatResult<()> {
14-
format_verbatim_node(node.syntax()).fmt(f)
17+
let CssPseudoClassFunctionCompoundSelectorListFields {
18+
name,
19+
l_paren_token,
20+
compound_selector_list,
21+
r_paren_token,
22+
} = node.as_fields();
23+
24+
write!(
25+
f,
26+
[
27+
name.format(),
28+
group(&format_args![
29+
l_paren_token.format(),
30+
soft_block_indent(&compound_selector_list.format()),
31+
r_paren_token.format()
32+
])
33+
]
34+
)
1535
}
1636
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionIdentifier;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssPseudoClassFunctionIdentifier, CssPseudoClassFunctionIdentifierFields};
3+
use biome_formatter::{format_args, write};
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssPseudoClassFunctionIdentifier;
67
impl FormatNodeRule<CssPseudoClassFunctionIdentifier> for FormatCssPseudoClassFunctionIdentifier {
@@ -9,6 +10,23 @@ impl FormatNodeRule<CssPseudoClassFunctionIdentifier> for FormatCssPseudoClassFu
910
node: &CssPseudoClassFunctionIdentifier,
1011
f: &mut CssFormatter,
1112
) -> FormatResult<()> {
12-
format_verbatim_node(node.syntax()).fmt(f)
13+
let CssPseudoClassFunctionIdentifierFields {
14+
name_token,
15+
l_paren_token,
16+
ident,
17+
r_paren_token,
18+
} = node.as_fields();
19+
20+
write!(
21+
f,
22+
[
23+
name_token.format(),
24+
group(&format_args![
25+
l_paren_token.format(),
26+
soft_block_indent(&ident.format()),
27+
r_paren_token.format()
28+
])
29+
]
30+
)
1331
}
1432
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionNth;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssPseudoClassFunctionNth, CssPseudoClassFunctionNthFields};
3+
use biome_formatter::{format_args, write};
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssPseudoClassFunctionNth;
67
impl FormatNodeRule<CssPseudoClassFunctionNth> for FormatCssPseudoClassFunctionNth {
@@ -9,6 +10,23 @@ impl FormatNodeRule<CssPseudoClassFunctionNth> for FormatCssPseudoClassFunctionN
910
node: &CssPseudoClassFunctionNth,
1011
f: &mut CssFormatter,
1112
) -> FormatResult<()> {
12-
format_verbatim_node(node.syntax()).fmt(f)
13+
let CssPseudoClassFunctionNthFields {
14+
name,
15+
l_paren_token,
16+
selector,
17+
r_paren_token,
18+
} = node.as_fields();
19+
20+
write!(
21+
f,
22+
[
23+
name.format(),
24+
group(&format_args![
25+
l_paren_token.format(),
26+
soft_block_indent(&selector.format()),
27+
r_paren_token.format()
28+
])
29+
]
30+
)
1331
}
1432
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionRelativeSelectorList;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{
3+
CssPseudoClassFunctionRelativeSelectorList, CssPseudoClassFunctionRelativeSelectorListFields,
4+
};
5+
use biome_formatter::{format_args, write};
6+
47
#[derive(Debug, Clone, Default)]
58
pub(crate) struct FormatCssPseudoClassFunctionRelativeSelectorList;
69
impl FormatNodeRule<CssPseudoClassFunctionRelativeSelectorList>
@@ -11,6 +14,23 @@ impl FormatNodeRule<CssPseudoClassFunctionRelativeSelectorList>
1114
node: &CssPseudoClassFunctionRelativeSelectorList,
1215
f: &mut CssFormatter,
1316
) -> FormatResult<()> {
14-
format_verbatim_node(node.syntax()).fmt(f)
17+
let CssPseudoClassFunctionRelativeSelectorListFields {
18+
name_token,
19+
l_paren_token,
20+
relative_selector_list,
21+
r_paren_token,
22+
} = node.as_fields();
23+
24+
write!(
25+
f,
26+
[
27+
name_token.format(),
28+
group(&format_args![
29+
l_paren_token.format(),
30+
soft_block_indent(&relative_selector_list.format()),
31+
r_paren_token.format()
32+
])
33+
]
34+
)
1535
}
1636
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionSelectorList;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{
3+
CssPseudoClassFunctionSelectorList, CssPseudoClassFunctionSelectorListFields,
4+
};
5+
use biome_formatter::{format_args, write};
6+
47
#[derive(Debug, Clone, Default)]
58
pub(crate) struct FormatCssPseudoClassFunctionSelectorList;
69
impl FormatNodeRule<CssPseudoClassFunctionSelectorList>
@@ -11,6 +14,23 @@ impl FormatNodeRule<CssPseudoClassFunctionSelectorList>
1114
node: &CssPseudoClassFunctionSelectorList,
1215
f: &mut CssFormatter,
1316
) -> FormatResult<()> {
14-
format_verbatim_node(node.syntax()).fmt(f)
17+
let CssPseudoClassFunctionSelectorListFields {
18+
name,
19+
l_paren_token,
20+
selector_list,
21+
r_paren_token,
22+
} = node.as_fields();
23+
24+
write!(
25+
f,
26+
[
27+
name.format(),
28+
group(&format_args![
29+
l_paren_token.format(),
30+
soft_block_indent(&selector_list.format()),
31+
r_paren_token.format()
32+
])
33+
]
34+
)
1535
}
1636
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassFunctionValueList;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssPseudoClassFunctionValueList, CssPseudoClassFunctionValueListFields};
3+
use biome_formatter::{format_args, write};
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssPseudoClassFunctionValueList;
67
impl FormatNodeRule<CssPseudoClassFunctionValueList> for FormatCssPseudoClassFunctionValueList {
@@ -9,6 +10,23 @@ impl FormatNodeRule<CssPseudoClassFunctionValueList> for FormatCssPseudoClassFun
910
node: &CssPseudoClassFunctionValueList,
1011
f: &mut CssFormatter,
1112
) -> FormatResult<()> {
12-
format_verbatim_node(node.syntax()).fmt(f)
13+
let CssPseudoClassFunctionValueListFields {
14+
name_token,
15+
l_paren_token,
16+
value_list,
17+
r_paren_token,
18+
} = node.as_fields();
19+
20+
write!(
21+
f,
22+
[
23+
name_token.format(),
24+
group(&format_args![
25+
l_paren_token.format(),
26+
soft_block_indent(&value_list.format()),
27+
r_paren_token.format()
28+
])
29+
]
30+
)
1331
}
1432
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassIdentifier;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssPseudoClassIdentifier, CssPseudoClassIdentifierFields};
3+
use biome_formatter::write;
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssPseudoClassIdentifier;
67
impl FormatNodeRule<CssPseudoClassIdentifier> for FormatCssPseudoClassIdentifier {
@@ -9,6 +10,8 @@ impl FormatNodeRule<CssPseudoClassIdentifier> for FormatCssPseudoClassIdentifier
910
node: &CssPseudoClassIdentifier,
1011
f: &mut CssFormatter,
1112
) -> FormatResult<()> {
12-
format_verbatim_node(node.syntax()).fmt(f)
13+
let CssPseudoClassIdentifierFields { name } = node.as_fields();
14+
15+
write!(f, [name.format()])
1316
}
1417
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
use crate::prelude::*;
2-
use biome_css_syntax::CssPseudoClassNth;
3-
use biome_rowan::AstNode;
2+
use biome_css_syntax::{CssPseudoClassNth, CssPseudoClassNthFields};
3+
use biome_formatter::write;
4+
45
#[derive(Debug, Clone, Default)]
56
pub(crate) struct FormatCssPseudoClassNth;
67
impl FormatNodeRule<CssPseudoClassNth> for FormatCssPseudoClassNth {
78
fn fmt_fields(&self, node: &CssPseudoClassNth, f: &mut CssFormatter) -> FormatResult<()> {
8-
format_verbatim_node(node.syntax()).fmt(f)
9+
let CssPseudoClassNthFields {
10+
sign,
11+
value,
12+
symbol_token,
13+
offset,
14+
} = node.as_fields();
15+
16+
write!(f, [sign.format(), value.format(), symbol_token.format(),])?;
17+
18+
if offset.is_some() {
19+
write!(f, [soft_line_break_or_space(), offset.format()])?;
20+
}
21+
22+
Ok(())
923
}
1024
}

0 commit comments

Comments
 (0)