diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index b2d9b0c0a..6f9277aa1 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -77,9 +77,12 @@ //! More info on how to improve this diffing algorithm: //! - -use crate::innerlude::{ - AnyProps, ElementId, Renderer, ScopeArena, ScopeId, TemplateNode, VComponent, VElement, - VFragment, VNode, VTemplate, VText, +use crate::{ + innerlude::{ + AnyProps, ElementId, Renderer, ScopeArena, ScopeId, TemplateNode, VComponent, VElement, + VFragment, VNode, VTemplate, VText, + }, + AttributeValue, }; use fxhash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; @@ -119,7 +122,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { } pub fn diff_node(&mut self, old_node: &'b VNode<'b>, new_node: &'b VNode<'b>) { - use VNode::{Component, Element, Fragment, Template, Text}; + use VNode::{Component, Element, Fragment, Placeholder, Template, Text}; match (old_node, new_node) { (Text(old), Text(new)) => { self.diff_text_nodes(old, new, old_node, new_node); @@ -141,9 +144,13 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { self.diff_templates(old, new, old_node, new_node); } + (Placeholder(_), Placeholder(_)) => { + self.diff_placeholder_nodes(old_node, new_node); + } + ( - Component(_) | Text(_) | Element(_) | Template(_) | Fragment(_), - Component(_) | Text(_) | Element(_) | Template(_) | Fragment(_), + Component(_) | Text(_) | Element(_) | Template(_) | Fragment(_) | Placeholder(_), + Component(_) | Text(_) | Element(_) | Template(_) | Fragment(_) | Placeholder(_), ) => self.replace_node(old_node, new_node), } } @@ -155,6 +162,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { VNode::Fragment(frag) => self.create_fragment_node(*frag), VNode::Component(component) => self.create_component_node(*component), VNode::Template(template) => self.create_template_node(template, node), + VNode::Placeholder(placeholder) => todo!(), } } @@ -195,7 +203,8 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { } for attr in attributes.iter() { - self.mutations.set_attribute(attr, real_id); + self.mutations + .set_attribute(attr.name, attr.value, attr.namespace, real_id); } if !children.is_empty() { @@ -303,23 +312,90 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { for (left, right) in old.dynamic_nodes.iter().zip(new.dynamic_nodes.iter()) { self.diff_node(left, right); } + + // todo: need a way to load up the element bound to these attributes + for (left, right) in old.dynamic_attrs.iter().zip(new.dynamic_attrs.iter()) { + // + } + + // hmm, what we do here? + for (left, right) in old.listeners.iter().zip(new.listeners.iter()) { + // + } } else { // else, diff them manually, taking the slow path self.replace_node(old_node, new_node); } } + fn create_static_template_nodes(&mut self, node: &'b TemplateNode) { + let id = ElementId(999999); + match node { + TemplateNode::Element { + tag, + attrs, + children, + } => { + self.mutations.create_element(tag, None, id); + + for attr in *attrs { + match attr { + crate::TemplateAttribute::Dynamic(_) => todo!(), + crate::TemplateAttribute::Static { name, value } => { + self.mutations.set_attribute( + name, + AttributeValue::Text(value), + None, + id, + ); + } + } + } + + for child in children.iter() { + self.create_static_template_nodes(child); + } + self.mutations.append_children(children.len() as u32); + } + TemplateNode::Text(ref text) => self.mutations.create_text_node(text, id), + TemplateNode::Dynamic(_) => self.mutations.create_placeholder(id), + } + } + /// Create the template from scratch using instructions, cache it, and then use the instructions to build it - fn create_template_node( - &mut self, - template: &'b VTemplate<'b>, - temp_node: &'b VNode<'b>, - ) -> usize { - /* - - Use a document fragment for holding nodes - - Assign IDs to any root nodes so we can find them later for shuffling around - - Build dynamic nodes in reverse order so indexing is preserved - */ + fn create_template_node(&mut self, template: &'b VTemplate<'b>, node: &'b VNode<'b>) -> usize { + let template_id = template.template.id; + let templates = self.scopes.template_cache.borrow_mut(); + + // create and insert the template if it doesn't exist within the VirtualDom (it won't exist on the renderer either) + if !templates.contains(&template.template) { + template + .template + .roots + .into_iter() + .for_each(|node| self.create_static_template_nodes(node)); + + self.mutations + .save(template_id, template.template.roots.len() as u32); + } + + self.mutations.load(template_id); + + let mut created = 0; + + // create the dynamic nodes + for node in template.dynamic_nodes.iter() { + created += self.create_node(node); + } + + // set any dynamic attributes + for attr in template.dynamic_attrs.iter() { + // assign an ID to the element + let id = self.scopes.reserve_node(node); + + self.mutations + .set_attribute(attr.name, attr.value, attr.namespace, id); + } todo!() @@ -357,7 +433,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { // nodes_created } - fn create_template_static_node(&mut self, nodes: &'static [TemplateNode]) -> usize { + fn create_template_static_node(&mut self, nodes: &'static [VNode<'static>]) -> usize { todo!() // let mut created = 0; // for node in nodes { @@ -442,7 +518,12 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { if old.attributes.len() == new.attributes.len() { for (old_attr, new_attr) in old.attributes.iter().zip(new.attributes.iter()) { if old_attr.value != new_attr.value || new_attr.volatile { - self.mutations.set_attribute(new_attr, root); + self.mutations.set_attribute( + new_attr.name, + new_attr.value, + new_attr.namespace, + root, + ); } } } else { @@ -450,7 +531,12 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { self.mutations.remove_attribute(attribute, root); } for attribute in new.attributes { - self.mutations.set_attribute(attribute, root); + self.mutations.set_attribute( + attribute.name, + attribute.value, + attribute.namespace, + root, + ); } } @@ -1000,7 +1086,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { self.scopes.collect_garbage(id); } - VNode::Text(_) => { + VNode::Text(_) | VNode::Placeholder(_) => { let id = old .try_mounted_id() .unwrap_or_else(|| panic!("broke on {:?}", old)); @@ -1059,15 +1145,15 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { } } } - // VNode::Placeholder(a) => { - // let id = a.id.get().unwrap(); - // self.scopes.collect_garbage(id); - // a.id.set(None); + VNode::Placeholder(a) => { + let id = a.id.get().unwrap(); + self.scopes.collect_garbage(id); + a.id.set(None); - // if gen_muts { - // self.mutations.remove(id); - // } - // } + if gen_muts { + self.mutations.remove(id); + } + } VNode::Element(e) => { let id = e.id.get().unwrap(); @@ -1157,6 +1243,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { VNode::Template(c) => { todo!() } + VNode::Placeholder(_) => todo!(), } } } @@ -1175,6 +1262,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { VNode::Template(t) => { todo!() } + VNode::Placeholder(_) => todo!(), } } } @@ -1182,7 +1270,7 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { // recursively push all the nodes of a tree onto the stack and return how many are there fn push_all_real_nodes(&mut self, node: &'b VNode<'b>) -> usize { match node { - VNode::Text(_) | VNode::Element(_) => { + VNode::Text(_) | VNode::Element(_) | VNode::Placeholder(_) => { self.mutations.push_root(node.mounted_id()); 1 } @@ -1205,4 +1293,8 @@ impl<'a, 'b, R: Renderer<'b>> DiffState<'a, 'b, R> { } } } + + pub(crate) fn diff_placeholder_nodes(&self, old_node: &VNode, new_node: &VNode) { + todo!() + } } diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 3213c05b8..c909e11f7 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -59,7 +59,7 @@ pub(crate) mod innerlude { } pub use crate::innerlude::{ - AnyEvent, ArbitraryAttributeValue, Attribute, AttributeValue, Component, Element, ElementId, + AnyAttributeValue, AnyEvent, Attribute, AttributeValue, Component, Element, ElementId, EventHandler, EventPriority, IntoVNode, LazyNodes, Listener, NodeFactory, Properties, Renderer, SchedulerMsg, Scope, ScopeId, ScopeState, TaskId, Template, TemplateAttribute, TemplateNode, UiEvent, UserEvent, VComponent, VElement, VNode, VTemplate, VText, VirtualDom, diff --git a/packages/core/src/mutations.rs b/packages/core/src/mutations.rs index 1bb768d72..2c347f24d 100644 --- a/packages/core/src/mutations.rs +++ b/packages/core/src/mutations.rs @@ -50,7 +50,13 @@ pub trait Renderer<'a> { /// Set the text content of a node fn set_text(&mut self, text: &'a str, root: ElementId); /// Set an attribute on an element - fn set_attribute(&mut self, attribute: &'a Attribute<'a>, root: ElementId); + fn set_attribute( + &mut self, + name: &'static str, + value: AttributeValue<'a>, + namespace: Option<&'a str>, + root: ElementId, + ); /// Save the current n nodes to the ID to be loaded later fn save(&mut self, id: &str, num: u32); diff --git a/packages/core/src/nodes/arbitrary_value.rs b/packages/core/src/nodes/arbitrary_value.rs index 4b3e44c53..f9590f208 100644 --- a/packages/core/src/nodes/arbitrary_value.rs +++ b/packages/core/src/nodes/arbitrary_value.rs @@ -4,19 +4,28 @@ use std::{ }; use bumpalo::Bump; -use serde::{Deserialize, Serialize}; /// Possible values for an attribute -// trying to keep values at 3 bytes -#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serialize", serde(untagged))] -#[derive(Clone, PartialEq)] -#[allow(missing_docs)] +#[derive(Clone, Copy)] pub enum AttributeValue<'a> { Text(&'a str), Float32(f32), Bool(bool), - Any(ArbitraryAttributeValue<'a>), + Any(&'a dyn AnyAttributeValue), +} + +// #[cfg(feature = "serialize")] + +impl<'a> PartialEq for AttributeValue<'a> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Text(l0), Self::Text(r0)) => l0 == r0, + (Self::Float32(l0), Self::Float32(r0)) => l0 == r0, + (Self::Bool(l0), Self::Bool(r0)) => l0 == r0, + // (Self::Any(l0), Self::Any(r0)) => l0.cmp(r0), + _ => false, + } + } } impl<'a> Display for AttributeValue<'a> { @@ -112,61 +121,25 @@ impl<'a> AttributeValue<'a> { } } -#[derive(Clone, Copy)] -#[allow(missing_docs)] -pub struct ArbitraryAttributeValue<'a> { - pub value: &'a dyn Any, - // pub value: &'a dyn AnyClone, - // pub cmp: fn(&dyn AnyClone, &dyn AnyClone) -> bool, -} - -#[cfg(feature = "serialize")] -impl<'a> Serialize for ArbitraryAttributeValue<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - todo!() - } -} -#[cfg(feature = "serialize")] -impl<'a, 'de> Deserialize<'de> for ArbitraryAttributeValue<'a> { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - todo!() +/// A trait that allows for comparing two values of the same type through the Any trait +/// +/// Defaults to false if the types are not the same +/// +/// This is an implicit trait, so any value that is 'static and PartialEq can be used directly +/// +/// If you want to override the default behavior, you should implement PartialEq through a wrapper type +pub trait AnyAttributeValue: Any { + /// Perform a comparison between two values + fn cmp_any(&self, _other: &dyn Any) -> bool { + false } } -impl PartialEq for ArbitraryAttributeValue<'_> { - fn eq(&self, other: &Self) -> bool { - todo!() - // (self.cmp)(self.value, other.value) - } -} - -// todo -#[allow(missing_docs)] -impl<'a> AttributeValue<'a> { - pub fn as_text(&self) -> Option<&'a str> { - match self { - AttributeValue::Text(s) => Some(s), - _ => None, - } - } - - pub fn as_float32(&self) -> Option { - match self { - AttributeValue::Float32(f) => Some(*f), - _ => None, - } - } - - pub fn as_any(&self) -> Option<&'a ArbitraryAttributeValue> { - match self { - AttributeValue::Any(a) => Some(a), - _ => None, +impl AnyAttributeValue for T { + fn cmp_any(&self, other: &dyn Any) -> bool { + match other.downcast_ref::() { + Some(t) => self == t, + None => false, } } } diff --git a/packages/core/src/nodes/element.rs b/packages/core/src/nodes/element.rs index 88e537ae4..11aeb7327 100644 --- a/packages/core/src/nodes/element.rs +++ b/packages/core/src/nodes/element.rs @@ -70,6 +70,10 @@ pub struct Attribute<'a> { /// Used in controlled components to ensure changes are propagated. pub volatile: bool, + /// A reverse lookup for tracking down attributes for templates + /// Not used for anything else + pub mounted_node: Cell>, + /// The value of the attribute. pub value: AttributeValue<'a>, } diff --git a/packages/core/src/nodes/factory.rs b/packages/core/src/nodes/factory.rs index 4a8bbf8e3..06694a706 100644 --- a/packages/core/src/nodes/factory.rs +++ b/packages/core/src/nodes/factory.rs @@ -35,7 +35,6 @@ impl<'a> NodeFactory<'a> { VNode::Text(self.bump.alloc(VText { id: Default::default(), text, - is_static: true, })) } @@ -57,11 +56,10 @@ impl<'a> NodeFactory<'a> { /// Create some text that's allocated along with the other vnodes /// pub fn text(&self, args: Arguments) -> VNode<'a> { - let (text, is_static) = self.raw_text(args); + let (text, _is_static) = self.raw_text(args); VNode::Text(self.bump.alloc(VText { text, - is_static, id: Default::default(), })) } @@ -110,6 +108,7 @@ impl<'a> NodeFactory<'a> { name, namespace, volatile: is_volatile, + mounted_node: Default::default(), value: val.into_value(self.bump), } } @@ -126,6 +125,7 @@ impl<'a> NodeFactory<'a> { name, namespace, volatile: is_volatile, + mounted_node: Default::default(), value, } } @@ -234,7 +234,7 @@ impl<'a> NodeFactory<'a> { /// Create a refrence to a template pub fn template_ref( &self, - template: Template, + template: fn() -> Template<'static>, nodes: &'a [VNode<'a>], attributes: &'a [Attribute<'a>], listeners: &'a [Listener<'a>], diff --git a/packages/core/src/nodes/mod.rs b/packages/core/src/nodes/mod.rs index cf5554f5b..f049ca142 100644 --- a/packages/core/src/nodes/mod.rs +++ b/packages/core/src/nodes/mod.rs @@ -5,11 +5,13 @@ use std::fmt::{Debug, Formatter}; +mod Placeholder; mod arbitrary_value; mod component; mod element; mod factory; mod fragment; +mod placeholder; mod suspense; mod template; mod text; @@ -23,6 +25,8 @@ pub use suspense::*; pub use template::*; pub use text::*; +use self::Placeholder::VPlaceholder; + /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM. /// /// VNodes are designed to be lightweight and used with with a bump allocator. To create a VNode, you can use either of: @@ -113,6 +117,9 @@ pub enum VNode<'src> { /// /// Template(&'src VTemplate<'src>), + + /// + Placeholder(&'src VPlaceholder), } /// An Element's unique identifier. @@ -131,8 +138,9 @@ impl<'src> VNode<'src> { VNode::Element(el) => el.key, VNode::Component(c) => c.key, VNode::Fragment(f) => f.key, - VNode::Text(_t) => None, VNode::Template(t) => t.key, + VNode::Text(_t) => None, + VNode::Placeholder(_p) => None, } } @@ -153,6 +161,7 @@ impl<'src> VNode<'src> { VNode::Fragment(_) => None, VNode::Component(_) => None, VNode::Template(_) => None, + VNode::Placeholder(el) => el.id.get(), } } @@ -164,6 +173,7 @@ impl<'src> VNode<'src> { VNode::Component(c) => VNode::Component(c), VNode::Fragment(f) => VNode::Fragment(f), VNode::Template(t) => VNode::Template(t), + VNode::Placeholder(p) => VNode::Placeholder(p), } } } @@ -199,6 +209,10 @@ impl Debug for VNode<'_> { .debug_struct("VNode::Templates") .field("template_id", &temp.template.id) .finish(), + VNode::Placeholder(place) => s + .debug_struct("VNode::Placeholder") + .field("id", &place.id) + .finish(), } } } diff --git a/packages/core/src/nodes/placeholder.rs b/packages/core/src/nodes/placeholder.rs new file mode 100644 index 000000000..d4967cf48 --- /dev/null +++ b/packages/core/src/nodes/placeholder.rs @@ -0,0 +1,8 @@ +use std::cell::Cell; + +use crate::ElementId; + +pub struct VPlaceholder { + pub id: Cell>, + pub dynamic_index: Option, +} diff --git a/packages/core/src/nodes/template.rs b/packages/core/src/nodes/template.rs index 3d68b42cf..d98102c39 100644 --- a/packages/core/src/nodes/template.rs +++ b/packages/core/src/nodes/template.rs @@ -1,6 +1,6 @@ use std::hash::Hash; -use crate::{Attribute, ElementId, Listener, VNode}; +use crate::{Attribute, Listener, VNode}; /// A reference to a template along with any context needed to hydrate it pub struct VTemplate<'a> { @@ -43,18 +43,15 @@ impl<'a> Hash for Template<'a> { pub enum TemplateNode<'a> { Element { tag: &'static str, - attrs: &'a [TemplateAttribute], + attrs: &'a [TemplateAttribute<'a>], children: &'a [TemplateNode<'a>], }, Text(&'static str), Dynamic(usize), } -pub enum TemplateAttribute { +pub enum TemplateAttribute<'a> { // todo: more values - Static { - name: &'static str, - value: &'static str, - }, + Static { name: &'static str, value: &'a str }, Dynamic(usize), } diff --git a/packages/core/src/nodes/text.rs b/packages/core/src/nodes/text.rs index ac5e02c89..e1302eded 100644 --- a/packages/core/src/nodes/text.rs +++ b/packages/core/src/nodes/text.rs @@ -18,8 +18,4 @@ pub struct VText<'src> { /// The text of the VText. pub text: &'src str, - - /// An indiciation if this VText can be ignored during diffing - /// Is usually only when there are no strings to be formatted (so the text is &'static str) - pub is_static: bool, } diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index 0d0682b8c..be14cc4b2 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -306,7 +306,6 @@ impl ScopeArena { let node = frame.bump.alloc(VNode::Text(frame.bump.alloc(VText { id: Cell::default(), text: "asd", - is_static: false, }))); frame.node.set(unsafe { extend_vnode(node) }); } @@ -943,7 +942,6 @@ impl BumpFrame { let node = bump.alloc(VText { text: "placeholdertext", id: Cell::default(), - is_static: false, }); let node = bump.alloc(VNode::Text(unsafe { &*(node as *mut VText as *const VText) @@ -957,7 +955,6 @@ impl BumpFrame { let node = self.bump.alloc(VText { text: "placeholdertext", id: Cell::default(), - is_static: false, }); let node = self.bump.alloc(VNode::Text(unsafe { &*(node as *mut VText as *const VText) diff --git a/packages/dioxus/tests/rsx_syntax.rs b/packages/dioxus/tests/rsx_syntax.rs index fcb38317b..88ce1ba65 100644 --- a/packages/dioxus/tests/rsx_syntax.rs +++ b/packages/dioxus/tests/rsx_syntax.rs @@ -1,17 +1,87 @@ use dioxus::prelude::*; +use dioxus_core::{Attribute, TemplateAttribute}; -#[test] -fn basic_syntax_is_a_template() { - // - let var = 123; +fn basic_syntax_is_a_template(cx: Scope) -> Element { let asd = 123; let g = rsx! { div { class: "asd", - class: "{asd}", - onclick: move |_| {}, - div { "{var}" } + // class: "{asd}", + // onclick: move |_| {}, + // div { "{var}" } } }; + + let __cx = NodeFactory::new(&cx); + + static attrs: &'static [TemplateAttribute<'static>] = + &[::dioxus::core::TemplateAttribute::Static( + ::dioxus::core::Attribute { + name: "class", + namespace: None, + volatile: false, + mounted_node: Default::default(), + value: ::dioxus::core::AttributeValue::Text("asd"), + }, + )]; + + __cx . template_ref ( + || :: dioxus :: core :: Template { + id : "packages/dioxus/tests/rsx_syntax.rs:7:13:/Users/jonkelley/Development/dioxus/packages/dioxus" , + roots : &[ + :: dioxus :: core :: TemplateNode :: Element { + tag : dioxus_elements :: div :: TAG_NAME , + attrs : attrs, + children : & [] , + }] , + } , + __cx . bump () . alloc ([]) , __cx . bump () . alloc ([]) , __cx . bump () . alloc ([]) , + None + ); + + // let static_attr = ::dioxus::core::TemplateAttribute::Static(::dioxus::core::Attribute { + // name: "class", + // namespace: None, + // volatile: false, + // mounted_node: Default::default(), + // value: ::dioxus::core::AttributeValue::Text("asd"), + // }); + + // __cx . template_ref (|| :: dioxus :: core :: Template { id : "packages/dioxus/tests/rsx_syntax.rs:7:13:/Users/jonkelley/Development/dioxus/packages/dioxus" , roots : & [:: dioxus :: core :: TemplateNode :: Element { tag : dioxus_elements :: div :: TAG_NAME , attrs : & [static_attr , :: dioxus :: core :: TemplateAttribute :: Dynamic (0usize)] , children : & [] , }] , } , __cx . bump () . alloc ([]) , __cx . bump () . alloc ([__cx . attr (dioxus_elements :: div :: class . 0 , :: core :: fmt :: Arguments :: new_v1 (& [""] , & [:: core :: fmt :: ArgumentV1 :: new_display (& asd)]) , None , false)]) , __cx . bump () . alloc ([]) , None); + + cx.render(g) + + // let __cx = NodeFactory::new(&cx); + + // let t = __cx.template_ref ( + // || :: dioxus :: core :: Template { + // id : "packages/dioxus/tests/rsx_syntax.rs:8:13:/Users/jonkelley/Development/dioxus/packages/dioxus" , + // roots : & [ + // :: dioxus :: core :: TemplateNode :: Element { + // tag : dioxus_elements :: div :: TAG_NAME , + // attrs : & [:: dioxus :: core :: TemplateAttribute :: Dynamic (0usize)] , + // children : & [] , + // } + // ], + // }, + // &[] , + // { + // let mut arr = dioxus_core::exports::bumpalo::vec![in __cx.bump()]; + // arr.push(Attribute { + // name: "asd", + // namespace: None, + // volatile: false, + // mounted_node: Default::default(), + // value: dioxus_core::AttributeValue::Text( + // __cx.raw_text(format_args!("{asd}")).0 + // ), + // }); + // arr.into_bump_slice() as &[::dioxus::core::Attribute] + // }, + // & [] , + // None + // ); + + // Some(t) } diff --git a/packages/rsx/src/element.rs b/packages/rsx/src/element.rs index 116f6790d..915fb26e5 100644 --- a/packages/rsx/src/element.rs +++ b/packages/rsx/src/element.rs @@ -244,22 +244,42 @@ impl ToTokens for ElementAttrNamed { tokens.append_all(match attr { ElementAttr::AttrText { name, value } => { quote! { - __cx.attr_disciption( dioxus_elements::#el_name::#name, #value) + __cx.attr( + dioxus_elements::#el_name::#name.0, + #value, + None, + false + ) } } ElementAttr::AttrExpression { name, value } => { quote! { - __cx.attr_disciption( dioxus_elements::#el_name::#name, #value) + __cx.attr( + dioxus_elements::#el_name::#name.0, + #value, + None, + false + ) } } ElementAttr::CustomAttrText { name, value } => { quote! { - __cx.attr( #name, #value, None, false ) + __cx.attr( + dioxus_elements::#el_name::#name.0, + #value, + None, + false + ) } } ElementAttr::CustomAttrExpression { name, value } => { quote! { - __cx.attr( #name, #value, None, false ) + __cx.attr( + dioxus_elements::#el_name::#name.0, + #value, + None, + false + ) } } ElementAttr::EventTokens { name, tokens } => { @@ -270,3 +290,11 @@ impl ToTokens for ElementAttrNamed { }); } } + +// ::dioxus::core::Attribute { +// name: stringify!(#name), +// namespace: None, +// volatile: false, +// mounted_node: Default::default(), +// value: ::dioxus::core::AttributeValue::Text(#value), +// } diff --git a/packages/rsx/src/elements.rs b/packages/rsx/src/elements.rs deleted file mode 100644 index f2d83d569..000000000 --- a/packages/rsx/src/elements.rs +++ /dev/null @@ -1,1387 +0,0 @@ -// map the rsx name of the element to the html name of the element and the namespace that contains it -pub fn element_to_static_str(element: &str) -> Option<(&'static str, Option<&'static str>)> { - ELEMENTS_WITH_MAPPED_ATTRIBUTES - .iter() - .find(|(el, _)| *el == element) - .map(|(el, _)| (*el, None)) - .or_else(|| { - ELEMENTS_WITH_NAMESPACE - .iter() - .find(|(el, _, _)| *el == element) - .map(|(el, ns, _)| (*el, Some(*ns))) - }) - .or_else(|| { - ELEMENTS_WITHOUT_NAMESPACE - .iter() - .find(|(el, _)| *el == element) - .map(|(el, _)| (*el, None)) - }) -} - -macro_rules! builder_constructors { - ( - $( - $(#[$attr:meta])* - $name:ident { - $( - $(#[$attr_method:meta])* - $fil:ident: $vil:ident, - )* - }; - )* - ) => { - pub const ELEMENTS_WITHOUT_NAMESPACE: &'static [(&'static str, &'static [&'static str])] = &[ - $( - ( - stringify!($name), - &[ - $( - stringify!($fil), - )* - ] - ), - )* - ]; - }; - - ( $( - $(#[$attr:meta])* - $name:ident <> $namespace:tt { - $($fil:ident: $vil:ident,)* - }; - )* ) => { - pub const ELEMENTS_WITH_NAMESPACE: &'static [(&'static str, &'static str, &'static [&'static str])] = &[ - $( - ( - stringify!($name), - $namespace, - &[ - $( - stringify!($fil), - )* - ] - ), - )* - ]; - }; -} - -type MappedAttributes = &'static [(&'static str, &'static [(&'static str, &'static str, bool)])]; - -/// All attributes that are tied to a specific element that either have a different name, or are volitile -pub const ELEMENTS_WITH_MAPPED_ATTRIBUTES: MappedAttributes = &[ - ( - "script", - &[("r#type", "type", false), ("r#script", "script", false)], - ), - ("button", &[("r#type", "type", false)]), - ("select", &[("value", "value", true)]), - ("option", &[("selected", "selected", true)]), - ("textarea", &[("value", "value", true)]), - ("label", &[("r#for", "for", false)]), - ( - "input", - &[("r#type", "type", false), ("value", "value", true)], - ), -]; - -// Organized in the same order as -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element -// -// Does not include obsolete elements. -// -// This namespace represents a collection of modern HTML-5 compatiable elements. -// -// This list does not include obsolete, deprecated, experimental, or poorly supported elements. -builder_constructors! { - // Document metadata - - /// Build a - /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) - /// element. - /// - base { - href: Uri, - target: Target, - }; - - /// Build a - /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head) - /// element. - head {}; - - /// Build a - /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link) - /// element. - link { - // as: Mime, - crossorigin: CrossOrigin, - href: Uri, - hreflang: LanguageTag, - media: String, // FIXME media query - rel: LinkType, - sizes: String, // FIXME - title: String, // FIXME - r#type: Mime, - integrity: String, - }; - - /// Build a - /// [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) - /// element. - meta { - charset: String, // FIXME IANA standard names - content: String, - http_equiv: HTTPEquiv, - name: Metadata, - }; - - /// Build a - /// [`