diff --git a/README.md b/README.md index 9a38ce09..313eac90 100644 --- a/README.md +++ b/README.md @@ -162,45 +162,38 @@ Or you can parse the input into an AST yourself, manipulate it, and then use you ``` rust extern crate comrak; -use comrak::{parse_document, format_html, Arena, Options}; -use comrak::nodes::{AstNode, NodeValue}; - -// The returned nodes are created in the supplied Arena, and are bound by its lifetime. -let arena = Arena::new(); - -let root = parse_document( - &arena, - "This is my input.\n\n1. Also my input.\n2. Certainly my input.\n", - &Options::default()); - -fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F) - where F : Fn(&'a AstNode<'a>) { - f(node); - for c in node.children() { - iter_nodes(c, f); - } -} +use comrak::nodes::NodeValue; +use comrak::{format_html, parse_document, Arena, Options}; + +fn replace_text(document: &str, orig_string: &str, replacement: &str) -> String { + // The returned nodes are created in the supplied Arena, and are bound by its lifetime. + let arena = Arena::new(); -iter_nodes(root, &|node| { - match &mut node.data.borrow_mut().value { - &mut NodeValue::Text(ref mut text) => { - let orig = std::mem::replace(text, vec![]); - *text = String::from_utf8(orig).unwrap().replace("my", "your").as_bytes().to_vec(); + // Parse the document into a root `AstNode` + let root = parse_document(&arena, document, &Options::default()); + + // Iterate over all the descendants of root. + for node in root.descendants() { + if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value { + // If the node is a text node, perform the string replacement. + *text = text.replace(orig_string, replacement) } - _ => (), } -}); - -let mut html = vec![]; -format_html(root, &Options::default(), &mut html).unwrap(); - -assert_eq!( - String::from_utf8(html).unwrap(), - "

This is your input.

\n\ -
    \n\ -
  1. Also your input.
  2. \n\ -
  3. Certainly your input.
  4. \n\ -
\n"); + + let mut html = vec![]; + format_html(root, &Options::default(), &mut html).unwrap(); + + String::from_utf8(html).unwrap() +} + +fn main() { + let doc = "This is my input.\n\n1. Also [my](#) input.\n2. Certainly *my* input.\n"; + let orig = "my"; + let repl = "your"; + let html = replace_text(&doc, &orig, &repl); + + println!("{}", html); +} ``` ## Benchmarking diff --git a/examples/iterator_replace.rs b/examples/iterator_replace.rs new file mode 100644 index 00000000..3fbef1fc --- /dev/null +++ b/examples/iterator_replace.rs @@ -0,0 +1,52 @@ +extern crate comrak; +use comrak::nodes::NodeValue; +use comrak::{format_html, parse_document, Arena, Options}; +use ntest::{assert_false, assert_true}; + +fn replace_text(document: &str, orig_string: &str, replacement: &str) -> String { + // The returned nodes are created in the supplied Arena, and are bound by its lifetime. + let arena = Arena::new(); + + // Parse the document into a root `AstNode` + let root = parse_document(&arena, document, &Options::default()); + + // Iterate over all the descendants of root. + for node in root.descendants() { + if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value { + // If the node is a text node, replace `orig_string` with `replacement`. + *text = text.replace(orig_string, replacement) + } + } + + let mut html = vec![]; + format_html(root, &Options::default(), &mut html).unwrap(); + + String::from_utf8(html).unwrap() +} + +fn main() { + let doc = "This is my input.\n\n1. Also [my](#) input.\n2. Certainly *my* input.\n"; + let orig = "my"; + let repl = "your"; + let html = replace_text(&doc, &orig, &repl); + + println!("{}", html); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sample_replace() { + let doc = "Replace deeply nested *[foo](https://example.com)* with bar.\n\nReplace shallow foo with bar."; + let orig = "foo"; + let repl = "bar"; + let html = replace_text(&doc, &orig, &repl); + println!("{:?}", html); + assert_false!(html.contains("foo")); + assert_true!(html.contains("bar")); + assert_true!(html.contains("