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 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 ]
""")
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, Diagram
s 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"),
)
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")
)
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")
)
)
The view-key
s 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.
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
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
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`.