mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-26 22:20:19 +00:00
clean up attribute parsing
This commit is contained in:
parent
b68a1f57e0
commit
8c47dfaf78
8 changed files with 278 additions and 261 deletions
|
@ -209,12 +209,25 @@ impl Writer<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_attribute(&mut self, attr: &ElementAttrNamed) -> Result {
|
||||
match &attr.attr {
|
||||
ElementAttr::AttrText { name, value } => {
|
||||
write!(self.out, "{name}: {value}", value = ifmt_to_string(value))?;
|
||||
fn write_attribute_name(&mut self, attr: &ElementAttrName) -> Result {
|
||||
match attr {
|
||||
ElementAttrName::BuiltIn(name) => {
|
||||
write!(self.out, "{}", name)?;
|
||||
}
|
||||
ElementAttr::AttrExpression { name, value } => {
|
||||
ElementAttrName::Custom(name) => {
|
||||
write!(self.out, "\"{}\"", name.to_token_stream())?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_attribute_value(&mut self, value: &ElementAttrValue) -> Result {
|
||||
match value {
|
||||
ElementAttrValue::AttrLiteral(value) => {
|
||||
write!(self.out, "{value}", value = ifmt_to_string(value))?;
|
||||
}
|
||||
ElementAttrValue::AttrExpr(value) => {
|
||||
let out = prettyplease::unparse_expr(value);
|
||||
let mut lines = out.split('\n').peekable();
|
||||
let first = lines.next().unwrap();
|
||||
|
@ -222,9 +235,9 @@ impl Writer<'_> {
|
|||
// a one-liner for whatever reason
|
||||
// Does not need a new line
|
||||
if lines.peek().is_none() {
|
||||
write!(self.out, "{name}: {first}")?;
|
||||
write!(self.out, "{first}")?;
|
||||
} else {
|
||||
writeln!(self.out, "{name}: {first}")?;
|
||||
writeln!(self.out, "{first}")?;
|
||||
|
||||
while let Some(line) = lines.next() {
|
||||
self.out.indented_tab()?;
|
||||
|
@ -237,22 +250,7 @@ impl Writer<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrText { name, value } => {
|
||||
write!(
|
||||
self.out,
|
||||
"{name}: {value}",
|
||||
name = name.to_token_stream(),
|
||||
value = ifmt_to_string(value)
|
||||
)?;
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
let out = prettyplease::unparse_expr(value);
|
||||
write!(self.out, "{}: {}", name.to_token_stream(), out)?;
|
||||
}
|
||||
|
||||
ElementAttr::EventTokens { name, tokens } => {
|
||||
ElementAttrValue::EventTokens(tokens) => {
|
||||
let out = self.retrieve_formatted_expr(tokens).to_string();
|
||||
|
||||
let mut lines = out.split('\n').peekable();
|
||||
|
@ -261,9 +259,9 @@ impl Writer<'_> {
|
|||
// a one-liner for whatever reason
|
||||
// Does not need a new line
|
||||
if lines.peek().is_none() {
|
||||
write!(self.out, "{name}: {first}")?;
|
||||
write!(self.out, "{first}")?;
|
||||
} else {
|
||||
writeln!(self.out, "{name}: {first}")?;
|
||||
writeln!(self.out, "{first}")?;
|
||||
|
||||
while let Some(line) = lines.next() {
|
||||
self.out.indented_tab()?;
|
||||
|
@ -281,6 +279,14 @@ impl Writer<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_attribute(&mut self, attr: &ElementAttrNamed) -> Result {
|
||||
self.write_attribute_name(&attr.attr.name)?;
|
||||
write!(self.out, ": ")?;
|
||||
self.write_attribute_value(&attr.attr.value)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// make sure the comments are actually relevant to this element.
|
||||
// test by making sure this element is the primary element on this line
|
||||
pub fn current_span_is_primary(&self, location: Span) -> bool {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus_rsx::{BodyNode, ElementAttr, ElementAttrNamed, ForLoop};
|
||||
use dioxus_rsx::{BodyNode, ElementAttrNamed, ElementAttrValue, ForLoop};
|
||||
use proc_macro2::{LineColumn, Span};
|
||||
use quote::ToTokens;
|
||||
use std::{
|
||||
|
@ -146,20 +146,18 @@ impl<'a> Writer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
total += match &attr.attr {
|
||||
ElementAttr::AttrText { value, name } => {
|
||||
ifmt_to_string(value).len() + name.span().line_length() + 6
|
||||
total += match &attr.attr.name {
|
||||
dioxus_rsx::ElementAttrName::BuiltIn(name) => {
|
||||
let name = name.to_string();
|
||||
name.len()
|
||||
}
|
||||
ElementAttr::AttrExpression { name, value } => {
|
||||
value.span().line_length() + name.span().line_length() + 6
|
||||
}
|
||||
ElementAttr::CustomAttrText { value, name } => {
|
||||
ifmt_to_string(value).len() + name.to_token_stream().to_string().len() + 6
|
||||
}
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
name.to_token_stream().to_string().len() + value.span().line_length() + 6
|
||||
}
|
||||
ElementAttr::EventTokens { tokens, name } => {
|
||||
dioxus_rsx::ElementAttrName::Custom(name) => name.value().len() + 2,
|
||||
};
|
||||
|
||||
total += match &attr.attr.value {
|
||||
ElementAttrValue::AttrLiteral(lit) => ifmt_to_string(lit).len(),
|
||||
ElementAttrValue::AttrExpr(expr) => expr.span().line_length(),
|
||||
ElementAttrValue::EventTokens(tokens) => {
|
||||
let location = Location::new(tokens.span().start());
|
||||
|
||||
let len = if let std::collections::hash_map::Entry::Vacant(e) =
|
||||
|
@ -177,9 +175,11 @@ impl<'a> Writer<'a> {
|
|||
self.cached_formats[&location].len()
|
||||
};
|
||||
|
||||
len + name.span().line_length() + 6
|
||||
len
|
||||
}
|
||||
};
|
||||
|
||||
total += 6;
|
||||
}
|
||||
|
||||
total
|
||||
|
@ -218,7 +218,7 @@ impl<'a> Writer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
trait SpanLength {
|
||||
pub(crate) trait SpanLength {
|
||||
fn line_length(&self) -> usize;
|
||||
}
|
||||
impl SpanLength for Span {
|
||||
|
|
|
@ -36,9 +36,11 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
|
|||
|
||||
ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::AttrText {
|
||||
value: ifmt_from_text(value.as_deref().unwrap_or("false")),
|
||||
name: ident,
|
||||
attr: ElementAttr {
|
||||
value: dioxus_rsx::ElementAttrValue::AttrLiteral(ifmt_from_text(
|
||||
value.as_deref().unwrap_or("false"),
|
||||
)),
|
||||
name: dioxus_rsx::ElementAttrName::BuiltIn(ident),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -48,9 +50,12 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
|
|||
if !class.is_empty() {
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::AttrText {
|
||||
name: Ident::new("class", Span::call_site()),
|
||||
value: ifmt_from_text(&class),
|
||||
attr: ElementAttr {
|
||||
name: dioxus_rsx::ElementAttrName::BuiltIn(Ident::new(
|
||||
"class",
|
||||
Span::call_site(),
|
||||
)),
|
||||
value: dioxus_rsx::ElementAttrValue::AttrLiteral(ifmt_from_text(&class)),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -58,9 +63,12 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
|
|||
if let Some(id) = &el.id {
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::AttrText {
|
||||
name: Ident::new("id", Span::call_site()),
|
||||
value: ifmt_from_text(id),
|
||||
attr: ElementAttr {
|
||||
name: dioxus_rsx::ElementAttrName::BuiltIn(Ident::new(
|
||||
"id",
|
||||
Span::call_site(),
|
||||
)),
|
||||
value: dioxus_rsx::ElementAttrValue::AttrLiteral(ifmt_from_text(id)),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,5 +22,7 @@ internment = { version = "0.7.0", optional = true }
|
|||
krates = { version = "0.12.6", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["html"]
|
||||
hot_reload = ["krates", "internment"]
|
||||
serde = ["dep:serde"]
|
||||
html = []
|
||||
|
|
165
packages/rsx/src/attribute.rs
Normal file
165
packages/rsx/src/attribute.rs
Normal file
|
@ -0,0 +1,165 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use super::*;
|
||||
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
Expr, Ident, LitStr, Result, Token,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct ElementAttrNamed {
|
||||
pub el_name: ElementName,
|
||||
pub attr: ElementAttr,
|
||||
}
|
||||
|
||||
impl ElementAttrNamed {
|
||||
pub(crate) fn try_combine(&self, other: Self) -> Option<Self> {
|
||||
if self.el_name == other.el_name && self.attr.name == other.attr.name {
|
||||
if let Some(separator) = todo!() {
|
||||
return Some(ElementAttrNamed {
|
||||
el_name: self.el_name.clone(),
|
||||
attr: ElementAttr {
|
||||
name: self.attr.name.clone(),
|
||||
value: self.attr.value.combine(separator, other.attr.value),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ElementAttrNamed {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
let ElementAttrNamed { el_name, attr } = self;
|
||||
|
||||
let ns = |name| match el_name {
|
||||
ElementName::Ident(i) => quote! { dioxus_elements::#i::#name.1 },
|
||||
ElementName::Custom(_) => quote! { None },
|
||||
};
|
||||
let volitile = |name| match el_name {
|
||||
ElementName::Ident(_) => quote! { #el_name::#name.2 },
|
||||
ElementName::Custom(_) => quote! { false },
|
||||
};
|
||||
let attribute = |name: &ElementAttrName| match name {
|
||||
ElementAttrName::BuiltIn(name) => match el_name {
|
||||
ElementName::Ident(_) => quote! { #el_name::#name.0 },
|
||||
ElementName::Custom(_) => {
|
||||
let as_string = name.to_string();
|
||||
quote!(#as_string)
|
||||
}
|
||||
},
|
||||
ElementAttrName::Custom(s) => quote! { #s },
|
||||
};
|
||||
|
||||
let attribute = {
|
||||
match &attr.value {
|
||||
ElementAttrValue::AttrLiteral(_) | ElementAttrValue::AttrExpr(_) => {
|
||||
let name = &self.attr.name;
|
||||
let ns = ns(name);
|
||||
let volitile = volitile(name);
|
||||
let attribute = attribute(name);
|
||||
let value = match &self.attr.value {
|
||||
ElementAttrValue::AttrLiteral(lit) => quote! { #lit },
|
||||
ElementAttrValue::AttrExpr(expr) => quote! { #expr },
|
||||
_ => unreachable!(),
|
||||
};
|
||||
quote! {
|
||||
__cx.attr(
|
||||
#attribute,
|
||||
#value,
|
||||
#ns,
|
||||
#volitile
|
||||
)
|
||||
}
|
||||
}
|
||||
ElementAttrValue::EventTokens(tokens) => match &self.attr.name {
|
||||
ElementAttrName::BuiltIn(name) => {
|
||||
quote! {
|
||||
dioxus_elements::events::#name(__cx, #tokens)
|
||||
}
|
||||
}
|
||||
ElementAttrName::Custom(_) => todo!(),
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
tokens.append_all(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct ElementAttr {
|
||||
pub name: ElementAttrName,
|
||||
pub value: ElementAttrValue,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub enum ElementAttrValue {
|
||||
/// attribute: "value"
|
||||
AttrLiteral(IfmtInput),
|
||||
/// attribute: true
|
||||
AttrExpr(Expr),
|
||||
/// onclick: move |_| {}
|
||||
EventTokens(Expr),
|
||||
}
|
||||
|
||||
impl ElementAttrValue {
|
||||
fn combine(&self, separator: &str, other: Self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub enum ElementAttrName {
|
||||
BuiltIn(Ident),
|
||||
Custom(LitStr),
|
||||
}
|
||||
|
||||
impl ElementAttrName {
|
||||
pub fn start(&self) -> Span {
|
||||
match self {
|
||||
ElementAttrName::BuiltIn(i) => i.span(),
|
||||
ElementAttrName::Custom(s) => s.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ElementAttrName {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
match self {
|
||||
ElementAttrName::BuiltIn(i) => tokens.append_all(quote! { #i }),
|
||||
ElementAttrName::Custom(s) => tokens.append_all(quote! { #s }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ElementAttrName {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ElementAttrName::BuiltIn(i) => write!(f, "{}", i),
|
||||
ElementAttrName::Custom(s) => write!(f, "{}", s.value()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ElementAttr {
|
||||
pub fn start(&self) -> Span {
|
||||
self.name.start()
|
||||
}
|
||||
|
||||
pub fn is_expr(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ElementAttr {
|
||||
value: ElementAttrValue::AttrExpr(_) | ElementAttrValue::EventTokens(_),
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ use syn::{
|
|||
parse::{Parse, ParseBuffer, ParseStream},
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
Error, Expr, Ident, LitStr, Result, Token,
|
||||
Expr, Ident, LitStr, Result, Token,
|
||||
};
|
||||
|
||||
// =======================================
|
||||
|
@ -34,7 +34,6 @@ impl Parse for Element {
|
|||
let mut attributes: Vec<ElementAttrNamed> = vec![];
|
||||
let mut children: Vec<BodyNode> = vec![];
|
||||
let mut key = None;
|
||||
let mut _el_ref = None;
|
||||
|
||||
// parse fields with commas
|
||||
// break when we don't get this pattern anymore
|
||||
|
@ -49,19 +48,20 @@ impl Parse for Element {
|
|||
|
||||
content.parse::<Token![:]>()?;
|
||||
|
||||
if content.peek(LitStr) {
|
||||
let value = if content.peek(LitStr) {
|
||||
let value = content.parse()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrText { name, value },
|
||||
});
|
||||
ElementAttrValue::AttrLiteral(value)
|
||||
} else {
|
||||
let value = content.parse::<Expr>()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrExpression { name, value },
|
||||
});
|
||||
}
|
||||
ElementAttrValue::AttrExpr(value)
|
||||
};
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr {
|
||||
name: ElementAttrName::Custom(name),
|
||||
value,
|
||||
},
|
||||
});
|
||||
|
||||
if content.is_empty() {
|
||||
break;
|
||||
|
@ -86,9 +86,9 @@ impl Parse for Element {
|
|||
if name_str.starts_with("on") {
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::EventTokens {
|
||||
name,
|
||||
tokens: content.parse()?,
|
||||
attr: ElementAttr {
|
||||
name: ElementAttrName::BuiltIn(name),
|
||||
value: ElementAttrValue::EventTokens(content.parse()?),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
|
@ -96,26 +96,21 @@ impl Parse for Element {
|
|||
"key" => {
|
||||
key = Some(content.parse()?);
|
||||
}
|
||||
"classes" => todo!("custom class list not supported yet"),
|
||||
// "namespace" => todo!("custom namespace not supported yet"),
|
||||
"node_ref" => {
|
||||
_el_ref = Some(content.parse::<Expr>()?);
|
||||
}
|
||||
_ => {
|
||||
if content.peek(LitStr) {
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::AttrText {
|
||||
name,
|
||||
value: content.parse()?,
|
||||
attr: ElementAttr {
|
||||
name: ElementAttrName::BuiltIn(name),
|
||||
value: ElementAttrValue::AttrLiteral(content.parse()?),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::AttrExpression {
|
||||
name,
|
||||
value: content.parse()?,
|
||||
attr: ElementAttr {
|
||||
name: ElementAttrName::BuiltIn(name),
|
||||
value: ElementAttrValue::AttrExpr(content.parse()?),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -137,6 +132,9 @@ impl Parse for Element {
|
|||
break;
|
||||
}
|
||||
|
||||
// Deduplicate any attributes that can be combined
|
||||
// For example, if there are two `class` attributes, combine them into one
|
||||
|
||||
while !content.is_empty() {
|
||||
if (content.peek(LitStr) && content.peek2(Token![:])) && !content.peek3(Token![:]) {
|
||||
attr_after_element!(content.span());
|
||||
|
@ -177,12 +175,12 @@ impl ToTokens for Element {
|
|||
let listeners = self
|
||||
.attributes
|
||||
.iter()
|
||||
.filter(|f| matches!(f.attr, ElementAttr::EventTokens { .. }));
|
||||
.filter(|f| matches!(f.attr.value, ElementAttrValue::EventTokens { .. }));
|
||||
|
||||
let attr = self
|
||||
.attributes
|
||||
.iter()
|
||||
.filter(|f| !matches!(f.attr, ElementAttr::EventTokens { .. }));
|
||||
.filter(|f| !matches!(f.attr.value, ElementAttrValue::EventTokens { .. }));
|
||||
|
||||
tokens.append_all(quote! {
|
||||
__cx.element(
|
||||
|
@ -264,136 +262,3 @@ impl ToTokens for ElementName {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub enum ElementAttr {
|
||||
/// `attribute: "value"`
|
||||
AttrText { name: Ident, value: IfmtInput },
|
||||
|
||||
/// `attribute: true`
|
||||
AttrExpression { name: Ident, value: Expr },
|
||||
|
||||
/// `"attribute": "value"`
|
||||
CustomAttrText { name: LitStr, value: IfmtInput },
|
||||
|
||||
/// `"attribute": true`
|
||||
CustomAttrExpression { name: LitStr, value: Expr },
|
||||
|
||||
// /// onclick: move |_| {}
|
||||
// EventClosure { name: Ident, closure: ExprClosure },
|
||||
/// onclick: {}
|
||||
EventTokens { name: Ident, tokens: Expr },
|
||||
}
|
||||
|
||||
impl ElementAttr {
|
||||
pub fn start(&self) -> Span {
|
||||
match self {
|
||||
ElementAttr::AttrText { name, .. } => name.span(),
|
||||
ElementAttr::AttrExpression { name, .. } => name.span(),
|
||||
ElementAttr::CustomAttrText { name, .. } => name.span(),
|
||||
ElementAttr::CustomAttrExpression { name, .. } => name.span(),
|
||||
ElementAttr::EventTokens { name, .. } => name.span(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_expr(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ElementAttr::AttrExpression { .. }
|
||||
| ElementAttr::CustomAttrExpression { .. }
|
||||
| ElementAttr::EventTokens { .. }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct ElementAttrNamed {
|
||||
pub el_name: ElementName,
|
||||
pub attr: ElementAttr,
|
||||
}
|
||||
|
||||
impl ToTokens for ElementAttrNamed {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
let ElementAttrNamed { el_name, attr } = self;
|
||||
|
||||
let ns = |name| match el_name {
|
||||
ElementName::Ident(i) => quote! { dioxus_elements::#i::#name.1 },
|
||||
ElementName::Custom(_) => quote! { None },
|
||||
};
|
||||
let volitile = |name| match el_name {
|
||||
ElementName::Ident(_) => quote! { #el_name::#name.2 },
|
||||
ElementName::Custom(_) => quote! { false },
|
||||
};
|
||||
let attribute = |name: &Ident| match el_name {
|
||||
ElementName::Ident(_) => quote! { #el_name::#name.0 },
|
||||
ElementName::Custom(_) => {
|
||||
let as_string = name.to_string();
|
||||
quote!(#as_string)
|
||||
}
|
||||
};
|
||||
|
||||
let attribute = match attr {
|
||||
ElementAttr::AttrText { name, value } => {
|
||||
let ns = ns(name);
|
||||
let volitile = volitile(name);
|
||||
let attribute = attribute(name);
|
||||
quote! {
|
||||
__cx.attr(
|
||||
#attribute,
|
||||
#value,
|
||||
#ns,
|
||||
#volitile
|
||||
)
|
||||
}
|
||||
}
|
||||
ElementAttr::AttrExpression { name, value } => {
|
||||
let ns = ns(name);
|
||||
let volitile = volitile(name);
|
||||
let attribute = attribute(name);
|
||||
quote! {
|
||||
__cx.attr(
|
||||
#attribute,
|
||||
#value,
|
||||
#ns,
|
||||
#volitile
|
||||
)
|
||||
}
|
||||
}
|
||||
ElementAttr::CustomAttrText { name, value } => {
|
||||
quote! {
|
||||
__cx.attr(
|
||||
#name,
|
||||
#value,
|
||||
None,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
quote! {
|
||||
__cx.attr(
|
||||
#name,
|
||||
#value,
|
||||
None,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
ElementAttr::EventTokens { name, tokens } => {
|
||||
quote! {
|
||||
dioxus_elements::events::#name(__cx, #tokens)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokens.append_all(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
// ::dioxus::core::Attribute {
|
||||
// name: stringify!(#name),
|
||||
// namespace: None,
|
||||
// volatile: false,
|
||||
// mounted_node: Default::default(),
|
||||
// value: ::dioxus::core::AttributeValue::Text(#value),
|
||||
// }
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
macro_rules! missing_trailing_comma {
|
||||
($span:expr) => {
|
||||
return Err(Error::new($span, "missing trailing comma"));
|
||||
return Err(syn::Error::new($span, "missing trailing comma"));
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! attr_after_element {
|
||||
($span:expr) => {
|
||||
return Err(Error::new($span, "expected element\n = help move the attribute above all the children and text elements"));
|
||||
return Err(syn::Error::new($span, "expected element\n = help move the attribute above all the children and text elements"));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#[macro_use]
|
||||
mod errors;
|
||||
mod attribute;
|
||||
mod component;
|
||||
mod element;
|
||||
#[cfg(feature = "hot_reload")]
|
||||
|
@ -23,6 +24,7 @@ mod node;
|
|||
use std::{fmt::Debug, hash::Hash};
|
||||
|
||||
// Re-export the namespaces into each other
|
||||
pub use attribute::*;
|
||||
pub use component::*;
|
||||
#[cfg(feature = "hot_reload")]
|
||||
use dioxus_core::{Template, TemplateAttribute, TemplateNode};
|
||||
|
@ -307,16 +309,9 @@ impl DynamicMapping {
|
|||
match node {
|
||||
BodyNode::Element(el) => {
|
||||
for attr in el.attributes {
|
||||
match &attr.attr {
|
||||
ElementAttr::CustomAttrText { value, .. }
|
||||
| ElementAttr::AttrText { value, .. }
|
||||
if value.is_static() => {}
|
||||
|
||||
ElementAttr::AttrExpression { .. }
|
||||
| ElementAttr::AttrText { .. }
|
||||
| ElementAttr::CustomAttrText { .. }
|
||||
| ElementAttr::CustomAttrExpression { .. }
|
||||
| ElementAttr::EventTokens { .. } => {
|
||||
match &attr.attr.value {
|
||||
ElementAttrValue::AttrLiteral(input) if input.is_static() => {}
|
||||
_ => {
|
||||
self.insert_attribute(attr.attr);
|
||||
}
|
||||
}
|
||||
|
@ -365,9 +360,10 @@ impl<'a> DynamicContext<'a> {
|
|||
|
||||
let mut static_attrs = Vec::new();
|
||||
for attr in &el.attributes {
|
||||
match &attr.attr {
|
||||
ElementAttr::AttrText { name, value } if value.is_static() => {
|
||||
match &attr.attr.value {
|
||||
ElementAttrValue::AttrLiteral(value) if value.is_static() => {
|
||||
let value = value.source.as_ref().unwrap();
|
||||
let name = &attr.attr.name;
|
||||
let attribute_name_rust = name.to_string();
|
||||
let (name, namespace) =
|
||||
Ctx::map_attribute(&element_name_rust, &attribute_name_rust)
|
||||
|
@ -379,20 +375,7 @@ impl<'a> DynamicContext<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrText { name, value } if value.is_static() => {
|
||||
let value = value.source.as_ref().unwrap();
|
||||
static_attrs.push(TemplateAttribute::Static {
|
||||
name: intern(name.value().as_str()),
|
||||
namespace: None,
|
||||
value: intern(value.value().as_str()),
|
||||
})
|
||||
}
|
||||
|
||||
ElementAttr::AttrExpression { .. }
|
||||
| ElementAttr::AttrText { .. }
|
||||
| ElementAttr::CustomAttrText { .. }
|
||||
| ElementAttr::CustomAttrExpression { .. }
|
||||
| ElementAttr::EventTokens { .. } => {
|
||||
_ => {
|
||||
let idx = match mapping {
|
||||
Some(mapping) => mapping.get_attribute_idx(&attr.attr)?,
|
||||
None => self.dynamic_attributes.len(),
|
||||
|
@ -464,10 +447,16 @@ impl<'a> DynamicContext<'a> {
|
|||
ElementName::Ident(i) => quote! { dioxus_elements::#i::#name },
|
||||
ElementName::Custom(_) => quote! { None },
|
||||
};
|
||||
let static_attrs = el.attributes.iter().map(|attr| match &attr.attr {
|
||||
ElementAttr::AttrText { name, value } if value.is_static() => {
|
||||
let static_attrs = el.attributes.iter().map(|attr| match &attr.attr.value {
|
||||
ElementAttrValue::AttrLiteral(value) if value.is_static() => {
|
||||
let value = value.to_static().unwrap();
|
||||
let ns = ns(quote!(#name.1));
|
||||
let ns = {
|
||||
match &attr.attr.name {
|
||||
ElementAttrName::BuiltIn(name) => ns(quote!(#name.1)),
|
||||
ElementAttrName::Custom(_) => quote!(None),
|
||||
}
|
||||
};
|
||||
let name = &attr.attr.name;
|
||||
let name = match el_name {
|
||||
ElementName::Ident(_) => quote! { #el_name::#name.0 },
|
||||
ElementName::Custom(_) => {
|
||||
|
@ -487,25 +476,7 @@ impl<'a> DynamicContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrText { name, value } if value.is_static() => {
|
||||
let value = value.to_static().unwrap();
|
||||
quote! {
|
||||
::dioxus::core::TemplateAttribute::Static {
|
||||
name: #name,
|
||||
namespace: None,
|
||||
value: #value,
|
||||
|
||||
// todo: we don't diff these so we never apply the volatile flag
|
||||
// volatile: dioxus_elements::#el_name::#name.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElementAttr::AttrExpression { .. }
|
||||
| ElementAttr::AttrText { .. }
|
||||
| ElementAttr::CustomAttrText { .. }
|
||||
| ElementAttr::CustomAttrExpression { .. }
|
||||
| ElementAttr::EventTokens { .. } => {
|
||||
_ => {
|
||||
let ct = self.dynamic_attributes.len();
|
||||
self.dynamic_attributes.push(attr);
|
||||
self.attr_paths.push(self.current_path.clone());
|
||||
|
|
Loading…
Reference in a new issue