Skip to content

Commit

Permalink
feat: add replace_with (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
lomirus committed Oct 7, 2023
1 parent a4b0e83 commit 0cdbc53
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
46 changes: 46 additions & 0 deletions src/operation/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub trait Editable {
/// vec![Node::Text("Cancel".to_string())]
/// ))
/// .html();
///
/// assert_eq!(html, r#"<div><span>Ok</span><span>Cancel</span></div>"#)
/// ```
fn insert_to(&mut self, selector: &Selector, target: Node) -> &mut Self;
Expand All @@ -57,6 +58,7 @@ pub trait Editable {
///
/// let selector = Selector::from(".ad");
/// let html = parse(html).unwrap().remove_by(&selector).html();
///
/// assert_eq!(html, r#"
/// <div>
/// <div class="recommend"></div>
Expand All @@ -65,6 +67,32 @@ pub trait Editable {
/// </div>"#)
/// ```
fn remove_by(&mut self, selector: &Selector) -> &mut Self;

/// Replace all elements that matches the `selector` with new nodes.
///
/// ```
/// use html_editor::{parse, Node, operation::*};
///
/// let html = r#"
/// <div>
/// <p>Hello</p>
/// </div>"#;
///
/// let selector = Selector::from("p");
/// let html = parse(html)
/// .unwrap()
/// .replace_with(&selector, |p| {
/// let new_text = format!("{} World!", p.children[0].html());
/// Node::Comment(new_text)
/// })
/// .html();
///
/// assert_eq!(html, r#"
/// <div>
/// <!--Hello World!-->
/// </div>"#)
/// ```
fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self;
}

impl Editable for Vec<Node> {
Expand Down Expand Up @@ -118,6 +146,19 @@ impl Editable for Vec<Node> {
}
self
}

fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self {
for node in self.iter_mut() {
if let Node::Element(ref mut el) = node {
if selector.matches(el) {
*node = f(el);
} else {
el.replace_with(selector, f);
}
}
}
self
}
}

impl Editable for Element {
Expand All @@ -138,4 +179,9 @@ impl Editable for Element {
self.children.remove_by(selector);
self
}

fn replace_with(&mut self, selector: &Selector, f: fn(el: &Element) -> Node) -> &mut Self {
self.children.replace_with(selector, f);
self
}
}
34 changes: 33 additions & 1 deletion tests/edit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use html_editor::operation::*;
use html_editor::{operation::*, Element};
use html_editor::{parse, Node};

const HTML: &str = r#"
Expand All @@ -9,6 +9,7 @@ const HTML: &str = r#"
<title>Document</title>
</head>
<body>
<p>Hello</p>
</body>
</html>"#;

Expand All @@ -20,6 +21,7 @@ const INSERTED_HTML: &str = r#"
<title>Document</title>
</head>
<body>
<p>Hello</p>
<script>console.log("Hello World")</script></body>
</html>"#;

Expand All @@ -31,6 +33,19 @@ const REMOVED_HTML: &str = r#"
<title>Document</title>
</head>
<body>
<p>Hello</p>
</body>
</html>"#;

const REPLACED_HTML: &str = r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>"#;

Expand All @@ -55,3 +70,20 @@ fn remove() {
let html = parse(HTML).unwrap().remove_by(&meta_selector).html();
assert_eq!(html, REMOVED_HTML);
}

#[test]
fn replace() {
let p_selector = Selector::from("p");
let html = parse(HTML)
.unwrap()
.replace_with(&p_selector, |p| {
let new_text = format!("{} World!", p.children[0].html());
Node::Element(Element {
name: "p".to_string(),
attrs: vec![],
children: vec![Node::Text(new_text)],
})
})
.html();
assert_eq!(html, REPLACED_HTML);
}

0 comments on commit 0cdbc53

Please sign in to comment.