mersinvald / aquamarine Goto Github PK
View Code? Open in Web Editor NEWInline diagrams for rustdoc with mermaid.js
License: MIT License
Inline diagrams for rustdoc with mermaid.js
License: MIT License
Currently is not possible to have diagrams at the inner doc comments, e.g.:
lib.rs
:
#[cfg_attr(doc, aquamarine::aquamarine)]
//! demo
//!
//! ```mermaid
//! graph LR
//! s([Source]) --> a[[aquamarine]]
//! r[[rustdoc]] --> f([Docs w/ Mermaid!])
//! subgraph rustc[Rust Compiler]
//! a -. inject mermaid.js .-> r
//! end
//! ```
since there can't be anything before the module-level doc-comment block...
Imrprovement:
Currently the Mermaid JS package is downloaded using URLs in Script-tags. These may point to local files or remote web-locations.
Modern browsers prevent loading scripts form local files (CORS), so file based Rust-Docs are not able to render the mermaid diagrams.
Downloading mermaid from remote web-soources may be time consuming, rendering of diagrams may be postponed by multiple seconds.
Instead of refering to external locations the mermaid JS might be embedded as base64 string the following way
<script type="text/javascript" src="data:text/javascript;base64,BASE64_STRING"></script>
The mermaid package v10.2.3 is shipped as single file of byte size 2.9MB. The estimated base64 will increase siize by 30%, around 3.8MB
The aquamarine macro might embed the mermaid JS package.
As the Rust-Docs process is creating an single Html file per Rust "mod", each of these file would require the mermaid code to be embedded.
Sadly, the Rust macro is not "told" the source file and line or mod-depth of the current Span/TokenStream. Therefor it is not possible to tell if a macro has been invoked within this Rust "mod" before. So each macro would perform the same
It might be an idea to define two macros, first one to embed the package into a Rust Doc Html file (per Rust "mod"), second macro might just rendert the diagram.
For example:
#[cfg_attr(doc, aquamarine::aquamarine, embed)]
PROS:
CONS:
Currently it doesn't seem to be possible to configure the theme. E.g.:
/// ```mermaid
/// %%{init: {'theme':'base'}}%%
/// graph LR
/// s([Source]) --> a[[aquamarine]]
/// r[[rustdoc]] --> f([Docs w/ Mermaid!])
/// subgraph rustc[Rust Compiler]
/// a -. inject mermaid.js .-> r
/// end
/// ```
pub fn example() {}
The generated html currently fetches mermaid.min.js
from a cdn on the internet, which is best practice in some contexts but is I think the wrong default in this case : rustdocs can normally be generated and viewed offline. They should also be impervious to API or url changes 10 years down the road, firewalls, etc.
I think that mermaid.min.js
should be saved alongside sidebar-items.js
. Not sure if there's a rustdoc naming convention to adhere to (like "cratename.crateversion.normalname") to avoid conflicts with a similar tool.
I don't see an example of using this as the root crate docs, is this possible?
Deal with multiple JS files instead of single mermaid.min.js
Change script-initialization, using the following ESM form in future
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
...
</script>
or accessing the local files location
To test the port, change the dependency in Cargo.toml to
[dependencies]
aquamarine = { git = "https://github.com/frehberg/aquamarine.git", branch = "35_port_mermaid_v10" }
Mermaid has support for interactions on flow-chart nodes and rustdocs can generate links to items by name. I'd be very helpful to be able to use both of these concepts and allow crate users to add links to nodes in mermaid syntax utilizing rustdocs item linkage syntax.
Something like:
graph TD
Item1["[Shown Text](rustdocs::symbol::path)"]
which would show something like
graph TD
Item1[Shown Text]
but where Shown Text
is also a hyperlink to wherever the rustdocs hyperlink for rustdocs::symbol::path
leads.
This WOULD require specifying securityLevel:'loose'
in the mermaid config.
When I use aquamarine = "0.3.2"
the Mermaid diagram does not render and instead shows this error:
You can also see this on the demo crate when you go to the latest version. The demo crate docs.rs links for versions 0.2.0 up to and including 0.3.0 are broken (build failed), but when testing in my own repo I can say that 0.3.0 is also broken but 0.2.2 works fine.
The generated html document contains primary and secondary source of mermaid.js (see below), but as the mermaid.js is not present in folder target/doc/{CRATENAME}, the secondary remote source is used always.
The doc files should not fetch JS code from remote. To solve the issue the aquamarine macro-processor should copy an embedded mermaid.js into the folder target/doc/{CRATENAME}
<script src="../mermaid.min.js"></script>
<script>window.mermaid || document.write('<script src="https://unpkg.com/[email protected]/dist/mermaid.min.js" crossorigin="anonymous"><\/script>')</script>
Hello,
First of all thanks for the crate, I think it's great!
We're trying to use it to enhance our documentation but we're coming across a silly issue. We can't render anything other than very very basic diagrams.
This works:
#[cfg_attr(doc, aquamarine::aquamarine)]
/// Enum 'Mode' can take values Privileged (supervisor) or Unprivileged (user).
/// ```mermaid
/// classDiagram
/// class Mode
/// ```
pub enum Mode {
Privileged,
Unprivileged,
}
This doesn't work:
#[cfg_attr(doc, aquamarine::aquamarine)]
/// Enum 'Mode' can take values Privileged (supervisor) or Unprivileged (user).
/// ```mermaid
/// classDiagram
/// class Mode {
/// <<enumeration>>
/// Privileged
/// Unprivileged
/// }
/// ```
pub enum Mode {
Privileged,
Unprivileged,
}
When testing on mermaid.live, there seems to be no issue with both diagrams.
I'm sure I'm doing something wrong but I can't seem to find what :) Thanks for the help!
Running with Rust 1.38
jmgd@kronos ~/D/m/r/typestate-rs (main)> cargo +1.38 build
Compiling proc-macro2 v1.0.26
Compiling unicode-xid v0.2.2
Compiling syn v1.0.72
Compiling version_check v0.9.3
Compiling fnv v1.0.7
Compiling strsim v0.10.0
Compiling ident_case v1.0.1
Compiling either v1.6.1
Compiling itertools v0.9.0
Compiling proc-macro-error-attr v1.0.4
Compiling proc-macro-error v1.0.4
Compiling quote v1.0.9
Compiling darling_core v0.13.0
Compiling aquamarine v0.1.9
error: cannot find macro `matches!` in this scope
--> /home/jmgd/.cargo/registry/src/github.com-1ecc6299db9ec823/aquamarine-0.1.9/src/attrs.rs:43:9
|
43 | matches!(self, Attr::DiagramEnd(_))
| ^^^^^^^
error: cannot find macro `matches!` in this scope
--> /home/jmgd/.cargo/registry/src/github.com-1ecc6299db9ec823/aquamarine-0.1.9/src/attrs.rs:168:9
|
168 | matches!(self, Location::InsideDiagram)
| ^^^^^^^
error: cannot find macro `matches!` in this scope
--> /home/jmgd/.cargo/registry/src/github.com-1ecc6299db9ec823/aquamarine-0.1.9/src/attrs.rs:138:28
|
138 | if matches!(attr, Attr::DiagramStart(_)) {
| ^^^^^^^
error: aborting due to 3 previous errors
error: Could not compile `aquamarine`.
warning: build failed, waiting for other jobs to finish...
error: build failed
Re-exporting another crate does not render diagrams with include_mmd!
, see paradigmxyz/reth#4430
Previously I proposed a patch read mermaid using relative path, with alternative folder levels "../", "../../", etc.
Sadly this does not work properly, and the web-page is loading mermaid from remote CDN always.
The solution might be to read the folder hierarchy via
let rootPath= document
.getElementById("rustdoc-vars")
.attributes["data-root-path"]
.value;
And adding a script element using this relative path,
see attached patch.
Since proc-macro-error
is unmaintained/abandoned, and depends on the legacy syn 1
, it's probably a good idea to move away from it.
It seems like the likely successor is manyhow
, though the API differs significantly.
Hey, decided to drop a line
First we created some doc-assets
header.html:
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
after-content:
<script> mermaid.init({ startOnLoad: true, theme: "neutral" }, "pre.language-mermaid > code");</script>
the magic is the pre.language-mermaid
selector. When rustdoc renders a mermaid comment, it renders it in a pre
element with class of .language-mermad
. So all we need to do is init the mermaid library with that selector.
Then we run rustdoc with
#!/usr/bin/env bash
set -eou pipefail
cargo rustdoc --open -- --default-theme=ayu --html-in-header=doc-assets/header.html --html-after-content=doc-assets/after-content.html
And now any comment block with a mermaid comment inside it will render graphs. This works both in item and module comments.
Once doc directives get support for html-in-header and html-after-content, the special build command can go away.
Compiling aquamarine v0.3.1
error: proc macro panicked
--> C:\Users\Kagami\.cargo\registry\src\index.crates.io-6f17d22bba15001f\aquamarine-0.3.1\src\attrs.rs:13:30
|
13 | static MERMAID_JS_DIR: Dir = include_dir!("..\\doc\\js\\");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: message: "..\\doc\\js\\" is not a directory
Lines 12 to 16 in 4282819
I guess the Windows code should also use $CARGO_MANIFEST_DIR
?
Hi, I recently published a crate (matrix-sdk
) that depends on v0.4 of aquamarine
. Shortly after, the only release in the 0.4.x range was yanked. This is resulting in problems for anybody who is trying to use matrix-sdk
.
Why was the crate yanked, and would you consider un-yanking it?
currently, the value of the include_mmd attribute (the path) is just directly:
Line 107 in 6701fdb
though it's unclear what the current path in this context is when invoked via cargo doc
in a workspace.
At the very least the panic should include the current working dir and the path that does not exist.
Aquamarine uses Mermaid v9.1.5.
In this minimal repro we're using some mermaid syntax which only was made available in later versions (correctly renders on Mermaid Live)
Recommended Fix:
Update mermaid version in https://github.com/mersinvald/aquamarine/tree/master/doc/js to latest. https://github.com/mermaid-js/mermaid/releases
I think this is a great project. I was trying to use aquamarine so I could have diagrams for some high-level designs in my crate, and given the potential complexity of this I wanted to write this documentation in its own file and add it to the module like so
#[cfg_attr(doc, aquamarine::aquamarine)]
#[doc = include_str!("../foobar.md")]
I've also tried
#[cfg_attr(doc, aquamarine::aquamarine, doc = include_str!("../foobar.md"))]
I've also tried rearranging the order but it seems not to matter.
However, in both cases what happens is that the file is included, and the mermaid code blocks are rendered as regular code blocks instead of diagrams. I'm a relatively new rustacean with no macro writing experience, is there a way to accomplish this?
When used in in a sub-crate of a larger workspace, when running cargo test
a file is created:
./<sub-crate-dir>/target/doc/mermaid.min.js
instead of expected ./target/doc/mermaid.min.js
for the whole workspace.
Seems to be caused by:
Line 140 in 636675b
Possibly CARGO_TARGET_DIR
should be used instead as per https://doc.rust-lang.org/cargo/reference/environment-variables.html ?
In the GitHub repo description, it says "mermade.js" instead of "mermaid.js"
Hello!
First of all, amazing crate being able to embed diagrams in the documentation is great!
I'm currently building an embedded DSL and part of my functionally is exporting diagrams of several kinds.
Logically, embedding them in the documentation would be the next step and hence I started using aquamarine.
During the process I noticed my diagrams were correct according to the Live Editor, but when rendered they would be missing the decision diamond for example.
This is the current renderization:
#[cfg_attr(doc, ::aquamarine::aquamarine)]
#[doc= "```mermaid"]
#[doc= "stateDiagram-v2"]
#[doc= " [*] --> AccountValidation : start_transaction"]
#[doc= " Error --> [*] : finish"]
#[doc= " Finish --> [*] : finish"]
#[doc= " state C_Valid <<choice>>"]
#[doc= " Valid --> C_Valid: perform_transaction"]
#[doc= " C_Valid --> Error"]
#[doc= " C_Valid --> Finish"]
#[doc= " state C_AccountValidation <<choice>>"]
#[doc= " AccountValidation --> C_AccountValidation: validate_accounts"]
#[doc= " C_AccountValidation --> Error"]
#[doc= " C_AccountValidation --> Valid"]
#[doc= "```"]
const WEIRD: i32 = 0;
I tried upgrading mermaid.js to the newest version and suddenly the diagrams present in main.rs
work.
#[cfg_attr(doc, ::aquamarine::aquamarine)]
#[doc= "```mermaid"]
#[doc= "stateDiagram-v2"]
#[doc= " [*] --> AccountValidation : start_transaction"]
#[doc= " Error --> [*] : finish"]
#[doc= " Finish --> [*] : finish"]
#[doc= " state C_Valid <<choice>>"]
#[doc= " Valid --> C_Valid: perform_transaction"]
#[doc= " C_Valid --> Error"]
#[doc= " C_Valid --> Finish"]
#[doc= " state C_AccountValidation <<choice>>"]
#[doc= " AccountValidation --> C_AccountValidation: validate_accounts"]
#[doc= " C_AccountValidation --> Error"]
#[doc= " C_AccountValidation --> Valid"]
#[doc= "```"]
const LOGIN: &'static str = "login";
But using the current version I get this:
If you're wondering why I am using #[doc="..."]
:
quote!
the docs like this///
and the same thing happenedAny idea what the problem might be? I'd be more than glad to help since this is a valuable feature for my crate but I'd need some guidance.
Comment blocks that utilise Mermaid's code blocks break footnote rendering, e.g.:
#[cfg_attr(doc, aquamarine::aquamarine)]
/// This is a comment.
///
/// This is a diagram[^1]:
/// ```mermaid
/// flowchart LR
/// A --> B
/// ```
///
/// [^1]: This is a footnote.
Found:
Expected (not including rendered diagram):
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.