1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use super::Selector;
use crate::{Element, Node};

/// Query the specific element(s) by [`Selector`].
pub trait Queryable {
    /// Query the node in `self` for the given selector.
    ///
    /// ```
    /// use html_editor::{parse, Element};
    /// use html_editor::operation::*;
    ///
    /// let html = r#"
    ///     <!DOCTYPE html>
    ///     <html lang="en">
    ///     <head>
    ///         <meta charset="UTF-8">
    ///         <title>App</title>
    ///     </head>
    ///     <body>
    ///         <div id="app"></div>
    ///     </body>
    ///     </html>"#;
    ///
    /// let selector: Selector = Selector::from("#app");
    /// let app: Element = parse(html).unwrap().query(&selector).unwrap();
    /// ```
    fn query(&self, selector: &Selector) -> Option<Element>;

    /// Query all the nodes in `self` for the given selector.
    ///
    /// ```
    /// use html_editor::{parse, Element};
    /// use html_editor::operation::*;
    ///
    /// let html = r#"
    ///     <!DOCTYPE html>
    ///     <html lang="en">
    ///     <head>
    ///         <meta charset="UTF-8">
    ///         <title>App</title>
    ///     </head>
    ///     <body>
    ///         <span class="btn">Ok</span>
    ///         <span class="btn">Cancel</span>
    ///         <span class="btn">Remind Me Later</span>
    ///     </body>
    ///     </html>"#;
    ///
    /// let selector: Selector = Selector::from(".btn");
    /// let app: Vec<Element> = parse(html).unwrap().query_all(&selector);
    /// ```
    fn query_all(&self, selector: &Selector) -> Vec<Element>;
}

impl Queryable for Vec<Node> {
    fn query(&self, selector: &Selector) -> Option<Element> {
        for node in self {
            if node.is_element() {
                let element = node.clone().into_element();

                if selector.matches(&element) {
                    return Some(element);
                } else if let Some(elem) = element.query(selector) {
                    return Some(elem);
                }
            }
        }
        None
    }

    fn query_all(&self, selector: &Selector) -> Vec<Element> {
        let mut elements = Vec::new();
        for node in self {
            if node.is_element() {
                let element = node.clone().into_element();
                // Recursively traverse the descendants nodes
                let sub_elements = element.query_all(selector);
                elements.extend(sub_elements);
                // Check if this element matches. If so, push it to the `elements`
                if selector.matches(&element) {
                    elements.push(element);
                }
            }
        }
        elements
    }
}

impl Queryable for Element {
    fn query(&self, selector: &Selector) -> Option<Element> {
        self.children.query(selector)
    }

    fn query_all(&self, selector: &Selector) -> Vec<Element> {
        self.children.query_all(selector)
    }
}