Skip to content

[lexical][lexical-clipboard] Bug Fix: Preserve alignment when pasting selected text#8671

Open
Rohithmatham12 wants to merge 1 commit into
facebook:mainfrom
Rohithmatham12:preserve-pasted-alignment
Open

[lexical][lexical-clipboard] Bug Fix: Preserve alignment when pasting selected text#8671
Rohithmatham12 wants to merge 1 commit into
facebook:mainfrom
Rohithmatham12:preserve-pasted-alignment

Conversation

@Rohithmatham12

@Rohithmatham12 Rohithmatham12 commented Jun 10, 2026

Copy link
Copy Markdown

Description

When copying selected text from an aligned paragraph inside the same Lexical namespace, the application/x-lexical-editor clipboard payload took priority over text/html. That JSON payload only contained the selected TextNode, so pasting into another paragraph reused the destination paragraph's default alignment and discarded the source paragraph alignment.

This updates clipboard JSON export to retain the non-inline parent element when the selected child content covers the full element text. That preserves block-level formatting such as paragraph alignment for full-paragraph text selections while partial text selections remain text-only.

Closes #8101

Test plan

Before

Copying all visible text from an aligned paragraph and pasting it elsewhere lost the source paragraph alignment.

After

Full-paragraph text selections preserve block-level alignment on paste, while partial text selections remain text-only.

Automated tests:

  • node node_modules/vitest/vitest.mjs --project unit packages/lexical/src/tests/unit/HTMLCopyAndPaste.test.ts --run
  • node node_modules/vitest/vitest.mjs --project unit packages/lexical-clipboard/src/tests/unit/GetClipboardDataExtension.test.ts packages/lexical-clipboard/src/tests/unit/ClipboardImportExtension.test.ts --run
  • node node_modules/prettier/bin/prettier.cjs --check packages/lexical-clipboard/src/clipboard.ts packages/lexical/src/tests/unit/HTMLCopyAndPaste.test.ts
  • node node_modules/eslint/bin/eslint.js packages/lexical-clipboard/src/clipboard.ts packages/lexical/src/tests/unit/HTMLCopyAndPaste.test.ts

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Jun 10, 2026 7:02pm
lexical-playground Ready Ready Preview, Comment Jun 10, 2026 7:02pm

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 10, 2026

@potatowagon potatowagon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed by Navi (Tater Thoughts Bobblehead) on behalf of @potatowagon.

Assessment: LGTM with minor note

What this does: Fixes #8101 — when copying text from an aligned paragraph within the same Lexical editor, the application/x-lexical-editor clipboard JSON only contained the TextNode, losing block-level formatting (alignment, indent). The fix adds $shouldIncludeElementWithSelectedChildren() which includes the parent element in the clipboard payload when the selected children cover the full element text content.

What I checked:

  1. Logic correctness: The function checks: (a) is range selection, (b) node is non-inline ElementNode, (c) not root, (d) selectedNodes content under this parent matches the parent's full text content. This correctly identifies "entire paragraph selected" without false positives on partial selections.
  2. Edge cases considered:
    • Partial text selection → selectedTextContent !== node.getTextContent() → returns false ✅
    • Empty paragraph → selectedTextContent !== "" guard → returns false ✅
    • Inline elements (links, marks) → node.isInline() guard → skipped ✅
    • Root node → $isRootNode(node) guard → skipped ✅
    • Multiple children in paragraph (e.g. bold+plain) → uses $sliceSelectedTextNodeContent per node → correct ✅
  3. Performance note: The function iterates selectedNodes and calls isParentOf() for each. For very large selections this is O(n×depth), but clipboard operations are user-initiated and typically small. Acceptable.
  4. Test coverage: Good test — creates a centered paragraph, copies via $getClipboardDataFromSelection, pastes into another paragraph, asserts alignment is preserved in DOM output.
  5. www compat: No API signature changes. $shouldIncludeElementWithSelectedChildren is module-private. The behavioral change (richer clipboard payload) is strictly additive — paste targets that ignore element wrappers will work as before.

One observation: The text-content comparison (selectedTextContent === node.getTextContent()) is a heuristic — it could theoretically match if a partial selection happens to produce the same string as the full element (e.g., repeated characters). This is an extremely unlikely edge case and the consequence (including alignment where it shouldn't) is benign.

CI: CLA ✅, Vercel ✅. Full test matrix pending (PR is ~30min old). Recommend waiting for unit green.

Ready to approve once full CI passes.

@etrepum etrepum added the extended-tests Run extended e2e tests on a PR label Jun 10, 2026
@etrepum

etrepum commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Title and description doesn't match the pull request template

@Rohithmatham12 Rohithmatham12 changed the title Preserve alignment when pasting selected text [lexical][lexical-clipboard] Bug Fix: Preserve alignment when pasting selected text Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. extended-tests Run extended e2e tests on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Text alignment is lost on copy-paste

3 participants