presenterm icon indicating copy to clipboard operation
presenterm copied to clipboard

Error with D2 in environments without browser

Open bakito opened this issue 4 months ago • 4 comments

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

bakito avatar Aug 06 '25 14:08 bakito

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.

mfontanini avatar Aug 06 '25 22:08 mfontanini

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.

mfontanini avatar Aug 06 '25 23:08 mfontanini

What about using an external tool to do the conversion like https://github.com/linebender/resvg that could be optionally toggled via render argument?

bakito avatar Aug 07 '25 05:08 bakito

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:

Image

mfontanini avatar Sep 05 '25 22:09 mfontanini