summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml1
-rw-r--r--src/bin/mdbook-mermaid.rs2
-rw-r--r--src/lib.rs97
4 files changed, 53 insertions, 57 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 043ecb4..3edef42 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -894,7 +894,6 @@ dependencies = [
"mdbook",
"pretty_assertions",
"pulldown-cmark",
- "pulldown-cmark-to-cmark",
"serde_json",
"tempfile",
"toml_edit",
@@ -1308,15 +1307,6 @@ dependencies = [
]
[[package]]
-name = "pulldown-cmark-to-cmark"
-version = "9.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f94dc756ef5c50ad28ccea8428ba5de9f4dca1fff6516a26b85e0b125a70d17"
-dependencies = [
- "pulldown-cmark",
-]
-
-[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 22bbeea..8329a0e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,6 @@ log = "0.4.11"
clap = "2.33.3"
serde_json = "1.0.57"
toml_edit = "0.13.0"
-pulldown-cmark-to-cmark = "9.0.0"
[dev-dependencies]
assert_cmd = "2.0.0"
diff --git a/src/bin/mdbook-mermaid.rs b/src/bin/mdbook-mermaid.rs
index 085bfbb..dec9657 100644
--- a/src/bin/mdbook-mermaid.rs
+++ b/src/bin/mdbook-mermaid.rs
@@ -73,7 +73,7 @@ fn handle_preprocessing() -> Result<(), Error> {
fn handle_supports(sub_args: &ArgMatches) -> ! {
let renderer = sub_args.value_of("renderer").expect("Required argument");
- let supported = Mermaid.supports_renderer(&renderer);
+ let supported = Mermaid.supports_renderer(renderer);
// Signal whether the renderer is supported by exiting with 1 or 0.
if supported {
diff --git a/src/lib.rs b/src/lib.rs
index c128a11..dff9c4e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,7 @@
use mdbook::book::{Book, BookItem, Chapter};
-use mdbook::errors::{Error, Result};
+use mdbook::errors::Result;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
use pulldown_cmark::{CodeBlockKind::*, Event, Options, Parser, Tag};
-use pulldown_cmark_to_cmark::{cmark_with_options, Options as COptions};
pub struct Mermaid;
@@ -48,7 +47,6 @@ fn escape_html(s: &str) -> String {
}
fn add_mermaid(content: &str) -> Result<String> {
- let mut buf = String::with_capacity(content.len());
let mut mermaid_content = String::new();
let mut in_mermaid_block = false;
@@ -58,49 +56,49 @@ fn add_mermaid(content: &str) -> Result<String> {
opts.insert(Options::ENABLE_STRIKETHROUGH);
opts.insert(Options::ENABLE_TASKLISTS);
- let events = Parser::new_ext(content, opts).map(|e| {
+ let mut mermaid_start = 0..0;
+
+ let mut mermaid_blocks = vec![];
+
+ let events = Parser::new_ext(content, opts);
+ for (e, span) in events.into_offset_iter() {
if let Event::Start(Tag::CodeBlock(Fenced(code))) = e.clone() {
+ log::debug!("e={:?}, span={:?}", e, span);
if &*code == "mermaid" {
+ mermaid_start = span;
in_mermaid_block = true;
mermaid_content.clear();
- return None;
- } else {
- return Some(e);
}
+ continue;
}
if !in_mermaid_block {
- return Some(e);
+ continue;
}
- match e {
- Event::End(Tag::CodeBlock(Fenced(code))) => {
- assert_eq!(
- "mermaid", &*code,
- "After an opening mermaid code block we expect it to close again"
- );
- in_mermaid_block = false;
-
- let mermaid_content = escape_html(&mermaid_content);
- let mermaid_code = format!("<pre class=\"mermaid\">{}</pre>\n\n", mermaid_content);
- return Some(Event::Html(mermaid_code.into()));
- }
- Event::Text(code) => {
- mermaid_content.push_str(&code);
- }
- _ => return Some(e),
+ if let Event::End(Tag::CodeBlock(Fenced(code))) = e {
+ assert_eq!(
+ "mermaid", &*code,
+ "After an opening mermaid code block we expect it to close again"
+ );
+ in_mermaid_block = false;
+ let pre = "```mermaid\n";
+ let post = "```";
+
+ let mermaid_content = &content[mermaid_start.start + pre.len()..span.end - post.len()];
+ let mermaid_content = escape_html(mermaid_content);
+ let mermaid_code = format!("<pre class=\"mermaid\">{}</pre>\n\n", mermaid_content);
+ mermaid_blocks.push((mermaid_start.start..span.end, mermaid_code.clone()));
}
+ }
- None
- });
- let events = events.flatten();
- let opts = COptions {
- newlines_after_codeblock: 1,
- ..Default::default()
- };
- cmark_with_options(events, &mut buf, None, opts)
- .map(|_| buf)
- .map_err(|err| Error::msg(format!("Markdown serialization failed: {}", err)))
+ let mut content = content.to_string();
+ for (span, block) in mermaid_blocks.iter().rev() {
+ let pre_content = &content[0..span.start];
+ let post_content = &content[span.end..];
+ content = format!("{}\n{}{}", pre_content, block, post_content);
+ }
+ Ok(content)
}
impl Mermaid {
@@ -129,12 +127,15 @@ Text
let expected = r#"# Chapter
+
<pre class="mermaid">graph TD
A --&gt; B
</pre>
-Text"#;
+
+Text
+"#;
assert_eq!(expected, add_mermaid(content).unwrap());
}
@@ -151,12 +152,12 @@ Text"#;
| Row 1 | Row 2 |
"#;
- // Markdown roundtripping removes some insignificant whitespace
let expected = r#"# Heading
-|Head 1|Head 2|
-|------|------|
-|Row 1|Row 2|"#;
+| Head 1 | Head 2 |
+|--------|--------|
+| Row 1 | Row 2 |
+"#;
assert_eq!(expected, add_mermaid(content).unwrap());
}
@@ -175,7 +176,6 @@ Text"#;
</del>
"#;
- // Markdown roundtripping removes some insignificant whitespace
let expected = r#"# Heading
<del>
@@ -202,20 +202,21 @@ Text"#;
2. paragraph 2
"#;
- // Markdown roundtripping removes some insignificant whitespace
let expected = r#"# Heading
1. paragraph 1
- ````
+ ```
code 1
- ````
-1. paragraph 2"#;
+ ```
+2. paragraph 2
+"#;
assert_eq!(expected, add_mermaid(content).unwrap());
}
#[test]
fn escape_in_mermaid_block() {
+ env_logger::init();
let content = r#"
```mermaid
classDiagram
@@ -225,15 +226,21 @@ classDiagram
}
```
+hello
"#;
- let expected = r#"<pre class="mermaid">classDiagram
+ let expected = r#"
+
+<pre class="mermaid">classDiagram
class PingUploader {
&lt;&lt;interface&gt;&gt;
+Upload() UploadResult
}
</pre>
+
+
+hello
"#;
assert_eq!(expected, add_mermaid(content).unwrap());