summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan-Erik Rediger <janerik@fnordig.de>2018-07-19 17:12:16 +0200
committerJan-Erik Rediger <janerik@fnordig.de>2018-07-19 17:12:16 +0200
commit800f3201db70136066189a5b3d9b60d03d87da90 (patch)
treeaa060fbf77704c739032fa932f2b3ab898e8d4a7 /src
init
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs75
-rw-r--r--src/main.rs30
2 files changed, 105 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..326883d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,75 @@
+extern crate mdbook;
+extern crate pulldown_cmark;
+extern crate pulldown_cmark_to_cmark;
+
+use mdbook::errors::{Error, Result};
+use mdbook::book::{Book, BookItem, Chapter};
+use mdbook::preprocess::{Preprocessor, PreprocessorContext};
+use pulldown_cmark::{Event, Parser, Tag};
+use pulldown_cmark_to_cmark::fmt::cmark;
+
+pub struct Mermaid;
+
+impl Preprocessor for Mermaid {
+ fn name(&self) -> &str {
+ "mermaid"
+ }
+
+ fn run(&self, _ctx: &PreprocessorContext, book: &mut Book) -> Result<()> {
+ let mut res: Option<_> = None;
+ book.for_each_mut(|item: &mut BookItem| {
+ if let Some(Err(_)) = res {
+ return;
+ }
+ if let BookItem::Chapter(ref mut chapter) = *item {
+ res = Some(Mermaid::add_mermaid(chapter).map(|md| {
+ chapter.content = md;
+ }));
+ }
+ });
+ res.unwrap_or(Ok(()))
+ }
+}
+
+impl Mermaid {
+ fn add_mermaid(chapter: &mut Chapter) -> Result<String> {
+ let mut buf = String::with_capacity(chapter.content.len());
+ let mut mermaid_content = String::new();
+ let mut in_mermaid_block = false;
+ let events = Parser::new(&chapter.content).map(|e| {
+ if let Event::Start(Tag::CodeBlock(code)) = e.clone() {
+ if code == "mermaid" {
+ in_mermaid_block = true;
+ mermaid_content.clear();
+ return None;
+ } else {
+ return Some(e);
+ }
+ }
+
+ if !in_mermaid_block {
+ return Some(e);
+ }
+
+ match e {
+ Event::End(Tag::CodeBlock(code)) => {
+ assert_eq!("mermaid", code, "After an opening mermaid code block we expect it to close again");
+ in_mermaid_block = false;
+
+ let mermaid_code = format!("<div class=\"mermaid\">{}</div>\n\n", mermaid_content);
+ return Some(Event::Text(mermaid_code.into()));
+ },
+ Event::Text(code) => {
+ mermaid_content.push_str(&code);
+ }
+ _ => return Some(e),
+ }
+
+ None
+ });
+ let events = events.filter_map(|e| e);
+ cmark(events, &mut buf, None)
+ .map(|_| buf)
+ .map_err(|err| Error::from(format!("Markdown serialization failed: {}", err)))
+ }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..9db9e11
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,30 @@
+extern crate env_logger;
+extern crate mdbook;
+extern crate mdbook_mermaid;
+
+use mdbook::MDBook;
+use mdbook::errors::Result;
+use mdbook_mermaid::Mermaid;
+
+use std::ffi::OsString;
+use std::env::{args, args_os};
+use std::process;
+
+fn do_it(book: OsString) -> Result<()> {
+ let mut book = MDBook::load(book)?;
+ book.with_preprecessor(Mermaid);
+ book.build()
+}
+
+fn main() {
+ env_logger::init();
+
+ 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);
+ }
+}