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

fix(format/html): make element children break if attributes break #5027

Merged
merged 3 commits into from
Feb 7, 2025
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
38 changes: 31 additions & 7 deletions crates/biome_html_formatter/src/html/auxiliary/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,11 @@ impl FormatNodeRule<HtmlElement> for FormatHtmlElement {
None
};

let attr_group_id = f.group_id("element-attr-group-id");
FormatNodeRule::fmt(
&FormatHtmlOpeningElement::default().with_options(FormatHtmlOpeningElementOptions {
r_angle_is_borrowed: borrowed_r_angle.is_some(),
attr_group_id,
}),
&opening_element,
f,
Expand All @@ -128,13 +130,35 @@ impl FormatNodeRule<HtmlElement> for FormatHtmlElement {
flat_children,
expanded_children,
} => {
write!(
f,
[best_fitting![
format_args![flat_children],
format_args![expanded_children]
]]
)?;
// FIXME: `if_group_breaks` and `if_group_fits_on_line` are supposed to be inverses of each other,
// and they are. However, if the condition in the `if` below is not met, then neither of the 2
// calls print any content. This is a bug.
if opening_element.attributes().len() > 1 {
write!(
f,
[
// If the attribute group breaks, prettier always breaks the children as well.
&if_group_breaks(&expanded_children)
.with_group_id(Some(attr_group_id)),
// If the attribute group does NOT break, print whatever fits best for the children.
&if_group_fits_on_line(&best_fitting![
format_args![flat_children],
format_args![expanded_children]
])
.with_group_id(Some(attr_group_id)),
]
)?;
} else {
// The workaround for the bug mentioned above is to unconditionally print the children in the
// cases where the previous block would not print anything.
write!(
f,
[&best_fitting![
format_args![flat_children],
format_args![expanded_children]
]]
)?;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::prelude::*;
use biome_formatter::{write, FormatRuleWithOptions};
use biome_formatter::{write, FormatRuleWithOptions, GroupId};
use biome_html_syntax::{HtmlOpeningElement, HtmlOpeningElementFields};
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatHtmlOpeningElement {
Expand All @@ -11,18 +11,23 @@ pub(crate) struct FormatHtmlOpeningElement {
/// [FormatHtmlElementList]: crate::html::lists::element_list::FormatHtmlElementList
/// [HtmlElementList]: biome_html_syntax::HtmlElementList
r_angle_is_borrowed: bool,

attr_group_id: Option<GroupId>,
}

pub(crate) struct FormatHtmlOpeningElementOptions {
/// Whether or not the r_angle is borrowed, and therefore managed by a different formatter.
pub r_angle_is_borrowed: bool,

pub attr_group_id: GroupId,
}

impl FormatRuleWithOptions<HtmlOpeningElement> for FormatHtmlOpeningElement {
type Options = FormatHtmlOpeningElementOptions;

fn with_options(mut self, options: Self::Options) -> Self {
self.r_angle_is_borrowed = options.r_angle_is_borrowed;
self.attr_group_id = Some(options.attr_group_id);
self
}
}
Expand All @@ -39,7 +44,6 @@ impl FormatNodeRule<HtmlOpeningElement> for FormatHtmlOpeningElement {
let bracket_same_line = f.options().bracket_same_line().value();
write!(f, [l_angle_token.format(), name.format()])?;

let attr_group_id = f.group_id("element-attr-group-id");
write!(
f,
[&group(&format_with(|f| {
Expand All @@ -58,7 +62,7 @@ impl FormatNodeRule<HtmlOpeningElement> for FormatHtmlOpeningElement {
}
Ok(())
}))
.with_group_id(Some(attr_group_id))]
.with_group_id(self.attr_group_id)]
)?;

Ok(())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div
test="content must break if attributes break"
explanation="This group of attributes should break and become multiline."
details="The content must do the same, despite it being short."
>short content</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
source: crates/biome_formatter_test/src/snapshot_builder.rs
info: content-breaks-when-attr-breaks.html
---
# Input

```html
<div
test="content must break if attributes break"
explanation="This group of attributes should break and become multiline."
details="The content must do the same, despite it being short."
>short content</div>

```


=============================

# Outputs

## Output 1

-----
Indent style: Tab
Indent width: 2
Line ending: LF
Line width: 80
Attribute Position: Auto
Bracket same line: false
Whitespace sensitivity: css
Indent script and style: false
-----

```html
<div
test="content must break if attributes break"
explanation="This group of attributes should break and become multiline."
details="The content must do the same, despite it being short."
>
short content
</div>
```
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ Indent script and style: false
style="color: red"
data-foo="bar"
data-bar="foo"
>hello world</div>
>
hello world
</div>
```

## Output 1
Expand All @@ -64,5 +66,7 @@ Indent script and style: false
class="world really-long-class-name another-really-long-class-name"
style="color: red"
data-foo="bar"
data-bar="foo">hello world</div>
data-bar="foo">
hello world
</div>
```