use std::collections::{HashMap,HashSet}; use std; use css; #[derive(Clone)] pub struct Attr { attrs: HashMap, } #[derive(Clone)] pub struct EData { pub name: String, pub attr: Attr, } impl EData { pub fn id(&self) -> Option<&String> { self.attr.attrs.get("id") } pub fn classes(&self) -> HashSet<&str> { match self.attr.attrs.get("class") { Some(classlist) => classlist.split(' ').collect(), None => HashSet::new() } } } #[derive(Clone)] pub struct SData { attr: Attr, content: css::Stylesheet, } #[derive(Clone)] pub enum NType { Text(String), Comment(String), Element(EData), Stylesheet(SData) } #[derive(Clone)] pub struct Node { pub children: Vec, pub ntype: NType, } pub fn text(d: String) -> Node { Node { children: Vec::new(), ntype: NType::Text(d) } } pub fn comment(d: String) -> Node { Node { children: Vec::new(), ntype: NType::Comment(d) } } pub fn elem(name: String, attr: Attr, children: Vec) -> Node { Node { children: children, ntype: NType::Element(EData { name: name, attr: attr, }), } } pub fn attr(attrs: HashMap) -> Attr { Attr { attrs } } pub fn style(style: String, attr: Attr) -> Node { Node { children: Vec::new(), ntype: NType::Stylesheet(SData { content: css::parse(style), attr: attr, }) } } impl std::fmt::Display for Node { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self.ntype { NType::Text(ref s) => write!(f, "{}", s), NType::Comment(ref s) => write!(f, "", s), NType::Element(ref d) => { write!(f, "<{}{}>", d.name, d.attr); for child in self.children.iter() { write!(f, "{}", child); } write!(f, "", d.name) }, NType::Stylesheet(ref s) => { write!(f, "", s.attr, s.content) } } } } impl std::fmt::Display for Attr { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { for (k, v) in self.attrs.iter() { write!(f, " {}=\"{}\"", k, v); } return Result::Ok(()) } } pub fn find_node(name: String, node: &Node) -> Option { match node.ntype { NType::Text(_) | NType::Comment(_) => None, NType::Element(ref d) => { if d.name == name { return Some(node.clone()); } for ref child in &node.children { if let Some(n) = find_node(name.clone(), child) { return Some(n); } } return None; }, NType::Stylesheet(_) => if name == "style" { return Some(node.clone()); } else { return None; } } } pub fn find_style(node: &Node) -> Option { match find_node("style".to_string(), node) { Some(n) => { match n.ntype { NType::Stylesheet(d) => Some(d.content), _ => None } } _ => None } }