From 9e3d533acc3bf2b80e8127062aa548d54ecf21fd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 2 Nov 2024 15:41:55 -0700 Subject: [PATCH] Add a real example of remove-emphasis --- Cargo.lock | 37 ++++++++- Cargo.toml | 9 ++ examples/remove-emphasis/.gitignore | 1 + examples/remove-emphasis/book.toml | 5 ++ .../mdbook-remove-emphasis/Cargo.toml | 10 +++ .../mdbook-remove-emphasis/src/main.rs | 82 +++++++++++++++++++ examples/remove-emphasis/src/SUMMARY.md | 3 + examples/remove-emphasis/src/chapter_1.md | 3 + examples/remove-emphasis/test.rs | 13 +++ guide/src/for_developers/preprocessors.md | 30 +------ 10 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 examples/remove-emphasis/.gitignore create mode 100644 examples/remove-emphasis/book.toml create mode 100644 examples/remove-emphasis/mdbook-remove-emphasis/Cargo.toml create mode 100644 examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs create mode 100644 examples/remove-emphasis/src/SUMMARY.md create mode 100644 examples/remove-emphasis/src/chapter_1.md create mode 100644 examples/remove-emphasis/test.rs diff --git a/Cargo.lock b/Cargo.lock index 2403de347c..ee69a6c499 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -999,7 +999,7 @@ dependencies = [ "pathdiff", "predicates", "pretty_assertions", - "pulldown-cmark", + "pulldown-cmark 0.10.3", "regex", "select", "semver", @@ -1014,6 +1014,16 @@ dependencies = [ "warp", ] +[[package]] +name = "mdbook-remove-emphasis" +version = "0.1.0" +dependencies = [ + "mdbook", + "pulldown-cmark 0.12.2", + "pulldown-cmark-to-cmark", + "serde_json", +] + [[package]] name = "memchr" version = "2.7.2" @@ -1421,12 +1431,32 @@ dependencies = [ "unicase", ] +[[package]] +name = "pulldown-cmark" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" +dependencies = [ + "bitflags 2.5.0", + "memchr", + "unicase", +] + [[package]] name = "pulldown-cmark-escape" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" +[[package]] +name = "pulldown-cmark-to-cmark" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e02b63adcb49f2eb675b1694b413b3e9fedbf549dfe2cc98727ad97a0c30650" +dependencies = [ + "pulldown-cmark 0.12.2", +] + [[package]] name = "quote" version = "1.0.36" @@ -1598,11 +1628,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index b1e681dd91..be75c90f34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,6 @@ +[workspace] +members = [".", "examples/remove-emphasis/mdbook-remove-emphasis"] + [package] name = "mdbook" version = "0.4.40" @@ -73,3 +76,9 @@ name = "mdbook" [[example]] name = "nop-preprocessor" test = true + +[[example]] +name = "remove-emphasis" +path = "examples/remove-emphasis/test.rs" +crate-type = ["lib"] +test = true diff --git a/examples/remove-emphasis/.gitignore b/examples/remove-emphasis/.gitignore new file mode 100644 index 0000000000..7585238efe --- /dev/null +++ b/examples/remove-emphasis/.gitignore @@ -0,0 +1 @@ +book diff --git a/examples/remove-emphasis/book.toml b/examples/remove-emphasis/book.toml new file mode 100644 index 0000000000..0e2540007a --- /dev/null +++ b/examples/remove-emphasis/book.toml @@ -0,0 +1,5 @@ +[book] +title = "remove-emphasis" + +[preprocessor.remove-emphasis] +command = "cargo run --manifest-path=mdbook-remove-emphasis/Cargo.toml --locked" diff --git a/examples/remove-emphasis/mdbook-remove-emphasis/Cargo.toml b/examples/remove-emphasis/mdbook-remove-emphasis/Cargo.toml new file mode 100644 index 0000000000..7571b18dad --- /dev/null +++ b/examples/remove-emphasis/mdbook-remove-emphasis/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "mdbook-remove-emphasis" +version = "0.1.0" +edition = "2021" + +[dependencies] +mdbook = { version = "0.4.40", path = "../../.." } +pulldown-cmark = { version = "0.12.2", default-features = false } +pulldown-cmark-to-cmark = "18.0.0" +serde_json = "1.0.132" diff --git a/examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs b/examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs new file mode 100644 index 0000000000..79f5f009f1 --- /dev/null +++ b/examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs @@ -0,0 +1,82 @@ +//! This is a demonstration of an mdBook preprocessor which parses markdown +//! and removes any instances of emphasis. + +use mdbook::book::{Book, Chapter}; +use mdbook::errors::Error; +use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext}; +use mdbook::BookItem; +use pulldown_cmark::{Event, Parser, Tag, TagEnd}; +use std::io; + +fn main() { + let mut args = std::env::args().skip(1); + match args.next().as_deref() { + Some("supports") => { + // Supports all renderers. + return; + } + Some(arg) => { + eprintln!("unknown argument: {arg}"); + std::process::exit(1); + } + None => {} + } + + if let Err(e) = handle_preprocessing() { + eprintln!("{}", e); + std::process::exit(1); + } +} + +struct RemoveEmphasis; + +impl Preprocessor for RemoveEmphasis { + fn name(&self) -> &str { + "remove-emphasis" + } + + fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result { + let mut total = 0; + book.for_each_mut(|item| { + let BookItem::Chapter(ch) = item else { + return; + }; + if ch.is_draft_chapter() { + return; + } + match remove_emphasis(&mut total, ch) { + Ok(s) => ch.content = s, + Err(e) => eprintln!("failed to process chapter: {e:?}"), + } + }); + eprintln!("removed {total} emphasis"); + Ok(book) + } +} + +// ANCHOR: remove_emphasis +fn remove_emphasis(num_removed_items: &mut usize, chapter: &mut Chapter) -> Result { + let mut buf = String::with_capacity(chapter.content.len()); + + let events = Parser::new(&chapter.content).filter(|e| match e { + Event::Start(Tag::Emphasis) | Event::Start(Tag::Strong) => { + *num_removed_items += 1; + false + } + Event::End(TagEnd::Emphasis) | Event::End(TagEnd::Strong) => false, + _ => true, + }); + + Ok(pulldown_cmark_to_cmark::cmark(events, &mut buf).map(|_| buf)?) +} +// ANCHOR_END: remove_emphasis + +pub fn handle_preprocessing() -> Result<(), Error> { + let pre = RemoveEmphasis; + let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?; + + let processed_book = pre.run(&ctx, book)?; + serde_json::to_writer(io::stdout(), &processed_book)?; + + Ok(()) +} diff --git a/examples/remove-emphasis/src/SUMMARY.md b/examples/remove-emphasis/src/SUMMARY.md new file mode 100644 index 0000000000..7390c82896 --- /dev/null +++ b/examples/remove-emphasis/src/SUMMARY.md @@ -0,0 +1,3 @@ +# Summary + +- [Chapter 1](./chapter_1.md) diff --git a/examples/remove-emphasis/src/chapter_1.md b/examples/remove-emphasis/src/chapter_1.md new file mode 100644 index 0000000000..5cb79dddeb --- /dev/null +++ b/examples/remove-emphasis/src/chapter_1.md @@ -0,0 +1,3 @@ +# Chapter 1 + +This has *light emphasis* and **bold emphasis**. diff --git a/examples/remove-emphasis/test.rs b/examples/remove-emphasis/test.rs new file mode 100644 index 0000000000..9b614163bb --- /dev/null +++ b/examples/remove-emphasis/test.rs @@ -0,0 +1,13 @@ +use mdbook::MDBook; + +#[test] +fn remove_emphasis_works() { + // Tests that the remove-emphasis example works as expected. + + // Workaround for https://github.com/rust-lang/mdBook/issues/1424 + std::env::set_current_dir("examples/remove-emphasis").unwrap(); + let book = MDBook::load(".").unwrap(); + book.build().unwrap(); + let ch1 = std::fs::read_to_string("book/chapter_1.html").unwrap(); + assert!(ch1.contains("This has light emphasis and bold emphasis.")); +} diff --git a/guide/src/for_developers/preprocessors.md b/guide/src/for_developers/preprocessors.md index 1ac462561a..1455aceb7a 100644 --- a/guide/src/for_developers/preprocessors.md +++ b/guide/src/for_developers/preprocessors.md @@ -68,33 +68,10 @@ The following code block shows how to remove all emphasis from markdown, without accidentally breaking the document. ```rust -fn remove_emphasis( - num_removed_items: &mut usize, - chapter: &mut Chapter, -) -> Result { - let mut buf = String::with_capacity(chapter.content.len()); - - let events = Parser::new(&chapter.content).filter(|e| { - let should_keep = match *e { - Event::Start(Tag::Emphasis) - | Event::Start(Tag::Strong) - | Event::End(Tag::Emphasis) - | Event::End(Tag::Strong) => false, - _ => true, - }; - if !should_keep { - *num_removed_items += 1; - } - should_keep - }); - - cmark(events, &mut buf, None).map(|_| buf).map_err(|err| { - Error::from(format!("Markdown serialization failed: {}", err)) - }) -} +{{#rustdoc_include ../../../examples/remove-emphasis/mdbook-remove-emphasis/src/main.rs:remove_emphasis}} ``` -For everything else, have a look [at the complete example][example]. +Take a look at the [full example source][emphasis-example] for more details. ## Implementing a preprocessor with a different language @@ -122,11 +99,10 @@ if __name__ == '__main__': ``` - +[emphasis-example]: https://github.com/rust-lang/mdBook/tree/master/examples/remove-emphasis/ [preprocessor-docs]: https://docs.rs/mdbook/latest/mdbook/preprocess/trait.Preprocessor.html [pc]: https://crates.io/crates/pulldown-cmark [pctc]: https://crates.io/crates/pulldown-cmark-to-cmark -[example]: https://github.com/rust-lang/mdBook/blob/master/examples/nop-preprocessor.rs [an example no-op preprocessor]: https://github.com/rust-lang/mdBook/blob/master/examples/nop-preprocessor.rs [`CmdPreprocessor::parse_input()`]: https://docs.rs/mdbook/latest/mdbook/preprocess/trait.Preprocessor.html#method.parse_input [`Book::for_each_mut()`]: https://docs.rs/mdbook/latest/mdbook/book/struct.Book.html#method.for_each_mut