virtual_dom/
lib.rs

1mod document;
2mod dom_node;
3mod html;
4
5use std::{collections::VecDeque, iter};
6
7pub use document::*;
8pub use dom_node::*;
9use html::*;
10pub use html::{parse_html, parse_html_from_string, Html};
11
12/// Used in dom-proc for converting braced variables into domnode and to allow any kind of dom element to be appended
13#[derive(Debug, PartialEq)]
14pub struct IterableNodes(pub Vec<DomNode>);
15
16impl From<String> for IterableNodes {
17    fn from(value: String) -> Self {
18        Self(vec![DomNode::create_text(value)])
19    }
20}
21impl From<&String> for IterableNodes {
22    fn from(value: &String) -> Self {
23        Self(vec![DomNode::create_text(value)])
24    }
25}
26
27impl From<&str> for IterableNodes {
28    fn from(value: &str) -> Self {
29        Self(vec![DomNode::create_text(value)])
30    }
31}
32
33impl From<DomNode> for IterableNodes {
34    fn from(value: DomNode) -> Self {
35        Self(vec![value])
36    }
37}
38
39impl From<Vec<DomNode>> for IterableNodes {
40    fn from(value: Vec<DomNode>) -> Self {
41        Self(value)
42    }
43}
44
45impl FromIterator<DomNode> for IterableNodes {
46    fn from_iter<T: IntoIterator<Item = DomNode>>(iter: T) -> Self {
47        Self(iter.into_iter().collect())
48    }
49}
50
51impl FromIterator<Html> for IterableNodes {
52    fn from_iter<T: IntoIterator<Item = Html>>(iter: T) -> Self {
53        iter.into_iter()
54            .map(|value| match value {
55                Html::Comment { .. } => panic!("root html can't be comment"),
56                Html::Text { text } => DomNode::create_text(text),
57                Html::Element {
58                    tag,
59                    attributes,
60                    children,
61                } => {
62                    let root = DomNode::create_element_with_attributes(tag, attributes);
63                    let mut queue: VecDeque<(Html, DomNode)> = VecDeque::from(
64                        children
65                            .into_iter()
66                            .zip(std::iter::repeat(root.clone()))
67                            .collect::<Vec<(Html, DomNode)>>(),
68                    );
69                    while let Some((c, parent)) = queue.pop_front() {
70                        if let Some(p) = match c {
71                            Html::Text { text } => Some(DomNode::create_text(text)),
72                            Html::Element {
73                                tag,
74                                attributes,
75                                children,
76                            } => {
77                                let p = DomNode::create_element_with_attributes(tag, attributes);
78                                queue
79                                    .extend(children.into_iter().zip(std::iter::repeat(p.clone())));
80                                Some(p)
81                            }
82                            _ => None,
83                        } {
84                            parent.append_child(p)
85                        }
86                    }
87                    root
88                }
89            })
90            .collect()
91    }
92}
93
94impl From<Vec<Html>> for IterableNodes {
95    fn from(value: Vec<Html>) -> Self {
96        value.into_iter().collect()
97    }
98}
99
100impl From<Html> for IterableNodes {
101    fn from(value: Html) -> Self {
102        iter::once(value).collect()
103    }
104}