Skip to content

fix(web): preserve selected text when copying over HTTP#2120

Merged
wbxl2000 merged 1 commit into
MoonshotAI:mainfrom
yicun:fix/web-clipboard-paste
Jul 24, 2026
Merged

fix(web): preserve selected text when copying over HTTP#2120
wbxl2000 merged 1 commit into
MoonshotAI:mainfrom
yicun:fix/web-clipboard-paste

Conversation

@yicun

@yicun yicun commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Related Issue

No tracking issue — the regression was reported through user feedback; the problem is described below.

Problem

Since #1714 (v0.27.0), copying selected chat text over plain HTTP replaces the clipboard contents with [object ClipboardEvent] instead of the selected text.

Root cause chain:

  1. fix(web): make code block copy work over plain HTTP #1714 added @copy="copyCodeBlockFallback" to <MarkdownRender> so code-block copy keeps working over plain HTTP, where navigator.clipboard is unavailable.
  2. markstream-vue's NodeRenderer forwards onCopy to every block-level child, but ParagraphNode and InlineCodeNode do not declare emits: ["copy"]. Vue 3 attrs fallthrough therefore registers onCopy as a native DOM copy listener on the <p> root element.
  3. When the user copies selected text inside a paragraph, the native ClipboardEvent is intercepted by that listener and re-emitted up the tree as the component copy event, so the fallback handler receives the event object instead of a code string.
  4. Over HTTPS this is harmless because the fallback early-returns when navigator.clipboard.writeText exists. Over plain HTTP it falls through to the legacy <textarea> + execCommand path, where assigning the event to textarea.value stringifies it to "[object ClipboardEvent]" and overwrites the user's real selection.

This matches the reports: inline code reproduces consistently (it always lives inside a <p>), while headings/lists/tables declare emits and are unaffected; Thinking blocks are unaffected because they are not rendered through markstream.

What changed

  • Moved the plain-HTTP fallback from Markdown.vue into clipboard.ts as copyCodeBlockFallback(payload: unknown).
  • Non-string payloads (the bubbled native ClipboardEvent) are discarded, so the browser's default selection copy proceeds untouched; genuine code-block copy emits (strings) still get the legacy fallback.
  • Added regression tests covering both cases over plain HTTP.

The durable fix belongs upstream (markstream-vue should declare emits: ["copy"] on ParagraphNode / InlineCodeNode); this PR stops the clipboard clobbering in the meantime.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 002aaf5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@002aaf5
npx https://pkg.pr.new/@moonshot-ai/kimi-code@002aaf5

commit: 002aaf5

@wbxl2000
wbxl2000 merged commit 0d00a07 into MoonshotAI:main Jul 24, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants