Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Inserting new block using insertContent function at paragraph start will create empty paragraph above #5943

Closed
1 task done
volarname opened this issue Dec 17, 2024 · 4 comments
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug

Comments

@volarname
Copy link
Contributor

Affected Packages

core

Version(s)

2.10.3

Bug Description

Steps to reproduce

  1. Open https://codesandbox.io/p/devbox/jovial-waterfall-z9nvpx
  2. Place cursor at paragraph start
  3. use button to insert block node (using tiptap insertContent function)
  4. check printed json output or visually check the spacing of created block
  5. it will create unwanted empty paragraph above

Browser Used

Chrome

Code Example URL

https://codesandbox.io/p/devbox/jovial-waterfall-z9nvpx

Expected Behavior

it should insert new node without creating additional empy paragraph

Additional Context (Optional)

when you now position at the end of paragraph and insert the block node using insertContent function it will do it correctly, it will just insert it after current paragraph, no empty paragraph will appear after, so it should do it same on paragraph start.

Dependency Updates

  • Yes, I've updated all my dependencies.
@volarname volarname added Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug labels Dec 17, 2024
@github-project-automation github-project-automation bot moved this to Needs Triage in Tiptap: Issues Dec 17, 2024
@guanriyue
Copy link
Contributor

This is not a bug. When you place the mouse at the beginning of a paragraph, the cursor is actually positioned at pos=1, not pos=0. Therefore, when you insert a node, the paragraph gets split. Since there's no text before pos=1, the first part of the paragraph becomes an empty paragraph, followed by the node you insert, and then the second part of the original paragraph forms a new paragraph.

I recorded a video to illustrate this. In your example, I changed the first node in the content to content-lock, which is an atom node. By using gapcursor, I was able to place the cursor at pos=0, so when I pressed the button to insert another content-lock, there were no issues. I also demonstrated inserting content-lock at the middle of a paragraph, where the paragraph gets split into two distinct parts.

2025-01-03.19.34.23.mov

@github-project-automation github-project-automation bot moved this from Needs Triage to Closed in Tiptap: Issues Jan 3, 2025
@nperez0111
Copy link

Agreed, closing

@volarname
Copy link
Contributor Author

@guanriyue @nperez0111

Thank you for your explanation and the video illustration! I understand the technical reasoning behind this behavior and why it happens due to the positioning logic.
However, from a UX perspective, this behavior feels unintuitive. When I insert a node at the beginning of a paragraph, the expectation is that the node would be added without creating an empty paragraph before it—especially since there is no whitespace before that position.

This can be confusing for users, as it introduces unexpected whitespace into the content. While I understand this is how the editor's logic currently works, I believe it would be helpful to have more control over the insertContent function. For example, an optional parameter could be introduced to prevent empty paragraphs from being created during this process.

What are your thoughts on providing this level of customization? I believe it could make the editor more flexible and user-friendly in scenarios like this.

@guanriyue
Copy link
Contributor

Your consideration also makes sense.

I cannot confirm whether adding an optional parameter is worthwhile.

Here are two solutions for your reference to address your current issue, although I can't confirm they are bug-free.

Customize a findSuitablePos command.

import { GapCursor } from '@tiptap/pm/gapcursor';

const findSuitablePos = (tr) => {
  tr.deleteSelection();

  const selection = tr.selection;
  const { $from } = selection;
  if ($from.parent.isTextblock && !$from.nodeBefore) {
    tr.setSelection(new GapCursor(tr.doc.resolve($from.before())));
  }

  return true;
};

const insertLock = () => {
  editor.value.chain().command(({ tr }) => findSuitablePos(tr)).insertContentLock().run()
}

Or redefine your insertContentLock command.

  addCommands() {
    return {
      insertContentLock:
        () =>
        ({ commands, tr }) => {
          const { $from, to } = tr.selection;
          let from = $from.pos;
          if ($from.parent.isTextblock && !$from.nodeBefore) {
            from = $from.before();
          }

          return commands.insertContentAt(
            { from, to },
            {
              type: this.name,
              attrs: {},
            }
          );
        },
    };
  },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug
Projects
Archived in project
Development

No branches or pull requests

3 participants