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