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)
}
}