Repository navigation
fix(session-ui): copy Markdown selections without theme colours - #59151
Conversation
There was a problem hiding this comment.
This fixes the problem. On the base, copying a selection from a message puts Chromium's inlined computed styles (text colour, background, fonts) into text/html. With this change the HTML is clean semantic markup and text/plain is unchanged. I checked this with a Playwright test that reads the real clipboard in both checkouts, plus the new unit and component tests and typecheck:tsc.
Public API: unchanged. This is internal to the session UI's Markdown component.
One thing worth fixing: once a Mermaid diagram has rendered, its hidden source block is still copied into the HTML (see the inline comment).
| "style", | ||
| "template", | ||
| "svg", | ||
| '[aria-hidden="true"]', |
There was a problem hiding this comment.
Once a Mermaid diagram renders, its source <pre> is still in the DOM, hidden with display: none ([data-mermaid-ready="true"] > pre / [data-mermaid-pending="true"] > pre in markdown.css). The clone picks it up. When I selected a message containing a diagram, text/html contained <pre><code>flowchart LR\n A[Start] --> B[End]</code></pre>. text/plain (and the base's HTML) don't contain that source; the plain text has the diagram labels instead. This is the same hidden-content problem that the fallback for selections leaving the message is meant to avoid. Could the hidden Mermaid <pre> be added to removedSelector, e.g. [data-mermaid-ready="true"] > pre, [data-mermaid-pending="true"] > pre? That would keep the HTML in line with what's on screen.
862a6ea to
51f1bff
Compare
There was a problem hiding this comment.
The latest push is a rebase onto dev with no changes to this PR's files. The clipboard unit test, the two new Chromium copy tests and typecheck:tsc still pass. The public API is unchanged.
The earlier point about the hidden Mermaid source being copied into text/html is still open.
Issue for this PR
Closes #54003
Type of change
What does this PR do?
When you select text in a message and copy it, Chromium writes
text/htmlwith the computed styles inlined. In a dark theme that includes the light text colour, and code blocks keep their syntax-highlightstylespans. Pasted into Docs, Gmail or Slack, you get white-on-white text and theme-coloured code.Markdownnow handlescopyfor selections that stay inside it:text/plainisselection.toString(), the same text as before.text/htmlis the selected range cloned from the DOM. Cloning doesn't carry computed styles. It drops the copy button, svg icons,aria-hiddenfavicons and.sr-only, and removes every attribute excepthref(http/https/mailto),img src(http/https),alt,colspan,rowspanandstart. So bold, italic, headings, lists, tables, code, links and blockquotes come through, but no colours or classes.strong,pre > code,ul > li, table rows, …) so it keeps its meaning. Selecting part of a code block pastes as code, for example.A selection that leaves the message (for example, across tool cards) keeps the browser's default copy, because the surrounding UI can contain hidden content that a DOM clone would pick up.
How did you verify your code works?
bun test src/components/markdown-clipboard.test.ts: structure kept, colours, classes and copy buttons removed, partial selections wrapped, unsafe or local links dropped.component-tests/markdown.spec.tsrun in Chromium: they render real Markdown in a light-text page, select it and press Ctrl/Cmd+C, then check thetext/htmlcontains<h2>,<strong>, a link, list items and<pre><code>with nostyle=,class=,<button>or<svg>. They also check that a selection extending outside the Markdown is left to the browser. The existing Markdown component specs I ran still pass.renders class and connected subgraph diagrams in lightalso fails ondevon this machine.bun run typecheck,bun run typecheck:tsc(session-ui) andbun run lint:changed.Checklist
Requested by: @Brendonovich (Brendan via Slack)
Added by the opencode bot (AI-generated).
Related: #54002, #56672