Error with D2 in environments without browser
I was trying D2 integration according to the Documentation and using the same example.
my_table: {
shape: sql_table
id: int {constraint: primary_key}
last_updated: timestamp with time zone
}
When rendering the image on a headless system without browser, the presentation fails on redering the D2 diagram and complains about missing browser dependencies.
I a browser needed to render D2 diagrams or is there an option to disable the requirement?
Error
Error in slide 3:
'd2' execution failed:
Playwright Host validation warning:
╔══════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ Missing libraries: ║
║ libglib-2.0.so.0 ║
║ libgobject-2.0.so.0 ║
║ libnss3.so ║
║ libnssutil3.so ║
║ libsmime3.so ║
║ libnspr4.so ║
Versions
presenterm: 0.15.0 d2: v0.7.0
References
#657
Oh wow this is crazy. So if you run d2 and spit out an svg file it doesn't need a browser. However, when you make it spit out a .png it actually downloads node, chromium and a bunch of things and executes them:
/tmp $ time strace -f -e trace=execve d2 thing.d2 out.png 2>&1 | grep execve | wc -l
9
________________________________________________________
Executed in 2.33 secs fish external
usr time 1.64 secs 812.00 micros 1.64 secs
sys time 0.93 secs 906.00 micros 0.93 secs
/tmp $ time strace -f -e trace=execve d2 thing.d2 out.svg 2>&1 | grep execve | wc -l
1
________________________________________________________
Executed in 110.95 millis fish external
usr time 122.72 millis 0.00 millis 122.72 millis
sys time 50.71 millis 1.68 millis 49.03 millis
/tmp $
This is downloading and executing so much just to convert an svg to png (!!!). Anyway, looks like if I use jpg instead of png it doesn't do all this nonsense. I'll fix in a bit.
lol nevermind:
/tmp $ d2 thing.d2 out.jpg
success: successfully compiled thing.d2 to out.jpg in 58.365877ms
/tmp $ d2 thing.d2 out.png
BEWARE: your OS is not officially supported by Playwright; downloading fallback build for ubuntu24.04-x64.
BEWARE: your OS is not officially supported by Playwright; downloading fallback build for ubuntu24.04-x64.
success: successfully compiled thing.d2 to out.png in 86.096011ms
/tmp $ file out.jpg
out.jpg: SVG Scalable Vector Graphics image
/tmp $ file out.png
out.png: PNG image data, 1248 x 620, 8-bit/color RGBA, non-interlaced
/tmp $
TLDR; if you ask for a .png it converts it with a browser. If you ask for a .jpg it creates an svg file, 10/10 behavior.
So to fix this we'd need to let it write an svg and then manually convert it to png/jpg. There's another open issue around supporting svgs; I'm a bit wary of this because I feel like it will pull in a ton of dependencies but maybe I'm wrong.
What about using an external tool to do the conversion like https://github.com/linebender/resvg that could be optionally toggled via render argument?
Sorry, I've been busy so just getting to this now. I actually started implementing this, but it seems like resvg doesn't support embedded fonts (https://github.com/linebender/resvg/issues/541) so this won't work:
/tmp $ d2 input.d2 out.svg
success: successfully compiled input.d2 to out.svg in 60.673658ms
/tmp $ resvg out.svg out.png
Warning (in simplecss:298): The @font-face rule is not supported. Skipped.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
Warning (in usvg::text:129): No match for '"d2-3955099942-font-regular"' font-family.
/tmp $
The result has no text so it's quite unuseable: