Skip to content

Commit

Permalink
refactor: move execute_for into Editable trait
Browse files Browse the repository at this point in the history
  • Loading branch information
lomirus committed Nov 15, 2023
1 parent 521327a commit c702398
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 69 deletions.
63 changes: 63 additions & 0 deletions src/operation/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,61 @@ pub trait Editable {
/// </div>"#)
/// ```
fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self;

/// Executes a given function for the node in `self` for the given selector.
///
/// ```
/// use html_editor::{parse, Element, Node};
/// use html_editor::operation::*;
///
/// let html = r#"
/// <!DOCTYPE html>
/// <html lang="en">
/// <head>
/// <meta charset="UTF-8">
/// <title>App</title>
/// </head>
/// <body>
/// <input type="text" />
/// <input type="text" />
/// <input type="text" />
/// </body>
/// </html>"#;
///
/// // Add a class to all the input elements
/// let selector: Selector = Selector::from("input");
/// let mut doc: Vec<Node> = parse(html).unwrap();
/// doc.execute_for(&selector, |elem| {
/// elem.attrs.push(("class".to_string(), "input".to_string()));
/// });
/// ```
fn execute_for(&mut self, selector: &Selector, f: impl FnMut(&mut Element));
}

// We meed this function to allow the trait interface to use `impl FnMut(&mut Element)` instead of `&mut impl FnMut(&mut Element)`
fn nodes_execute_for_internal(
nodes: &mut Vec<Node>,
selector: &Selector,
f: &mut impl FnMut(&mut Element),
) {
for node in nodes {
if let Some(element) = node.as_element_mut() {
// Recursively traverse the descendants nodes
element_execute_for_internal(element, selector, f);
}
}
}

// We meed this function to allow the trait interface to use `impl FnMut(&mut Element)` instead of `&mut impl FnMut(&mut Element)`
fn element_execute_for_internal(
element: &mut Element,
selector: &Selector,
f: &mut impl FnMut(&mut Element),
) {
if selector.matches(element) {
f(element);
}
nodes_execute_for_internal(&mut element.children, selector, f);
}

impl Editable for Vec<Node> {
Expand Down Expand Up @@ -159,6 +214,10 @@ impl Editable for Vec<Node> {
}
self
}

fn execute_for(&mut self, selector: &Selector, mut f: impl FnMut(&mut Element)) {
nodes_execute_for_internal(self, selector, &mut f);
}
}

impl Editable for Element {
Expand All @@ -184,4 +243,8 @@ impl Editable for Element {
self.children.replace_with(selector, f);
self
}

fn execute_for(&mut self, selector: &Selector, mut f: impl FnMut(&mut Element)) {
element_execute_for_internal(self, selector, &mut f);
}
}
69 changes: 0 additions & 69 deletions src/operation/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,61 +73,6 @@ pub trait Queryable {
/// let app: &mut Element = parse(html).unwrap().query_mut(&selector).unwrap();
/// ```
fn query_mut(&mut self, selector: &Selector) -> Option<&mut Element>;

/// Executes a given function for the node in `self` for the given selector.
///
/// ```
/// use html_editor::{parse, Element, Node};
/// use html_editor::operation::*;
///
/// let html = r#"
/// <!DOCTYPE html>
/// <html lang="en">
/// <head>
/// <meta charset="UTF-8">
/// <title>App</title>
/// </head>
/// <body>
/// <input type="text" />
/// <input type="text" />
/// <input type="text" />
/// </body>
/// </html>"#;
///
/// // Add a class to all the input elements
/// let selector: Selector = Selector::from("input");
/// let mut doc: Vec<Node> = parse(html).unwrap();
/// doc.execute_for(&selector, |elem| {
/// elem.attrs.push(("class".to_string(), "input".to_string()));
/// });
/// ```
fn execute_for(&mut self, selector: &Selector, f: impl FnMut(&mut Element));
}

// We meed this function to allow the trait interface to use `impl FnMut(&mut Element)` instead of `&mut impl FnMut(&mut Element)`
fn nodes_execute_for_internal(
nodes: &mut Vec<Node>,
selector: &Selector,
f: &mut impl FnMut(&mut Element),
) {
for node in nodes {
if let Some(element) = node.as_element_mut() {
// Recursively traverse the descendants nodes
element_execute_for_internal(element, selector, f);
}
}
}

// We meed this function to allow the trait interface to use `impl FnMut(&mut Element)` instead of `&mut impl FnMut(&mut Element)`
fn element_execute_for_internal(
element: &mut Element,
selector: &Selector,
f: &mut impl FnMut(&mut Element),
) {
if selector.matches(element) {
f(element);
}
nodes_execute_for_internal(&mut element.children, selector, f);
}

impl Queryable for Vec<Node> {
Expand Down Expand Up @@ -164,10 +109,6 @@ impl Queryable for Vec<Node> {
}
None
}

fn execute_for(&mut self, selector: &Selector, mut f: impl FnMut(&mut Element)) {
nodes_execute_for_internal(self, selector, &mut f);
}
}

impl Queryable for Element {
Expand All @@ -194,10 +135,6 @@ impl Queryable for Element {
self.children.query_mut(selector)
}
}

fn execute_for(&mut self, selector: &Selector, mut f: impl FnMut(&mut Element)) {
element_execute_for_internal(self, selector, &mut f);
}
}

impl Queryable for Node {
Expand All @@ -224,10 +161,4 @@ impl Queryable for Node {
None
}
}

fn execute_for(&mut self, selector: &Selector, f: impl FnMut(&mut Element)) {
if let Some(element) = self.as_element_mut() {
element.execute_for(selector, f);
}
}
}

0 comments on commit c702398

Please sign in to comment.