pub use simple_rsx_macros::rsx;
use std::{collections::HashMap, fmt::Display};
pub enum Node {
Element(Element),
Text(String),
Fragment(Vec<Node>),
}
impl From<String> for Node {
fn from(value: String) -> Self {
Node::Text(value.to_string())
}
}
impl From<&str> for Node {
fn from(value: &str) -> Self {
Node::Text(value.to_string())
}
}
impl From<&&str> for Node {
fn from(value: &&str) -> Self {
Node::Text(value.to_string())
}
}
impl<T: ToString> From<Vec<T>> for Node {
fn from(value: Vec<T>) -> Self {
Node::Fragment(
value
.into_iter()
.map(|t| Node::Text(t.to_string()))
.collect(),
)
}
}
impl From<i32> for Node {
fn from(value: i32) -> Self {
Node::Text(value.to_string())
}
}
impl FromIterator<i32> for Node {
fn from_iter<T: IntoIterator<Item = i32>>(iter: T) -> Self {
let mut result = Vec::new();
for i in iter {
result.push(Node::Text(i.to_string()));
}
Node::Fragment(result)
}
}
impl From<f32> for Node {
fn from(value: f32) -> Self {
Node::Text(value.to_string())
}
}
impl From<bool> for Node {
fn from(value: bool) -> Self {
Node::Text(value.to_string())
}
}
impl<I, F, R> From<std::iter::Map<I, F>> for Node
where
I: Iterator,
F: FnMut(I::Item) -> R,
R: Into<Node>,
Vec<Node>: FromIterator<R>,
{
fn from(iter: std::iter::Map<I, F>) -> Self {
let nodes: Vec<Node> = iter.collect();
Node::from(nodes)
}
}
impl Display for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Node::Element(el) => {
write!(f, "<{}", el.tag)?;
for (key, value) in &el.attributes {
write!(f, " {}=\"{}\"", key, value)?;
}
write!(f, ">")?;
for child in &el.children {
write!(f, "{}", child)?;
}
write!(f, "</{}>", el.tag)?;
Ok(())
}
Node::Text(text) => {
write!(f, "{}", text)?;
Ok(())
}
Node::Fragment(nodes) => {
for node in nodes {
write!(f, "{}", node)?;
}
Ok(())
}
}
}
}
pub trait NodeValue {
fn value(&self) -> String;
}
impl<T: ToString> NodeValue for T {
fn value(&self) -> String {
self.to_string()
}
}
pub struct Element {
tag: String,
attributes: HashMap<String, String>,
children: Vec<Node>,
}
impl Element {
pub fn new(tag: &str) -> Node {
Node::Element(Element {
tag: tag.to_string(),
attributes: HashMap::new(),
children: Vec::new(),
})
}
pub fn set_attribute(&mut self, name: &str, value: impl NodeValue) {
self.attributes.insert(name.to_string(), value.value());
}
pub fn append_child(&mut self, node: Node) {
self.children.push(node);
}
}
impl Node {
pub fn as_element_mut(&mut self) -> Option<&mut Element> {
match self {
Node::Element(el) => Some(el),
_ => None,
}
}
pub fn append_child(&mut self, node: Node) {
if let Node::Element(el) = self {
el.children.push(node);
}
}
}
pub struct TextNode;
impl TextNode {
pub fn new(text: &str) -> Node {
Node::Text(text.to_string())
}
}