Răsfoiți Sursa

feat: buff up html allowed attributes

Jonathan Kelley 4 ani în urmă
părinte
comite
c79d9ae

+ 1 - 1
packages/core/Cargo.toml

@@ -41,5 +41,5 @@ smallvec = "1.6.1"
 
 
 [features]
-default = []
+default = ["serialize"]
 serialize = ["slotmap/serde", "serde"]

+ 16 - 16
packages/core/examples/alternative.rs

@@ -1,20 +1,20 @@
 fn main() {}
 
-use dioxus::*;
-use dioxus_core as dioxus;
-use dioxus_core::prelude::*;
+// use dioxus::*;
+// use dioxus_core as dioxus;
+// use dioxus_core::prelude::*;
 
-static Example: FC<()> = |cx| {
-    let list = (0..10).map(|f| LazyNodes::new(move |f| todo!()));
+// static Example: FC<()> = |cx| {
+//     let list = (0..10).map(|f| LazyNodes::new(move |f| todo!()));
 
-    cx.render(LazyNodes::new(move |cx| {
-        let bump = cx.bump();
-        cx.raw_element("div")
-            .children([
-                cx.text(format_args!("hello")),
-                cx.text(format_args!("hello")),
-                cx.fragment_from_iter(list),
-            ])
-            .finish()
-    }))
-};
+//     cx.render(LazyNodes::new(move |cx| {
+//         let bump = cx.bump();
+//         cx.raw_element("div")
+//             .children([
+//                 cx.text(format_args!("hello")),
+//                 cx.text(format_args!("hello")),
+//                 cx.fragment_from_iter(list),
+//             ])
+//             .finish()
+//     }))
+// };

+ 1 - 2
packages/core/src/component.rs

@@ -5,7 +5,7 @@
 //! if the type suppports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
 //! that ensures compile-time required and optional fields on cx.
 
-use crate::innerlude::FC;
+use crate::innerlude::{Context, LazyNodes, VNode, FC};
 
 pub trait Properties: Sized {
     type Builder;
@@ -50,7 +50,6 @@ pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
 ///
 /// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
 /// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
-use crate::prelude::*;
 #[allow(non_upper_case_globals, non_snake_case)]
 pub fn Fragment<'a>(cx: Context<'a, ()>) -> VNode<'a> {
     cx.render(LazyNodes::new(move |f| f.fragment_from_iter(cx.children())))

+ 1 - 12
packages/core/src/diff.rs

@@ -107,18 +107,6 @@ pub trait RealDom<'a> {
     fn raw_node_as_any_mut(&self) -> &mut dyn Any;
 }
 
-/// The DiffState is a cursor internal to the VirtualDOM's diffing algorithm that allows persistence of state while
-/// diffing trees of components. This means we can "re-enter" a subtree of a component by queuing a "NeedToDiff" event.
-///
-/// By re-entering via NodeDiff, we can connect disparate edits together into a single EditList. This batching of edits
-/// leads to very fast re-renders (all done in a single animation frame).
-///
-/// It also means diffing two trees is only ever complex as diffing a single smaller tree, and then re-entering at a
-/// different cursor position.
-///
-/// The order of these re-entrances is stored in the DiffState itself. The DiffState comes pre-loaded with a set of components
-/// that were modified by the eventtrigger. This prevents doubly evaluating components if they were both updated via
-/// subscriptions and props changes.
 pub struct DiffMachine<'real, 'bump, Dom: RealDom<'bump>> {
     pub dom: &'real mut Dom,
     pub components: &'bump SharedArena,
@@ -170,6 +158,7 @@ where
                     self.dom.set_text(new.text);
                     self.dom.pop();
                 }
+
                 new_node.dom_id.set(root);
             }
 

+ 31 - 34
packages/core/src/lib.rs

@@ -8,23 +8,20 @@
 //!
 //!
 
-#[cfg(feature = "serialize")]
-pub mod serialize;
+pub use crate::innerlude::{
+    format_args_f, html, rsx, DioxusElement, DomEdit, EventTrigger, LazyNodes, NodeFactory,
+    Properties, RealDom, RealDomNode, ScopeIdx, VNode, VNodeKind, VirtualDom, VirtualEvent, FC,
+};
 
-pub mod arena;
-pub mod bumpframe;
-pub mod component;
-pub mod context;
-pub mod diff;
-pub mod error;
-pub mod events;
-pub mod hooklist;
-pub mod nodes;
-pub mod scope;
-pub mod signals;
-pub mod tasks;
-pub mod util;
-pub mod virtual_dom;
+pub mod prelude {
+    pub use crate::component::{fc_to_builder, Fragment, Properties};
+    pub use crate::context::Context;
+    pub use crate::innerlude::DioxusElement;
+    pub use crate::innerlude::{LazyNodes, NodeFactory, FC};
+    pub use crate::nodes::VNode;
+    pub use crate::VirtualDom;
+    pub use dioxus_core_macro::{format_args_f, html, rsx, Props};
+}
 
 // types used internally that are important
 pub(crate) mod innerlude {
@@ -43,26 +40,26 @@ pub(crate) mod innerlude {
 
     pub type FC<P> = fn(Context<P>) -> VNode;
 
-    pub use dioxus_core_macro::{html, rsx};
-}
-
-pub use crate::{
-    innerlude::{
-        DioxusElement, DomEdit, LazyNodes, NodeFactory, RealDom, RealDomNode, ScopeIdx, FC,
-    },
-    virtual_dom::VirtualDom,
-};
-
-pub mod prelude {
-    pub use crate::component::{fc_to_builder, Fragment, Properties};
-    pub use crate::context::Context;
-    pub use crate::innerlude::DioxusElement;
-    pub use crate::innerlude::{LazyNodes, NodeFactory, FC};
-    pub use crate::nodes::VNode;
-    pub use crate::VirtualDom;
-    pub use dioxus_core_macro::{format_args_f, html, rsx, Props};
+    pub use dioxus_core_macro::{format_args_f, html, rsx};
 }
 
 pub mod exports {
     // export important things here
 }
+
+pub mod arena;
+pub mod bumpframe;
+pub mod component;
+pub mod context;
+pub mod diff;
+pub mod error;
+pub mod events;
+pub mod hooklist;
+pub mod nodes;
+pub mod scope;
+#[cfg(feature = "serialize")]
+pub mod serialize;
+pub mod signals;
+pub mod tasks;
+pub mod util;
+pub mod virtual_dom;

+ 0 - 1
packages/core/src/nodebuilder.rs

@@ -1 +0,0 @@
-

+ 31 - 13
packages/core/src/nodes.rs

@@ -40,6 +40,7 @@ pub struct VText<'src> {
 
 pub struct VFragment<'src> {
     pub children: &'src [VNode<'src>],
+    pub is_static: bool,
 }
 
 pub trait DioxusElement {
@@ -52,6 +53,7 @@ pub trait DioxusElement {
 pub struct VElement<'a> {
     // tag is always static
     pub tag_name: &'static str,
+    pub namespace: Option<&'static str>,
 
     pub static_listeners: bool,
     pub listeners: &'a [Listener<'a>],
@@ -61,9 +63,6 @@ pub struct VElement<'a> {
 
     pub static_children: bool,
     pub children: &'a [VNode<'a>],
-
-    // namespace is always static
-    pub namespace: Option<&'static str>,
 }
 
 /// An attribute on a DOM node, such as `id="my-thing"` or
@@ -92,14 +91,16 @@ pub struct Listener<'bump> {
 /// Only supports the functional syntax
 pub struct VComponent<'src> {
     pub ass_scope: Cell<Option<ScopeIdx>>,
-    pub caller: Rc<dyn Fn(&Scope) -> VNode>,
-    pub children: &'src [VNode<'src>],
-    pub comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
+    pub(crate) caller: Rc<dyn Fn(&Scope) -> VNode>,
+    pub(crate) children: &'src [VNode<'src>],
+    pub(crate) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
+    pub is_static: bool,
+
     // a pointer into the bump arena (given by the 'src lifetime)
-    raw_props: *const (),
+    pub(crate) raw_props: *const (),
+
     // a pointer to the raw fn typ
-    pub user_fc: *const (),
-    pub is_static: bool,
+    pub(crate) user_fc: *const (),
 }
 
 /// This struct provides an ergonomic API to quickly build VNodes.
@@ -118,6 +119,20 @@ impl<'a> NodeFactory<'a> {
         &self.scope_ref.cur_frame().bump
     }
 
+    pub const fn const_text(&self, text: &'static str) -> VNodeKind<'static> {
+        VNodeKind::Text(VText {
+            is_static: true,
+            text,
+        })
+    }
+
+    pub const fn const_fragment(&self, children: &'static [VNode<'static>]) -> VNodeKind<'static> {
+        VNodeKind::Fragment(VFragment {
+            children,
+            is_static: true,
+        })
+    }
+
     pub fn static_text(text: &'static str) -> VNode {
         VNode {
             dom_id: RealDomNode::empty_cell(),
@@ -151,8 +166,6 @@ impl<'a> NodeFactory<'a> {
         }
     }
 
-    pub const fn const_el(&self) {}
-
     pub fn raw_element(
         &self,
         tag: &'static str,
@@ -279,6 +292,7 @@ impl<'a> NodeFactory<'a> {
             key: None,
             kind: VNodeKind::Fragment(VFragment {
                 children: nodes.into_bump_slice(),
+                is_static: false,
             }),
         }
     }
@@ -385,12 +399,16 @@ impl<'a> Clone for VNode<'a> {
             }),
             VNodeKind::Fragment(fragment) => VNodeKind::Fragment(VFragment {
                 children: fragment.children,
+                is_static: fragment.is_static,
             }),
             VNodeKind::Component(component) => VNodeKind::Component(component),
             VNodeKind::Suspended => VNodeKind::Suspended,
         };
-
-        todo!()
+        VNode {
+            kind,
+            dom_id: self.dom_id.clone(),
+            key: self.key.clone(),
+        }
     }
 }
 

+ 709 - 113
packages/html/src/lib.rs

@@ -6,11 +6,73 @@
 //! An added benefit of this approach is the ability to lend comprehensive documentation on how to use these elements inside
 //! of the Rsx and Html macros. Each element comes with a substantial amount of documentation on how to best use it, hopefully
 //! making the development cycle quick.
+//!
+//! All elements are used as zero-sized unit structs with trait impls.
+//!
+//! Currently, we don't validate for structures, but do validate attributes.
+//!
+//!
+//!
+//!
 
-use dioxus_core::{DioxusElement, NodeFactory};
+use std::fmt::Arguments;
+
+use dioxus_core::{nodes::Attribute, DioxusElement, NodeFactory};
+
+trait GlobalAttributes {
+    fn accesskey<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
+        cx.attr("accesskey", val, None, false)
+    }
+    fn class<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("class", val, None, false)
+    }
+    fn contenteditable<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("contenteditable", val, None, false)
+    }
+    fn data<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("data", val, None, false)
+    }
+    fn dir<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("dir", val, None, false)
+    }
+    fn draggable<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("draggable", val, None, false)
+    }
+    fn hidden<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("hidden", val, None, false)
+    }
+    fn id<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("id", val, None, false)
+    }
+    fn lang<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("lang", val, None, false)
+    }
+    fn spellcheck<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("spellcheck", val, None, false)
+    }
+    fn style<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("style", val, Some("style"), false)
+    }
+    fn tabindex<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("tabindex", val, None, false)
+    }
+    fn title<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("title", val, None, false)
+    }
+    fn translate<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+        cx.attr("translate", val, None, false)
+    }
+}
 
 macro_rules! builder_constructors {
-    ( $( $(#[$attr:meta])* $name:ident; )* ) => {
+    (
+        $(
+            $(#[$attr:meta])*
+            $name:ident {
+                $($fil:ident: $vil:ident,)*
+            };
+         )*
+    ) => {
         $(
             #[allow(non_camel_case_types)]
             $(#[$attr])*
@@ -20,6 +82,16 @@ macro_rules! builder_constructors {
                 const TAG_NAME: &'static str = stringify!($name);
                 const NAME_SPACE: Option<&'static str> = None;
             }
+
+            impl GlobalAttributes for $name {}
+
+            impl $name {
+                $(
+                    pub fn $fil<'a>(&self, cx: NodeFactory<'a>, val: Arguments<'a>) -> Attribute<'a> {
+                        cx.attr(stringify!($fil), val, None, false)
+                    }
+                )*
+            }
         )*
     };
 
@@ -44,7 +116,7 @@ macro_rules! builder_constructors {
 // 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.
@@ -55,63 +127,91 @@ builder_constructors! {
     /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
     /// element.
     ///
-    /// A base element is your mom!
-    base;
+    base {
+        href: Uri,
+        target: Target,
+    };
 
     /// Build a
     /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
     /// element.
-    head;
+    head {};
 
     /// Build a
     /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
     /// element.
-    link;
+    link {
+        // as: Mime,
+        crossorigin: CrossOrigin,
+        href: Uri,
+        hreflang: LanguageTag,
+        media: String, // FIXME media query
+        rel: LinkType,
+        sizes: String, // FIXME
+        title: String, // FIXME
+        // type: Mime,
+    };
 
     /// Build a
     /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
     /// element.
-    meta;
+    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;
+    style {
+        // 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;
+    title { };
 
     // Sectioning root
 
     /// Build a
     /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
     /// element.
-    body;
+    body {};
 
+    // ------------------
     // Content sectioning
+    // ------------------
 
     /// Build a
     /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
     /// element.
-    address;
+    address {};
+
     /// Build a
     /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
     /// element.
-    article;
+    article {};
+
     /// Build a
     /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
     /// element.
-    aside;
+    aside {};
+
     /// Build a
     /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
     /// element.
-    footer;
+    footer {};
+
     /// Build a
     /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
     /// element.
-    header;
+    header {};
 
     /// Build a
     /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
@@ -131,8 +231,7 @@ builder_constructors! {
     /// rsx!(h1 { "A header element" })
     /// LazyNodes::new(|f| f.el(h1).children([f.text("A header element")]).finish())
     /// ```
-    ///
-    h1;
+    h1 {};
 
 
     /// Build a
@@ -152,7 +251,7 @@ builder_constructors! {
     /// rsx!(h2 { "A header element" })
     /// LazyNodes::new(|f| f.el(h2).children([f.text("A header element")]).finish())
     /// ```
-    h2;
+    h2 {};
 
 
     /// Build a
@@ -165,416 +264,739 @@ builder_constructors! {
     /// - 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;
+    h3 {};
     /// Build a
     /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
     /// element.
-    h4;
+    h4 {};
     /// Build a
     /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
     /// element.
-    h5;
+    h5 {};
     /// Build a
     /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
     /// element.
-    h6;
+    h6 {};
 
     /// Build a
     /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
     /// element.
-    main;
+    main {};
     /// Build a
     /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
     /// element.
-    nav;
+    nav {};
     /// Build a
     /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
     /// element.
-    section;
+    section {};
 
     // Text content
 
     /// Build a
     /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
     /// element.
-    blockquote;
+    blockquote {
+        cite: Uri,
+    };
     /// Build a
     /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
     /// element.
-    dd;
+    dd {};
+
     /// Build a
     /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
     /// element.
-    div;
+    div {};
+
     /// Build a
     /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
     /// element.
-    dl;
+    dl {};
+
     /// Build a
     /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
     /// element.
-    dt;
+    dt {};
+
     /// Build a
     /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
     /// element.
-    figcaption;
+    figcaption {};
+
     /// Build a
     /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
     /// element.
-    figure;
+    figure {};
+
     /// Build a
     /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
     /// element.
-    hr;
+    hr {};
+
     /// Build a
     /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
     /// element.
-    li;
+    li {
+        value: isize,
+    };
+
     /// Build a
     /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
     /// element.
-    ol;
+    ol {
+        reversed: Bool,
+        start: isize,
+        // type: OrderedListType,
+    };
+
     /// Build a
     /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
     /// element.
-    p;
+    p {};
+
     /// Build a
     /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
     /// element.
-    pre;
+    pre {};
+
     /// Build a
     /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
     /// element.
-    ul;
+    ul {};
+
 
     // Inline text semantics
 
     /// Build a
     /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
     /// element.
-    a;
+    a {
+        download: String,
+        href: Uri,
+        hreflang: LanguageTag,
+        target: Target,
+        // type: Mime,
+        // ping: SpacedList<Uri>,
+        // rel: SpacedList<LinkType>,
+    };
+
     /// Build a
     /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
     /// element.
-    abbr;
+    abbr {};
+
     /// Build a
     /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
     /// element.
-    b;
+    b {};
+
     /// Build a
     /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
     /// element.
-    bdi;
+    bdi {};
+
     /// Build a
     /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
     /// element.
-    bdo;
+    bdo {};
+
     /// Build a
     /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
     /// element.
-    br;
+    br {};
+
     /// Build a
     /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
     /// element.
-    cite;
+    cite {};
+
     /// Build a
     /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
     /// element.
-    code;
+    code {};
+
     /// Build a
     /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
     /// element.
-    data;
+    data {
+        value: String,
+    };
+
     /// Build a
     /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
     /// element.
-    dfn;
+    dfn {};
+
     /// Build a
     /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
     /// element.
-    em;
+    em {};
+
     /// Build a
     /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
     /// element.
-    i;
+    i {};
+
     /// Build a
     /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
     /// element.
-    kbd;
+    kbd {};
+
     /// Build a
     /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
     /// element.
-    mark;
+    mark {};
+
     /// Build a
     /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
     /// element.
-    q;
+    q {
+        cite: Uri,
+    };
+
 
     /// Build a
     /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
     /// element.
-    rp;
+    rp {};
+
 
     /// Build a
     /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
     /// element.
-    rt;
+    rt {};
+
 
     /// Build a
     /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
     /// element.
-    ruby;
+    ruby {};
+
     /// Build a
     /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
     /// element.
-    s;
+    s {};
+
     /// Build a
     /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
     /// element.
-    samp;
+    samp {};
+
     /// Build a
     /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
     /// element.
-    small;
+    small {};
+
     /// Build a
     /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
     /// element.
-    span;
+    span {};
+
     /// Build a
     /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
     /// element.
-    strong;
+    strong {};
+
     /// Build a
     /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
     /// element.
-    sub;
+    sub {};
+
     /// Build a
     /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
     /// element.
-    sup;
+    sup {};
+
     /// Build a
     /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
     /// element.
-    time;
+    time {};
+
     /// Build a
     /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
     /// element.
-    u;
+    u {};
+
     /// Build a
     /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
     /// element.
-    var;
+    var {};
+
     /// Build a
     /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
     /// element.
-    wbr;
+    wbr {};
+
 
     // Image and multimedia
 
     /// Build a
     /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
     /// element.
-    area;
+    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;
+    audio {
+        autoplay: Bool,
+        controls: Bool,
+        crossorigin: CrossOrigin,
+        // loop: Bool,
+        muted: Bool,
+        preload: Preload,
+        src: Uri,
+    };
+
     /// Build a
     /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
     /// element.
-    img;
+    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,
+        // 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;
+    map {
+        name: Id,
+    };
+
     /// Build a
     /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
     /// element.
-    track;
+    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;
+    video {
+        autoplay: Bool,
+        controls: Bool,
+        crossorigin: CrossOrigin,
+        height: usize,
+        // 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;
+    embed {
+        height: usize,
+        src: Uri,
+        // type: Mime,
+        width: usize,
+    };
+
     /// Build a
     /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
     /// element.
-    iframe;
+    iframe {
+        allow: FeaturePolicy,
+        allowfullscreen: Bool,
+        allowpaymentrequest: Bool,
+        height: usize,
+        name: Id,
+        referrerpolicy: ReferrerPolicy,
+        src: Uri,
+        srcdoc: Uri,
+        width: usize,
+        // sandbox: SpacedSet<Sandbox>,
+    };
+
     /// Build a
     /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
     /// element.
-    object;
+    object {
+        data: Uri,
+        form: Id,
+        height: usize,
+        name: Id,
+        // 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;
+    param {
+        name: String,
+        value: String,
+    };
+
     /// Build a
     /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
     /// element.
-    picture;
+    picture {};
+
     /// Build a
     /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
     /// element.
-    source;
+    source {
+        src: Uri,
+        // type: Mime,
+    };
+
 
     // Scripting
 
     /// Build a
     /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
     /// element.
-    canvas;
+    canvas {
+        height: usize,
+        width: usize,
+    };
+
     /// Build a
     /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
     /// element.
-    noscript;
+    noscript {};
+
     /// Build a
     /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
     /// element.
-    script;
+    script {
+        crossorigin: CrossOrigin,
+        defer: Bool,
+        integrity: Integrity,
+        nomodule: Bool,
+        nonce: Nonce,
+        src: Uri,
+        text: String,
+        // async: Bool,
+        // type: String, // TODO could be an enum
+    };
+
 
     // Demarcating edits
 
     /// Build a
     /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
     /// element.
-    del;
+    del {
+        cite: Uri,
+        datetime: Datetime,
+    };
+
     /// Build a
     /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
     /// element.
-    ins;
+    ins {
+        cite: Uri,
+        datetime: Datetime,
+    };
+
 
     // Table content
 
     /// Build a
     /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
     /// element.
-    caption;
+    caption {};
+
     /// Build a
     /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
     /// element.
-    col;
+    col {
+        span: usize,
+    };
+
     /// Build a
     /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
     /// element.
-    colgroup;
+    colgroup {
+        span: usize,
+    };
+
     /// Build a
     /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
     /// element.
-    table;
+    table {};
+
     /// Build a
     /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
     /// element.
-    tbody;
+    tbody {};
+
     /// Build a
     /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
     /// element.
-    td;
+    td {
+        colspan: usize,
+        rowspan: usize,
+        // headers: SpacedSet<Id>,
+    };
+
     /// Build a
     /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
     /// element.
-    tfoot;
+    tfoot {};
+
     /// Build a
     /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
     /// element.
-    th;
+    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;
+    thead {};
+
     /// Build a
     /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
     /// element.
-    tr;
+    tr {};
+
 
     // Forms
 
     /// Build a
     /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
     /// element.
-    button;
+    button {
+        autofocus: Bool,
+        disabled: Bool,
+        form: Id,
+        formaction: Uri,
+        formenctype: FormEncodingType,
+        formmethod: FormMethod,
+        formnovalidate: Bool,
+        formtarget: Target,
+        name: Id,
+        // type: ButtonType,
+        value: String,
+    };
+
     /// Build a
     /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
     /// element.
-    datalist;
+    datalist {};
+
     /// Build a
     /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
     /// element.
-    fieldset;
+    fieldset {};
+
     /// Build a
     /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
     /// element.
-    form;
+    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;
+    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,
+        // type: InputType,
+        value: String,
+        width: isize,
+    };
+
     /// Build a
     /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
     /// element.
-    label;
+    label {
+        // for: Id,
+        form: Id,
+    };
+
     /// Build a
     /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
     /// element.
-    legend;
+    legend {};
+
     /// Build a
     /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
     /// element.
-    meter;
+    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;
+    optgroup {
+        disabled: Bool,
+        label: String,
+    };
+
     /// Build a
     /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
     /// element.
-    option;
+    option {
+        disabled: Bool,
+        label: String,
+        selected: Bool,
+        value: String,
+    };
+
     /// Build a
     /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
     /// element.
-    output;
+    output {
+        form: Id,
+        name: Id,
+        // for: SpacedSet<Id>,
+    };
+
     /// Build a
     /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
     /// element.
-    progress;
+    progress {
+        max: f64,
+        value: f64,
+    };
+
     /// Build a
     /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
     /// element.
-    select;
+    select {
+        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;
+    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;
+    details {
+        open: Bool,
+    };
+
 
 
     /// Build a
     /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
     /// element.
-    summary;
+    summary {};
 
     // Web components
 
     /// Build a
     /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
     /// element.
-    slot;
+    slot {};
 
     /// Build a
     /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
     /// element.
-    template;
+    template {};
 }
 
 builder_constructors! {
@@ -583,36 +1005,210 @@ builder_constructors! {
     /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
     /// element.
     svg <> "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
     /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
     /// element.
     circle <>  "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
     /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
     /// element.
     line <> "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
     /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
     /// element.
     rect <> "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";
+
+}
+
+/*
+Ideal format:
+    /// 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
+    ///
+    /// ```
+    /// html!(<h1> A header element </h1>)
+    /// rsx!(h1 { "A header element" })
+    /// LazyNodes::new(|f| f.el(h1).children([f.text("A header element")]).finish())
+    /// ```
+
+Full List:
+---------
+base
+head
+link
+meta
+style
+title
+body
+address
+article
+aside
+footer
+header
+h1
+h1
+h2
+h2
+h3
+h4
+h5
+h6
+main
+nav
+section
+blockquote
+dd
+div
+dl
+dt
+figcaption
+figure
+hr
+li
+ol
+p
+pre
+ul
+a
+abbr
+b
+bdi
+bdo
+br
+cite
+code
+data
+dfn
+em
+i
+kbd
+mark
+q
+rp
+rt
+ruby
+s
+samp
+small
+span
+strong
+sub
+sup
+time
+u
+var
+wbr
+area
+audio
+img
+map
+track
+video
+embed
+iframe
+object
+param
+picture
+source
+canvas
+noscript
+script
+del
+ins
+caption
+col
+colgroup
+table
+tbody
+td
+tfoot
+th
+thead
+tr
+button
+datalist
+fieldset
+form
+input
+label
+legend
+meter
+optgroup
+option
+output
+progress
+select
+textarea
+details
+summary
+slot
+template
+*/
+
+trait AsAttributeValue: Sized {
+    fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a>;
+}
+enum AttributeValue<'a> {
+    Int(i32),
+    Float(f32),
+    Str(&'a str),
+    Bool(bool),
+}
+impl<'b> AsAttributeValue for Arguments<'b> {
+    fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
+        todo!()
+    }
+}
+impl AsAttributeValue for &'static str {
+    fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
+        todo!()
+    }
+}
+impl AsAttributeValue for f32 {
+    fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
+        todo!()
+    }
+}
+impl AsAttributeValue for i32 {
+    fn into_attribute_value<'a>(self, cx: NodeFactory<'a>) -> AttributeValue<'a> {
+        todo!()
+    }
 }

+ 7 - 7
packages/ssr/src/lib.rs

@@ -8,7 +8,7 @@
 
 use std::fmt::{Display, Formatter};
 
-use dioxus_core::{nodes::VNode, virtual_dom::VirtualDom};
+use dioxus_core::*;
 
 pub fn render_root(vdom: &VirtualDom) -> String {
     format!("{:}", TextRenderer::new(vdom))
@@ -69,8 +69,8 @@ impl<'a> TextRenderer<'a> {
     }
 
     fn html_render(&self, node: &VNode, f: &mut std::fmt::Formatter, il: u16) -> std::fmt::Result {
-        match node {
-            VNode::Text(text) => {
+        match &node.kind {
+            VNodeKind::Text(text) => {
                 if self.cfg.indent {
                     for _ in 0..il {
                         write!(f, "    ")?;
@@ -78,7 +78,7 @@ impl<'a> TextRenderer<'a> {
                 }
                 write!(f, "{}", text.text)?
             }
-            VNode::Element(el) => {
+            VNodeKind::Element(el) => {
                 if self.cfg.indent {
                     for _ in 0..il {
                         write!(f, "    ")?;
@@ -112,12 +112,12 @@ impl<'a> TextRenderer<'a> {
                     write!(f, "\n")?;
                 }
             }
-            VNode::Fragment(frag) => {
+            VNodeKind::Fragment(frag) => {
                 for child in frag.children {
                     self.html_render(child, f, il + 1)?;
                 }
             }
-            VNode::Component(vcomp) => {
+            VNodeKind::Component(vcomp) => {
                 let idx = vcomp.ass_scope.get().unwrap();
 
                 let new_node = self
@@ -130,7 +130,7 @@ impl<'a> TextRenderer<'a> {
 
                 self.html_render(new_node, f, il + 1)?;
             }
-            VNode::Suspended { .. } => todo!(),
+            VNodeKind::Suspended => todo!(),
         }
         Ok(())
     }

+ 3 - 2
packages/webview/examples/test.rs

@@ -1,3 +1,6 @@
+use dioxus_core as dioxus;
+use dioxus_core::prelude::*;
+
 fn main() {
     dioxus_webview::launch(App, |f| f.with_focus().with_maximized(true)).expect("Failed");
 }
@@ -11,8 +14,6 @@ static App: FC<()> = |cx| {
     ))
 };
 
-use dioxus_core as dioxus;
-use dioxus_core::prelude::*;
 mod dioxus_elements {
     use super::*;
     pub struct div;

+ 2 - 2
packages/webview/src/lib.rs

@@ -3,8 +3,8 @@ use std::ops::{Deref, DerefMut};
 use std::sync::mpsc::channel;
 use std::sync::{Arc, RwLock};
 
-use dioxus_core::virtual_dom::VirtualDom;
-use dioxus_core::{prelude::*, serialize::DomEdit};
+use dioxus_core::*;
+
 use wry::{
     application::window::{Window, WindowBuilder},
     webview::{RpcRequest, RpcResponse},