1
0

extensions.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. use dioxus_core::TemplateNode;
  2. use dioxus_core_types::HotReloadingContext;
  3. use dioxus_rsx::*;
  4. use internment::Intern;
  5. use std::hash::Hash;
  6. // interns a object into a static object, reusing the value if it already exists
  7. pub(crate) fn intern<T: Eq + Hash + Send + Sync + ?Sized + 'static>(
  8. s: impl Into<Intern<T>>,
  9. ) -> &'static T {
  10. s.into().as_ref()
  11. }
  12. pub(crate) fn html_tag_and_namespace<Ctx: HotReloadingContext>(
  13. attr: &Attribute,
  14. ) -> (&'static str, Option<&'static str>) {
  15. let attribute_name_rust = attr.name.to_string();
  16. let element_name = attr.el_name.as_ref().unwrap();
  17. let rust_name = match element_name {
  18. ElementName::Ident(i) => i.to_string(),
  19. // If this is a web component, just use the name of the elements instead of mapping the attribute
  20. // through the hot reloading context
  21. ElementName::Custom(_) => return (intern(attribute_name_rust.as_str()), None),
  22. };
  23. Ctx::map_attribute(&rust_name, &attribute_name_rust)
  24. .unwrap_or((intern(attribute_name_rust.as_str()), None))
  25. }
  26. pub fn to_template_attribute<Ctx: HotReloadingContext>(
  27. attr: &Attribute,
  28. ) -> dioxus_core::TemplateAttribute {
  29. use dioxus_core::TemplateAttribute;
  30. // If it's a dynamic node, just return it
  31. // For dynamic attributes, we need to check the mapping to see if that mapping exists
  32. // todo: one day we could generate new dynamic attributes on the fly if they're a literal,
  33. // or something sufficiently serializable
  34. // (ie `checked`` being a bool and bools being interpretable)
  35. //
  36. // For now, just give up if that attribute doesn't exist in the mapping
  37. if !attr.is_static_str_literal() {
  38. let id = attr.dyn_idx.get();
  39. return TemplateAttribute::Dynamic { id };
  40. }
  41. // Otherwise it's a static node and we can build it
  42. let (_, value) = attr.as_static_str_literal().unwrap();
  43. let (name, namespace) = html_tag_and_namespace::<Ctx>(attr);
  44. TemplateAttribute::Static {
  45. name,
  46. namespace,
  47. value: intern(value.to_static().unwrap().as_str()),
  48. }
  49. }
  50. /// Convert this BodyNode into a TemplateNode.
  51. ///
  52. /// dioxus-core uses this to understand templates at compiletime
  53. pub fn to_template_node<Ctx: HotReloadingContext>(node: &BodyNode) -> dioxus_core::TemplateNode {
  54. use dioxus_core::TemplateNode;
  55. match node {
  56. BodyNode::Element(el) => {
  57. let rust_name = el.name.to_string();
  58. let (tag, namespace) =
  59. Ctx::map_element(&rust_name).unwrap_or((intern(rust_name.as_str()), None));
  60. TemplateNode::Element {
  61. tag,
  62. namespace,
  63. children: intern(
  64. el.children
  65. .iter()
  66. .map(|c| to_template_node::<Ctx>(c))
  67. .collect::<Vec<_>>(),
  68. ),
  69. attrs: intern(
  70. el.merged_attributes
  71. .iter()
  72. .map(|attr| to_template_attribute::<Ctx>(attr))
  73. .collect::<Vec<_>>(),
  74. ),
  75. }
  76. }
  77. BodyNode::Text(text) => text_to_template_node(text),
  78. BodyNode::RawExpr(exp) => TemplateNode::Dynamic {
  79. id: exp.dyn_idx.get(),
  80. },
  81. BodyNode::Component(comp) => TemplateNode::Dynamic {
  82. id: comp.dyn_idx.get(),
  83. },
  84. BodyNode::ForLoop(floop) => TemplateNode::Dynamic {
  85. id: floop.dyn_idx.get(),
  86. },
  87. BodyNode::IfChain(chain) => TemplateNode::Dynamic {
  88. id: chain.dyn_idx.get(),
  89. },
  90. }
  91. }
  92. pub fn text_to_template_node(node: &TextNode) -> TemplateNode {
  93. match node.input.to_static() {
  94. Some(text) => TemplateNode::Text {
  95. text: intern(text.as_str()),
  96. },
  97. None => TemplateNode::Dynamic {
  98. id: node.dyn_idx.get(),
  99. },
  100. }
  101. }