pub use simple_rsx_macros::rsx;
use std::{collections::HashMap, fmt::Display};
pub enum NodeList {
Fragment(Vec<Node>),
Single(Node),
}
impl From<String> for NodeList {
fn from(value: String) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<&str> for NodeList {
fn from(value: &str) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<&&str> for NodeList {
fn from(value: &&str) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<i32> for NodeList {
fn from(value: i32) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<f32> for NodeList {
fn from(value: f32) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<bool> for NodeList {
fn from(value: bool) -> Self {
NodeList::Single(Node::Text(value.to_string()))
}
}
impl From<Node> for NodeList {
fn from(node: Node) -> Self {
NodeList::Single(node)
}
}
impl From<Vec<Node>> for NodeList {
fn from(nodes: Vec<Node>) -> Self {
NodeList::Fragment(nodes)
}
}
impl From<Vec<NodeList>> for NodeList {
fn from(nodes: Vec<NodeList>) -> Self {
let mut result = Vec::new();
for node in nodes {
match node {
NodeList::Fragment(nodes) => {
result.extend(nodes);
}
NodeList::Single(node) => {
result.push(node);
}
}
}
NodeList::Fragment(result)
}
}
impl<I, F> From<std::iter::Map<I, F>> for NodeList
where
I: Iterator,
F: FnMut(I::Item) -> NodeList,
{
fn from(iter: std::iter::Map<I, F>) -> Self {
let nodes: Vec<NodeList> = iter.collect();
NodeList::from(nodes)
}
}
impl Display for NodeList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NodeList::Fragment(nodes) => {
for node in nodes {
write!(f, "{}", node)?;
}
Ok(())
}
NodeList::Single(node) => {
write!(f, "{}", node)?;
Ok(())
}
}
}
}
pub enum Node {
Element(Element),
Text(String),
}
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(())
}
}
}
}
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())
}
}