2018-02-24 18:14:52 +08:00
|
|
|
//! This program removes all forms of emphasis from the markdown of the book.
|
|
|
|
extern crate mdbook;
|
|
|
|
extern crate pulldown_cmark;
|
|
|
|
extern crate pulldown_cmark_to_cmark;
|
|
|
|
|
|
|
|
use mdbook::book::{Book, BookItem, Chapter};
|
2018-07-24 01:45:01 +08:00
|
|
|
use mdbook::errors::{Error, Result};
|
2018-02-24 18:14:52 +08:00
|
|
|
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
|
2018-07-24 01:45:01 +08:00
|
|
|
use mdbook::MDBook;
|
2018-02-24 18:14:52 +08:00
|
|
|
use pulldown_cmark::{Event, Parser, Tag};
|
|
|
|
use pulldown_cmark_to_cmark::fmt::cmark;
|
|
|
|
|
|
|
|
use std::env::{args, args_os};
|
2018-07-24 01:45:01 +08:00
|
|
|
use std::ffi::OsString;
|
2018-02-24 18:14:52 +08:00
|
|
|
use std::process;
|
|
|
|
|
2018-08-30 21:31:14 +08:00
|
|
|
const NAME: &str = "md-links-to-html-links";
|
|
|
|
|
|
|
|
fn do_it(book: OsString) -> Result<()> {
|
|
|
|
let mut book = MDBook::load(book)?;
|
|
|
|
book.with_preprecessor(Deemphasize);
|
|
|
|
book.build()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
if args_os().count() != 2 {
|
|
|
|
eprintln!("USAGE: {} <book>", args().next().expect("executable"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if let Err(e) = do_it(args_os().skip(1).next().expect("one argument")) {
|
|
|
|
eprintln!("{}", e);
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-24 18:14:52 +08:00
|
|
|
struct Deemphasize;
|
|
|
|
|
|
|
|
impl Preprocessor for Deemphasize {
|
|
|
|
fn name(&self) -> &str {
|
2018-08-30 21:31:14 +08:00
|
|
|
NAME
|
2018-02-24 18:14:52 +08:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:31:14 +08:00
|
|
|
fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
|
2018-02-24 18:14:52 +08:00
|
|
|
eprintln!("Running '{}' preprocessor", self.name());
|
|
|
|
let mut num_removed_items = 0;
|
2018-08-30 21:31:14 +08:00
|
|
|
|
|
|
|
process(&mut book.sections, &mut num_removed_items)?;
|
|
|
|
|
2018-02-24 18:14:52 +08:00
|
|
|
eprintln!(
|
|
|
|
"{}: removed {} events from markdown stream.",
|
|
|
|
self.name(),
|
|
|
|
num_removed_items
|
|
|
|
);
|
2018-08-30 21:31:14 +08:00
|
|
|
|
|
|
|
Ok(book)
|
2018-02-24 18:14:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:31:14 +08:00
|
|
|
fn process<'a, I>(items: I, num_removed_items: &mut usize) -> Result<()>
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = &'a mut BookItem> + 'a,
|
|
|
|
{
|
|
|
|
for item in items {
|
|
|
|
if let BookItem::Chapter(ref mut chapter) = *item {
|
|
|
|
eprintln!("{}: processing chapter '{}'", NAME, chapter.name);
|
2018-02-24 18:14:52 +08:00
|
|
|
|
2018-08-30 21:31:14 +08:00
|
|
|
let md = remove_emphasis(num_removed_items, chapter)?;
|
|
|
|
chapter.content = md;
|
|
|
|
}
|
2018-02-24 18:14:52 +08:00
|
|
|
}
|
2018-08-30 21:31:14 +08:00
|
|
|
|
|
|
|
Ok(())
|
2018-02-24 18:14:52 +08:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:31:14 +08:00
|
|
|
fn remove_emphasis(
|
|
|
|
num_removed_items: &mut usize,
|
|
|
|
chapter: &mut Chapter,
|
|
|
|
) -> Result<String> {
|
|
|
|
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))
|
|
|
|
})
|
2018-02-24 18:14:52 +08:00
|
|
|
}
|