123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- use std::fmt::{Display, Formatter};
- use super::*;
- use proc_macro2::{Span, TokenStream as TokenStream2};
- use quote::{quote, ToTokens, TokenStreamExt};
- use syn::{Expr, Ident, LitStr};
- #[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) = self.attr.name.multi_attribute_separator() {
- 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: &ElementAttrName| match (el_name, name) {
- (ElementName::Ident(i), ElementAttrName::BuiltIn(_)) => {
- quote! { dioxus_elements::#i::#name.1 }
- }
- _ => quote! { None },
- };
- let volitile = |name: &ElementAttrName| match (el_name, name) {
- (ElementName::Ident(i), ElementAttrName::BuiltIn(_)) => {
- quote! { dioxus_elements::#i::#name.2 }
- }
- _ => 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 {
- match (self, other) {
- (Self::AttrLiteral(lit1), Self::AttrLiteral(lit2)) => {
- let fmt = lit1.clone().join(lit2.clone(), separator);
- Self::AttrLiteral(fmt)
- }
- (Self::AttrLiteral(expr1), Self::AttrExpr(expr2)) => {
- let mut ifmt = expr1.clone();
- ifmt.push_str(separator);
- ifmt.push_expr(expr2.clone());
- Self::AttrLiteral(ifmt)
- }
- (Self::AttrExpr(expr1), Self::AttrLiteral(expr2)) => {
- let mut ifmt = expr2.clone();
- ifmt.push_str(separator);
- ifmt.push_expr(expr1.clone());
- Self::AttrLiteral(ifmt)
- }
- (Self::AttrExpr(expr1), Self::AttrExpr(expr2)) => {
- let mut ifmt = IfmtInput::default();
- ifmt.push_expr(expr1.clone());
- ifmt.push_str(separator);
- ifmt.push_expr(expr2.clone());
- Self::AttrLiteral(ifmt)
- }
- _ => todo!(),
- }
- }
- }
- #[derive(PartialEq, Eq, Clone, Debug, Hash)]
- pub enum ElementAttrName {
- BuiltIn(Ident),
- Custom(LitStr),
- }
- impl ElementAttrName {
- fn multi_attribute_separator(&self) -> Option<&'static str> {
- match self {
- ElementAttrName::BuiltIn(i) => match i.to_string().as_str() {
- "class" => Some(" "),
- "style" => Some(";"),
- _ => None,
- },
- ElementAttrName::Custom(_) => None,
- }
- }
- 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(_),
- ..
- }
- )
- }
- }
|