fix(chat): drop link marks whose text was replaced by a paste (JS-9869) #2363

Merged
requilence opened 1:00pm on September 1, 2026 wanted to merge 1 commit into anyproto/anytype-ts develop from
fix/JS-9869-chat-paste-link-marks

Pull Request Overview

  • Opened on September 1, 2026
  • Status Merged
  • Commit count 1 with first commit September 1, 2026

Total Delta

0 Total Diff Delta

Open Days

Open 14 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Data pending calculation for pull request

Author avatar

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 typecheck exit 0, eslint clean

Repro


  1. Paste text containing two or more auto-linkable URLs into the chat composer

  2. Select that text and paste replacement text over it

  3. 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.