Skip to content

Commit

Permalink
Merge pull request #904 from veryl-lang/mermaid_support
Browse files Browse the repository at this point in the history
Mermaid support for documentation comment
  • Loading branch information
dalance authored Aug 22, 2024
2 parents a06342d + e3524fc commit 529022e
Show file tree
Hide file tree
Showing 19 changed files with 2,372 additions and 202 deletions.
252 changes: 61 additions & 191 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ log = "0.4.22"
mdbook = "0.4.40"
miette = {version = "7.2"}
once_cell = "1.19"
pulldown-cmark = "0.12.0"
regex = "1.10.6"
semver = {version = "1.0", features = ["serde"]}
serde = {version = "1.0", features = ["derive"]}
Expand Down
2 changes: 1 addition & 1 deletion crates/mdbook/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ anyhow = {workspace = true}
clap = {workspace = true}
line-col = "0.2.1"
mdbook = {workspace = true}
pulldown-cmark = "0.12.0"
pulldown-cmark = {workspace = true}
regex = {workspace = true}
semver = {workspace = true}
serde_json = {workspace = true}
Expand Down
2 changes: 1 addition & 1 deletion crates/veryl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ handlebars = "6.0"
log = {workspace = true}
once_cell = {workspace = true}
mdbook = {workspace = true}
mdbook-wavedrom = "0.10.0"
miette = {workspace = true}
pulldown-cmark = {workspace = true}
regex = {workspace = true}
serde = {workspace = true}
serde_json = {workspace = true}
Expand Down
5 changes: 5 additions & 0 deletions crates/veryl/resource/mermaid/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The files in this directory are based on:

https://github.com/mermaid-js/mermaid
Copyright (c) 2014-2022 Knut Sveidqvist
Released under the MIT License
1 change: 1 addition & 0 deletions crates/veryl/resource/mermaid/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10.9.1
2,029 changes: 2,029 additions & 0 deletions crates/veryl/resource/mermaid/mermaid.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/veryl/resource/wavedrom/LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The files in this directory is based on:
The files in this directory are based on:

https://github.com/wavedrom/wavedrom
Copyright (c) 2011-2024 Aliaksei Chapyzhenka
Expand Down
1 change: 1 addition & 0 deletions crates/veryl/resource/wavedrom/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.5.0
2 changes: 1 addition & 1 deletion crates/veryl/src/cmd_doc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::doc_builder::DocBuilder;
use crate::doc::DocBuilder;
use crate::OptDoc;
use log::info;
use miette::{IntoDiagnostic, Result, WrapErr};
Expand Down
7 changes: 7 additions & 0 deletions crates/veryl/src/doc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod doc_builder;
mod mermaid;
mod utils;
mod wavedrom;
pub use doc_builder::*;
pub use mermaid::*;
pub use wavedrom::*;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::doc::{Mermaid, Wavedrom};
use handlebars::Handlebars;
use mdbook::{Config, MDBook};
use mdbook_wavedrom::Wavedrom;
use miette::{IntoDiagnostic, Result};
use serde::Serialize;
use std::collections::{BTreeMap, HashSet};
Expand Down Expand Up @@ -317,13 +317,19 @@ impl DocBuilder {
.unwrap();
cfg.set(
"output.html.additional-js",
vec!["theme/wavedrom.min.js", "theme/wavedrom_skin.js"],
vec![
"theme/wavedrom.min.js",
"theme/wavedrom_skin.js",
"theme/mermaid.min.js",
],
)
.unwrap();

let wavedrom = Wavedrom;
let mermaid = Mermaid;
let mut md = MDBook::load_with_config(&self.root_dir, cfg).unwrap();
md.with_preprocessor(wavedrom);
md.with_preprocessor(mermaid);
md.build().unwrap();
Ok(())
}
Expand Down Expand Up @@ -351,21 +357,26 @@ impl DocBuilder {
let mut file = File::create(file).into_diagnostic()?;
write!(file, "{}", custom_css).into_diagnostic()?;

let favicon = include_bytes!("../resource/favicon.png");
let favicon = include_bytes!("../../resource/favicon.png");
let file = self.theme_dir.join("favicon.png");
let mut file = File::create(file).into_diagnostic()?;
file.write(favicon).into_diagnostic()?;

let wavedrom = include_bytes!("../resource/wavedrom/wavedrom.min.js");
let wavedrom = include_bytes!("../../resource/wavedrom/wavedrom.min.js");
let file = self.theme_dir.join("wavedrom.min.js");
let mut file = File::create(file).into_diagnostic()?;
file.write(wavedrom).into_diagnostic()?;

let wavedrom_skin = include_bytes!("../resource/wavedrom/skins/default.js");
let wavedrom_skin = include_bytes!("../../resource/wavedrom/skins/default.js");
let file = self.theme_dir.join("wavedrom_skin.js");
let mut file = File::create(file).into_diagnostic()?;
file.write(wavedrom_skin).into_diagnostic()?;

let mermaid = include_bytes!("../../resource/mermaid/mermaid.min.js");
let file = self.theme_dir.join("mermaid.min.js");
let mut file = File::create(file).into_diagnostic()?;
file.write(mermaid).into_diagnostic()?;

Ok(())
}

Expand Down
108 changes: 108 additions & 0 deletions crates/veryl/src/doc/mermaid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// This file is based on:
//
// https://github.com/badboy/mdbook-mermaid
// Released under the MPL-2.0 license

use crate::doc::utils::escape_html;
use mdbook::book::{Book, BookItem, Chapter};
use mdbook::errors::Result;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
use pulldown_cmark::{CodeBlockKind::*, Event, Options, Parser, Tag, TagEnd};

pub struct Mermaid;

impl Preprocessor for Mermaid {
fn name(&self) -> &str {
"mermaid"
}

fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
let mut res = 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(())).map(|_| book)
}

fn supports_renderer(&self, renderer: &str) -> bool {
renderer == "html"
}
}

impl Mermaid {
fn add_mermaid(chapter: &mut Chapter) -> Result<String> {
let content = &chapter.content;
let mut mermaid_content = String::new();
let mut in_mermaid_block = false;

let mut opts = Options::empty();
opts.insert(Options::ENABLE_TABLES);
opts.insert(Options::ENABLE_FOOTNOTES);
opts.insert(Options::ENABLE_STRIKETHROUGH);
opts.insert(Options::ENABLE_TASKLISTS);

let mut code_span = 0..0;
let mut start_new_code_span = true;

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() {
if &*code == "mermaid" {
in_mermaid_block = true;
mermaid_content.clear();
}
continue;
}

if !in_mermaid_block {
continue;
}

// We're in the code block. The text is what we want.
// Code blocks can come in multiple text events.

if let Event::Text(_) = e {
if start_new_code_span {
code_span = span;
start_new_code_span = false;
} else {
code_span = code_span.start..span.end;
}

continue;
}

if let Event::End(TagEnd::CodeBlock) = e {
in_mermaid_block = false;

let mermaid_content = &content[code_span.clone()];
let mermaid_content = escape_html(mermaid_content);
let mermaid_content = mermaid_content.replace("\r\n", "\n");
let mermaid_code = format!("<pre class=\"mermaid\">{}</pre>\n\n", mermaid_content);
mermaid_blocks.push((span, mermaid_code));

start_new_code_span = true;
}
}

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)
}
}
13 changes: 13 additions & 0 deletions crates/veryl/src/doc/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub fn escape_html(s: &str) -> String {
let mut output = String::new();
for c in s.chars() {
match c {
'<' => output.push_str("&lt;"),
'>' => output.push_str("&gt;"),
'"' => output.push_str("&quot;"),
'&' => output.push_str("&amp;"),
_ => output.push(c),
}
}
output
}
108 changes: 108 additions & 0 deletions crates/veryl/src/doc/wavedrom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// This file is based on:
//
// https://github.com/JasMoH/mdbook-wavedrom
// Released under the MPL-2.0 license

use crate::doc::utils::escape_html;
use mdbook::book::{Book, BookItem, Chapter};
use mdbook::errors::Result;
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
use pulldown_cmark::{CodeBlockKind::*, Event, Options, Parser, Tag, TagEnd};

pub struct Wavedrom;

impl Preprocessor for Wavedrom {
fn name(&self) -> &str {
"wavedrom"
}

fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result<Book> {
let mut res = None;
book.for_each_mut(|item: &mut BookItem| {
if let Some(Err(_)) = res {
return;
}

if let BookItem::Chapter(ref mut chapter) = *item {
res = Some(Wavedrom::add_wavedrom(chapter).map(|md| {
chapter.content = md;
}));
}
});

res.unwrap_or(Ok(())).map(|_| book)
}

fn supports_renderer(&self, renderer: &str) -> bool {
renderer == "html"
}
}

impl Wavedrom {
fn add_wavedrom(chapter: &mut Chapter) -> Result<String> {
let content = &chapter.content;
let mut wavedrom_content = String::new();
let mut in_wavedrom_block = false;

let mut opts = Options::empty();
opts.insert(Options::ENABLE_TABLES);
opts.insert(Options::ENABLE_FOOTNOTES);
opts.insert(Options::ENABLE_STRIKETHROUGH);
opts.insert(Options::ENABLE_TASKLISTS);

let mut code_span = 0..0;
let mut start_new_code_span = true;

let mut wavedrom_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() {
if &*code == "wavedrom" {
in_wavedrom_block = true;
wavedrom_content.clear();
}
continue;
}

if !in_wavedrom_block {
continue;
}

// We're in the code block. The text is what we want.
// Code blocks can come in multiple text events.

if let Event::Text(_) = e {
if start_new_code_span {
code_span = span;
start_new_code_span = false;
} else {
code_span = code_span.start..span.end;
}

continue;
}

if let Event::End(TagEnd::CodeBlock) = e {
in_wavedrom_block = false;

let wavedrom_content = &content[code_span.clone()];
let wavedrom_content = escape_html(wavedrom_content);
let wavedrom_content = wavedrom_content.replace("\r\n", "\n");
let wavedrom_code = format!("<body onload=\"WaveDrom.ProcessAll()\">\n\n<script type=\"WaveDrom\">{}</script>\n\n", wavedrom_content);
wavedrom_blocks.push((span, wavedrom_code));

start_new_code_span = true;
}
}

let mut content = content.to_string();
for (span, block) in wavedrom_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)
}
}
2 changes: 1 addition & 1 deletion crates/veryl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod cmd_new;
mod cmd_publish;
mod cmd_test;
mod cmd_update;
mod doc_builder;
mod doc;
mod runner;

// ---------------------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion testcases/map/testcases/sv/36_doc_comment.sv.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions testcases/sv/36_doc_comment.sv
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
/// ]}
/// ```
///
/// ```mermaid
/// graph TD;
/// A-->B;
/// A-->C;
/// B-->D;
/// C-->D;
/// ```
///
module veryl_testcase_Module36 #(
/// Data width
parameter int unsigned ParamA = 1,
Expand Down
8 changes: 8 additions & 0 deletions testcases/veryl/36_doc_comment.veryl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
/// ]}
/// ```
///
/// ```mermaid
/// graph TD;
/// A-->B;
/// A-->C;
/// B-->D;
/// C-->D;
/// ```
///
pub module Module36 #(
/// Data width
param ParamA: u32 = 1,
Expand Down

0 comments on commit 529022e

Please sign in to comment.