fix: backslash newlines when copying from a code block#2709
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughCode block selections in clipboard operations now bypass HTML-to-markdown conversion and use raw text directly. HTML serialization pipelines thread block type metadata through to enable this, and test helpers are configured to properly validate code element handling. ChangesCode block clipboard and export handling
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@blocknote/ariakit
@blocknote/code-block
@blocknote/core
@blocknote/mantine
@blocknote/react
@blocknote/server-util
@blocknote/shadcn
@blocknote/xl-ai
@blocknote/xl-docx-exporter
@blocknote/xl-email-exporter
@blocknote/xl-multi-column
@blocknote/xl-odt-exporter
@blocknote/xl-pdf-exporter
commit: |
9352e24 to
eb3498b
Compare
matthewlipski
left a comment
There was a problem hiding this comment.
Looks good, agree that copying within code blocks should preserve the block HTML, rather than just the inline HTML. Though I'm seeing different behaviour on main to what you describe. Given this code block:
const a = 1;
const b = 2;This is the plain text I see get pasted:
const a = 1; const b = 2;
Whereas if I understand correctly, you were seeing this:
const a = 1;\n
const b = 2;
Any idea what's up with that?
|
@matthewlipski, it depends on where you paste the content after. |
|
^ just realizing the code fence will mess this up |
When copying inline content from inside a code block, the text/plain clipboard payload had a backslash before every newline (markdown's hard-break syntax) and the text/html had `<br>` separators inside the code instead of literal newlines. Two changes fix this: - copyExtension routes selections inside a code block through the block-export path so the code block's own toExternalHTML produces the proper `<pre><code>` wrapper. - serializeInlineContentExternalHTML now plumbs blockType through to inlineContentToNodes (mirroring the internal HTML serializer) so `\n` in code-block content stays as literal text instead of being split into hardBreak nodes that render as `<br>`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`as const` typed `ignore` as a readonly tuple, which doesn't match `UserConfig.ignore: string[]`, breaking CI typecheck. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address PR review: - Drop standalone codeBlockMarkdown.test.ts; add `codeBlockFullContent` and `codeBlockPartialSelection` cases to copyTestInstances.ts and snapshot text/plain markdown for all copy test instances via a new `Copy tests (Markdown)` describe block (mirrors the export test pattern). - Trim verbose comments in copyExtension and serializeBlocksExternalHTML. - copyPasteEquality executor now passes the actual markdown payload as the text/plain MIME instead of a literal "text" placeholder, so paste handlers that prefer text/plain (e.g. inside code blocks) round-trip correctly. - Update mixedInParagraph snapshots: prettify's `ignore: ["code"]` preserves trailing whitespace inside `<code>` spans, which is the actual HTML output.
eb3498b to
ec02d44
Compare




Summary
Copying content from inside a code block produced a clipboard payload littered with backslashes — every newline in
text/plainwas prefixed with\(markdown's hard-break syntax), andtext/htmlhad<br>separators inside the code instead of literal newlines.Reproduction: select code in a code block → paste into any plain-text app:
This PR fixes the root cause so both
text/htmlandtext/plaincome out clean.Rationale
Tracing the clipboard pipeline showed two compounding issues:
Inline-only export path was used for code-block selections. When the selection lives inside a single block, copyExtension takes a shortcut that strips the block wrapper — producing inline HTML for cleaner pastes. For paragraphs that's right; for code blocks it's wrong, because the
<pre><code>wrapper carries semantic meaning. Without it, the markdown converter has no idea this is code and treats every line break as a paragraph hard-break (\+ newline).serializeInlineContentExternalHTMLre-introduced<br>for code content. It callsinlineContentToNodeswithout ablockType, which makes it split every\ninto ahardBreakPM node. Those serialize as<br>— even when wrapped in<pre><code>. The internal-HTML serializer already passedblockTypethrough; the external one didn't.Changes
copyExtension.ts— guard the inline-only optimization with aparent.type.spec.codecheck. Code-block selections fall through to the existing block-export path, which invokes the code block's owntoExternalHTML(proper<pre><code class="language-X" data-language="X">).serializeBlocksExternalHTML.ts— plumbblockTypethroughserializeInlineContentExternalHTML(viaoptions.blockType) soinlineContentToNodeskeeps\nas literal text for code-content blocks.serializeBlockpassesblock.type.tests/.../exportTestExecutors.ts—prettify(..., { ignore: ["code"] })so code-block snapshots show real newlines instead of having them collapsed by the prettifier.tests/.../codeBlockMarkdown.test.ts— three regression tests: full code-block copy, partial selection within a code block, and a paragraph-copy guard to prove non-code paths are untouched.<br />inside<pre><code>).Impact
After the fix, for the user's repro:
text/html: `}` — proper code semantics, real newlines.text/plain: clean fenced markdown block, no backslashes.No behavior change for non-code blocks. The inline-only optimization for paragraphs, headings, etc. is preserved exactly.
Testing
tests/src/unit/core/clipboard/copy/codeBlockMarkdown.test.ts(full code-block copy, partial selection, paragraph guard).<br />).src/unit/nextjs/serverUtilandsrc/unit/react/BlockNoteView*Remount*are unrelated (fail onmaintoo).Checklist
🤖 Generated with Claude Code
Summary by CodeRabbit