1pub use simple_rsx_macros::rsx;
2use std::{collections::HashMap, fmt::Display};
3
4pub enum Node {
5 Element(Element),
6 Text(String),
7 Fragment(Vec<Node>),
8}
9
10impl From<String> for Node {
11 fn from(value: String) -> Self {
12 Node::Text(value.to_string())
13 }
14}
15
16impl From<&str> for Node {
17 fn from(value: &str) -> Self {
18 Node::Text(value.to_string())
19 }
20}
21
22impl From<&&str> for Node {
23 fn from(value: &&str) -> Self {
24 Node::Text(value.to_string())
25 }
26}
27
28impl<T: ToString> From<Vec<T>> for Node {
29 fn from(value: Vec<T>) -> Self {
30 Node::Fragment(
31 value
32 .into_iter()
33 .map(|t| Node::Text(t.to_string()))
34 .collect(),
35 )
36 }
37}
38
39impl From<i32> for Node {
40 fn from(value: i32) -> Self {
41 Node::Text(value.to_string())
42 }
43}
44
45impl FromIterator<i32> for Node {
46 fn from_iter<T: IntoIterator<Item = i32>>(iter: T) -> Self {
47 let mut result = Vec::new();
48 for i in iter {
49 result.push(Node::Text(i.to_string()));
50 }
51 Node::Fragment(result)
52 }
53}
54
55impl From<f32> for Node {
56 fn from(value: f32) -> Self {
57 Node::Text(value.to_string())
58 }
59}
60
61impl From<bool> for Node {
62 fn from(value: bool) -> Self {
63 Node::Text(value.to_string())
64 }
65}
66
67impl<I, F, R> From<std::iter::Map<I, F>> for Node
68where
69 I: Iterator,
70 F: FnMut(I::Item) -> R,
71 R: Into<Node>,
72 Vec<Node>: FromIterator<R>,
73{
74 fn from(iter: std::iter::Map<I, F>) -> Self {
75 let nodes: Vec<Node> = iter.collect();
76 Node::from(nodes)
77 }
78}
79
80impl Display for Node {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 match self {
83 Node::Element(el) => {
84 write!(f, "<{}", el.tag)?;
85 for (key, value) in &el.attributes {
86 write!(f, " {}=\"{}\"", key, value)?;
87 }
88 write!(f, ">")?;
89 for child in &el.children {
90 write!(f, "{}", child)?;
91 }
92 write!(f, "</{}>", el.tag)?;
93 Ok(())
94 }
95 Node::Text(text) => {
96 write!(f, "{}", text)?;
97 Ok(())
98 }
99 Node::Fragment(nodes) => {
100 for node in nodes {
101 write!(f, "{}", node)?;
102 }
103 Ok(())
104 }
105 }
106 }
107}
108
109pub trait NodeValue {
110 fn value(&self) -> String;
111}
112
113impl<T: ToString> NodeValue for T {
114 fn value(&self) -> String {
115 self.to_string()
116 }
117}
118
119pub struct Element {
120 tag: String,
121 attributes: HashMap<String, String>,
122 children: Vec<Node>,
123}
124
125impl Element {
126 pub fn new(tag: &str) -> Node {
127 Node::Element(Element {
128 tag: tag.to_string(),
129 attributes: HashMap::new(),
130 children: Vec::new(),
131 })
132 }
133
134 pub fn set_attribute(&mut self, name: &str, value: impl NodeValue) {
135 self.attributes.insert(name.to_string(), value.value());
136 }
137
138 pub fn append_child(&mut self, node: Node) {
139 self.children.push(node);
140 }
141}
142
143impl Node {
144 pub fn as_element_mut(&mut self) -> Option<&mut Element> {
145 match self {
146 Node::Element(el) => Some(el),
147 _ => None,
148 }
149 }
150
151 pub fn append_child(&mut self, node: Node) {
152 if let Node::Element(el) = self {
153 el.children.push(node);
154 }
155 }
156}
157
158pub struct TextNode;
159
160impl TextNode {
161 pub fn new(text: &str) -> Node {
162 Node::Text(text.to_string())
163 }
164}