use {
crate::Node,
html5ever::{
namespace_url,
ns,
tendril::Tendril,
Attribute,
LocalName,
QualName,
},
rcdom::NodeData,
std::cell::RefCell,
};
pub trait NodeExt
where
Self: Sized,
{
fn children(&self) -> &RefCell<Vec<Node>>;
fn data(&self) -> &rcdom::NodeData;
fn append_children(&self, children: Vec<Node>);
fn append_child(&self, child: Node);
fn tag_name(&self) -> Option<String> {
match &self.data() {
NodeData::Doctype { name, .. } => Some(name.to_string()),
NodeData::Element { name, .. } => Some(name.local.to_string()),
_ => None,
}
}
fn attr(self, name: &str, value: &str) -> Self {
{
let attrs = match &self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return self,
};
let mut attrs = attrs.borrow_mut();
attrs.push(Attribute {
name: QualName::new(None, ns!(), LocalName::from(name)),
value: Tendril::from(value),
});
}
self
}
fn borrow_attr(&self, name: &str, value: &str) {
{
let attrs = match &self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return,
};
let mut attrs = attrs.borrow_mut();
attrs.push(Attribute {
name: QualName::new(None, ns!(), LocalName::from(name)),
value: Tendril::from(value),
});
}
}
fn attrs(mut self, attributes: Vec<(&str, &str)>) -> Self {
for attr in attributes {
self = self.attr(attr.0, attr.1);
}
self
}
fn borrow_attrs(&self, attributes: Vec<(&str, &str)>) {
for attr in attributes {
self.borrow_attr(attr.0, attr.1);
}
}
fn find_attribute(&self, attribute_name: &str) -> Option<usize> {
let attrs = match &self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return None,
};
for (idx, attr) in attrs.borrow().iter().enumerate() {
if attr.name
!= QualName::new(None, ns!(), LocalName::from(attribute_name))
{
continue;
}
return Some(idx);
}
None
}
fn attribute_eq(&self, attribute_name: &str, value: &str) -> bool {
if let Some(index) = self.find_attribute(attribute_name) {
let attrs = match &self.data() {
NodeData::Element { attrs, .. } => attrs.borrow_mut(),
_ => return false,
};
return &*attrs[index].value == value;
}
false
}
fn add_class(&self, class_value: &str) {
let attribute_index = self.find_attribute("class");
let attrs = match self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return,
};
let mut attrs = attrs.borrow_mut();
match attribute_index {
None => {
attrs.push(Attribute {
name: QualName::new(None, ns!(), LocalName::from("class")),
value: Tendril::from(class_value),
});
}
Some(index) => {
let value = String::from(attrs[index].value.clone());
let mut value = value.split(' ').collect::<Vec<_>>();
if value.contains(&class_value) {
return;
}
value.push(class_value);
attrs[index].value = Tendril::from(value.join(" "));
}
};
}
fn remove_class(&self, class_value: &str) {
let attribute_index = self.find_attribute("class");
let attrs = match self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return,
};
let mut attrs = attrs.borrow_mut();
if let Some(index) = attribute_index {
let value = String::from(attrs[index].value.clone());
let mut value = value.split(' ').collect::<Vec<_>>();
value.retain(|x| x != &class_value);
attrs[index].value = Tendril::from(value.join(" "));
};
}
fn has_class(&self, class_value: &str) -> bool {
let attribute_index = self.find_attribute("class");
let attrs = match self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return false,
};
let attrs = attrs.borrow();
match attribute_index {
None => false,
Some(index) => {
attrs[index].value.split(' ').any(|x| x == class_value)
}
}
}
fn toggle_class(&self, class_value: &str) {
let attribute_index = self.find_attribute("class");
let attrs = match self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return,
};
let mut attrs = attrs.borrow_mut();
match attribute_index {
None => {
attrs.push(Attribute {
name: QualName::new(None, ns!(), LocalName::from("class")),
value: Tendril::from(class_value),
});
}
Some(index) => {
let value = String::from(attrs[index].value.clone());
let mut value = value.split(' ').collect::<Vec<_>>();
if value.contains(&class_value) {
return;
}
value.push(class_value);
attrs[index].value = Tendril::from(value.join(" "));
}
};
}
fn remove_attribute(&self, name: &str) {
let attribute_index = self.find_attribute(name);
let attrs = match self.data() {
NodeData::Element { attrs, .. } => attrs,
_ => return,
};
let mut attrs = attrs.borrow_mut();
if let Some(index) = attribute_index {
attrs.remove(index);
};
}
}