fix: do not sort class and style that are after spread marker

This commit is contained in:
Greg Johnston 2024-09-16 21:33:46 -04:00
parent f3dcdc057d
commit 8dc600ca02

View file

@ -279,10 +279,25 @@ pub(crate) fn element_to_tokens(
global_class: Option<&TokenTree>, global_class: Option<&TokenTree>,
view_marker: Option<&str>, view_marker: Option<&str>,
) -> Option<TokenStream> { ) -> Option<TokenStream> {
// attribute sorting:
//
// the `class` and `style` attributes overwrite individual `class:` and `style:` attributes // the `class` and `style` attributes overwrite individual `class:` and `style:` attributes
// when they are set. as a result, we're going to sort the attributes so that `class` and // when they are set. as a result, we're going to sort the attributes so that `class` and
// `style` always come before all other attributes. // `style` always come before all other attributes.
node.attributes_mut().sort_by(|a, b| {
// if there's a spread marker, we don't want to move `class` or `style` before it
// so let's only sort attributes that come *before* a spread marker
let spread_position = node
.attributes()
.iter()
.position(|n| match n {
NodeAttribute::Block(node) => as_spread_attr(node).is_some(),
_ => false,
})
.unwrap_or_else(|| node.attributes().len());
// now, sort the attributes
node.attributes_mut()[0..spread_position].sort_by(|a, b| {
let key_a = match a { let key_a = match a {
NodeAttribute::Attribute(attr) => match &attr.key { NodeAttribute::Attribute(attr) => match &attr.key {
NodeName::Path(attr) => { NodeName::Path(attr) => {
@ -496,6 +511,25 @@ fn is_spread_marker(node: &NodeElement<impl CustomNode>) -> bool {
} }
} }
fn as_spread_attr(node: &NodeBlock) -> Option<Option<&Expr>> {
if let NodeBlock::ValidBlock(block) = node {
match block.stmts.first() {
Some(Stmt::Expr(
Expr::Range(ExprRange {
start: None,
limits: RangeLimits::HalfOpen(_),
end,
..
}),
_,
)) => Some(end.as_deref()),
_ => None,
}
} else {
None
}
}
fn attribute_to_tokens( fn attribute_to_tokens(
tag_type: TagType, tag_type: TagType,
node: &NodeAttribute, node: &NodeAttribute,
@ -503,29 +537,18 @@ fn attribute_to_tokens(
is_custom: bool, is_custom: bool,
) -> TokenStream { ) -> TokenStream {
match node { match node {
NodeAttribute::Block(node) => { NodeAttribute::Block(node) => as_spread_attr(node)
let dotted = if let NodeBlock::ValidBlock(block) = node { .flatten()
match block.stmts.first() { .map(|end| {
Some(Stmt::Expr( quote! {
Expr::Range(ExprRange { .add_any_attr(#end)
start: None,
limits: RangeLimits::HalfOpen(_),
end: Some(end),
..
}),
_,
)) => Some(quote! { .add_any_attr(#end) }),
_ => None,
} }
} else { })
None .unwrap_or_else(|| {
};
dotted.unwrap_or_else(|| {
quote! { quote! {
.add_any_attr(#[allow(unused_braces)] { #node }) .add_any_attr(#[allow(unused_braces)] { #node })
} }
}) }),
}
NodeAttribute::Attribute(node) => { NodeAttribute::Attribute(node) => {
let name = node.key.to_string(); let name = node.key.to_string();
if name == "node_ref" { if name == "node_ref" {