Are there disadvantages to outsources diagram creation to WASM plugins that return SVG vs. using the Typst drawing primitives (`#line()`)?

Correct me if I am wrong but I notice that CeTZ is a pure Typst pacakge. I am thinking of using diagraph – Typst Universe which is a really cool WASM package for Typst that generates graphs using GraphViz. I like it because you can layout planar graphs using spring layouts/force directed layouts. I am a bit nervous to use it though because it returns pure SVG and does not call the Typst primitives for drawing like #line() etc.

Before discovering Diagraph I thought I could help contribute to CeTZ by re-implementing planar graph layouts in pure Typst, but now I do not know if that would be a meaningful contribution.

For those of us choosing diagram creation packages in Typst, should we prefer ones that are pure Typst or is using WASM based ones equivalent?

Thanks!

2 Likes

I don’t think you should inherently prefer either; it’s a question of requirements:

  • if there is an external tool doing the job well, then using that tool will be the better fit. That can mean using a WASM wrapper to use that tool inside Typst, or just generating SVG or other image files and including the result.
    Note that there’s a tradeoff between convenience (only having to cal Typst) and performance (doing the same work from WASM on each (fresh) compilation instead of on-demand using a native application).
    Example: I use PlantUML to create class diagrams manually. PlantUML is written in Java, so I have no choice at all; I probably would use a WASM plugin if it was possible. I can still set the font after including the SVG, so that suits me fairly well.
  • if such a tool doesn’t exist, or its results don’t look good after inclusion, you’ll prefer a Typst-native tool. Reasons could be
    • you would like to use rich text in the image, but text formatting in that tool is limited
    • you would like to have ways to introspect the result, e.g. position Typst content on top of the image without having to hard code the coordinates
    • you would like to use Typst’s scripting or styling tools to affect the content/appearance of the graphics
  • but Typst-native can still mean WASM! Diagraph (from what you say) creates SVG, so the rendering is not done by Typst (well, Typst still renders the SVG as PDF, but you get the point). But a WASM plugin can also return structured data and leave the rendering up to Typst. That is an attractive route if there’s either much to compute (performance benefits of WASM vs Typst) or much complexity to handle (benefits of using a general purpose programming language)
    Example: there’s still some tiny problems with PlantUML so I’m writing Plum (currently a bit on hold, but I’ll come back to it for sure). The WASM plugin parses the textual diagram representation (benefitting from a static type system and larger ecosystem) and gives all the parts back to Typst, where it is rendered using CeTZ and Fletcher.

I can imagine this also working well as a standalone package; I’d be very happy re Plum if there was a package that I could tell “this is the size of some nodes and the edges between them; please tell me where to place each note but let me do that myself”. Depending on how complex the layout algorithm(s) are, and whether there’s maybe an existing Rust or C implementation that can be compiled to WASM, a plugin would be an option as well, and it would still be in the “Typst natice graphics” category.

2 Likes

This makes a lot of sense, and the idea came to me too: that is, emit the coordinates with a WASM plugin to use them in the calling Typst function to construct the graph using the drawing primitives.
Personally, I think it is always best to write a plugin in pure Typst just for the fact that Typst functions are stateless, and although the WASM environment is lockedown (no networking access etc), I just feel more comfortable doing anything for Typst in Typst (ok this is not a reason) .
However, the immediate tradeoff is the complexity of re-implementing.

But what I am curious about is the performance. WASM plugin multithreading was introduced by Typst recently, so maybe we choose WASM for that alone? Or maybe we stick with Typst because it is faster? Curious what your thoughts are.

That absolutely is a reason :) if that is what’s fun/comfortable to you, do that because it improves the chances that you’ll stick with it. Abandonment is the bane of open source!

If I understand this correctly, that change basically brings WASM on par with Typst: Typst uses multithreading to process page runs separated by page breaks in parallel, but because there was no guarantee that WASM plugins are actually pure they were the exception:

The wasm multi-threading just means that wasm calls can be parallelized if things are already parallel due to layout parallelity. It does not mean that all wasm calls are parallel.
@laurmaedje, 2025-02-27T07:57:00Z; on Discord

So multithreading alone would not be a reason for WASM, just not a reason against WASM anymore.

One reason why WASM may be slower is because all data needs to be transferred to the plugin, then processed, and then transferred back. Each transfer requires serialization to a sequence of bytes and deserialization, so there’s a bit of overhead. (Unless you use the transition API in which case you can keep state inside WASM, but I don’t know the performance implications of that one either.) If your WASM computation is small, the overhead will outweigh the benefit, but it’s hard (impossible?) to tell if that’s the case without looking at hard data for a specific use case.

Personally I would focus on the complexity: do whatever is easier. Whether that means Typst because it’s familiar and more fun, or Rust (etc.) because of better ecosystem and more general features doesn’t matter; just do what’s easier. Ideally the language of the implementation is not visible to your users anyway. It’s just a package that works, so you can transition later.

1 Like