{{ message }}
Repository navigation
fix(muya): take the image references from the live DOM after selecting (#5391) - #5534
Merged
Merged
Conversation
#5391) Clicking an image emitted `muya-transformer` (and the image toolbar's rect) from the nodes that were in the document at click time, and only then called `selectImage`. That call nulls `editor.activeContentBlock`, which runs `Format.blurHandler` -> `checkNeedRender()` -> `update()`, and the inline renderer's `patch` reassigns the paragraph's `innerHTML`. Every node inside it, the clicked image's wrapper and container included, is replaced. `checkNeedRender()` is true whenever the caret sits within one character of a token's range, so a caret anywhere on the image's own line always triggers it -- the state a document that opens on an image is already in, since `Editor.init()` focuses the first block at offset 0. `ImageResizeBar` renders on a `setTimeout`, so by then it held a detached container: an all-zero bounding rect, drawing both handles at `left: -5px; top: -25px` instead of on the image's edges, where only a sliver shows and dragging cannot resize. `autoUpdate` never recovers, because a detached node never moves. A second click found the block already blurred, hence no re-render and correct handles. Select first, then read both references off the live DOM. The clicked image is re-found by its position among the paragraph's images, which survives the re-render -- ids do not identify it (images sharing a src and paragraph offset render with the same id). Taking the toolbar's rect afterwards too fixes the second manifestation: when the caret revealed markers of another token in the paragraph, hiding them on blur reflows the line and shifts the image sideways, so the pre-render rect left the toolbar behind by that offset. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

Closes #5391.
The bug
With the caret on the image's line, the first click on an image showed the image toolbar but no resize handles — both were drawn at the window's top-left corner (
left: -5px; top: -25px), where only a ~5px sliver is visible and dragging cannot resize. A second click placed them correctly.Root cause
ImageSelection._handleClickInlineImageemittedmuya-transformer(and the toolbar's rect) from the nodes present at click time, and only afterwards calledselectImage. That call nullseditor.activeContentBlock, which runsFormat.blurHandler→checkNeedRender()→update(), andInlineRenderer.patchreassigns the paragraph'sinnerHTML— replacing the clicked image's wrapper and container.checkNeedRender()is true whenever the caret sits within one character of a token's range, so a caret anywhere on the image's own line always triggers it. That is the state a document opening on an image is already in:Editor.init()focuses the first block at offset 0.ImageResizeBarrenders on asetTimeout, so it was left holding a detached container — an all-zero bounding rect, hence the corner. ItsautoUpdateloop never recovers, because a detached node never moves. The second click found the block already blurred, so nothing re-rendered and the handles landed correctly.Instrumented confirmation (tagging the container before the click):
The fix
Select first, then read both references off the live DOM. The clicked image is re-found by its position among the paragraph's images, which survives the re-render; ids do not identify it (images sharing a src and paragraph offset render with the same id, which is why the previous code resolved from the clicked wrapper in the first place).
Taking the toolbar's rect after the re-render too fixes a second manifestation found while investigating: when the caret had revealed the markers of another token in the same paragraph, hiding them on blur reflows the line and shifts the image sideways (measured: 35.25px for
**bold**  tail), so the pre-render snapshot left the toolbar behind by that offset.Tests
packages/muya/src/selection/__tests__/imageResizeBarCaretOnImageLine.spec.ts— 2 unit specs asserting the emitted reference is still attached to the document, and is the clicked one when a paragraph holds several. Both fail ondevelop.packages/muya/e2e/tests/drag/image-resize-bar-caret-on-image-line-5391.spec.ts— 3 Playwright specs measuring real handle/toolbar geometry for the issue's three entry paths. All three fail ondevelop(handles off by 290px).Verified locally: full muya unit suite unchanged apart from the 2 new passes; full muya e2e chromium run 390 passed, the remaining failures reproduced identically on
developin isolation (plantuml/sequence network flakes,inline/format-toolbar).🤖 Generated with Claude Code