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](@ref api-string-literals).
using Kroki
The most straightforward way to create diagrams is to rely on the [string
literals](@ref api-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](@ref examples-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 ┊ .------------------------
┊ |
┊ |
*---'┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄▶
"""
!!! note "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](https://github.com/bauglir/Kroki.jl/issues/new) when encountering
unexpected behavior.
alice = "Kroki"
bob = "Julia"
plantuml"""
$alice -> $bob: I'm here to help.
$bob -> $alice: With what?
$alice -> $bob: Rendering diagrams!
"""
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 ]
""")
!!! warning "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`](@ref).
Escaping is not typically necessary when using [string literals](@ref
api-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
"""
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"),
)
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 struct to show the result of `render` within `Documenter`
struct DocumenterSvg
svg::Vector{UInt8}
end
function Base.show(io::IO, ::MIME"image/svg+xml", (; svg)::DocumenterSvg)
write(io, svg)
end
# 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")
)
)
!!! info "A note on view-key
s"
The `view-key`s for Structurizr diagrams can either be dynamic and obtained
from the [Structurizr (Lite) software](https://structurizr.com/help/lite),
or they can be specified as [the second argument to 'view definitions'
using the Structurizr
DSL](https://docs.structurizr.com/dsl/language#views).
To render to a specific format, explicitly call the render
function
on a Diagram
, specifying the desired output format.
!!! warning "Output format support"
All diagram types support SVG output, other supported output formats vary
per diagram type. See [the support table](@ref diagram-support) 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])
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)
Note the difference in file size when rendering to SVG.
write("mermaid_diagram.svg", render(mermaid_diagram, "svg"))
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
!!! tip "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)
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
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.
text_plain_show_mime_type_backup = Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[]
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))
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))
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
Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = text_plain_show_mime_type_backup