pub use attribute::Attribute;
pub use element::Element;
use std::fmt::Debug;
pub(crate) mod attribute;
mod element;
#[derive(Clone, Debug, PartialEq)]
pub enum Node<NS, TAG, ATT, VAL>
where
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
Element(Element<NS, TAG, ATT, VAL>),
Text(Text),
}
#[derive(PartialEq, Default, Debug, Clone)]
pub struct Text {
pub text: String,
pub safe_html: bool,
}
impl Text {
pub fn new(txt: impl ToString) -> Self {
Text {
text: txt.to_string(),
safe_html: false,
}
}
pub fn safe_html(txt: impl ToString) -> Self {
Text {
text: txt.to_string(),
safe_html: true,
}
}
pub fn set_text(&mut self, txt: impl ToString) {
self.text = txt.to_string();
}
}
impl<NS, TAG, ATT, VAL> Node<NS, TAG, ATT, VAL>
where
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
pub fn is_text(&self) -> bool {
match self {
Node::Element(_) => false,
Node::Text(_) => true,
}
}
pub fn take_element(self) -> Option<Element<NS, TAG, ATT, VAL>> {
match self {
Node::Element(element) => Some(element),
Node::Text(_) => None,
}
}
pub fn as_element_mut(
&mut self,
) -> Option<&mut Element<NS, TAG, ATT, VAL>> {
match *self {
Node::Element(ref mut element) => Some(element),
Node::Text(_) => None,
}
}
pub fn as_element_ref(&self) -> Option<&Element<NS, TAG, ATT, VAL>> {
match *self {
Node::Element(ref element) => Some(element),
Node::Text(_) => None,
}
}
pub fn add_children(
mut self,
children: Vec<Node<NS, TAG, ATT, VAL>>,
) -> Self {
if let Some(element) = self.as_element_mut() {
element.add_children(children);
} else {
panic!("Can not add children to a text node");
}
self
}
pub fn add_children_ref_mut(
&mut self,
children: Vec<Node<NS, TAG, ATT, VAL>>,
) {
if let Some(element) = self.as_element_mut() {
element.add_children(children);
} else {
panic!("Can not add children to a text node");
}
}
pub fn add_attributes(
mut self,
attributes: Vec<Attribute<NS, ATT, VAL>>,
) -> Self {
if let Some(elm) = self.as_element_mut() {
elm.add_attributes(attributes);
} else {
panic!("Can not add attributes to a text node");
}
self
}
pub fn add_attributes_ref_mut(
&mut self,
attributes: Vec<Attribute<NS, ATT, VAL>>,
) {
if let Some(elm) = self.as_element_mut() {
elm.add_attributes(attributes);
} else {
panic!("Can not add attributes to a text node");
}
}
pub fn get_attributes(&self) -> Option<&[Attribute<NS, ATT, VAL>]> {
match *self {
Node::Element(ref element) => Some(element.get_attributes()),
Node::Text(_) => None,
}
}
pub fn tag(&self) -> Option<&TAG> {
if let Some(e) = self.as_element_ref() {
Some(&e.tag)
} else {
None
}
}
pub fn text(&self) -> Option<&str> {
match self {
Node::Text(t) => Some(&t.text),
Node::Element(_) => None,
}
}
pub fn get_children(&self) -> Option<&[Node<NS, TAG, ATT, VAL>]> {
if let Some(element) = self.as_element_ref() {
Some(element.get_children())
} else {
None
}
}
pub fn get_children_count(&self) -> usize {
if let Some(children) = self.get_children() {
children.len()
} else {
0
}
}
pub fn children_mut(&mut self) -> Option<&mut [Node<NS, TAG, ATT, VAL>]> {
if let Some(element) = self.as_element_mut() {
Some(element.children_mut())
} else {
None
}
}
pub fn swap_remove_child(
&mut self,
index: usize,
) -> Node<NS, TAG, ATT, VAL> {
match self {
Node::Element(element) => element.swap_remove_child(index),
Node::Text(_) => panic!("text has no child"),
}
}
pub fn swap_children(&mut self, a: usize, b: usize) {
match self {
Node::Element(element) => element.swap_children(a, b),
Node::Text(_) => panic!("text has no child"),
}
}
pub fn node_count(&self) -> usize {
1 + self.descendant_node_count()
}
pub fn descendant_node_count(&self) -> usize {
let mut cnt = 0;
match self {
Node::Text(_) => (),
Node::Element(element) => {
for child in element.children.iter() {
cnt += child.node_count();
}
}
}
cnt
}
pub fn set_attributes_ref_mut(
&mut self,
attributes: Vec<Attribute<NS, ATT, VAL>>,
) {
if let Some(elm) = self.as_element_mut() {
elm.set_attributes(attributes);
}
}
pub fn merge_attributes(
mut self,
attributes: Vec<Attribute<NS, ATT, VAL>>,
) -> Self {
if let Some(elm) = self.as_element_mut() {
elm.merge_attributes(attributes);
}
self
}
pub fn get_attribute_value(&self, name: &ATT) -> Option<Vec<&VAL>> {
if let Some(elm) = self.as_element_ref() {
elm.get_attribute_value(name)
} else {
None
}
}
}
#[inline]
pub fn element<NS, TAG, ATT, VAL>(
tag: TAG,
attrs: Vec<Attribute<NS, ATT, VAL>>,
children: Vec<Node<NS, TAG, ATT, VAL>>,
) -> Node<NS, TAG, ATT, VAL>
where
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
element_ns(None, tag, attrs, children, false)
}
pub fn element_ns<NS, TAG, ATT, VAL>(
namespace: Option<NS>,
tag: TAG,
attrs: Vec<Attribute<NS, ATT, VAL>>,
children: Vec<Node<NS, TAG, ATT, VAL>>,
self_closing: bool,
) -> Node<NS, TAG, ATT, VAL>
where
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
Node::Element(Element::new(namespace, tag, attrs, children, self_closing))
}
pub fn text<S, NS, TAG, ATT, VAL>(s: S) -> Node<NS, TAG, ATT, VAL>
where
S: ToString,
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
Node::Text(Text::new(s))
}
pub fn safe_html<S, NS, TAG, ATT, VAL>(s: S) -> Node<NS, TAG, ATT, VAL>
where
S: ToString,
NS: PartialEq + Clone + Debug,
TAG: PartialEq + Clone + Debug,
ATT: PartialEq + Clone + Debug,
VAL: PartialEq + Clone + Debug,
{
Node::Text(Text::safe_html(s))
}