Переглянути джерело

wip: more modifications to templates

Jonathan Kelley 2 роки тому
батько
коміт
7cbb4d52dd

+ 123 - 31
packages/core/src/diff.rs

@@ -77,9 +77,12 @@
 //! More info on how to improve this diffing algorithm:
 //!  - <https://hacks.mozilla.org/2019/03/fast-bump-allocated-virtual-doms-with-rust-and-wasm/>
 
-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);
-
-                //     if gen_muts {
-                //         self.mutations.remove(id);
-                //     }
-                // }
+                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);
+                    }
+                }
                 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!()
+    }
 }

+ 1 - 1
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,

+ 7 - 1
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);

+ 32 - 59
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: serde::Serializer,
-    {
-        todo!()
-    }
-}
-#[cfg(feature = "serialize")]
-impl<'a, 'de> Deserialize<'de> for ArbitraryAttributeValue<'a> {
-    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-    where
-        D: serde::Deserializer<'de>,
-    {
-        todo!()
-    }
-}
-
-impl PartialEq for ArbitraryAttributeValue<'_> {
-    fn eq(&self, other: &Self) -> bool {
-        todo!()
-        // (self.cmp)(self.value, other.value)
+/// 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
     }
 }
 
-// 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<f32> {
-        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<T: Any + PartialEq> AnyAttributeValue for T {
+    fn cmp_any(&self, other: &dyn Any) -> bool {
+        match other.downcast_ref::<T>() {
+            Some(t) => self == t,
+            None => false,
         }
     }
 }

+ 4 - 0
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<Option<ElementId>>,
+
     /// The value of the attribute.
     pub value: AttributeValue<'a>,
 }

+ 4 - 4
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>],

+ 15 - 1
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(),
         }
     }
 }

+ 8 - 0
packages/core/src/nodes/placeholder.rs

@@ -0,0 +1,8 @@
+use std::cell::Cell;
+
+use crate::ElementId;
+
+pub struct VPlaceholder {
+    pub id: Cell<Option<ElementId>>,
+    pub dynamic_index: Option<usize>,
+}

+ 4 - 7
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),
 }

+ 0 - 4
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,
 }

+ 0 - 3
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)

+ 77 - 7
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)
 }

+ 32 - 4
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),
+// }

+ 0 - 1387
packages/rsx/src/elements.rs

@@ -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
-    /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
-    /// element.
-    ///
-    base {
-        href: Uri,
-        target: Target,
-    };
-
-    /// Build a
-    /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
-    /// element.
-    head {};
-
-    /// Build a
-    /// [`<link>`](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
-    /// [`<meta>`](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
-    /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
-    /// element.
-    style {
-        r#type: Mime,
-        media: String, // FIXME media query
-        nonce: Nonce,
-        title: String, // FIXME
-    };
-
-    /// Build a
-    /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
-    /// element.
-    title { };
-
-    // Sectioning root
-
-    /// Build a
-    /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
-    /// element.
-    body {};
-
-    // ------------------
-    // Content sectioning
-    // ------------------
-
-    /// Build a
-    /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
-    /// element.
-    address {};
-
-    /// Build a
-    /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
-    /// element.
-    article {};
-
-    /// Build a
-    /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
-    /// element.
-    aside {};
-
-    /// Build a
-    /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
-    /// element.
-    footer {};
-
-    /// Build a
-    /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
-    /// element.
-    header {};
-
-    /// Build a
-    /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
-    /// element.
-    ///
-    /// # About
-    /// - The HTML `<h1>` element is found within the `<body>` tag.
-    /// - Headings can range from `<h1>` to `<h6>`.
-    /// - The most important heading is `<h1>` and the least important heading is `<h6>`.
-    /// - The `<h1>` heading is the first heading in the document.
-    /// - The `<h1>` heading is usually a large bolded font.
-    ///
-    /// # Usage
-    ///
-    /// ```rust, ignore
-    /// html!(<h1> A header element </h1>)
-    /// rsx!(h1 { "A header element" })
-    /// LazyNodes::new(|f| f.el(h1).children([f.text("A header element")]).finish())
-    /// ```
-    h1 {};
-
-
-    /// Build a
-    /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
-    /// element.
-    ///
-    /// # About
-    /// - The HTML `<h2>` element is found within the `<body>` tag.
-    /// - Headings can range from `<h1>` to `<h6>`.
-    /// - The most important heading is `<h1>` and the least important heading is `<h6>`.
-    /// - The `<h2>` heading is the second heading in the document.
-    /// - The `<h2>` heading is usually a large bolded font.
-    ///
-    /// # Usage
-    /// ```rust, ignore
-    /// html!(<h2> A header element </h2>)
-    /// rsx!(h2 { "A header element" })
-    /// LazyNodes::new(|f| f.el(h2).children([f.text("A header element")]).finish())
-    /// ```
-    h2 {};
-
-
-    /// Build a
-    /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
-    /// element.
-    ///
-    /// # About
-    /// - The HTML <h1> element is found within the <body> tag.
-    /// - Headings can range from <h1> to <h6>.
-    /// - The most important heading is <h1> and the least important heading is <h6>.
-    /// - The <h1> heading is the first heading in the document.
-    /// - The <h1> heading is usually a large bolded font.
-    h3 {};
-    /// Build a
-    /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
-    /// element.
-    h4 {};
-    /// Build a
-    /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
-    /// element.
-    h5 {};
-    /// Build a
-    /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
-    /// element.
-    h6 {};
-
-    /// Build a
-    /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
-    /// element.
-    main {};
-    /// Build a
-    /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
-    /// element.
-    nav {};
-    /// Build a
-    /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
-    /// element.
-    section {};
-
-    // Text content
-
-    /// Build a
-    /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
-    /// element.
-    blockquote {
-        cite: Uri,
-    };
-    /// Build a
-    /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
-    /// element.
-    dd {};
-
-    /// Build a
-    /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
-    /// element.
-    ///
-    /// Part of the HTML namespace. Only works in HTML-compatible renderers
-    ///
-    /// ## Definition and Usage
-    /// - The <div> tag defines a division or a section in an HTML document.
-    /// - The <div> tag is used as a container for HTML elements - which is then styled with CSS or manipulated with  JavaScript.
-    /// - The <div> tag is easily styled by using the class or id attribute.
-    /// - Any sort of content can be put inside the <div> tag!
-    ///
-    /// Note: By default, browsers always place a line break before and after the <div> element.
-    ///
-    /// ## Usage
-    /// ```rust, ignore
-    /// html!(<div> A header element </div>)
-    /// rsx!(div { "A header element" })
-    /// LazyNodes::new(|f| f.element(div, &[], &[], &[], None))
-    /// ```
-    ///
-    /// ## References:
-    /// - <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div>
-    /// - <https://www.w3schools.com/tags/tag_div.asp>
-    div {};
-
-    /// Build a
-    /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
-    /// element.
-    dl {};
-
-    /// Build a
-    /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
-    /// element.
-    dt {};
-
-    /// Build a
-    /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
-    /// element.
-    figcaption {};
-
-    /// Build a
-    /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
-    /// element.
-    figure {};
-
-    /// Build a
-    /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
-    /// element.
-    hr {};
-
-    /// Build a
-    /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
-    /// element.
-    li {
-        value: isize,
-    };
-
-    /// Build a
-    /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
-    /// element.
-    ol {
-        reversed: Bool,
-        start: isize,
-        r#type: OrderedListType,
-    };
-
-    /// Build a
-    /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
-    /// element.
-    p {};
-
-    /// Build a
-    /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
-    /// element.
-    pre {};
-
-    /// Build a
-    /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
-    /// element.
-    ul {};
-
-
-    // Inline text semantics
-
-    /// Build a
-    /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
-    /// element.
-    a {
-        download: String,
-        href: Uri,
-        hreflang: LanguageTag,
-        target: Target,
-        r#type: Mime,
-        // ping: SpacedList<Uri>,
-        // rel: SpacedList<LinkType>,
-        ping: SpacedList,
-        rel: SpacedList,
-    };
-
-    /// Build a
-    /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
-    /// element.
-    abbr {};
-
-    /// Build a
-    /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
-    /// element.
-    b {};
-
-    /// Build a
-    /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
-    /// element.
-    bdi {};
-
-    /// Build a
-    /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
-    /// element.
-    bdo {};
-
-    /// Build a
-    /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
-    /// element.
-    br {};
-
-    /// Build a
-    /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
-    /// element.
-    cite {};
-
-    /// Build a
-    /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
-    /// element.
-    code {
-        language: String,
-    };
-
-    /// Build a
-    /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
-    /// element.
-    data {
-        value: String,
-    };
-
-    /// Build a
-    /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
-    /// element.
-    dfn {};
-
-    /// Build a
-    /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
-    /// element.
-    em {};
-
-    /// Build a
-    /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
-    /// element.
-    i {};
-
-    /// Build a
-    /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
-    /// element.
-    kbd {};
-
-    /// Build a
-    /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
-    /// element.
-    mark {};
-
-    /// Build a
-    /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
-    /// element.
-    menu {};
-
-    /// Build a
-    /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
-    /// element.
-    q {
-        cite: Uri,
-    };
-
-
-    /// Build a
-    /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
-    /// element.
-    rp {};
-
-
-    /// Build a
-    /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
-    /// element.
-    rt {};
-
-
-    /// Build a
-    /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
-    /// element.
-    ruby {};
-
-    /// Build a
-    /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
-    /// element.
-    s {};
-
-    /// Build a
-    /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
-    /// element.
-    samp {};
-
-    /// Build a
-    /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
-    /// element.
-    small {};
-
-    /// Build a
-    /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
-    /// element.
-    span {};
-
-    /// Build a
-    /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
-    /// element.
-    strong {};
-
-    /// Build a
-    /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
-    /// element.
-    sub {};
-
-    /// Build a
-    /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
-    /// element.
-    sup {};
-
-    /// Build a
-    /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
-    /// element.
-    time {};
-
-    /// Build a
-    /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
-    /// element.
-    u {};
-
-    /// Build a
-    /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
-    /// element.
-    var {};
-
-    /// Build a
-    /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
-    /// element.
-    wbr {};
-
-
-    // Image and multimedia
-
-    /// Build a
-    /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
-    /// element.
-    area {
-        alt: String,
-        coords: String, // TODO could perhaps be validated
-        download: Bool,
-        href: Uri,
-        hreflang: LanguageTag,
-        shape: AreaShape,
-        target: Target,
-        // ping: SpacedList<Uri>,
-        // rel: SpacedSet<LinkType>,
-    };
-
-    /// Build a
-    /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
-    /// element.
-    audio {
-        autoplay: Bool,
-        controls: Bool,
-        crossorigin: CrossOrigin,
-        muted: Bool,
-        preload: Preload,
-        src: Uri,
-        r#loop: Bool,
-    };
-
-    /// Build a
-    /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
-    /// element.
-    img {
-        alt: String,
-        crossorigin: CrossOrigin,
-        decoding: ImageDecoding,
-        height: usize,
-        ismap: Bool,
-        src: Uri,
-        srcset: String, // FIXME this is much more complicated
-        usemap: String, // FIXME should be a fragment starting with '#'
-        width: usize,
-        referrerpolicy: String,
-        // sizes: SpacedList<String>, // FIXME it's not really just a string
-    };
-
-    /// Build a
-    /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
-    /// element.
-    map {
-        name: Id,
-    };
-
-    /// Build a
-    /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
-    /// element.
-    track {
-        default: Bool,
-        kind: VideoKind,
-        label: String,
-        src: Uri,
-        srclang: LanguageTag,
-    };
-
-    /// Build a
-    /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
-    /// element.
-    video {
-        autoplay: Bool,
-        controls: Bool,
-        crossorigin: CrossOrigin,
-        height: usize,
-        r#loop: Bool,
-        muted: Bool,
-        preload: Preload,
-        playsinline: Bool,
-        poster: Uri,
-        src: Uri,
-        width: usize,
-    };
-
-
-    // Embedded content
-
-    /// Build a
-    /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
-    /// element.
-    embed {
-        height: usize,
-        src: Uri,
-        r#type: Mime,
-        width: usize,
-    };
-
-    /// Build a
-    /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
-    /// element.
-    iframe {
-        allow: FeaturePolicy,
-        allowfullscreen: Bool,
-        allowpaymentrequest: Bool,
-        height: usize,
-        name: Id,
-        referrerpolicy: ReferrerPolicy,
-        src: Uri,
-        srcdoc: Uri,
-        width: usize,
-
-        marginWidth: String,
-        align: String,
-        longdesc: String,
-
-        scrolling: String,
-        marginHeight: String,
-        frameBorder: String,
-        // sandbox: SpacedSet<Sandbox>,
-    };
-
-    /// Build a
-    /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
-    /// element.
-    object {
-        data: Uri,
-        form: Id,
-        height: usize,
-        name: Id,
-        r#type: Mime,
-        typemustmatch: Bool,
-        usemap: String, // TODO should be a fragment starting with '#'
-        width: usize,
-    };
-
-    /// Build a
-    /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
-    /// element.
-    param {
-        name: String,
-        value: String,
-    };
-
-    /// Build a
-    /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
-    /// element.
-    picture {};
-
-    /// Build a
-    /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
-    /// element.
-    source {
-        src: Uri,
-        r#type: Mime,
-    };
-
-
-    // Scripting
-
-    /// Build a
-    /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
-    /// element.
-    canvas {
-        height: usize,
-        width: usize,
-    };
-
-    /// Build a
-    /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
-    /// element.
-    noscript {};
-
-    /// Build a
-    /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
-    /// element.
-    ///
-    /// The [`script`] HTML element is used to embed executable code or data; this is typically used to embed or refer to
-    /// JavaScript code. The [`script`] element can also be used with other languages, such as WebGL's GLSL shader
-    /// programming language and JSON.
-    script {
-        /// Normal script elements pass minimal information to the window.onerror for scripts which do not pass the
-        /// standard CORS checks. To allow error logging for sites which use a separate domain for static media, use
-        /// this attribute. See CORS settings attributes for a more descriptive explanation of its valid arguments.
-        crossorigin: CrossOrigin,
-
-        /// This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the
-        /// document has been parsed, but before firing DOMContentLoaded.
-        ///
-        /// Scripts with the defer attribute will prevent the DOMContentLoaded event from firing until the script has
-        /// loaded and finished evaluating.
-        ///
-        /// ----
-        /// ### Warning:
-        ///
-        /// This attribute must not be used if the src attribute is absent (i.e. for inline scripts), in this
-        /// case it would have no effect.
-        ///
-        /// ----
-        ///
-        /// The defer attribute has no effect on module scripts — they defer by default.
-        /// Scripts with the defer attribute will execute in the order in which they appear in the document.
-        ///
-        /// This attribute allows the elimination of parser-blocking JavaScript where the browser would have to load and
-        /// evaluate scripts before continuing to parse. async has a similar effect in this case.
-        defer: Bool,
-        integrity: Integrity,
-        nomodule: Bool,
-        nonce: Nonce,
-        src: Uri,
-        text: String,
-
-    };
-
-
-    // Demarcating edits
-
-    /// Build a
-    /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
-    /// element.
-    del {
-        cite: Uri,
-        datetime: Datetime,
-    };
-
-    /// Build a
-    /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
-    /// element.
-    ins {
-        cite: Uri,
-        datetime: Datetime,
-    };
-
-
-    // Table content
-
-    /// Build a
-    /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
-    /// element.
-    caption {};
-
-    /// Build a
-    /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
-    /// element.
-    col {
-        span: usize,
-    };
-
-    /// Build a
-    /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
-    /// element.
-    colgroup {
-        span: usize,
-    };
-
-    /// Build a
-    /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
-    /// element.
-    table {};
-
-    /// Build a
-    /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
-    /// element.
-    tbody {};
-
-    /// Build a
-    /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
-    /// element.
-    td {
-        colspan: usize,
-        rowspan: usize,
-        // headers: SpacedSet<Id>,
-    };
-
-    /// Build a
-    /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
-    /// element.
-    tfoot {};
-
-    /// Build a
-    /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
-    /// element.
-    th {
-        abbr: String,
-        colspan: usize,
-        rowspan: usize,
-        scope: TableHeaderScope,
-        // headers: SpacedSet<Id>,
-    };
-
-    /// Build a
-    /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
-    /// element.
-    thead {};
-
-    /// Build a
-    /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
-    /// element.
-    tr {};
-
-
-    // Forms
-
-    /// Build a
-    /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
-    /// element.
-    button {
-        autofocus: Bool,
-        disabled: Bool,
-        form: Id,
-        formaction: Uri,
-        formenctype: FormEncodingType,
-        formmethod: FormMethod,
-        formnovalidate: Bool,
-        formtarget: Target,
-        name: Id,
-        value: String,
-    };
-
-    /// Build a
-    /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
-    /// element.
-    datalist {};
-
-    /// Build a
-    /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
-    /// element.
-    fieldset {};
-
-    /// Build a
-    /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
-    /// element.
-    form {
-        // accept-charset: SpacedList<CharacterEncoding>,
-        action: Uri,
-        autocomplete: OnOff,
-        enctype: FormEncodingType,
-        method: FormMethod,
-        name: Id,
-        novalidate: Bool,
-        target: Target,
-    };
-
-    /// Build a
-    /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
-    /// element.
-    input {
-        accept: String,
-        alt: String,
-        autocomplete: String,
-        autofocus: Bool,
-        capture: String,
-        checked: Bool,
-        disabled: Bool,
-        form: Id,
-        formaction: Uri,
-        formenctype: FormEncodingType,
-        formmethod: FormDialogMethod,
-        formnovalidate: Bool,
-        formtarget: Target,
-        height: isize,
-        list: Id,
-        max: String,
-        maxlength: usize,
-        min: String,
-        minlength: usize,
-        multiple: Bool,
-        name: Id,
-        pattern: String,
-        placeholder: String,
-        readonly: Bool,
-        required: Bool,
-        size: usize,
-        spellcheck: Bool,
-        src: Uri,
-        step: String,
-        tabindex: usize,
-        width: isize,
-
-        // Manual implementations below...
-        // r#type: InputType,
-        // value: String,
-    };
-
-    /// Build a
-    /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
-    /// element.
-    label {
-        form: Id,
-        // r#for: Id,
-    };
-
-    /// Build a
-    /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
-    /// element.
-    legend {};
-
-    /// Build a
-    /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
-    /// element.
-    meter {
-        value: isize,
-        min: isize,
-        max: isize,
-        low: isize,
-        high: isize,
-        optimum: isize,
-        form: Id,
-    };
-
-    /// Build a
-    /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
-    /// element.
-    optgroup {
-        disabled: Bool,
-        label: String,
-    };
-
-    /// Build a
-    /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
-    /// element.
-    option {
-        disabled: Bool,
-        label: String,
-
-
-        value: String,
-
-        // defined below
-        // selected: Bool,
-    };
-
-    /// Build a
-    /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
-    /// element.
-    output {
-        form: Id,
-        name: Id,
-        // r#for: SpacedSet<Id>,
-    };
-
-    /// Build a
-    /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
-    /// element.
-    progress {
-        max: f64,
-        value: f64,
-    };
-
-    /// Build a
-    /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
-    /// element.
-    select {
-        // defined below
-        // value: String,
-        autocomplete: String,
-        autofocus: Bool,
-        disabled: Bool,
-        form: Id,
-        multiple: Bool,
-        name: Id,
-        required: Bool,
-        size: usize,
-    };
-
-    /// Build a
-    /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
-    /// element.
-    textarea {
-        autocomplete: OnOff,
-        autofocus: Bool,
-        cols: usize,
-        disabled: Bool,
-        form: Id,
-        maxlength: usize,
-        minlength: usize,
-        name: Id,
-        placeholder: String,
-        readonly: Bool,
-        required: Bool,
-        rows: usize,
-        spellcheck: BoolOrDefault,
-        wrap: Wrap,
-    };
-
-
-    // Interactive elements
-
-    /// Build a
-    /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
-    /// element.
-    details {
-        open: Bool,
-    };
-
-
-
-    /// Build a
-    /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
-    /// element.
-    summary {};
-
-    // Web components
-
-    /// Build a
-    /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
-    /// element.
-    slot {};
-
-    /// Build a
-    /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
-    /// element.
-    template {};
-}
-
-builder_constructors! {
-    // SVG components
-    /// Build a
-    /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
-    /// element.
-    svg <> "http://www.w3.org/2000/svg" { };
-
-
-    // /// Build a
-    // /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/a)
-    // /// element.
-    // a <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<animate>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animate)
-    /// element.
-    animate <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<animateMotion>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateMotion)
-    /// element.
-    animateMotion <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<animateTransform>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateTransform)
-    /// element.
-    animateTransform <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
-    /// element.
-    circle <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<clipPath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath)
-    /// element.
-    clipPath <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<defs>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs)
-    /// element.
-    defs <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<desc>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc)
-    /// element.
-    desc <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<discard>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/discard)
-    /// element.
-    discard <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
-    /// element.
-    ellipse <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feBlend>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feBlend)
-    /// element.
-    feBlend <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feColorMatrix>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix)
-    /// element.
-    feColorMatrix <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feComponentTransfer>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComponentTransfer)
-    /// element.
-    feComponentTransfer <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feComposite>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite)
-    /// element.
-    feComposite <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feConvolveMatrix>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feConvolveMatrix)
-    /// element.
-    feConvolveMatrix <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feDiffuseLighting>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDiffuseLighting)
-    /// element.
-    feDiffuseLighting <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feDisplacementMap>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDisplacementMap)
-    /// element.
-    feDisplacementMap <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feDistantLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDistantLight)
-    /// element.
-    feDistantLight <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feDropShadow>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDropShadow)
-    /// element.
-    feDropShadow <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feFlood>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFlood)
-    /// element.
-    feFlood <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feFuncA>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncA)
-    /// element.
-    feFuncA <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feFuncB>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncB)
-    /// element.
-    feFuncB <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feFuncG>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncG)
-    /// element.
-    feFuncG <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feFuncR>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncR)
-    /// element.
-    feFuncR <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feGaussianBlur>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feGaussianBlur)
-    /// element.
-    feGaussianBlur <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feImage>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feImage)
-    /// element.
-    feImage <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feMerge>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMerge)
-    /// element.
-    feMerge <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feMergeNode>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMergeNode)
-    /// element.
-    feMergeNode <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feMorphology>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMorphology)
-    /// element.
-    feMorphology <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feOffset>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feOffset)
-    /// element.
-    feOffset <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<fePointLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/fePointLight)
-    /// element.
-    fePointLight <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feSpecularLighting>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpecularLighting)
-    /// element.
-    feSpecularLighting <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feSpotLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpotLight)
-    /// element.
-    feSpotLight <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feTile>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feTile)
-    /// element.
-    feTile <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<feTurbulence>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feTurbulence)
-    /// element.
-    feTurbulence <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<filter>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter)
-    /// element.
-    filter <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<foreignObject>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject)
-    /// element.
-    foreignObject <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<g>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g)
-    /// element.
-    g <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<hatch>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/hatch)
-    /// element.
-    hatch <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<hatchpath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/hatchpath)
-    /// element.
-    hatchpath <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
-    // /// element.
-    // image <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
-    /// element.
-    line <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<linearGradient>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient)
-    /// element.
-    linearGradient <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<marker>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/marker)
-    /// element.
-    marker <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<mask>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mask)
-    /// element.
-    mask <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<metadata>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/metadata)
-    /// element.
-    metadata <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<mpath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mpath)
-    /// element.
-    mpath <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
-    /// element.
-    path <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<pattern>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/pattern)
-    /// element.
-    pattern <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
-    /// element.
-    polygon <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
-    /// element.
-    polyline <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<radialGradient>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/radialGradient)
-    /// element.
-    radialGradient <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
-    /// element.
-    rect <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/script)
-    // /// element.
-    // script <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<set>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/set)
-    /// element.
-    set <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<stop>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/stop)
-    /// element.
-    stop <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/style)
-    // /// element.
-    // style <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
-    // /// element.
-    // svg <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<switch>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/switch)
-    /// element.
-    switch <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<symbol>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol)
-    /// element.
-    symbol <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<text>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text)
-    /// element.
-    text <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<textPath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/textPath)
-    /// element.
-    textPath <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title)
-    // /// element.
-    // title <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<tspan>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/tspan)
-    /// element.
-    tspan <> "http://www.w3.org/2000/svg" {};
-
-    /// Build a
-    /// [`<view>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/view)
-    /// element.
-    view <> "http://www.w3.org/2000/svg" {};
-
-    // /// Build a
-    // /// [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use)
-    // /// element.
-    // use <> "http://www.w3.org/2000/svg" {};
-
-
-}

+ 33 - 12
packages/rsx/src/lib.rs

@@ -67,7 +67,7 @@ impl Parse for CallBody {
 impl ToTokens for CallBody {
     fn to_tokens(&self, out_tokens: &mut TokenStream2) {
         // As we print out the dynamic nodes, we want to keep track of them in a linear fashion
-        // We'll use the size of the vecs to determine the index of the dynamic node in the final output
+        // We'll use the size of the vecs to determine the index of the dynamic node in the final
         struct DynamicContext<'a> {
             dynamic_nodes: Vec<&'a BodyNode>,
             dynamic_attributes: Vec<&'a ElementAttrNamed>,
@@ -95,11 +95,28 @@ impl ToTokens for CallBody {
                         match &attr.attr {
                             ElementAttr::AttrText { name, value } if value.is_static() => {
                                 let value = value.source.as_ref().unwrap();
-                                quote! { ::dioxus::core::TemplateAttribute::Static { name: stringify!(#name), value: #value } }
+                                quote! {
+                                    ::dioxus::core::TemplateAttribute::Static(::dioxus::core::Attribute {
+                                        name: stringify!(#name),
+                                        namespace: None,
+                                        volatile: false,
+                                        mounted_node: Default::default(),
+                                        value: ::dioxus::core::AttributeValue::Text(#value),
+                                    })
+                                }
                             }
 
                             ElementAttr::CustomAttrText { name, value } if value.is_static() => {
-                                quote! { ::dioxus::core::TemplateAttribute::Static { name: #name, value: #value } }
+                                let value = value.source.as_ref().unwrap();
+                                quote! {
+                                    ::dioxus::core::TemplateAttribute::Static(::dioxus::core::Attribute {
+                                        name: stringify!(#name),
+                                        namespace: None,
+                                        volatile: false,
+                                        mounted_node: Default::default(),
+                                        value: ::dioxus::core::AttributeValue::Text(#value),
+                                    })
+                                }
                             },
 
                             ElementAttr::AttrExpression { .. }
@@ -155,16 +172,20 @@ impl ToTokens for CallBody {
 
         out_tokens.append_all(quote! {
             LazyNodes::new(move | __cx: ::dioxus::core::NodeFactory| -> ::dioxus::core::VNode {
-                static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
-                    id: ::dioxus::core::get_line_num!(),
-                    roots: &[ #roots ]
-                };
-
                 __cx.template_ref(
-                    TEMPLATE,
-                    &[ #( #dyn_printer ),* ],
-                    &[ #( #attr_printer ),* ],
-                    &[ #( #listener_printer ),* ],
+                    || ::dioxus::core::Template {
+                        id: ::dioxus::core::get_line_num!(),
+                        roots: &[ #roots ]
+                    },
+                    __cx.bump().alloc([
+                       #( #dyn_printer ),*
+                    ]),
+                    __cx.bump().alloc([
+                       #( #attr_printer ),*
+                    ]),
+                    __cx.bump().alloc([
+                       #( #listener_printer ),*
+                    ]),
                     None
                 )
             })

+ 3 - 0
packages/ssr/src/lib.rs

@@ -237,6 +237,9 @@ impl<'a: 'c, 'c> TextRenderer<'a, '_, 'c> {
                     panic!("Cannot render template without vdom");
                 }
             }
+            VNode::Placeholder(_) => {
+                todo!()
+            }
         }
         Ok(())
     }