Pull Request Overview
- Opened on September 1, 2026
- Status Merged
- Commit count 1 with first commit September 1, 2026
Total Delta
Open Days
Test Delta
How long has this pull request spent in each phase of its lifecycle?
Data pending calculation for pull request
fix(chat): drop link marks whose text was replaced by a paste (JS-9869)
Problem
Pasting over selected text in the chat composer leaves behind the Link marks that belonged to the replaced text. The sent message ends up with grey markuplink runs sitting on ordinary words, each still pointing at a URL from the earlier paste.
Cause
parseText adjusted marks with:
marks.current = Mark.adjust(marks.current, from, newText.length - (to - from));
Mark.adjust only knows an insertion point and a net delta β it has no idea a range was deleted. A mark that sat entirely inside the replaced selection matches mark.range.from >= from, so it is shifted by the delta instead of dropped, and lands on whatever text now occupies that offset. Mark.checkRanges keeps it (in-bounds, non-empty), and checkUrls then adds a correct mark for the real URL because its dedupe only checks the newly-found range β so the message carries one correct link plus one stranded link per URL that was in the replaced text.
Fix
Mark.adjustForReplace(marks, from, to, length) drops param-carrying marks whose whole range sat inside the replaced text, then adjusts the rest. It uses the same needsBreak predicate onKeyUpInput already applies when a character is typed over a selection (form.tsx:362-369) β that guard existed for typing but not for pasting. Wired into both chat paste paths (βV and ββ§V).
Verification
Replaying the reported sequence through the real getUrlsFromText / Mark.adjust / checkRanges / checkUrls:
Before β 3 Link marks, 2 of them stranded:
264-282 https://example.com covers "schemas.anytype.io" β correct
362-380 https://example.com covers "ed, that's likely " β stranded
424-434 https://example.org covers "hboard cli" β stranded
After β 1 mark:
264-282 https://example.com covers "schemas.anytype.io"
- 6 new unit tests in
mark.test.ts, written failing first; 107 pass in that file -
bun run typecheckexit 0, eslint clean
Repro
- Paste text containing two or more auto-linkable URLs into the chat composer
- Select that text and paste replacement text over it
- Send β the message renders links over non-URL words
Notes
Not a regression of JS-9819 (bare-domain over-detection). That fix is intact: the detector finds exactly one URL in the affected message; the extra links come from stale marks, not from detection.
The editor's paste path (component/block/text.tsx:518-520) already does this as an explicit delete-then-insert pair and is unaffected.
Closes JS-9869
PR was closed without comments.