Skip to content

Strip the presentational trailing newline when importing code blocks - #1216

Open
wintan1418 wants to merge 2 commits into
basecamp:mainfrom
wintan1418:fix-code-block-trailing-newline
Open

Strip the presentational trailing newline when importing code blocks#1216
wintan1418 wants to merge 2 commits into
basecamp:mainfrom
wintan1418:fix-code-block-trailing-newline

Conversation

@wintan1418

@wintan1418 wintan1418 commented Jul 30, 2026

Copy link
Copy Markdown

Fixes #917

Markdown renderers like Redcarpet emit <pre> blocks whose text content ends with a newline before the closing tag. Lexical imports that newline as an extra code line, so the editor showed a spurious blank line (<br><br>) at the end of every imported code block.

The fix

stripTrailingCodeBlockNewlines(doc) (in html_helper.js, alongside the existing addBlockSpacing DOM-preprocessing helper) trims a single trailing newline from the last text node of each <pre> in the parsed document. It runs in editor.$generateNodesFromDOM, the single choke point all import paths share (initial value, setValue, paste, prompt templates).

This mirrors how the HTML spec disregards a leading newline right after <pre> — the trailing one is presentational, not content. Only one newline is trimmed, so interior line breaks and deliberate blank lines beyond the final one survive unchanged.

Tests

  • Playwright (test/browser/tests/formatting/code_block_trailing_newline.test.js): importing a <pre> with a trailing newline yields no blank last line; interior line breaks are kept; a <pre> without a trailing newline is untouched. The first two fail on main and pass with this change.
  • Vitest (test/javascript/unit/helpers/html_helper.test.js): unit coverage of the helper, including nested markup inside <pre>, the keep-deliberate-blank-lines case, and empty code blocks.

Full Playwright suite passes on Chromium (621) and the new tests on Firefox too; WebKit couldn't launch locally (missing system libraries), so relying on CI for that project. yarn lint and yarn test are clean.

Markdown renderers like Redcarpet emit <pre> blocks whose text content
ends with a newline before the closing tag. Lexical imports that newline
as an extra code line, so the editor showed a spurious blank line at the
end of every imported code block.

Trim a single trailing newline from the last text node of each <pre>
before generating Lexical nodes, mirroring how the HTML spec disregards
a leading newline right after <pre>. Interior newlines and deliberate
blank lines beyond the final one are unaffected.

Fixes basecamp#917
@wintan1418
wintan1418 marked this pull request as ready for review July 30, 2026 18:40
Copilot AI review requested due to automatic review settings July 30, 2026 18:40

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copilot AI 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.

Pull request overview

This PR fixes an import artifact where HTML <pre> blocks that end with a trailing newline (common from Markdown renderers) were being imported into Lexical as an extra empty code line, producing a spurious blank line at the end of code blocks in Lexxy.

Changes:

  • Added stripTrailingCodeBlockNewlines(doc) DOM pre-processing helper to trim a single trailing newline from each <pre>’s last text node before Lexical import.
  • Wired the helper into the shared import choke point (editor.$generateNodesFromDOM) so it applies to initial value, setValue, paste, and templates.
  • Added Playwright + Vitest coverage for trailing-newline <pre> imports, including nested markup cases.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/helpers/html_helper.js Introduces DOM preprocessing to strip a single presentational trailing newline from <pre> blocks.
src/elements/editor.js Applies the preprocessing during $generateNodesFromDOM so all import paths benefit.
test/javascript/unit/helpers/html_helper.test.js Adds unit tests for the new helper across several edge cases.
test/browser/tests/formatting/code_block_trailing_newline.test.js Adds Playwright regression tests verifying no spurious blank code line is imported.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +68 to +70
function lastTextNodeIn(element) {
const walker = element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_TEXT)
let lastTextNode = null

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch — switched to the numeric constant with the inline comment, matching the pattern in selection.js and code_highlighting_helper.js. Fixed in 6409ee1.

Match the convention used by the other tree-walker helpers, which avoid
referencing the NodeFilter global so the helper keeps working where it
is not defined.
Copilot AI review requested due to automatic review settings July 30, 2026 18:46

Copilot AI 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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

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.

Importing <pre> with trailing newline produces spurious <br><br> in code block

2 participants