How to define diagrams and integrate Kroki outputs into a Typst document?

We just started experimenting with Typst to understand if it can replace our asciidoc-based solution for some technical documentation.

It looks very promising with fast updates and pipeline-able document generation. The addition of a WYSIWYG editor is compelling and not something our current setup can offer, so I wanted to understand whether our current documentation and use cases can be covered adequately with Typst.

One of our biggest use cases is dynamically embedding various diagram types (mermaid, wavedrom, graphviz, others) by the use of an internally-hosted kroki server. Asciidoctor can handle this well; the diagram code itself lives in the .adoc file and with proper editor settings, can show real-time previews of the entire document as arbitrary diagrams or other document contents are updated.

I spent some time trying to understand how such an integration might function for Typst documentation and the solution is not as clear as I expected it to be. I did not find any mention of “kroki” on the forums or in documentation. While we could generate an image output from Kroki and have it imported, the code itself would not live in the Typst document (that I can tell), and is very static. I think it would require a mutli-step build process of running a script to re-generate all Kroki diagrams, then previewing with Typst to pull in all new images.

Because I am not familiar with the Typst ecosystem, I expect there is a better way to do what we need. What is the “right” way to solve this?

Welcome! Seeing as this is a typst forum and I have no idea what kroki is beyond what I just now learned scrolling through their website, I might ask some stupid questions.

First, do I understand that you can use kroki to generate (for example) svg images from some “code”? If you can use it to export images, typst of course supports including images in your document, see the documentation for image.

Do you mean that you have the code inside your asciidoc plaintext file, then asciidoctor uses kroki to generate an image of the diagram on the fly, and then includes this image inside your document? Typst cannot run external commands due to security concerns, so this isn’t possible. You’d need some sort of preprocessor to compile compile the images first, and then include those in your document. I saw that there are some rust crates for kroki, so you might be able to write a custom WASM plugin to do this.

Perhaps someone more knowlegable in plugin development could chime in?

If by diagram code you mean something like svg data, then sure:

#let circle-svg = bytes(
```
<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
  <circle r="45" cx="50" cy="50" fill="red" />
</svg>
```.text,
)

#image(circle-svg)

And if you only need some sort of way to include diagrams in your outputs (not necessarily using kroki), there are some nice visualisation libraries available on typst universe. Fletcher comes to mind: fletcher – Typst Universe

Thank you for the quick response. No such thing as a stupid question, I may have jumped a bit fast into Kroki so hopefully I can clear a few things up.

Yes, this is the desired use case (not just embedding static images). For example, here is a valid sanitized snippet of one of our plantext asciidoc files:

A visual depiction of the packet structure is shown in <<protocol_frame>>.

[[protocol_frame]]
.Protocol Frame Definition
[wavedrom]
----
{
  reg: [
    { "name": "SIZE", "bits": 16},
    { "name": "TYPE", "bits": 8},
    { "name": "...", "bits": 8, "type": 0},
    { "name": "CRC", "bits": 32,},
  ],
  config: {
    bits: 64,
    lanes: 8,
    hflip:true,
    vflip:false,
    compact:true,
    margin: {left: 180},
    label: {
      left: [
        'SIZE 0',
        'SIZE 1',
        'TYPE 2',
        'PAYLOAD ...',
        'CRC N+6',
        'CRC N+7',
        'CRC N+8',
    	'CRC N+9',
      ]
    },
  }
}
----

The messaging format follows a transactional pattern where every message as an immediate corresponding response.
For commands, the expected response is an Ack message, whereas the expected response to a query is a corresponding message.

[edit: here’s a rendered example of that output: wavedrom]

The above can be edited within the file itself and is rendered real time in an adjacent preview window. As a user types or modifies a part of that block in their IDE, that text gets sent via an HTTP API request to Kroki, which then returns an SVG representing that content. That image is subsequently placed into the full document content preview. I call this “real time”, but it is more like 1-2 seconds delay per edit.

This is what I was thinking might need to happen, but didn’t have the right search terms. I think fletcher is the closest to the functionality I am expecting (nice tool, by the way, thank you for pointing that out). I want to be able to do something similar with any of the diagrams that Kroki supports, effectively passing the diagram off to an external handler to return the rendered image for the preview. Seeing that it needs to be internal and I cannot reference an external HTTP API however gives me pause. I am hearing that the only way to do this to is embed Kroki functionality into a rust crate to be called locally via a plugin?

I think even making a plugin based on one of the existing Kroki Rust crates is not an option: as I understand these crates communicate with a Kroki instance, and plugins cannot do that (whether the instance is local or remote doesn’t matter). You would need to build the whole Kroki server in WebAssembly as a Typst plugin and that seems prohibitively difficult.

If you want to go with the preprocessing workflow, have a look at the prequery package, which was made for this kind of tasks.

However I think the best solution by far is to embrace the Typst model: do not try to use a network API during compilation. Use the existing diagram-drawing packages, maybe write your own wrapper package to support many formats with a unified API, and make new packages/plugins yourself when you find that you need something that’s not already available in the Typst Universe.

By the way there’s already a lot of diagramming packages in the Universe! Maybe the first step should be to research which tools are already supported as packages/plugins and which are missing. For example, there are already packages that support the syntax of wavedrom, graphviz and mermaid…

1 Like

Thank you for the thorough reply. I am intrigued by the prequery package as it looks like it could potentially be a good stop-gap solution while we identify what types of solutions we need to expand upon.

Regarding the diagramming packages, if they do truly support the same syntax and produce the same outputs as our current wavedrom solution for example, I see little reason why we can’t also use those. I did an experiment with wavy and was able to use, without modification, two of our existing diagram definitions within a Typst document, so there is a good chance that solution can continue to work for other diagrams.

1 Like

I am working on using Typst to generate PDFs from Antora documentation projects, which involve AsciiDoc documents and can easily include Kroki diagrams.

The high-level flow involves using Antora Assembler’s PDF extension to generate an all-in-one AsciiDoc document, process that with asciidoctor to generate DocBook XML, process that to generate Typst markup, and finally run Typst to generate PDFs.

During the AsciiDoc → DocBook processing, Kroki diagrams can be generated and included in the output. My current projects don’t use Kroki, but including its processing is easy with the usual -r flag for asciidoctor.

I haven’t published anything yet. I have a prototype running for a single project, but I haven’t managed to publish packages yet due to other priorities. I’ll post an update here when packages are available.