Files
r/src/dom.rs
2017-08-28 19:22:08 +02:00

145 lines
3.3 KiB
Rust

use std::collections::{HashMap,HashSet};
use std;
use css;
#[derive(Clone)]
pub struct Attr {
attrs: HashMap<String, String>,
}
#[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<Node>,
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 {
Node {
children: children,
ntype: NType::Element(EData {
name: name,
attr: attr,
}),
}
}
pub fn attr(attrs: HashMap<String, String>) -> 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, "<style {}>{}</style>", 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<Node> {
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<css::Stylesheet> {
match find_node("style".to_string(), node) {
Some(n) => {
match n.ntype {
NType::Stylesheet(d) => Some(d.content),
_ => None
}
}
_ => None
}
}