use crate::{Html, HtmlContainer, HtmlTag};
use std::fmt::{self, Display, Formatter};
#[derive(Debug, Clone)]
pub enum HtmlChild {
Element(HtmlElement),
Raw(String),
}
impl Display for HtmlChild {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::Element(e) => write!(f, "{e}"),
Self::Raw(r) => write!(f, "{r}"),
}
}
}
impl Html for HtmlChild {
fn to_html_string(&self) -> String {
match self {
Self::Element(e) => e.to_html_string(),
Self::Raw(r) => r.to_owned(),
}
}
}
impl From<HtmlElement> for HtmlChild {
fn from(value: HtmlElement) -> Self {
Self::Element(value)
}
}
impl<S: AsRef<str>> From<S> for HtmlChild {
fn from(value: S) -> Self {
Self::Raw(value.as_ref().to_owned())
}
}
#[derive(Debug, Clone)]
pub struct HtmlElement {
pub tag: HtmlTag,
pub attributes: Vec<(String, String)>,
pub children: Vec<HtmlChild>,
}
impl Display for HtmlElement {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if self.children.is_empty() {
write!(f, "<{}", self.tag)?;
self.write_attributes(f)?;
write!(f, "/>")
} else {
write!(f, "<{}", self.tag,)?;
self.write_attributes(f)?;
write!(f, ">")?;
self.write_children(f)?;
write!(f, "</{}>", self.tag)
}
}
}
impl Html for HtmlElement {
fn to_html_string(&self) -> String {
format!("{}", self)
}
}
impl HtmlContainer for HtmlElement {
fn add_html<H: Html>(&mut self, html: H) {
self.children.push(HtmlChild::Raw(html.to_html_string()))
}
}
impl HtmlElement {
pub fn new(tag: HtmlTag) -> Self {
Self {
tag,
attributes: Default::default(),
children: Default::default(),
}
}
pub fn add_child(&mut self, content: HtmlChild) {
self.children.push(content);
}
pub fn with_child(mut self, content: HtmlChild) -> Self {
self.add_child(content);
self
}
pub fn add_attribute(&mut self, k: impl ToString, v: impl ToString) {
self.attributes.push((k.to_string(), v.to_string()));
}
pub fn with_attribute(mut self, k: impl ToString, v: impl ToString) -> Self {
self.add_attribute(k, v);
self
}
fn write_attributes(&self, f: &mut Formatter<'_>) -> fmt::Result {
for (k, v) in self.attributes.iter() {
write!(f, r#" {}="{}""#, k, v)?;
}
Ok(())
}
fn write_children(&self, f: &mut Formatter<'_>) -> fmt::Result {
for child in self.children.iter() {
write!(f, "{}", child)?;
}
Ok(())
}
}