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