feat: implement spreading attributes onto elements (#1619)
This commit is contained in:
parent
d9e83121c1
commit
4a43983f4e
|
@ -63,7 +63,9 @@ cfg_if! {
|
|||
use crate::{
|
||||
ev::EventDescriptor,
|
||||
hydration::HydrationCtx,
|
||||
macro_helpers::{IntoAttribute, IntoClass, IntoProperty, IntoStyle},
|
||||
macro_helpers::{
|
||||
Attribute, IntoAttribute, IntoClass, IntoProperty, IntoStyle,
|
||||
},
|
||||
Element, Fragment, IntoView, NodeRef, Text, View,
|
||||
};
|
||||
use leptos_reactive::Oco;
|
||||
|
@ -593,8 +595,6 @@ impl<El: ElementDescriptor + 'static> HtmlElement<El> {
|
|||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
use crate::macro_helpers::Attribute;
|
||||
|
||||
let mut this = self;
|
||||
|
||||
let mut attr = attr.into_attribute();
|
||||
|
@ -622,6 +622,18 @@ impl<El: ElementDescriptor + 'static> HtmlElement<El> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds multiple attributes to the element
|
||||
#[track_caller]
|
||||
pub fn attrs(
|
||||
mut self,
|
||||
attrs: impl std::iter::IntoIterator<Item = (&'static str, Attribute)>,
|
||||
) -> Self {
|
||||
for (name, value) in attrs {
|
||||
self = self.attr(name, value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a class to an element.
|
||||
///
|
||||
/// **Note**: In the builder syntax, this will be overwritten by the `class`
|
||||
|
|
|
@ -217,6 +217,27 @@ pub(crate) fn element_to_tokens(
|
|||
None
|
||||
}
|
||||
});
|
||||
let spread_attrs = node.attributes().iter().filter_map(|node| {
|
||||
use rstml::node::NodeBlock;
|
||||
use syn::{Expr, ExprRange, RangeLimits, Stmt};
|
||||
|
||||
if let NodeAttribute::Block(NodeBlock::ValidBlock(block)) = node {
|
||||
match block.stmts.first()? {
|
||||
Stmt::Expr(
|
||||
Expr::Range(ExprRange {
|
||||
start: None,
|
||||
limits: RangeLimits::HalfOpen(_),
|
||||
end: Some(end),
|
||||
..
|
||||
}),
|
||||
_,
|
||||
) => Some(quote! { .attrs(#[allow(unused_brace)] {#end}) }),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let class_attrs = node.attributes().iter().filter_map(|node| {
|
||||
if let NodeAttribute::Attribute(node) = node {
|
||||
let name = node.key.to_string();
|
||||
|
@ -332,6 +353,7 @@ pub(crate) fn element_to_tokens(
|
|||
#(#ide_helper_close_tag)*
|
||||
#name
|
||||
#(#attrs)*
|
||||
#(#spread_attrs)*
|
||||
#(#class_attrs)*
|
||||
#(#style_attrs)*
|
||||
#global_class_expr
|
||||
|
|
|
@ -265,6 +265,31 @@ fn element_to_tokens_ssr(
|
|||
);
|
||||
}
|
||||
}
|
||||
for attr in node.attributes() {
|
||||
use syn::{Expr, ExprRange, RangeLimits, Stmt};
|
||||
|
||||
if let NodeAttribute::Block(NodeBlock::ValidBlock(block)) = attr {
|
||||
if let Some(Stmt::Expr(
|
||||
Expr::Range(ExprRange {
|
||||
start: None,
|
||||
limits: RangeLimits::HalfOpen(_),
|
||||
end: Some(end),
|
||||
..
|
||||
}),
|
||||
_,
|
||||
)) = block.stmts.first()
|
||||
{
|
||||
// should basically be the resolved attributes, joined on spaces, placed into
|
||||
// the template
|
||||
template.push_str(" {}");
|
||||
holes.push(quote! {
|
||||
{#end}.into_iter().filter_map(|(name, attr)| {
|
||||
Some(format!("{}={}", name, ::leptos::leptos_dom::ssr::escape_attr(&attr.as_nameless_value_string()?)))
|
||||
}).collect::<Vec<_>>().join(" ")
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// insert hydration ID
|
||||
let hydration_id = if is_root {
|
||||
|
|
Loading…
Reference in New Issue