dom_manipulator/element_ref/
mod.rs1use std::ops::Deref;
4
5use ego_tree::iter::{Edge, Traverse};
6use ego_tree::NodeRef;
7use html5ever::serialize::{serialize, SerializeOpts, TraversalScope};
8
9use crate::node::Element;
10use crate::{Node, Selector};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct ElementRef<'a> {
18    node: NodeRef<'a, Node>,
19}
20
21impl<'a> ElementRef<'a> {
22    fn new(node: NodeRef<'a, Node>) -> Self {
23        ElementRef { node }
24    }
25
26    pub fn wrap(node: NodeRef<'a, Node>) -> Option<Self> {
28        if node.value().is_element() {
29            Some(ElementRef::new(node))
30        } else {
31            None
32        }
33    }
34
35    pub fn value(&self) -> &'a Element {
37        self.node.value().as_element().unwrap()
38    }
39
40    pub fn select<'b>(&self, selector: &'b Selector) -> Select<'a, 'b> {
42        let mut inner = self.traverse();
43        inner.next(); Select {
46            scope: *self,
47            inner,
48            selector,
49        }
50    }
51
52    fn serialize(&self, traversal_scope: TraversalScope) -> String {
53        let opts = SerializeOpts {
54            scripting_enabled: false, traversal_scope,
56            create_missing_parent: false,
57        };
58        let mut buf = Vec::new();
59        serialize(&mut buf, self, opts).unwrap();
60        String::from_utf8(buf).unwrap()
61    }
62
63    pub fn html(&self) -> String {
65        self.serialize(TraversalScope::IncludeNode)
66    }
67
68    pub fn inner_html(&self) -> String {
70        self.serialize(TraversalScope::ChildrenOnly(None))
71    }
72
73    pub fn text(&self) -> Text<'a> {
75        Text {
76            inner: self.traverse(),
77        }
78    }
79}
80
81impl<'a> Deref for ElementRef<'a> {
82    type Target = NodeRef<'a, Node>;
83    fn deref(&self) -> &NodeRef<'a, Node> {
84        &self.node
85    }
86}
87
88#[derive(Debug, Clone)]
90pub struct Select<'a, 'b> {
91    scope: ElementRef<'a>,
92    inner: Traverse<'a, Node>,
93    selector: &'b Selector,
94}
95
96impl<'a, 'b> Iterator for Select<'a, 'b> {
97    type Item = ElementRef<'a>;
98
99    fn next(&mut self) -> Option<ElementRef<'a>> {
100        for edge in &mut self.inner {
101            if let Edge::Open(node) = edge {
102                if let Some(element) = ElementRef::wrap(node) {
103                    if self.selector.matches_with_scope(&element, Some(self.scope)) {
104                        return Some(element);
105                    }
106                }
107            }
108        }
109        None
110    }
111}
112
113#[derive(Debug, Clone)]
115pub struct Text<'a> {
116    inner: Traverse<'a, Node>,
117}
118
119impl<'a> Iterator for Text<'a> {
120    type Item = &'a str;
121
122    fn next(&mut self) -> Option<&'a str> {
123        for edge in &mut self.inner {
124            if let Edge::Open(node) = edge {
125                if let Node::Text(ref text) = node.value() {
126                    return Some(&**text);
127                }
128            }
129        }
130        None
131    }
132}
133
134mod element;
135mod serializable;
136
137#[cfg(test)]
138mod tests {
139    use crate::html::Html;
140    use crate::selector::Selector;
141
142    #[test]
143    fn test_scope() {
144        let html = r"
145            <div>
146                <b>1</b>
147                <span>
148                    <span><b>2</b></span>
149                    <b>3</b>
150                </span>
151            </div>
152        ";
153        let fragment = Html::parse_fragment(html);
154        let sel1 = Selector::parse("div > span").unwrap();
155        let sel2 = Selector::parse(":scope > b").unwrap();
156
157        let element1 = fragment.select(&sel1).next().unwrap();
158        let element2 = element1.select(&sel2).next().unwrap();
159        assert_eq!(element2.inner_html(), "3");
160    }
161}