Skip to content

fix(exports): preserve SVG HTML labels in image exports - #277

Merged
yaacovcorcos merged 1 commit into
mainfrom
codex/svg-export-fix-20260910
Sep 11, 2026
Merged

fix(exports): preserve SVG HTML labels in image exports#277
yaacovcorcos merged 1 commit into
mainfrom
codex/svg-export-fix-20260910

Conversation

@yaacovcorcos

@yaacovcorcos yaacovcorcos commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Mermaid's sanitized, HTML-compatible SVG is not always valid standalone XML (notably HTML line breaks). Separately, loading an SVG containing HTML labels from a blob URL can taint Chromium's canvas and prevent PNG encoding. Copying a saved SVG in the shared image viewer follows the same affected path.

Targeted fix

  • Serialize Mermaid output through an inert DOM into valid SVG/XML, preserving SVG, XHTML and MathML content, geometry, IDs and references.
  • Share one image decoder: SVG uses a self-contained data URL in the browser's non-interactive image context; raster images retain short-lived blob URLs. No browser-security relaxation or remote renderer.
  • Give the diagram raster copy explicit dimensions and preserve existing output bounds. Release canvases after encoding, including failures.
  • Preserve original-file downloads, asset fetch/CORS checks, clipboard handoff, Mermaid source and on-screen rendering. No dependency, provider, guidance or UI changes.

The production change is confined to three files and removes duplicate decoding code. Most added lines are regression tests.

Verification

  • Before realignment, full pnpm run test: 19,903 passed, 108 skipped across 27 package suites. The original PR CI passed in full.
  • After rebasing onto current main and Mermaid 12.0.0: 70 focused tests passed; the existing Mermaid rendering smoke passed with zero XML/PNG failures; the deeper real-Electron/Chromium export test passed 28 diagram/theme cases.
  • The Chromium check covers SVG structure/namespaces, actual label pixels, PNG copy/download consistency, copying saved SVGs, Unicode/RTL/line breaks, invalid XML, bounded images, 24 concurrent SVG decodes and PNG/JPEG copy. External-resource requests: zero.
  • After realignment, frozen-lockfile install, formatting, lint, full type checks, full build and git diff --check passed. Existing unrelated lint warnings remain; no lockfile change.
  • Added the export regression command to the existing CI Test job under Xvfb. Linux CI is pending.

No computer-use or manual visual acceptance was performed. A target-isolated app from the rebased commit is running for owner review. The targeted hidden Electron test uses a temporary profile and does not touch the user's clipboard.

Relationship to the other Mermaid work

Rebased onto current main after #276 merged. The sole command-list conflict retained both complementary smoke tests, and #276's rendering test now requires successful standalone SVG and PNG export instead of preserving the old known-failure baseline. No repair-UX or rendering behavior was changed.

This fixes export correctness; SVG readers still need HTML-label (foreignObject) support. Converting HTML labels to SVG text is not included.

Documentation impact: Updated — docs/internals/scient-chat-diagrams.md.

Model and harness: GPT-5; Codex desktop harness.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 10, 2026
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.5 KiB 13.6 KiB +103 B (+0.7%) 15.1 KiB
Codex Thread snapshot wire 7.1 KiB 7.1 KiB +2 B (+0.0%) 7.3 KiB
Codex Live turn WebSocket wire 6.4 KiB 6.5 KiB +101 B (+1.5%) 7.8 KiB
Codex Live turn WebSocket decoded 56.2 KiB 57.0 KiB +822 B (+1.4%) 66.4 KiB
Codex Live turn messages 8 8 0 (0.0%) 21
Claude Total thread wire 13.6 KiB 13.5 KiB −81 B (−0.6%) 15.1 KiB
Claude Thread snapshot wire 7.1 KiB 7.1 KiB +5 B (+0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.5 KiB 6.4 KiB −86 B (−1.3%) 7.8 KiB
Claude Live turn WebSocket decoded 57.8 KiB 57.0 KiB −840 B (−1.4%) 66.4 KiB
Claude Live turn messages 8 8 0 (0.0%) 21

Baseline: 7937489 · PR result: abde9e5 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 114.1 KiB
  • Claude decoded thread snapshot: 114.7 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@yaacovcorcos
yaacovcorcos force-pushed the codex/svg-export-fix-20260910 branch from e366f74 to abde9e5 Compare September 11, 2026 03:50
@yaacovcorcos
yaacovcorcos marked this pull request as ready for review September 11, 2026 04:05
@yaacovcorcos
yaacovcorcos merged commit afe6213 into main Sep 11, 2026
30 checks passed
@yaacovcorcos
yaacovcorcos deleted the codex/svg-export-fix-20260910 branch September 11, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant