(macros): Permite (expr) como atributo en html!

Introduce `Attribute::Splice` en el AST de Maud, de modo que `(expr)` en
posición de atributo renderiza la expresión directamente sobre el buffer
de salida del elemento.
This commit is contained in:
Manuel Cillero 2026-06-11 06:46:16 +02:00
parent 47b6553fe4
commit 35a5221c92
2 changed files with 24 additions and 2 deletions

View file

@ -212,6 +212,7 @@ impl DiagnosticParse for Element {
|| input.peek(Lit)
|| input.peek(Dot)
|| input.peek(Pound)
|| input.peek(Paren)
{
let attr = input.diagnostic_parse(diagnostics)?;
@ -346,6 +347,10 @@ pub enum Attribute {
name: HtmlName,
attr_type: AttributeType,
},
Splice {
paren_token: Paren,
expr: Expr,
},
}
impl DiagnosticParse for Attribute {
@ -374,6 +379,12 @@ impl DiagnosticParse for Attribute {
pound_token: input.parse()?,
name: input.diagnostic_parse(diagnostics)?,
})
} else if lookahead.peek(Paren) {
let content;
Ok(Self::Splice {
paren_token: parenthesized!(content in input),
expr: content.parse()?,
})
} else {
let name = input.diagnostic_parse::<HtmlName>(diagnostics)?;
@ -424,6 +435,11 @@ impl ToTokens for Attribute {
name.to_tokens(tokens);
attr_type.to_tokens(tokens);
}
Self::Splice { paren_token, expr } => {
paren_token.surround(tokens, |tokens| {
expr.to_tokens(tokens);
});
}
}
}
}

View file

@ -139,7 +139,7 @@ impl Generator {
}
fn attrs(&self, attrs: Vec<Attribute>, build: &mut Builder) {
let (classes, id, named_attrs) = split_attrs(attrs);
let (classes, id, named_attrs, spliced) = split_attrs(attrs);
if !classes.is_empty() {
let mut toggle_class_exprs = vec![];
@ -184,6 +184,9 @@ impl Generator {
for (name, attr_type) in named_attrs {
self.attr(name, attr_type, build);
}
for expr in spliced {
self.splice(expr, build);
}
}
fn control_flow<E: Into<Element>>(&self, control_flow: ControlFlow<E>, build: &mut Builder) {
@ -316,10 +319,12 @@ fn split_attrs(
Vec<(HtmlNameOrMarkup, Option<Expr>)>,
Option<HtmlNameOrMarkup>,
Vec<(HtmlName, AttributeType)>,
Vec<Expr>,
) {
let mut classes = vec![];
let mut id = None;
let mut named_attrs = vec![];
let mut spliced = vec![];
for attr in attrs {
match attr {
@ -328,10 +333,11 @@ fn split_attrs(
}
Attribute::Id { name, .. } => id = Some(name),
Attribute::Named { name, attr_type } => named_attrs.push((name, attr_type)),
Attribute::Splice { expr, .. } => spliced.push(expr),
}
}
(classes, id, named_attrs)
(classes, id, named_attrs, spliced)
}
////////////////////////////////////////////////////////