html_parse/html/
node.rs

1use std::ops::Deref;
2
3use html5ever::{tendril::StrTendril, Attribute, LocalName, QualName};
4use indexmap::IndexSet;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum Node {
8    /// The document root.
9    Document,
10
11    /// The fragment root.
12    Fragment,
13
14    /// A doctype.
15    Doctype(Doctype),
16
17    /// A comment.
18    Comment(Comment),
19
20    /// Text.
21    Text(Text),
22
23    /// An element.
24    Element(Element),
25
26    /// A processing instruction.
27    ProcessingInstruction(ProcessingInstruction),
28}
29
30impl Node {
31    /// Returns self as an element.
32    pub fn as_element(&self) -> Option<&Element> {
33        match *self {
34            Node::Element(ref e) => Some(e),
35            _ => None,
36        }
37    }
38}
39
40/// A doctype.
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct Doctype {
43    /// The doctype name.
44    pub name: StrTendril,
45
46    /// The doctype public ID.
47    pub public_id: StrTendril,
48
49    /// The doctype system ID.
50    pub system_id: StrTendril,
51}
52
53// An HTML comment.
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct Comment {
56    /// The comment text.
57    pub comment: StrTendril,
58}
59
60/// HTML text.
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct Text {
63    /// The text.
64    pub text: StrTendril,
65}
66
67pub type Attributes = indexmap::IndexMap<QualName, StrTendril>;
68
69/// An HTML element.
70#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct Element {
72    /// The element name.
73    pub name: QualName,
74
75    /// The element ID.
76    pub id: Option<LocalName>,
77
78    /// The element classes.
79    pub classes: IndexSet<LocalName>,
80
81    /// The element attributes.
82    pub attrs: Attributes,
83}
84
85impl Element {
86    #[doc(hidden)]
87    pub fn new(name: QualName, attrs: Vec<Attribute>) -> Self {
88        let id = attrs
89            .iter()
90            .find(|a| a.name.local.deref() == "id")
91            .map(|a| LocalName::from(a.value.deref()));
92
93        let classes: IndexSet<LocalName> = attrs
94            .iter()
95            .find(|a| a.name.local.deref() == "class")
96            .map_or(IndexSet::new(), |a| {
97                a.value
98                    .deref()
99                    .split_whitespace()
100                    .map(LocalName::from)
101                    .collect()
102            });
103
104        Element {
105            attrs: attrs.into_iter().map(|a| (a.name, a.value)).collect(),
106            name,
107            id,
108            classes,
109        }
110    }
111}
112
113/// HTML Processing Instruction.
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub struct ProcessingInstruction {
116    /// The PI target.
117    pub target: StrTendril,
118
119    /// The PI data.
120    pub data: StrTendril,
121}