simple_rsx/
lib.rs

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}