attribute.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. use std::fmt::{Display, Formatter};
  2. use super::*;
  3. use proc_macro2::{Span, TokenStream as TokenStream2};
  4. use quote::{quote, ToTokens, TokenStreamExt};
  5. use syn::{Expr, Ident, LitStr};
  6. #[derive(PartialEq, Eq, Clone, Debug, Hash)]
  7. pub struct ElementAttrNamed {
  8. pub el_name: ElementName,
  9. pub attr: ElementAttr,
  10. }
  11. impl ElementAttrNamed {
  12. pub(crate) fn try_combine(&self, other: &Self) -> Option<Self> {
  13. if self.el_name == other.el_name && self.attr.name == other.attr.name {
  14. if let Some(separator) = self.attr.name.multi_attribute_separator() {
  15. return Some(ElementAttrNamed {
  16. el_name: self.el_name.clone(),
  17. attr: ElementAttr {
  18. name: self.attr.name.clone(),
  19. value: self.attr.value.combine(separator, &other.attr.value),
  20. },
  21. });
  22. }
  23. }
  24. None
  25. }
  26. }
  27. impl ToTokens for ElementAttrNamed {
  28. fn to_tokens(&self, tokens: &mut TokenStream2) {
  29. let ElementAttrNamed { el_name, attr } = self;
  30. let ns = |name: &ElementAttrName| match (el_name, name) {
  31. (ElementName::Ident(i), ElementAttrName::BuiltIn(_)) => {
  32. quote! { dioxus_elements::#i::#name.1 }
  33. }
  34. _ => quote! { None },
  35. };
  36. let volitile = |name: &ElementAttrName| match (el_name, name) {
  37. (ElementName::Ident(i), ElementAttrName::BuiltIn(_)) => {
  38. quote! { dioxus_elements::#i::#name.2 }
  39. }
  40. _ => quote! { false },
  41. };
  42. let attribute = |name: &ElementAttrName| match name {
  43. ElementAttrName::BuiltIn(name) => match el_name {
  44. ElementName::Ident(_) => quote! { #el_name::#name.0 },
  45. ElementName::Custom(_) => {
  46. let as_string = name.to_string();
  47. quote!(#as_string)
  48. }
  49. },
  50. ElementAttrName::Custom(s) => quote! { #s },
  51. };
  52. let attribute = {
  53. match &attr.value {
  54. ElementAttrValue::AttrLiteral(_) | ElementAttrValue::AttrExpr(_) => {
  55. let name = &self.attr.name;
  56. let ns = ns(name);
  57. let volitile = volitile(name);
  58. let attribute = attribute(name);
  59. let value = match &self.attr.value {
  60. ElementAttrValue::AttrLiteral(lit) => quote! { #lit },
  61. ElementAttrValue::AttrExpr(expr) => quote! { #expr },
  62. _ => unreachable!(),
  63. };
  64. quote! {
  65. __cx.attr(
  66. #attribute,
  67. #value,
  68. #ns,
  69. #volitile
  70. )
  71. }
  72. }
  73. ElementAttrValue::EventTokens(tokens) => match &self.attr.name {
  74. ElementAttrName::BuiltIn(name) => {
  75. quote! {
  76. dioxus_elements::events::#name(__cx, #tokens)
  77. }
  78. }
  79. ElementAttrName::Custom(_) => todo!(),
  80. },
  81. }
  82. };
  83. tokens.append_all(attribute);
  84. }
  85. }
  86. #[derive(PartialEq, Eq, Clone, Debug, Hash)]
  87. pub struct ElementAttr {
  88. pub name: ElementAttrName,
  89. pub value: ElementAttrValue,
  90. }
  91. #[derive(PartialEq, Eq, Clone, Debug, Hash)]
  92. pub enum ElementAttrValue {
  93. /// attribute: "value"
  94. AttrLiteral(IfmtInput),
  95. /// attribute: true
  96. AttrExpr(Expr),
  97. /// onclick: move |_| {}
  98. EventTokens(Expr),
  99. }
  100. impl ElementAttrValue {
  101. fn combine(&self, separator: &str, other: &Self) -> Self {
  102. match (self, other) {
  103. (Self::AttrLiteral(lit1), Self::AttrLiteral(lit2)) => {
  104. let fmt = lit1.clone().join(lit2.clone(), separator);
  105. Self::AttrLiteral(fmt)
  106. }
  107. (Self::AttrLiteral(expr1), Self::AttrExpr(expr2)) => {
  108. let mut ifmt = expr1.clone();
  109. ifmt.push_str(separator);
  110. ifmt.push_expr(expr2.clone());
  111. Self::AttrLiteral(ifmt)
  112. }
  113. (Self::AttrExpr(expr1), Self::AttrLiteral(expr2)) => {
  114. let mut ifmt = expr2.clone();
  115. ifmt.push_str(separator);
  116. ifmt.push_expr(expr1.clone());
  117. Self::AttrLiteral(ifmt)
  118. }
  119. (Self::AttrExpr(expr1), Self::AttrExpr(expr2)) => {
  120. let mut ifmt = IfmtInput::default();
  121. ifmt.push_expr(expr1.clone());
  122. ifmt.push_str(separator);
  123. ifmt.push_expr(expr2.clone());
  124. Self::AttrLiteral(ifmt)
  125. }
  126. _ => todo!(),
  127. }
  128. }
  129. }
  130. #[derive(PartialEq, Eq, Clone, Debug, Hash)]
  131. pub enum ElementAttrName {
  132. BuiltIn(Ident),
  133. Custom(LitStr),
  134. }
  135. impl ElementAttrName {
  136. fn multi_attribute_separator(&self) -> Option<&'static str> {
  137. match self {
  138. ElementAttrName::BuiltIn(i) => match i.to_string().as_str() {
  139. "class" => Some(" "),
  140. "style" => Some(";"),
  141. _ => None,
  142. },
  143. ElementAttrName::Custom(_) => None,
  144. }
  145. }
  146. pub fn start(&self) -> Span {
  147. match self {
  148. ElementAttrName::BuiltIn(i) => i.span(),
  149. ElementAttrName::Custom(s) => s.span(),
  150. }
  151. }
  152. }
  153. impl ToTokens for ElementAttrName {
  154. fn to_tokens(&self, tokens: &mut TokenStream2) {
  155. match self {
  156. ElementAttrName::BuiltIn(i) => tokens.append_all(quote! { #i }),
  157. ElementAttrName::Custom(s) => tokens.append_all(quote! { #s }),
  158. }
  159. }
  160. }
  161. impl Display for ElementAttrName {
  162. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  163. match self {
  164. ElementAttrName::BuiltIn(i) => write!(f, "{}", i),
  165. ElementAttrName::Custom(s) => write!(f, "{}", s.value()),
  166. }
  167. }
  168. }
  169. impl ElementAttr {
  170. pub fn start(&self) -> Span {
  171. self.name.start()
  172. }
  173. pub fn is_expr(&self) -> bool {
  174. matches!(
  175. self,
  176. ElementAttr {
  177. value: ElementAttrValue::AttrExpr(_) | ElementAttrValue::EventTokens(_),
  178. ..
  179. }
  180. )
  181. }
  182. }