use std::collections::HashMap; pub trait Render { /// Render into HTML. fn render(&self) -> String; } pub const SELF_CLOSING_TAGS: &[&str] = &["img", "br", "hr", "input", "meta", "link"]; /// The entire document can be boiled down to just elements with children... so just /// a simple tree structure (just without the linking to parent since that's annoying) #[derive(Clone, Debug, Default)] pub struct Element { pub tag: String, pub attrs: HashMap, pub children: Vec, } impl Render for Element { fn render(&self) -> String { if self.tag == "text" { return self.attrs.get("content").unwrap().to_owned(); } else if self.tag == "v" { return self.attrs.get("0").unwrap().to_owned(); } else if self.tag == "null?" { // just render children of null element let mut inner: String = String::new(); for element in &self.children { inner.push_str(&element.render()); } return inner; } let closing = format!("", self.tag); format!( "<{}{}{}{}{}", self.tag, { let mut attrs: String = String::new(); for attr in &self.attrs { attrs.push_str(" "); attrs.push_str(attr.0); attrs.push_str("=\""); attrs.push_str(attr.1); attrs.push_str("\""); } attrs }, if SELF_CLOSING_TAGS.contains(&self.tag.as_str()) { "/>" } else { ">" }, { let mut inner: String = String::new(); for element in &self.children { inner.push_str(&element.render()); } inner }, if SELF_CLOSING_TAGS.contains(&self.tag.as_str()) { "" } else { &closing } ) } }