Skip to content

Add SoftBreakExtension for opt-in soft line break behavior#738

Closed
flavorjones wants to merge 1 commit into
mainfrom
flavorjones/soft-line-breaks
Closed

Add SoftBreakExtension for opt-in soft line break behavior#738
flavorjones wants to merge 1 commit into
mainfrom
flavorjones/soft-line-breaks

Conversation

@flavorjones
Copy link
Copy Markdown
Member

@flavorjones flavorjones commented Feb 17, 2026

When loaded, the SoftBreakExtension changes some keystrokes to preserve true markdown-style vertical whitespace:

  • Single Enter inserts a <br> instead of a paragraph break,
  • double Enter converts to a paragraph break,
  • and Backspace at a paragraph start merges with a <br>.

This allows apps like BC5 and Fizzy to format pasted Markdown properly while preserving the application-specific typing experience.

Consumers opt in via:

  import { configure, SoftBreakExtension } from "lexxy"
  configure({ global: { extensions: [SoftBreakExtension] } })

ref: https://app.3.basecamp.com/2914079/buckets/44335813/messages/9589745694

Single Enter inserts a <br> instead of a paragraph break, double
Enter converts to a paragraph break, and Backspace at a paragraph
start merges with a <br>. This allows apps like BC5 and Fizzy to
use proper paragraph spacing CSS while preserving the expected
typing experience.

Consumers opt in via:

  import { configure, SoftBreakExtension } from "lexxy"
  configure({ global: { extensions: [SoftBreakExtension] } })
@flavorjones flavorjones force-pushed the flavorjones/soft-line-breaks branch from b5e9926 to e176435 Compare February 18, 2026 00:22
Copy link
Copy Markdown
Collaborator

@samuelpecher samuelpecher left a comment

Choose a reason for hiding this comment

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

I like this, especially fitting with Lexical's $ convention.

As I was reviewing, I paused as I noticed the commands seem to be overriding two in-built Element node behaviors: insertNewParagraph and collapseAtStart. I wonder if an overriden ParagraphNode with node replacement might be more natural?

Comment on lines +20 to +26
KEY_ENTER_COMMAND,
(event) => handleEnterKey(event),
COMMAND_PRIORITY_NORMAL
)

editor.registerCommand(
KEY_BACKSPACE_COMMAND,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the better move here is to move an abstraction level up and handle INSERT_PARAGRAPH_COMMAND and DELETE_CHARACTER_COMMAND (with backwards=true) unless you really need to handle the event.

Comment on lines +85 to +92
let currentNode = node
while (currentNode) {
if ($isParagraphNode(currentNode)) {
return currentNode
}
currentNode = currentNode.getParent()
}
return null
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this pattern can usually be collapsed into $getNearestNodeOfType(node, ParagraphNode) or $findMatchingParent(node, $isParagraphNode) ( I prefer n ° 1 😉)

There's a few of these in the code due to be tightened

Comment on lines +170 to +172
secondChildren.forEach(child => {
firstParagraph.append(child)
})
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Very nittish: append can take a destructed array

Suggested change
secondChildren.forEach(child => {
firstParagraph.append(child)
})
firstParagraph.append(...secondChildren)

OR a step further

Suggested change
secondChildren.forEach(child => {
firstParagraph.append(child)
})
firstParagraph.append(lineBreak, ...secondChildren)

Comment on lines +182 to +186
export default class SoftBreakExtension extends LexxyExtension {
get lexicalExtension() {
return SoftBreakExtensionDefinition
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As a user of Lexxy Extensions, does the API feel right?

@flavorjones
Copy link
Copy Markdown
Member Author

Please see #741 for an alternative approach.

@flavorjones
Copy link
Copy Markdown
Member Author

Closing in favor of #741 which is simpler, more extensible, and doesn't modify the editing experience.

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.

2 participants