simple_rsx/
lib.rs

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}