{{ message }}
Repository navigation
fix(muya): size an image from where its resize handle was grabbed (#5392) - #5535
Merged
Merged
Conversation
) `_mouseMove` measured the new width against the opposite handle's current position, read fresh on every event. For the left handle that reference is the image's right edge, and a left-aligned image grows on its right side -- so each width it wrote moved the very edge the next event measured from, re-adding the whole accumulated delta. A 60 px drag widened the image by 210 px, ran away to the column width after ~25 px of travel, and saved a width wider than the one on screen. The right handle measured against the left edge, which does not move, so it tracked the pointer correctly. Snapshot the pointer position and the image width at mousedown and offset from those instead. Nothing read during the drag is affected by what the drag writes, so both handles now track the pointer 1:1, for centre- and right-aligned images as much as the default left-aligned one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Jocs
force-pushed
the
fix/image-resize-left-handle-5392
branch
from
September 23, 2026 14:49
d8dbecb to
0940711
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 #5392.
The bug
Dragging an image's left resize handle resized it several times faster than the pointer moved. A 60 px outward drag widened a 400 px image to 610 px instead of 460; the image hit the column width after about 25 px of travel, and the width saved to the file was larger than the one displayed. A 60 px inward drag collapsed the image to the 50 px floor. The right handle was correct.
Reproduced on
developwith real Chromium input. Width sampled every 10 px of pointer travel on a 400 px image:Root cause
_mouseMovecomputed the width from the opposite handle's current position, read fresh on every event:For the left handle that reference is the image's right edge. A left-aligned image is pinned on its left and grows on its right, so every width the handler wrote moved the very edge the next event measured from. Each move therefore re-added the whole accumulated delta —
width += (leftEdge - clientX)— which compounds per mousemove, so the result depended on drag speed and on how many move events the browser delivered.The right handle measured against the left edge, which does not move, so it tracked the pointer correctly. That asymmetry is why only one handle misbehaved.
The display/save mismatch follows from the same loop: once the runaway width exceeded the column,
max-width: 100%clamped what was rendered while thewidthattribute kept climbing.The fix
Snapshot the pointer position and the image width at mousedown, and offset from those. Nothing read during the drag is affected by what the drag writes, so the feedback loop is gone rather than compensated for. This also drops the need to read either handle's geometry while dragging.
Because the reference is no longer a particular edge, the fix is layout-independent: verified 1:1 tracking for
data-aligncenterandrightas well as the default left-aligned image.Tests
packages/muya/e2e/tests/drag/image-resize-left-handle-5392.spec.ts— new. Drags each handle 60 px in six steps with real Chromium mouse input and asserts the saved width lands within 4 px of the distance dragged, plus that the saved width matches the displayed one. A/B verified: the two left-handle cases fail by 150 px on the unfixed source and pass on the fixed one; the right-handle case passes on both.imageResizeBar.spec.ts— the unit drag helper built its mousedown with no coordinates, which no real browser does; it now carriesxlike the mousemove already did. The pinned width changes from 195 to 200 because the width is now measured from the press rather than from a handle's rect.Fixture note: the spec uses a 400×300 image on purpose.
usesDefaultObjectSizepins an inlinestyle="width"on any image measuring 300 wide or 150 tall (#4991), and that inline style overrides thewidthattribute the bar writes, so such an image does not resize at all — a fixture of those dimensions passes the test without exercising the code.Verification
packages/muya/e2etests/drag/— 72/72 (24 × 3 repeats), and 48/48 on a final re-run.tsc --noEmit,madge --circular— clean. (The worktree is missingpackages/muya/node_modules, which reds out 10 export/prism/katex spec files; that failure set is byte-identical with and without this change.)Cmd/Ctrl+D applies strikethrough, which flips ✘✘✓✘ across four identical repeats with this change in place — flaky, and untouched by it.🤖 Generated with Claude Code