Hi HN, I'm Alex, at Terrastruct, where we've been making D2. This actually popped up on HN a couple months back, though it wasn't ready, e.g. not open source yet. It is now!
We also put up a site for you to compare D2 with MermaidJS, Graphviz, and PlantUML: https://text-to-diagram.com.
Full disclosure, we're a for-profit company. The open-core part is that we make an alternative layout engine which we sell (Jetbrains model, i.e. your copy is your's forever if you've paid for 12+ months). It's not packaged with D2, so you won't see it if you don't want it. D2 is perfectly usable without it, and integrates with multiple free open source layout engines (e.g. the one that Mermaid uses, "dagre", is D2's default). If you want to read more about our plans for D2: https://d2lang.com/tour/future.
Hope you can check it out! It's got an easy install (and uninstall) process.
thank you! There isn't right now, we'd need to add a simpler layout algorithm for those, e.g. force-directed, radial, etc. That use case is not something D2 is trying to tackle though, we're just focused on software architecture diagrams right now, and I've yet to see one span that many nodes
Picking a set of domain specific targets and honing a tool to service
that seems a good way to start building - rather than a general
solver.
I also love graphviz but had a project to create an app for legible
quality management, and it was a headache to shoehorn some concepts
into "nodes in an edge connected graph" way of thinking (ended up
programatically scripting LaTeX).
With so many visualisation concepts there's room for niche approaches
(same in plotting; Matlab/Octave vs Gnuplot vs Pyplot vs R and so on)
agreed! that reminds me, there's a company that specializes in this niche of visualizing large data: https://www.graphistry.com/ (haven't used it myself, looks well-made).
100% agreement, spot on observations! Indeed, we end up referring folks to cool diagramming tools all the time at Graphistry as d2/mermaid/diagrams.net are well-optimized for quick & beautiful diagram presentation tasks on manageably sized & fairly static datasets. Using Graphistry to do a quick markdown of how a 4 node cluster might work is a bit like driving a tank to pick up some milk :) Teams go to us more for gnarly investigation & splunking tasks that need a visual power tool, like looking at alert logs or big systems, so we optimize for making that scale interactive & easy.
The overlap is real however, so a lot of room for teams to learn. Ex: We're the easiest graph tool for jupyter/databricks/streamlit etc teams who use dataframes, and I can imagine those tools learning from us here. In the reverse direction, our work more in terms of quickly configurable global data<>viz data bindings ("using the UI or API, bind each event's score to a hot-and-cold coloring palette and use a warning icon on all type=alert events"), but we have a ways to go to support the more manual artisinal effects of diagramming tools like Figma, where each element might have a super fancy & unique border style.
IDK if it's quite the use case you're looking for, but at my company, we turn our CI YAML for our monorepo into Dot (Graphviz), and graph it, to visualize the dependencies between steps in our CI, & to highlight the critical path.
It's an ~100 node DAG. Graphviz struggles a bit with it, particularly with edge layout.
(Though really, the layout I want for it is a Gnatt chart style layout.)
I have made software architecture diagrams, but more "descriptive" than "prescriptive" ones, by generating graphviz from source code analysis tooling. (The objective here was getting oriented in a large codebase where there wasn't really a rigorous diagram of anything written down anywhere, and trying to find sort of a min-cut where putting a line through the graph of imports would cross the fewest edges)
In my experience graphviz handles up to thousands of nodes and tens of thousands of edges without really breaking a sweat.
edit: I've done the same thing with extracting AWS diagrams from aws describe* calls, with good results.
I am always quite astonished how bad the default layouters for graphs perform. When I was still doing compiler optimization in the beginning of the 2000s we did not struggle with quite big graphs thanks to cool graph visualizers such as vcg [1] . Two weeks ago I was tempted to try it again after nearly 20 years because I was frustrated even visualising a relatively small graph in python (cytoscape seemed to be the only working software in the end but it was quite a pain to get it to just render what I wanted)
Laying out larger graphs is tricky, often because the size simply stands in the way of generating anything that's useful to the viewer. To add to that, most layout algorithms prioritize optimizing certain criteria, while other parts of the visualization emerge from that; and if the human viewer chooses a layout algorithm because of one of the latter properties, they are often surprised that the result doesn't look like they envisioned (because, hey, the algorithm optimized something entirely different). We see this disconnect fairly often in our own customer support, but I haven't really found a good way of putting an explanation in writing.
Then there's generally the problem of larger graphs, which tend to devolve into a tangled mess and hairballs, simply because they often tend to be well-connected. If there's no way of pruning them beforehand, or perhaps grouping, aggregating or clustering (in a way that makes sense to the viewer, not necessarily only structurally), then it can be hard to get good result.
This is a great idea; my go-to approach is the "I'll use PowerPoint to do that and take a screenshot" mindset since I don't have a need for publication quality output.
I really like the comparison site that you have created - it's great for learning these languages. I would love to see a plugin for Obsidian for the times where I need to add a custom drawing to my notes. It looks like there already are plugins for PlantUML[1] and graphviz[2] today.
thanks! i don't use Obsidian personally and don't know how the plugins work, but if anyone sees this and wants to do a plugin for it, please reach out or open a Github issue and we'll support whatever API changes are needed (if any) to D2's plugin system to make integration easy.
This looks really interesting. It made me curious about something.
As an example your tree is laid or left-to-right. The GraphViz one in comparison is top down. It’s not clear to me as a user if that’s forced or a choice (in either case).
Are you able to clarify that sort of difference by either making the diagrams similarly laid out or adding a note if something isn’t possible?
wow thank you for the transparency - you literally answered all the questions up front that I care about re open core, for profit, killswitches, etc etc that usually take hours to find from a marketing landing page.
not that i know of, but there's a lot of research papers, under the topic of "graph visualization". we read a ton of these and combined and modified ideas for TALA.
The folks at ELK are doing fantastic work in public as an academic team out of Germany.
In general they are surprisingly readable even without an academic background. Sometimes they go into proofs of correctness like method X really results in minimal edge crossings, and those are gnarly math, but skippable. The bad part is that a lot of these research papers have code that's just broken or wrong, or is NP-hard.
I'm excited to see this. It's the first repository I've starred in a long time. I'm asked for these types of diagrams from time to time and I've bounced between many different tools, none of which I've found to be satisfactory. I will try this next. Thank you for your work on it.
we maintain a wrapper around dagre, which adds functionality like supporting container to container connection. dagre is unmaintained, but it's also "complete", in that it implements the theoretical papers it set out to.
The comparison website is neat. I don't like to draw the architectural diagrams which graphical tools for my Open-source projects, I'll try D2 for my next project.
An even earlier tool: Pic, which had its paper released in 1981. It belongs to the troff ecosystem of tools. I'd be interested to know about other tools from this era!
Wow. I thought mermaid was the future but I think I've been won over by D2. Can use markdown inside, can use code inside, and has some auto formatting tools apparently. This seems like such a better experience than literally any of the other comparisons.
I've been using PlantUML and Mermaid for my own diagrams.
Mermaid is quite basic; it lacks functionalities that for me were necessary; for example, direct connection between attributes of different classes.
All in all, PlantUML seems superior to Mermaid, at no cost (both languages are relatively simple to learn).
Mermaid is supported by Github, which may be a necessary requirement for some. On the other hand, among the many functionalities, PlantUML's JSON is unusually good looking out of the box, and if one required the diagram it outputs, it's a great feature, because it requires no syntax knowledge.
Both PlantUML and Mermaid mostly produce (Mermaid more) ugly-looking diagrams (dated, to say the least). In PlantUML, this problem is compounded by the explicit lack of layout, by design.
Other warts: both (PlantUML and Mermaid) languages have limited comment support - they are only supported in specific locations of the diagram declarations.
D2 could be a very welcome "next gen" diagramming language. However, the devil is in the details - text-to-diagram.com show a very basic functionality, so one must carefully check the requirements.
Regarding text-to-diagram.com:
- there's a mistake - PlantUML does support rich text (although "rich" is a fuzzy definition)
- class diagrams are an important use case, which is currently missing
EDIT: clarification about the comment limitations.
Have you taken a look at Ilograph [0]? It's also a "next gen" diagrams-as-code alternative that goes in a different direction: interactive, model-based, and multi-perspective. It also has in an IDE for autocomplete.
wow, I'm just walking through the demo linked by Veuxdo and that's exactly what I was thinking: each step in the walkthrough drills context down deeper or widens context in a very clear way.
I've tried to do similar things in graphviz but pulling out individual subgraphs or subsets of nodes + edges isn't easy and I always end up with multiple files for each view that I want to show and they get out of sync.
This looks great, but I'm not terribly jazzed about having my diagrams permanently hosted on a third-party site. I know it's hard to make self-hosted interactive diagrams like this, but I'd like my documentation to last longer than this site.
Yeah, self-hosting is a bit of a nightmare. There is a Desktop version that allows you to export diagrams to HTML, which you then can be host or share.
As they say, the best diagram language is the one your tool supports; and by that metric Mermaid and graphviz seem to be winning (depending on which ecosystem you are in, Mermaid seems to have the edge in the Markdown world, graphviz everywhere else).
D2 looks like a nice upgrade, but to be as useful as e.g. Mermaid a bunch of plugins will need to be written.
yup agreed. we prioritized IDE plugins, and have a native plugin system, recognizing the importance of ecosystem. e.g. a proof of concept plugin to make diagrams look hand-drawn: https://github.com/terrastruct/d2/pull/91
Also Dublin 2 (postcode of Dublin city), a thai hotel chain operating in the middle east also, the video game destiny 2, a german magazine, roads in several countries, a vitamin, multiple airplanes, deuterium, a paper size, 2 sided dice and a variant of steel.
I don't think anyone expects short acronyms to be globally unique
Sure, many namespace collisions for D2 exit in the universe of possible meanings for the acronym, but in a computer context, and whose headline is “now open source”, it’s reasonable, expected even perhaps, to assume Diablo 2.
Also, and I may be showing my age here, who refers to Destiny 2 as D2 without any context?
Sorry, I'm just annoyed about the demo .gif. Why is it not a video I can watch full-screen? I want to actually see the text. Why is there a huge empty border around the window?
Otherwise, the shown workflow seems nice. I'll check out the syntax to see what it brings in comparison to DOT. Thank you.
Demo gif is not annoying per se, but UX is awful: not only I can't see anything on a FullHD monitor, I needed two right clicks to get to the actual .gif, I still needed to go to a fullscreen view to see the text, it is still ends too soon and I have no way to pause/stop the playback.
I saw a no border version (why was it recorded with a border in the first place?), but still the left part could be easily half the size, it would integrate nicely in the GH page. If you increase the notes font than it would be (probably) legible even on GH.
I think it's a classical example of 'works for me'.
Plus controls. This is a separate rant, but for incomprehensible reasons, Chrome removed the ability to even enable controls for animated GIFs.
So if I miss some detail I was interested in, I can't rewind. I have to wait for it to loop around again. And when it does come back up, I can't pause there; instead, I have to frantically try to memorize what I saw.
Also, I don't know the length, so I don't know if it's worth my time investment to wait for it to loop.
I recently discovered Pikchr from Sqlite/Fossil [0] if anyone is looking for something in a similar vein, although it has it's own scripting/layout language rather than using go (a plus IMO, as it's not tied to a specific ecosystem).
It's fantastic for making diagrams when you want more control over the layout than graphviz or mermaidjs but are looking for a similar type of tool. It's also clean C so easy to embed, and there's a WASM build for browser use.
It is fairly simple in any general purpose language to output pikchr code - I've done this previously for producing autogenerated packet diagrams in documentation.
I am a huge fan of Pikchr. I ported it to Go, and integrated it with Hugo, for my blog. I need to get back to fixing it though — a big reorganization commit in either Hugo or Goldmark made it stop working
I would love to see this as a plugin for an IDE like Visual Studio or Qt Creator. The diagram commands would be in comments, and the graphic representation rendered in-line with the source code.
you can do this in VSCode now actually. the CLI has a live-reloader, so if you put the PNG on a side by side window with the code, every code change will see the PNG change.
100%, these are TODOs! But to be transparent, there's been a lott of TODOs opened from this launch. It's likely going to be a few releases away before we get to this one.
I just wanted to drop a reference to Burnt Sushi's ERD tool [0]. It only does one diagram type: Entity Relationship Diagram. It's wonderful. Human-first syntax, code comments, and some simple formatting settings like colors and font sizes that help make more complex diagram pleasing and informative.
In theory could ERD be quite easily extended to use D2 as another renderer? It looks very simple with one render.hs file which uses Graphviz but that could be parametrized.
What would be a reasonable way to bring the diagrams to a frontend and make them interactive? Not in the sense of editing the diagrams but rather attaching onClick handlers to nodes, or displaying metadata when hovering over a node or edge?
interactive tooltips are a wip, but to the larger point, D2 has a plugin system which enables extensions like this (https://github.com/terrastruct/d2/pull/91). there's still some fleshing out to do with the API, but once it's up, it should be a straightforward plugin for custom handlers.
To further elaborate, the output is an SVG so you can embed it into your DOM and then add make it interactive like any other part of the DOM. Though until we set each svg node's ID to its D2 ID, you'll have to add event handlers by selecting on value.
When it comes to generating diagrams that look nice from just about any diagram scripting language, I tend to go to "Kroki!". Hopefully they'll do some work to support D2 as well, although going from D2 -> PlantUML is something you can do in the meantime.
This looks great, but sequence diagrams are one of the things I use most with PlantUML. Most commonly I find these super useful to document various caching scenarios, and I use them all the time to help explain payment processing flows.
> D2 intends to integrate with a variety of layout engines, e.g. dot, as well as single-purpose layout types like sequence diagrams. You can choose whichever layout engine you like and works best for the diagram you're making.
Can you explain a bit more about this, if I wanted to create a sequence diagram with D2 today is there a simple path to follow to do this?
that's not contradictory. we plan to do this in the next month or so, but text-to-diagram reflects current state, so it'll say it's not supported until it's publicly released. if this is a blocker, feel free to watch this issue to be notified! https://github.com/terrastruct/d2/issues/99
2. with any integration, if there's enough demand, we'll do it. Once we add interactivity to diagrams, it should be trivial to emulate. However I should mention that Simon Brown (the creator of C4) has his own DSL for C4 https://github.com/structurizr/dsl)! We have no intention of competing with it.
3. Currently the options to tune are limited. The Terrastruct app has granular layout control via drag-and-drop, and we're working to bring some of that to native/open-source.
The syntax is much friendlier than any other tool of this sort, and being programmable and extensible from Go is a great plus. I think you should add this aspect to your comparison on https://text-to-diagram.com/ (also a nice touch!), as I don't remember this being possible with others, though I might be wrong.
I'm looking forward to this having sequence diagram support, and it might just become my go-to next time. Definitely keeping an eye on this project.
166 comments
[ 3.5 ms ] story [ 230 ms ] threadWe also put up a site for you to compare D2 with MermaidJS, Graphviz, and PlantUML: https://text-to-diagram.com.
Full disclosure, we're a for-profit company. The open-core part is that we make an alternative layout engine which we sell (Jetbrains model, i.e. your copy is your's forever if you've paid for 12+ months). It's not packaged with D2, so you won't see it if you don't want it. D2 is perfectly usable without it, and integrates with multiple free open source layout engines (e.g. the one that Mermaid uses, "dagre", is D2's default). If you want to read more about our plans for D2: https://d2lang.com/tour/future.
Hope you can check it out! It's got an easy install (and uninstall) process.
Any examples of larger diagrams (1000+s of nodes) and how does that perform in layout?
I also love graphviz but had a project to create an app for legible quality management, and it was a headache to shoehorn some concepts into "nodes in an edge connected graph" way of thinking (ended up programatically scripting LaTeX).
With so many visualisation concepts there's room for niche approaches (same in plotting; Matlab/Octave vs Gnuplot vs Pyplot vs R and so on)
The overlap is real however, so a lot of room for teams to learn. Ex: We're the easiest graph tool for jupyter/databricks/streamlit etc teams who use dataframes, and I can imagine those tools learning from us here. In the reverse direction, our work more in terms of quickly configurable global data<>viz data bindings ("using the UI or API, bind each event's score to a hot-and-cold coloring palette and use a warning icon on all type=alert events"), but we have a ways to go to support the more manual artisinal effects of diagramming tools like Figma, where each element might have a super fancy & unique border style.
It's an ~100 node DAG. Graphviz struggles a bit with it, particularly with edge layout.
(Though really, the layout I want for it is a Gnatt chart style layout.)
In my experience graphviz handles up to thousands of nodes and tens of thousands of edges without really breaking a sweat.
edit: I've done the same thing with extracting AWS diagrams from aws describe* calls, with good results.
[1] https://www.rw.cdl.uni-saarland.de/people/sander/private/htm...
Then there's generally the problem of larger graphs, which tend to devolve into a tangled mess and hairballs, simply because they often tend to be well-connected. If there's no way of pruning them beforehand, or perhaps grouping, aggregating or clustering (in a way that makes sense to the viewer, not necessarily only structurally), then it can be hard to get good result.
edit: guessing URL found https://d2lang.com/tour/intro/ which covers it, perhaps worth linking to there from the GitHub page
edit2: ok it is linked, just above the section I was looking at:
Reference
A more formal reference specification is in the works.
I really like the comparison site that you have created - it's great for learning these languages. I would love to see a plugin for Obsidian for the times where I need to add a custom drawing to my notes. It looks like there already are plugins for PlantUML[1] and graphviz[2] today.
[1] https://github.com/QAMichaelPeng/obsidian-graphviz
[2] https://github.com/joethei/obsidian-plantuml
(created a Github Discussion to track. https://github.com/terrastruct/d2/discussions/138 . if there's enough demand, we'll do it ourselves)
As an example your tree is laid or left-to-right. The GraphViz one in comparison is top down. It’s not clear to me as a user if that’s forced or a choice (in either case).
Are you able to clarify that sort of difference by either making the diagrams similarly laid out or adding a note if something isn’t possible?
The folks at ELK are doing fantastic work in public as an academic team out of Germany.
https://www.eclipse.org/elk/documentation/algorithmdeveloper... https://www.rtsys.informatik.uni-kiel.de/en/team/soren-domro...
Graphviz's papers are also must-reads (for hierarchical layouts): https://graphviz.org/theory/
In general they are surprisingly readable even without an academic background. Sometimes they go into proofs of correctness like method X really results in minimal edge crossings, and those are gnarly math, but skippable. The bad part is that a lot of these research papers have code that's just broken or wrong, or is NP-hard.
https://github.com/dagrejs/dagre/wiki#recommended-reading
Can't wait for an Obsidian plugin! :D
The project looks to be deprecated: https://github.com/dagrejs/dagre
https://github.com/tbo47/dagre-es
The comparison website is neat. I don't like to draw the architectural diagrams which graphical tools for my Open-source projects, I'll try D2 for my next project.
https://en.wikipedia.org/wiki/Graphviz
Paper: https://dl.acm.org/doi/10.1145/872730.806459
Mention in troff doc: https://www.troff.org/prog.html#pic
Wikipedia page: https://en.wikipedia.org/wiki/PIC_(markup_language)
https://pikchr.org/home/doc/trunk/homepage.md
It's buried in the FAQ but it was an interesting comparison
Mermaid is quite basic; it lacks functionalities that for me were necessary; for example, direct connection between attributes of different classes.
All in all, PlantUML seems superior to Mermaid, at no cost (both languages are relatively simple to learn).
Mermaid is supported by Github, which may be a necessary requirement for some. On the other hand, among the many functionalities, PlantUML's JSON is unusually good looking out of the box, and if one required the diagram it outputs, it's a great feature, because it requires no syntax knowledge.
Both PlantUML and Mermaid mostly produce (Mermaid more) ugly-looking diagrams (dated, to say the least). In PlantUML, this problem is compounded by the explicit lack of layout, by design.
Other warts: both (PlantUML and Mermaid) languages have limited comment support - they are only supported in specific locations of the diagram declarations.
D2 could be a very welcome "next gen" diagramming language. However, the devil is in the details - text-to-diagram.com show a very basic functionality, so one must carefully check the requirements.
Regarding text-to-diagram.com:
- there's a mistake - PlantUML does support rich text (although "rich" is a fuzzy definition)
- class diagrams are an important use case, which is currently missing
EDIT: clarification about the comment limitations.
i've added a TODO for the class diagrams, will be included this week. https://github.com/terrastruct/text-to-diagram-site/issues/2...
AFAIK they all have comments (see the "Chess" example). what is the limitation of comments you're referring to?
Regarding the comments, here's a PlantUML example:
[0] https://app.ilograph.com/demo.ilograph.Ilograph
I've tried to do similar things in graphviz but pulling out individual subgraphs or subsets of nodes + edges isn't easy and I always end up with multiple files for each view that I want to show and they get out of sync.
The Desktop version can also export diagrams when called via CLI, though that is less suitable for CI/CD.
D2 looks like a nice upgrade, but to be as useful as e.g. Mermaid a bunch of plugins will need to be written.
On a side note, one of the Diablo 2 creators posts here from time to time.
I don't think anyone expects short acronyms to be globally unique
Also, and I may be showing my age here, who refers to Destiny 2 as D2 without any context?
Supposedly naming things is one of the problems in programming.
Otherwise, the shown workflow seems nice. I'll check out the syntax to see what it brings in comparison to DOT. Thank you.
and if you want to see a fuller static text and rendering: https://text-to-diagram.com/?example=wiiu
I saw a no border version (why was it recorded with a border in the first place?), but still the left part could be easily half the size, it would integrate nicely in the GH page. If you increase the notes font than it would be (probably) legible even on GH.
I think it's a classical example of 'works for me'.
But anyway, is there are plans for Win* release?
yep. should be in a week or so, along with other installation stuff: https://github.com/terrastruct/d2/blob/master/docs/INSTALL.m...
Plus controls. This is a separate rant, but for incomprehensible reasons, Chrome removed the ability to even enable controls for animated GIFs.
So if I miss some detail I was interested in, I can't rewind. I have to wait for it to loop around again. And when it does come back up, I can't pause there; instead, I have to frantically try to memorize what I saw.
Also, I don't know the length, so I don't know if it's worth my time investment to wait for it to loop.
For now, we zoomed the gif in so you can see it better. And we added a syntax example front and center.
VS Code extension, too: https://github.com/terrastruct/d2-vscode
It's fantastic for making diagrams when you want more control over the layout than graphviz or mermaidjs but are looking for a similar type of tool. It's also clean C so easy to embed, and there's a WASM build for browser use.
It is fairly simple in any general purpose language to output pikchr code - I've done this previously for producing autogenerated packet diagrams in documentation.
0: https://pikchr.org/home/doc/trunk/homepage.md
You can see the results at https://zellyn.com/2022/02/cs-ramble/
I just wanted to drop a reference to Burnt Sushi's ERD tool [0]. It only does one diagram type: Entity Relationship Diagram. It's wonderful. Human-first syntax, code comments, and some simple formatting settings like colors and font sizes that help make more complex diagram pleasing and informative.
[0] https://github.com/BurntSushi/erd
made an issue to track: https://github.com/terrastruct/d2/issues/134
* https://kroki.io/
https://text-to-diagram.com/ says the sequence diagrams aren't supported, but your github description says
> D2 intends to integrate with a variety of layout engines, e.g. dot, as well as single-purpose layout types like sequence diagrams. You can choose whichever layout engine you like and works best for the diagram you're making.
Can you explain a bit more about this, if I wanted to create a sequence diagram with D2 today is there a simple path to follow to do this?
Thanks for the work on the project!
Through certain configurations, the arrows will end up going directly through unrelated objects.
A crappy example here. The line from x -> cont3.y goes through the cont2 container:
x -> cont.y -> z
x -> cont2.y
x -> cont3.y
cont {
x -> y -> z
}
cont2 {
x -> y -> z
}
cont3 {
x -> y -> z
}
2. Any plans for native C4 model support, or examples how to emulate it?
3. What about layout control? By default D2 generate way nicer layout, but it is synthetic. How I can tune it, give some hints, etc?
2. with any integration, if there's enough demand, we'll do it. Once we add interactivity to diagrams, it should be trivial to emulate. However I should mention that Simon Brown (the creator of C4) has his own DSL for C4 https://github.com/structurizr/dsl)! We have no intention of competing with it.
3. Currently the options to tune are limited. The Terrastruct app has granular layout control via drag-and-drop, and we're working to bring some of that to native/open-source.
The syntax is much friendlier than any other tool of this sort, and being programmable and extensible from Go is a great plus. I think you should add this aspect to your comparison on https://text-to-diagram.com/ (also a nice touch!), as I don't remember this being possible with others, though I might be wrong.
I'm looking forward to this having sequence diagram support, and it might just become my go-to next time. Definitely keeping an eye on this project.
Basically the choices were down to:
1. Graphics tools (Google Drawings / Draw.io) - which were a pain for complex charts and maintenance.
2. Code-based tools such as plantUML which was mature and solid, but required Java :|
https://github.com/terrastruct/d2/issues/96