// Local render sidecar for whiteboard frame mode: turns Excalidraw scene // JSON (the format Nextcloud Whiteboard's .whiteboard files use -- // {"elements", "appState", "files"}, see app/webdav_client.py) into a // PNG, using the real Excalidraw export code rather than a hand-rolled // reimplementation of its element types/styling/fonts. That's the whole // reason this exists as Node rather than more Python: @excalidraw/utils // IS the renderer real whiteboards are drawn with, so this reproduces // whatever a user actually sees in their whiteboard exactly, and never // drifts out of sync with new element types as Excalidraw adds them. // // Runs as a second process inside the main Python server's own // container (see ../Dockerfile installing Node, and ../start.sh // launching this in the background before exec'ing uvicorn) -- not a // separate deployment, no independent scaling/restart needs, so one // container is simpler than a second docker-compose service. Bound to // 127.0.0.1 only: reachable from the Python process in the same // container, never from outside it, so there's no auth on top of that // -- the network boundary IS the access control here. // // No headless browser (Puppeteer/Playwright) -- jsdom provides just // enough of a browser-like global environment for @excalidraw/utils' // internal DOM calls (e.g. text measurement) to work, and // @resvg/resvg-js (a native Rust SVG rasterizer, no browser process) // turns the resulting SVG into the actual PNG. const { JSDOM } = require('jsdom'); // @excalidraw/utils is a browser bundle: it references things like // `devicePixelRatio` and `location` as bare identifiers, the same way // inline