{{ message }}
Repository navigation
fix(muya): render SVG images that state no size of their own (#4991) - #5462
Merged
Merged
Conversation
An SVG carrying only a `viewBox` has no intrinsic size, so it resolves its used width against its containing block (CSS 2.1 §10.3.2). But `.mu-image-container` is shrink-to-fit: the container's width comes from the image and the image's from the container, so Chromium settles on 0 and the image renders as an empty 0x0 box — nothing is shown at all. Pin the width the browser fell back to (the CSS default object size, 300x150 contained to the image's ratio, which `loadImage` already measures) whenever neither the image nor the markdown states a size. The height stays automatic, so `max-width: 100%` keeps scaling such an image by its ratio, and an image with an intrinsic size is left untouched. The pin is applied on the first async load and restated by the renderer, which rebuilds the <img> from vnodes on every re-render. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The collapse is a layout outcome, so no unit test in happy-dom can see it: only a real browser lays the image out. This spec renders a `viewBox`-only SVG and asserts the box the browser gives it (300x150), with a sized SVG as the control. It fails on develop (0x0) and passes with the pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Jocs
force-pushed
the
fix/svg-viewbox-only-collapses-4991
branch
from
September 19, 2026 15:43
c35a597 to
647ec50
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #4991.
The bug
A local SVG that states no
width/height, only aviewBox— the shape everyrich/Textual/mermaid-style export produces — renders as nothing in the editor.Reproduced on 0.20.0-rc.4 with the exact file from the issue: the
<img>loadsfine (
.mu-image-success,complete === true,naturalWidth300), yet itslayout box measures 0x0.
Why
Such an image has no intrinsic size, so CSS 2.1 §10.3.2 resolves its used width
against its containing block.
.mu-inline-imageand.mu-image-containerareboth
inline-block, i.e. shrink-to-fit: the container's width comes from theimage, the image's from the container, and Chromium breaks the cycle at 0. The
same SVG in ordinary block flow (or on GitHub) lays out at 300x136.
This is not a regression — the legacy engine's
.ag-inline-image/.ag-image-containerchain is identical, which is why the issue was filedagainst 0.19.1. An SVG that states its own size has always worked.
CSS alone can't fix it: there is no selector for "replaced element with no
intrinsic size", and
max-width: none,width: fit-content,display: blockon the container and
100cqwwere each measured in the real app — all still 0.The fix
When a loaded image's measured size is the browser's fallback (the CSS default
object size, 300x150 contained to the image's ratio — what
loadImagealreadyreports), pin that width on the
<img>, so the shrink-to-fit container hassomething to shrink to. The height stays automatic, so
max-width: 100%stillscales the image by its ratio when the editor is narrow.
renders identically.
Applied in both render paths:
loadImageAsync's success handler (first load)and
image.ts(every re-render rebuilds the<img>from vnodes).Verification
Real app (electron-vite build of this branch), the issue's own SVG plus a
matrix of local files:
screenshot.svg(viewBox only)viewbox-only.svg(viewBox 200x100)percent.svg(width="100%", viewBox)sized.svg(120x60)big-sized.svg(4000x2000)big.png(2000x1000)Sizes survive a re-render, and narrowing the editor still scales every image by
its ratio (
max-width: 100%unaffected).Tests: new e2e spec fails on develop (0) and passes with the fix (300x150);
unit tests cover the helper and both render paths.
vitest run1911 passed,eslintclean,tsc --noEmitclean,madge --circularclean, and the imagee2e suites (drag, image tools, reference images, inline) all pass.
🤖 Generated with Claude Code