Skip to content

Excalidraw 2.2.0: edit .excalidraw.svg and .excalidraw.png images - #79

Merged
nwparker merged 4 commits into
mainfrom
nwparker/support-editable-.excalidraw.svg-and-.excalidraw
Nov 8, 2026
Merged

nwparker merged 4 commits into
mainfrom
nwparker/support-editable-.excalidraw.svg-and-.excalidraw

Conversation

@nwparker

@nwparker nwparker commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Closes #77. The Excalidraw plugin (2.1.0 → 2.2.0) now opens and saves .excalidraw.svg and .excalidraw.png images that carry an embedded scene. These are the files Excalidraw writes when you export with "Embed scene" on.

  • Two new editors, excalidraw-svg and excalidraw-png. They are served from a second entry page, editor/image.html. Plain .svg/.png files are not claimed.
  • Embed codec (build/src/excalidraw-image.js, synchronous): reads and writes Excalidraw's embed format.
    • SVG: the <!-- payload-start --> base64 JSON wrapper, compressed (deflate) or plain, in the legacy v1 or the current v2 form.
    • PNG: the tEXt chunk with keyword application/vnd.excalidraw+json, written right after IHDR because Excalidraw reads only the first tEXt chunk. Each chunk gets a correct CRC.
    • Files without a scene, or with a broken one, open with a clear message instead of an empty canvas that would overwrite them.
  • Saving keeps the format. It redraws the picture with Excalidraw's own exportToSvg/exportToBlob and embeds the scene again. The picture keeps the file's scale, padding, background and dark mode. Excalidraw's loadFromBlob reads our output back unchanged.
  • Save deadline. Saves stay within Orca's 1 s editor.flush deadline.
    • The picture controller registers its flush handler before the session's, so it can time the save from the start.
    • The session reports how long its last encode and decode took.
    • A fresh picture goes into the save only if it still fits within 800 ms. Otherwise the save keeps the previous picture and the new one is sent right after, so the tab shows as changed until the next save.
    • A picture finished during a save is held until the save is decided.
  • Other changes:
    • Rebuilt editor/; the build is deterministic.
    • Docs updated in README.md and build/README.md.
    • Release 2.2.0 added to orca-catalog.json, generated by scripts/release-entry.mjs --write and re-pinned after the deadline fix.

Verification

  • cd plugins/excalidraw/build && npm test: 22/22 pass. Covered:
    • Codec round trips, including legacy and plain payloads, and pictures without a scene or with a broken one.
    • Merge and edit behaviour.
    • Picture timing: idle redraw, the deadline, render failure, and the case where re-encoding would not fit. I confirmed the last test fails if the cost estimate or the handler order is reverted.
  • Playwright E2E of the built editor/ against a fake Orca host that enforces Orca's CSP and the 1 s flush deadline: 65/65 checks pass. Covered:
    • Open, edit, save and reopen for SVG and PNG.
    • Scale, background and dark mode preserved.
    • Excalidraw's loadFromBlob reads our output.
    • External changes are merged.
    • A scene holding 3.7 MB of images saves in about 430–540 ms, without the new picture. A 0.4 MB scene saves its picture in about 75–145 ms.
  • ORCA_DIR=<orca@81ec82b> node scripts/release-entry.mjs: release entries: ok. node scripts/check-catalog.mjs: catalog: ok.
  • orca plugin validate plugins/excalidraw: valid, 3 custom editors.
  • orca plugin check plugins/excalidraw: valid with no errors. It shows the same 4 editor_eval warnings (from bundled Excalidraw code) as on main.
  • orca plugin shot --editor in real Orca (1.4.254) rendered both new editors with their embedded scenes.

Execution profile (for anything above data, say why it is needed)

sandboxed-ui, the same as 2.1.0. Excalidraw has to run as a custom editor in Orca's isolated editor frame. This change adds no capabilities, permissions or network access.

nwparker and others added 4 commits November 7, 2026 22:47
Opens SVG and PNG images that carry an embedded Excalidraw scene in the
editor, and saves them in the same format: the scene is embedded the way
Excalidraw does (deflated bstring payload in SVG <metadata> or a PNG tEXt
chunk) and the picture is drawn again from it, keeping the image's scale,
background and dark mode. Edits send the new scene at once; the picture
follows once the canvas is idle, and a save waits for it within Orca's
flush deadline.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A save of an .excalidraw.svg or .excalidraw.png now times itself from the
start of Orca's flush: the picture's handler registers before the session's,
and the session reports how long its last encode and decode took. The new
picture goes into the save only if sending it still ends within 800 ms of
Orca's 1 s; otherwise it is drawn once the canvas is idle and sent after the
save. A picture drawn during a save is held until the save decides, and the
drawing starts only after the scene's own send, so it never slows a save it
cannot join.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nwparker
nwparker merged commit 6ba20e1 into main Nov 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support editable .excalidraw.svg and .excalidraw.png files

1 participant