Skip to content

Commit

Permalink
fix(format/html): make element children break if attributes break (#5027
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dyc3 authored Feb 7, 2025
1 parent 141f858 commit 2696970
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 12 deletions.
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>
```

0 comments on commit 2696970

Please sign in to comment.