ProseMirror / prosemirror

The ProseMirror WYSIWYM editor

Home Page:http://prosemirror.net/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

control / fix behaviour of normalizeSiblings on paste

YousefED opened this issue · comments

I have a schema with an extra level of nesting, see demo setup @ https://codesandbox.io/s/gifted-shape-xmvs84?file=/src/components/App/App.js

I'm running into trouble making this work with paste handling. When pasting 2 paragraphs, the second paragraph gets nested in the first:

image

When pasting 3 paragraphs, all 3 are turned into top-level elements:

image

Of course, both constructs are valid in the schema, but I find it weird that there's a difference in behavior when pasting 2 vs 3 paragraphs. The behaviour I'm looking for is to get top-level paragraphs only (so, when pasting 3 paragraphs it works well, but when pasting 2 paragraphs, the nesting is undesirable).

I tried debugging, and think the part where this happens is normalizeSiblings, but it's difficult to figure out what exactly needs to be changed to support this.

It tries to fit the content at the cursor position, which is possible in the first case (paste the rest of the paragraph at the start into the focused textblock, add the container after that as a sibling) but not in the second (because you can't add multiple containers after a paragraph). You may be able to override this with a transformPasted hook that closes the slice at the start when it looks like that is a sequence of container nodes.

Thanks for the pointers @marijnh. While I couldn't get to "closing the slice" succesfully, I took a different approach.

I noticed the slice in transformPasted is [paragraph<...>, container<paragraph<...>].

By using the following code to wrap the first paragraph in a container, it seems to work:

transformPasted(slice, view) {
          let f = Fragment.from(slice.content);
          for (let i = 0; i < f.childCount; i++) {
            if (f.child(i).type.spec.group !== "container") {
              const container = view.state.schema.nodes.container.create(
                undefined,
                f.child(i)
              );
              f = f.replaceChild(i, container);
            }
          }
          return Slice.maxOpen(f);
        },

Do you think this approach makes sense? Or am I missing a more obvious solution?

That sounds like it should work.