Skip to content

Instantly share code, notes, and snippets.

@plamentotev
Last active March 4, 2024 06:57
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plamentotev/be495e81abd52dc10e7dd51fbb71dd8c to your computer and use it in GitHub Desktop.
Save plamentotev/be495e81abd52dc10e7dd51fbb71dd8c to your computer and use it in GitHub Desktop.

Hello, Diagrams!

GitHub recently added support for including Mermaid diagrams in Markdown files. The good news is that it works for AsciiDoc files as well. Here is an example:

sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!

The catch? The way it works for AsciiDoc is similar to how it works for Markdown. Here is the source code for the above diagram:

[source,mermaid]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

When a source code block marked with mermaid is encountered, GitHub generates an iframe that takes the raw Mermaid code and turns it into diagram using Mermaid.js. This approach is common workaround for the lack of custom blocks in Makrdown. The correct way to add diagram in AsciiDoc is to use custom diagram block, in this case [mermaid]:

[mermaid]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

Using code block to display Mermaid.js diagrams works only in GitHub and would be displayed as source code by AsciiDoc tools such as Asciidoctor. Using mermaid block works with Asciidoctor, given Asciidoctor Diagram extension is enabled, but not in GitHub. This means that the same file would be displayed differently in GitHub and in HTML file generated by Asciidoctor. This is not an issue if the file is intended to be rendered only in GitHub, e.g. Wiki pages. But what if we want to generate HTML documentation from the AsciiDoc files and in the same time to get the diagrams rendered in GitHub?

Conditional processing

Thanks to @umutsahin for suggesting this approach. Conditional preprocessor directives allow content to be included only if given attribute is set. For example:

ifdef::env-github[]
[source,mermaid]
endif::[]

would add [source,mermaid] if the env-github is set, which is the case when the document is rendered on GitHub. The above could be shortened to ifdef::env-github[[source,mermaid]]. The following code would properly display diagram when the document is rendered both on GitHub and using Asciidoctor.

[mermaid]
ifdef::env-github[[source,mermaid]]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

Custom preprocessor

Another solution is to use custom preprocessor. Here is an example using Asciidoctor Gradle plugin:

asciidoctorj {
    modules {
       diagram.use()
       diagram.version '2.2.1'
    }

    docExtensions {
        preprocessor {
            document, reader ->
            List<String> lines = reader.readLines();
            List<String> newLines = new ArrayList<String>();
            for (String line: lines) {
                if("[source,mermaid]".equals(line)) {
                    line = "[mermaid]"
                }
                newLines.add(line)
            }
            reader.restoreLines(newLines)
        }
    }
}

It would replace [source,mermaid] with [mermaid]. This way the same AsciiDoc file would look the same both in GitHub and in the generated HTML file.

@JoeArauzo
Copy link

Fantastic! Thanks for sharing.

@pmotch
Copy link

pmotch commented Dec 7, 2023

Great suggestion; was just running into the same issue myself. Thanks for taking the time to share this.

@umutsahin
Copy link

I have an alternative solution to this:

ifdef::env-github[]
[source,mermaid]
endif::[]
ifndef::env-github[]
[mermaid]
endif::[]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

@plamentotev
Copy link
Author

I have an alternative solution to this:

ifdef::env-github[]
[source,mermaid]
endif::[]
ifndef::env-github[]
[mermaid]
endif::[]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

Thanks @umutsahin for the suggestion. This is a great way to solve the issue. A lot better than my suggestion. If you don't mind I'll update my gist with it.

@umutsahin
Copy link

I have an alternative solution to this:

ifdef::env-github[]
[source,mermaid]
endif::[]
ifndef::env-github[]
[mermaid]
endif::[]
....
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>Bob: Hello Bob, how are you?
    Bob-->>Alice: Great!
....

Thanks @umutsahin for the suggestion. This is a great way to solve the issue. A lot better than my suggestion. If you don't mind I'll update my gist with it.

Sure @plamentotev, ofc, no issues...

@snowe2010
Copy link

snowe2010 commented Dec 28, 2023

none of these solutions are working for me :/

edit: never mind, the documents wouldn't render because github seems to require text on each arrow, no matter what. I used a non-breaking space to trick it.

@plamentotev
Copy link
Author

none of these solutions are working for me :/

edit: never mind, the documents wouldn't render because github seems to require text on each arrow, no matter what. I used a non-breaking space to trick it.

I'm glad it worked. Out of curiosity - would you give an example of non-working code?

@snowe2010
Copy link

Sure thing. Here's a mermaid.live example, showing that there is no required name after the : https://mermaid.live/edit#pako:eNo1jDEOgzAQBL-CtiYfuAIpET9Ie83JXgISNonxFRHi7zhFthppRnsgbJEQ7Pw4c-C42KtY0ty13W_D8JAOPRJLsiW28PgpRZ2ZqJCGkZP5WhWaz5aa1-35zQFSi7OHv6PV_y9ksnXneQEZIyfE

but when you try to do this in intellij it will strip the space. You can turn that off of course, but even doing so both intellij and github refuse to render it until you add some text. In my case I just used a non-breaking space to trick it.

@plamentotev
Copy link
Author

Sure thing. Here's a mermaid.live example, showing that there is no required name after the : https://mermaid.live/edit#pako:eNo1jDEOgzAQBL-CtiYfuAIpET9Ie83JXgISNonxFRHi7zhFthppRnsgbJEQ7Pw4c-C42KtY0ty13W_D8JAOPRJLsiW28PgpRZ2ZqJCGkZP5WhWaz5aa1-35zQFSi7OHv6PV_y9ksnXneQEZIyfE

but when you try to do this in intellij it will strip the space. You can turn that off of course, but even doing so both intellij and github refuse to render it until you add some text. In my case I just used a non-breaking space to trick it.

I see, thanks for the example. Looks like Mermaid do require message text. The syntax for messages is:

[Actor][Arrow][Actor]:Message text

If Message text is missing(empty string), then Mermaid returns error. It does accept single space as message text, but as you mention some IDEs/editors strip trailing whitespaces. What is more AsciiDoctor normalizes the lines, which also removes the trailing whitespaces. The work around is either to include non-breakable space or to end the line with semicolon:

sequenceDiagram
    A->>B: #nbsp;
    B-->>A: ;

@snowe2010
Copy link

semicolon is a nice way to solve it, thanks. I would think that the mermaid.live site would have the correct functionality, but I guess not.

@LaurinHerbsthofer
Copy link

Very helpful, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment