Files
Gaudenz Alder 40f960e839 feat(libavoid): adopt the pure-JS two-file js/libavoid-js CDN layout
The next draw.io release replaces the three-part WASM bundle (glue +
base64 wasm payload + loader) with a single self-contained pure-JS
libavoid.min.js that publishes globalThis.Avoid and parks
window.__libavoidReady itself, next to the shared routing core.

- mcp-app-server: load the bundle + routing core from the CDN as two
  ETag-versioned URLs and drop the loader plumbing the new bundle makes
  obsolete (processLibavoidBundle, libavoidWasmB64, wasm-unsafe-eval
  notes). No pre-release fallback: deploy once the release is on
  viewer.diagrams.net - against the old CDN layout routing degrades
  gracefully to unrouted edges.
- mcp-tool-server: refresh the vendored cold-cache/offline fallback copy
  of libavoid-routing.js verbatim from drawio-dev (dangling-end
  free-point routing, lazily-requested jetty checkpoints, cappedJetty,
  snapToPoint candidate pins).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 19:14:38 +02:00

2.9 KiB

libavoid Vendor (tool server)

Obstacle-avoiding orthogonal edge routing for the routing: "libavoid" option on open_drawio_xml. Vendored from libavoid-js.

Unlike the app server (which loads the pure-JS browser bundle from the viewer.diagrams.net CDN into a sandboxed iframe), the tool server runs in plain Node, so we vendor the node build and let it read the wasm from disk — no patching, no base64.

Artifacts:

  • libavoid-node.mjs — the Node ESM build (libavoid-js dist/index-node.mjs). Exposes AvoidLib.load(wasmPath) / AvoidLib.getInstance(). It reads the wasm via fs.readFileSync (no fetch).
  • libavoid.wasm — the Emscripten binary (~492 KB). Loaded by path: await AvoidLib.load(join(__dirname, "vendor/libavoid/libavoid.wasm")).
  • libavoid-routing.js — the shared routing core (globalThis.AvoidRouting: computeRoutes incl. fixed-connection-point pins, jetty checkpoints, and dangling-end free-point routing, plus the pure geometry helpers). Verbatim copy — the canonical source is drawio-dev src/main/webapp/js/libavoid-js/ libavoid-routing.js (the same artifact the draw.io editor bundles and the app server loads from the CDN); copy it over when it changes there. At runtime libavoid-pass.js loads the CURRENT core through an ETag-revalidated per-user disk cache (src/routing-core-cache.js, primed by npm postinstall, revalidated against https://viewer.diagrams.net/js/libavoid-js/libavoid-routing.js once per process — a 304 unless a draw.io release changed it), so routing fixes ship here automatically. This copy is the last fallback — CDN unreachable with a cold cache, path not yet in a release, or the source failing the sanity check.
  • libavoid.d.ts — TypeScript typings.
  • LICENSE — libavoid-js is LGPL-2.1-or-later.

Usage

import { AvoidLib } from "./vendor/libavoid/libavoid-node.mjs";
// Plain browser script that assigns globalThis.AvoidRouting — a script
// without import/export is valid ESM, so import it for its side effect:
await import("./vendor/libavoid/libavoid-routing.js");
await AvoidLib.load(join(__dirname, "vendor", "libavoid", "libavoid.wasm"));
const Avoid = AvoidLib.getInstance();
const routes = globalThis.AvoidRouting.computeRoutes(Avoid, vertices, edges); // edgeId -> waypoints

Versioning

Vendored from libavoid-js@0.5.0-beta.5.

Refreshing

npm pack libavoid-js && tar -xzf libavoid-js-*.tgz
cp package/dist/index-node.mjs  vendor/libavoid/libavoid-node.mjs
cp package/dist/libavoid.wasm   vendor/libavoid/libavoid.wasm
cp package/dist/index-node.d.ts vendor/libavoid/libavoid.d.ts
cp package/LICENSE              vendor/libavoid/LICENSE

libavoid-routing.js is NOT part of the upstream package — refresh it from drawio-dev (cp ../drawio-dev/src/main/webapp/js/libavoid-js/libavoid-routing.js vendor/libavoid/).