BlockNote icon indicating copy to clipboard operation
BlockNote copied to clipboard

Remove blank line under a 'none' content block will remove 'none' block together

Open tcper opened this issue 1 year ago • 4 comments

Describe the bug When I need to remove a blank line under a 'none' type content, it never works, remove the 'none' content together. I think remove a blank line is reasonable action. 20240305-161541

const blockConfig = {
  type: "image" as const,
  propSchema: imagePropSchema,
  content: "none",
} satisfies CustomBlockConfig;

I tried, all content: "none", will cause this bug.

To Reproduce

  1. Insert a 'none' content block, like 'image'
  2. Insert a blank line under the 'none' content block
  3. Press Backspace in the blank line

Misc

  • Node version:
  • Package manager:
  • Browser:
  • [ ] I'm a sponsor and would appreciate if you could look into this sooner than later 💖

tcper avatar Mar 05 '24 08:03 tcper

Is the solution here to check if the block is paragraph, has no content, and focus is start of block (should be impossible to meet these criteria and not meet this one). If that matches, then delete the block rather than merging it?

sb8244 avatar Aug 12 '24 19:08 sb8244

Yeah that sounds right - we should already have quite some backspace handling logic here for that, but seems like this case isn't accounted for

matthewlipski avatar Aug 27 '24 13:08 matthewlipski

@matthewlipski I'm not sure any of the code blocks there handle that cases this. At least when I looked into it, I came to that conclusion.

I wrote some custom keydown handlers (on BlockNoteView) that handle this case and another. One big thing here is pulling the children from the block to the prevBlock:

if (e.key === "Backspace") {
          const selection = blockNoteEditor.getSelection()
          const position = blockNoteEditor.getTextCursorPosition()

          if (selection === undefined && position && position.block.type === "paragraph") {
            const block = position.block
            const blockPos = getBlockInfoFromPos(
              blockNoteEditor._tiptapEditor.state.doc,
              blockNoteEditor._tiptapEditor.state.selection.anchor
            )

            const isTopBlock = blockPos.depth === 2
            const isEmptyBlock = block.content.length === 0 && block.children.length === 0
            const isEmptyContentWithChildren = block.content.length === 0 && block.children.length > 0

            if (isTopBlock && isEmptyBlock) {
              e.stopPropagation()
              e.preventDefault()
              blockNoteEditor.removeBlocks([block])

              if (position.prevBlock) {
                blockNoteEditor.setTextCursorPosition(position.prevBlock, "end")
              }
            } else if (isTopBlock && position.prevBlock && isEmptyContentWithChildren && Array.isArray(position.prevBlock.children)) {
              e.stopPropagation()
              e.preventDefault()
              blockNoteEditor.updateBlock(position.prevBlock, { children: position.prevBlock.children.concat(block.children) })
              blockNoteEditor.removeBlocks([block])

              if (position.prevBlock) {
                blockNoteEditor.setTextCursorPosition(position.prevBlock, "end")
              }
            }
          }
        }

sb8244 avatar Aug 27 '24 14:08 sb8244

Hmm have you tried modifying the code from BNMergeBlocks? I think if you just remove the .replace here, you should get pretty close to the correct behaviour. The difference is that BNMergeBlocks will just un-nest the children of the later block, rather than attaching them to the previous one which might still be a dealbreaker. Either way I think it's smth you might want to look into

matthewlipski avatar Aug 28 '24 17:08 matthewlipski