Build a virtual DOM structure.

This commit is contained in:
Bodil Stokke 2018-11-12 16:29:48 +00:00
parent 2806bde178
commit 73344d0dbf
4 changed files with 80 additions and 9 deletions

5
clippy.toml Normal file
View File

@ -0,0 +1,5 @@
blacklisted-names = []
cyclomatic-complexity-threshold = 100
single-char-binding-names-threshold = 15
# I HAVE THE POWER OF OLEG
type-complexity-threshold = 999999

View File

@ -96,11 +96,6 @@ impl Declare {
let mut body = TokenStream::new();
body.extend(quote!(
pub attrs: $attr_type_name,
pub data_attributes: std::collections::BTreeMap<String, String>,
));
for (child_name, child_type, _) in self.req_children() {
body.extend(quote!( pub $child_name: Box<$child_type>, ));
}
@ -112,6 +107,8 @@ impl Declare {
quote!(
pub struct $elem_name {
pub attrs: $attr_type_name,
pub data_attributes: std::collections::BTreeMap<String, String>,
$body
}
)
@ -154,10 +151,58 @@ impl Declare {
)
}
fn impl_vnode(&self) -> TokenStream {
let elem_name = TokenTree::Literal(Literal::string(self.name.to_string().as_str()));
let mut req_children = TokenStream::new();
for (child_name, _, _) in self.req_children() {
req_children.extend(quote!(
children.push(self.$child_name.vnode());
));
}
let mut opt_children = TokenStream::new();
if self.opt_children.is_some() {
opt_children.extend(quote!(for child in &self.children {
children.push(child.vnode());
}));
}
let mut push_attrs = TokenStream::new();
for (attr_name, _, attr_str) in self.attrs() {
push_attrs.extend(quote!(
if let Some(ref value) = self.attrs.$attr_name {
attributes.push(($attr_str.to_string(), value.to_string()));
}
));
}
quote!(
let mut attributes = Vec::new();
$push_attrs
for (key, value) in &self.data_attributes {
attributes.push((format!("data-{}", key), value.to_string()));
}
let mut children = Vec::new();
$req_children
$opt_children
::elements::VNode::Element(::elements::VElement {
name: $elem_name,
attributes,
children
})
)
}
fn impl_node(&self) -> TokenStream {
let elem_name = self.elem_name();
let vnode = self.impl_vnode();
quote!(
impl ::elements::Node for $elem_name {}
impl ::elements::Node for $elem_name {
fn vnode(&self) -> ::elements::VNode {
$vnode
}
}
)
}
@ -270,7 +315,7 @@ impl Declare {
quote!(
impl std::fmt::Display for $elem_name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "<{}", $name);
write!(f, "<{}", $name)?;
$print_attrs
for (key, value) in &self.data_attributes {
write!(f, " data-{}={:?}", key, value)?;

View File

@ -5,6 +5,7 @@
extern crate typed_html;
extern crate typed_html_macros;
use typed_html::elements::Node;
use typed_html::types::*;
use typed_html_macros::html;
@ -37,4 +38,5 @@ fn main() {
</html>
);
println!("{}", doc.to_string());
println!("{:?}", doc.vnode());
}

View File

@ -6,7 +6,22 @@ use typed_html_macros::declare_element;
use super::types::*;
pub trait Node: Display {}
#[derive(Clone, Debug)]
pub enum VNode {
Text(String),
Element(VElement),
}
#[derive(Clone, Debug)]
pub struct VElement {
pub name: &'static str,
pub attributes: Vec<(String, String)>,
pub children: Vec<VNode>,
}
pub trait Node: Display {
fn vnode(&self) -> VNode;
}
pub trait Element: Node {
fn name() -> &'static str;
@ -61,7 +76,11 @@ impl Display for TextNode {
}
}
impl Node for TextNode {}
impl Node for TextNode {
fn vnode(&self) -> VNode {
VNode::Text(self.0.clone())
}
}
impl FlowContent for TextNode {}
impl PhrasingContent for TextNode {}