aquamarine/lib.rs
1//! Aquamarine is a procedural macro extension for [rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html),
2//! that aims to improve the visual component of Rust documentation through use of the [mermaid.js](https://mermaid-js.github.io/mermaid/#/) diagrams.
3//!
4//! `#[aquamarine]` macro works through embedding the [mermaid.js](https://github.com/mermaid-js/mermaid) into the generated rustdoc HTML page, modifying the doc comment attributes.
5//!
6//! To inline a diagram into the documentation, use the `mermaid` snippet in a doc-string:
7//!
8//! ```rust
9//! # use aquamarine::aquamarine;
10//! #[cfg_attr(doc, aquamarine)]
11//! /// ```mermaid
12//! /// graph LR
13//! /// s([Source]) --> a[[aquamarine]]
14//! /// r[[rustdoc]] --> f([Docs w/ Mermaid!])
15//! /// subgraph rustc[Rust Compiler]
16//! /// a -. inject mermaid.js .-> r
17//! /// end
18//! /// ```
19//! pub fn example() {}
20//! ```
21//! The diagram will appear in place of the `mermaid` code block, preserving all the comments around it.
22//!
23//! You can even add multiple diagrams!
24//!
25//! To see it in action, go to the [demo crate](https://docs.rs/aquamarine-demo-crate/0.5.0/aquamarine_demo_crate/fn.example.html) docs.rs page.
26//!
27//! ### Dark-mode
28//!
29//! Aquamarine will automatically select the `dark` theme as a default, if the current `rustdoc` theme is either `ayu` or `dark`.
30//!
31//! You might need to reload the page to redraw the diagrams after changing the theme.
32//!
33//! ### Custom themes
34//!
35//! Theming is supported on per-diagram basis, through the mermaid's `%%init%%` attribute.
36//!
37//! *Note*: custom theme will override the default theme
38//!
39//! ```no_run
40//! /// ```mermaid
41//! /// %%{init: {
42//! /// 'theme': 'base',
43//! /// 'themeVariables': {
44//! /// 'primaryColor': '#ffcccc',
45//! /// 'edgeLabelBackground':'#ccccff',
46//! /// 'tertiaryColor': '#fff0f0' }}}%%
47//! /// graph TD
48//! /// A(Diagram needs to be drawn) --> B{Does it have 'init' annotation?}
49//! /// B -->|No| C(Apply default theme)
50//! /// B -->|Yes| D(Apply customized theme)
51//! /// ```
52//! # fn example() {}
53//! ```
54//! [Demo on docs.rs](https://docs.rs/aquamarine-demo-crate/0.5.0/aquamarine_demo_crate/fn.example_with_styling.html)
55//!
56//! To learn more, see the [Theming Section](https://mermaid-js.github.io/mermaid/#/theming) of the mermaid.js book
57//!
58//! ### Loading from a file
59//!
60//! When describing complex logic, a diagram can get quite big.
61//!
62//! To reduce clutter in your doc comments, you can load a diagram from file using the `include_mmd!` macro-like syntax.
63//!
64//! ```no_run
65//! /// Diagram #1
66//! /// include_mmd!("diagram_1.mmd")
67//! ///
68//! /// Diagram #2
69//! /// include_mmd!("diagram_2.mmd")
70//! # fn example() {}
71//! ```
72//! [Demo on docs.rs](https://docs.rs/aquamarine-demo-crate/0.5.0/aquamarine_demo_crate/fn.example_load_from_file.html)
73
74extern crate proc_macro;
75
76use proc_macro::TokenStream;
77use proc_macro_error::{abort, proc_macro_error};
78
79use quote::quote;
80use syn::{parse_macro_input, Attribute};
81
82mod attrs;
83mod parse;
84
85/// Aquamarine is a proc-macro that adds [Mermaid](https://mermaid-js.github.io/mermaid/#/) diagrams to rustdoc
86///
87/// To inline a diagram into the documentation, use the `mermaid` snippet:
88///
89/// ```rust
90/// # use aquamarine::aquamarine;
91/// #[aquamarine]
92/// /// ```mermaid
93/// /// --- here goes your mermaid diagram ---
94/// /// ```
95/// struct Foo;
96/// ```
97#[proc_macro_attribute]
98#[proc_macro_error]
99pub fn aquamarine(_args: TokenStream, input: TokenStream) -> TokenStream {
100 let input = parse_macro_input!(input as parse::Input);
101
102 check_input_attrs(&input.attrs);
103
104 let attrs = attrs::Attrs::from(input.attrs);
105 let forward = input.rest;
106
107 let tokens = quote! {
108 #attrs
109 #forward
110 };
111
112 tokens.into()
113}
114
115fn check_input_attrs(input: &[Attribute]) {
116 for attr in input {
117 if attr.path().is_ident("aquamarine") {
118 abort!(
119 attr,
120 "multiple `aquamarine` attributes on one entity are illegal"
121 );
122 }
123 }
124}