Examples

This page shows the different ways diagrams can be rendered. Most content for the examples is taken from Kroki's website, or the individual diagramming tools websites as linked from the docstring of various string literals.

String literals

The most straightforward way to create diagrams is to rely on the string literals for each of the available diagram types. The package needs to be updated to add string literals whenever the Kroki service adds a new diagramming tool. In case a string literal is not available, it will be necessary to resort to using the Diagram type directly.

ditaa"""
      +--------+
      |        |
      | Julia  |
      |        |
      +--------+
          ^
  request |
          v
  +-------------+
  |             |
  |    Kroki    |
  |             |---+
  +-------------+   |
       ^  ^         | inflate
       |  |         |
       v  +---------+
  +-------------+
  |             |
  |    Ditaa    |
  |             |----+
  +-------------+    |
             ^       | process
             |       |
             +-------+
"""
blockdiag"""
blockdiag {
  Kroki -> generates -> "Block diagrams";
  Kroki -> is -> "very easy!";

  Kroki [color = "greenyellow"];
  "Block diagrams" [color = "pink"];
  "very easy!" [color = "orange"];
}
"""
svgbob"""
        ▲
    Uin ┊   .------------------------
        ┊   |
        ┊   |
        *---'┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄▶
"""
String Interpolation

String interpolation for string literals is not readily supported by Julia, requiring custom logic by the package providing them. Kroki.jl's string literals support string interpolation. Please file an issue when encountering unexpected behavior.

alice = "Kroki"
bob = "Julia"

plantuml"""
$alice -> $bob: I'm here to help.
$bob -> $alice: With what?
$alice -> $bob: Rendering diagrams!
"""

The Diagram type

String literals are effectively short-hands for instantiating a Diagram for a specific type of diagram. In certain cases, it may be more straightforward, or even necessary, to directly instantiate a Diagram. For instance, when a type of diagram is supported by the Kroki service but support for it has not been added to this package. In those cases, basic functionality like rendering to an SVG should typically still work in line with the following examples.

Diagram(:mermaid, """
graph TD
  A[ Anyone ] --> | Can help | B( Go to github.com/yuzutech/kroki )
  B --> C{ How to contribute? }
  C --> D[ Reporting bugs ]
  C --> E[ Sharing ideas ]
  C --> F[ Advocating ]
""")
Example block output
Escaping special characters

When the diagram description contains special characters, e.g. \s, keep in mind that these need to be escaped for proper handling when instantiating a Diagram.

Escaping is not typically necessary when using string literals.

Diagram(:svgbob, """
    0       3                          P *
     *-------*      +y                    \\
  1 /|    2 /|       ^                     \\
   *-+-----* |       |                v0    \\       v3
   | |4    | |7      | ◄╮               *----\\-----*
   | *-----|-*     ⤹ +-----> +x        /      v X   \\
   |/      |/       / ⤴               /        o     \\
   *-------*       v                 /                \\
  5       6      +z              v1 *------------------* v2
""")
svgbob"""
    0       3                          P *
     *-------*      +y                    \
  1 /|    2 /|       ^                     \
   *-+-----* |       |                v0    \       v3
   | |4    | |7      | ◄╮               *----\-----*
   | *-----|-*     ⤹ +-----> +x        /      v X   \
   |/      |/       / ⤴               /        o     \
   *-------*       v                 /                \
  5       6      +z              v1 *------------------* v2
"""

Loading from a file

Instead of directly specifying a diagram, Diagrams can also load the specifications from files. This is particularly useful when creating diagrams using other tooling, e.g. Structurizr or Excalidraw, or when sharing diagram definitions across documentation.

To load a diagram from a file, specify the path of the file as the path keyword argument to Diagram.

Diagram(
  :structurizr;
  path = joinpath(@__DIR__, "..", "architecture", "workspace.dsl"),
)
Example block output

Diagram options

Some diagram types support diagram options controlling their apearance. These options can be set when instantiating a Diagram.

For instance, the workspace.dsl file referenced in the previous section defines multiple diagrams. The diagram that is rendered in the previous section is picked randomly from this set every time the documentation is generated. The Structurizr diagrams support a view-key option to indicate which diagram should be rendered from the set defined in the file.

structurizr_diagram = Diagram(
  :structurizr;
  path = joinpath(@__DIR__, "..", "architecture", "workspace.dsl"),
  options = Dict("view-key" => "ServiceContainers")
)
Example block output

Another use case is specifying a theme for PlantUML diagrams.

Diagram(:plantuml, "Kroki -> Julia: Hello"; options = Dict("theme" => "amiga"))
Diagram(:plantuml, "Julia -> Kroki: Hello!"; options = Dict("theme" => "crt-amber"))

Instead of specifying diagram options at Diagram construction, they can also be passed directly to the render function. For instance, to select a different diagram from the set of Structurizr diagrams previously loaded from file.

# A helper wrapper to ensure the output of `render` can be visualized directly
# within `Documenter`
DocumenterSvg(
  render(
    structurizr_diagram, "svg";
    options = Dict("view-key" => "PackageComponents")
  )
)
Example block output
A note on `view-key`s

The view-keys for Structurizr diagrams can either be dynamic and obtained from the Structurizr (Lite) software, or they can be specified as the second argument to 'view definitions' using the Structurizr DSL.

Rendering to a specific format

To render to a specific format, explicitly call the render function on a Diagram, specifying the desired output format.

Output format support

All diagram types support SVG output, other supported output formats vary per diagram type. See the support table for an overview.

mermaid_diagram = mermaid"""
graph LR
  Foo --> Bar
  Bar --> Baz
  Bar --> Bar
  Baz --> Quuz
  Quuz --> Foo
  Quuz --> Bar
"""

mermaid_diagram_as_png = render(mermaid_diagram, "png")

# The PNG header
# See http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
Char.(mermaid_diagram_as_png[1:8])
8-element Vector{Char}:
 '\u89': Unicode U+0089 (category Cc: Other, control)
 'P': ASCII/Unicode U+0050 (category Lu: Letter, uppercase)
 'N': ASCII/Unicode U+004E (category Lu: Letter, uppercase)
 'G': ASCII/Unicode U+0047 (category Lu: Letter, uppercase)
 '\r': ASCII/Unicode U+000D (category Cc: Other, control)
 '\n': ASCII/Unicode U+000A (category Cc: Other, control)
 '\x1a': ASCII/Unicode U+001A (category Cc: Other, control)
 '\n': ASCII/Unicode U+000A (category Cc: Other, control)

Saving to a file

Once a diagram has been rendered, it's straightforward to write it to a file using write.

write("mermaid_diagram.png", mermaid_diagram_as_png)
9761

Note the difference in file size when rendering to SVG.

write("mermaid_diagram.svg", render(mermaid_diagram, "svg"))
10254

Overriding Base.show behavior

In some cases the output format that is used may affect how the final diagram renders. Although it is always possible to explicitly fall back to calling render in these cases, this may be cumbersome when writing documentation, etc. and having to explicitly do that for every diagram of a specific type. As an alternative, it is possible to instruct Kroki to ignore certain output formats when rendering a specific diagram type using Base.show.

For instance, by default (in most cases) a Mermaid diagram will be rendered as an SVG. Due to the way these diagrams are rendered by Kroki this may result in text getting cut off, see yuzutech/kroki#1345 for details.

mermaid_diagram
Example block output
Inspecting the output format of an image

The most straightforward way of inspecting the output format is to open the image in a new tab in your browser and checking its extension, e.g. by right clicking on it and selecting Open image in new tab in Chrome or a similar browser. Alternatively the type of the rendered image can be seen by inspecting the source of this page.

Using Kroki.overrideShowable, Kroki can be instructed to not render to SVG and pick the next most suitable output format with a fallback of rendering the diagram to text if none are available.

Kroki.overrideShowable(MIME"image/svg+xml"(), :mermaid, false)
false

For Mermaid diagrams in the context of Documenter this means rendering the diagram as a PNG. When rendering to PNG the previously mentioned font issues do not arise.

mermaid_diagram
Example block output

Controlling text rendering

Some diagrams support rendering to text, e.g. PlantUML and Structurizr. This can be based on ASCII or Unicode character sets. Which character set is used, is controlled using the Kroki.TEXT_PLAIN_SHOW_MIME_TYPE variable.

Setting a text/plain MIME type results in the use of the limited ASCII character set.

plantuml_diagram = plantuml"""
Kroki -> Documenter: I can render this as text in two ways!
Kroki <- Documenter: Nice!
"""

Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain"()
println(sprint(show, MIME"text/plain"(), plantuml_diagram))
     ,-----.                              ,----------.
     |Kroki|                              |Documenter|
     `--+--'                              `----+-----'
        |I can render this as text in two ways!|
        |-------------------------------------->
        |                                      |
        |                Nice!                 |
        |<--------------------------------------
     ,--+--.                              ,----+-----.
     |Kroki|                              |Documenter|
     `-----'                              `----------'

Setting a text/plain; charset=utf-8 MIME type, which is the default, results in nicer looking diagrams due to the use of Unicode characters.

Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain; charset=utf-8"()
println(sprint(show, MIME"text/plain"(), plantuml_diagram))
     ┌─────┐                              ┌──────────┐
     │Kroki│                              │Documenter│
     └──┬──┘                              └────┬─────┘
        │I can render this as text in two ways!│
        │──────────────────────────────────────>
        │                                      │
        │                Nice!                 │
        │<──────────────────────────────────────
     ┌──┴──┐                              ┌────┴─────┐
     │Kroki│                              │Documenter│
     └─────┘                              └──────────┘

Configuring an invalid MIME type results in an error upon rendering to a text/plain target.

Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"not-a-known/mime-type"()

try
  sprint(show, MIME"text/plain"(), plantuml_diagram)
catch exception
  println(sprint(showerror, exception))
end
The selected `MIME` type must be one of `text/plain; charset=utf-8` or `text/plain`. Got `not-a-known/mime-type`.