Skip to content

fix(web): copying a code block no longer copies triple backticks - #8448

Open
ipanasenko wants to merge 4 commits into
pingdotgg:mainfrom
ipanasenko:t3code/address-macroscope-comments
Open

fix(web): copying a code block no longer copies triple backticks#8448
ipanasenko wants to merge 4 commits into
pingdotgg:mainfrom
ipanasenko:t3code/address-macroscope-comments

Conversation

@ipanasenko

@ipanasenko ipanasenko commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

In code block, when the very last linebreak is highlighed and copied, it also copies markdown's backticks. This should not happen

Before After
image image

===== TEXT BELOW IS GENERATED BY AI =======

Problem

Dragging a selection over the final linebreak of a fenced code block ends the range after the closing pre. The clipboard serializer then no longer saw the selection as sitting inside the block, so it re-fenced the content as markdown. Copying a shell command that way pasted it wrapped in stray backticks, which breaks the paste into a terminal.

Fix

serializeRenderedMarkdownFragment now scans the fragment first. If the only thing a reader would see in it is one code block (header chrome, select-none elements and whitespace do not count), the fragment copies as plain code, matching a selection that never left the pre. Prose alongside the block, or a second block, still copies as fenced markdown.

Surfaces

  • Clients: web, and desktop by wrapping it. Mobile has no rendered-markdown clipboard path.
  • Providers / contracts: untouched, this is client-side clipboard serialization only.

Verification

Added unit coverage in apps/web/src/markdown-clipboard.test.ts for the drag-past-the-last-line case and for the fragments that must keep their fences. All 6 cases in that file pass. A workspace pnpm install is blocked in my environment by an unrelated registry policy on @clerk/electron@0.0.37 (pinned on main), so I ran the file against the module directly and am leaning on CI for the full suite.

No visual change: the behavior is clipboard content only.

Model: Claude Opus 5. Harness: Claude Code.

Note

Fix copying a code block to no longer include triple backticks

  • Adds scanForSoleCodeBlock and soleCodeBlock helpers in markdown-clipboard.ts to detect when a selection contains exactly one <pre> element and no other visible content
  • serializeRenderedMarkdownFragment now returns plain textContent (trailing newline trimmed) when the sole-code-block condition is met, skipping the fenced-code path that was always used before
  • Visible-content detection treats non-empty text, images, <hr>, list items that don't wrap the <pre>, and non-empty data-markdown-copy elements as "other" content, so mixed selections still produce fenced code as before
  • Risk: the scanner skips elements flagged by isSkippedElement and treats empty data-markdown-copy as non-visible; edge cases where a selection has a lone <pre> plus only skipped or empty elements will now copy without fences

Macroscope summarized 5a8cb5c.


Note

Low Risk
Client-only clipboard serialization in the web app; behavior is more nuanced around list items and data-markdown-copy, but no auth, data, or API impact.

Overview
Fixes highlight-and-copy in rendered chat markdown so a selection that is only one code block (including when the range extends past the final newline and pulls in the whole pre) pastes raw code instead of fenced ``` markdown.

serializeRenderedMarkdownFragment now runs a soleCodeBlock scan before normal serialization. If the fragment has a single PRE and no other visible content—while treating list markers, data-markdown-copy chips, images, and similar as disqualifying—it returns the block’s textContent. Prose beside a block, multiple blocks, or mixed fragments still get the existing fenced markdown path.

Tests expand the DOM fakes (attributes, querySelector, rendered Shiki blocks) and add cases for list items, file chips, drag-past-last-line, and prose+code combinations.

Reviewed by Cursor Bugbot for commit 5a8cb5c. Bugbot is set up for automated code reviews on this repo. Configure here.

Dragging a selection over the final linebreak of a fenced block ends the range after the closing pre, so the clipboard serializer no longer saw the selection as inside the block and re-fenced it. Pasting a shell command then carried stray backticks.

A rendered fragment whose only visible content is one code block now copies as plain code, matching a selection that never left the pre. Prose or a second block alongside it still copies as fenced markdown.

Model: Claude Opus 5. Harness: Claude Code.
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 861424ba-55f3-4af5-8e84-6f7e0b7615f7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 27, 2026
Comment thread apps/web/src/markdown-clipboard.ts Outdated
Comment thread apps/web/src/markdown-clipboard.ts
The sole-code-block scan tested isSkippedElement before data-markdown-copy,
the reverse of serializeNode. A file chip renders as a button, a skipped tag,
so the scan read it as invisible chrome and copied the fragment as bare code,
dropping the file reference.

Model: Claude Opus 5. Harness: Claude Code.
serializeListItem emits a marker for every item, so an item with no visible
text still carries content: a bare "- " or a task state. The sole-code-block
scan recursed through such items without counting them, so a fragment holding
an empty or checkbox-only item plus a code block copied as bare code and lost
the marker.

An item that does not hold the block now counts as other content. An item that
wraps the block still does not, since a selection that never left the pre would
drop its marker too.

Model: Claude Opus 5. Harness: Claude Code.
Model: Claude Opus 5. Harness: Claude Code.
@ipanasenko ipanasenko changed the title fix(web): copying a code block no longer pastes its fences fix(web): copying a code block no longer copies triple backticks Aug 27, 2026
@ipanasenko
ipanasenko marked this pull request as ready for review August 27, 2026 21:45
@macroscopeapp

macroscopeapp Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 5a8cb5c

Macroscope's review found this PR approvable — This is a focused client-side clipboard bug fix that changes formatting only when a selection consists solely of one rendered code block; mixed selections retain the existing fenced-markdown behavior. The implementation is localized and covered by targeted tests, with no API, data, infrastructure, authentication, billing, or security impact.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant