[EW] Canvas image replacement updates every matching source
- Dominant language
- JavaScript
- Stars
- 34
- Forks
- 71
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 29
Description
## Summary
Replacing an image from Canvas layout/split view is keyed by `originalSrc`, and the da-live host updates **every** ProseMirror image whose source/path matches. If the same authored image URL is used in more than one field, dropping a replacement onto one field can replace all matching fields.
## Current behavior
The quick-edit request includes `cursorOffset`, but the da-live handler ignores it:
- Protocol payload: `nx/utils/message-types.js` documents `{ cursorOffset, imageData, fileName, mimeType, originalSrc }`.
- Request handling: `blocks/canvas/ew-editor-wysiwyg/utils/image.js:61` destructures only `imageData`, `fileName`, and `originalSrc`.
- `updateImageInDocument()` walks the entire document and calls `tr.setNodeMarkup()` for every image whose source/path matches: `blocks/canvas/ew-editor-wysiwyg/utils/image.js:6-40`.
The current da-nx sender also derives `cursorOffset` from `data-prose-index` on the ``, while Canvas instrumentation places exact image identity in `data-image-index`. That makes the intended positional identity unavailable or null in common cases and should be coordinated with the host hardening.
## Reproduction
1. Author two image fields that reference the same source URL/path.
2. Open the page in Canvas layout or split view.
3. Drop a replacement image onto only one of the two rendered images.
4. Observe that both matching canonical ProseMirror image nodes receive the new source.
The defect is also directly visible from the unbounded `state.doc.descendants()` loop: it does not stop after a match.
## Expected behavior
Only the canonical image node corresponding to the image field that received the drop is updated.
When exact positional identity is unavailable:
- a unique source match may be used as a backward-compatible fallback;
- multiple source matches must fail safely rather than mutating all matching fields or guessing.
## Suggested direction
1. Resolve the target image by a validated canonical image position (`cursorOffset`) when present.
2. Fall back to source/path only when exactly one canonical image matches.
3. Return an explicit ambiguity error when more than one source match exists.
4. Update the da-nx sender to provide the exact image position from `data-image-index` or from the mounted mini-editor's local position plus its canonical base offset.
5. Add unit coverage for exact-position targeting, unique-source fallback, stale offsets, and duplicate-source ambiguity.
## Impact
This is an authored-content identity/data-integrity issue in pre-GA Canvas: one direct manipulation can change multiple fields that the author did not target.
Contributor guide
Research direction
Start with blocks/canvas/ew-editor-wysiwyg/utils/image.js:6-40 and :61, then read nx/utils/message-types.js for the cursorOffset payload. Trace how the da-nx sender obtains image identity and verify exact-position, unique-source fallback, stale-offset, and duplicate-source cases. Done means only the targeted canonical image changes and ambiguous matches fail safely, with unit coverage for those cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100