ProseMirror’s behavior when pasting content, despite already being scarily complicated, doesn’t seem to correspond to common user expectations (#397). So I’m trying to rethink it from first principles, in the hope of coming up with a somewhat coherent, yet user-acceptable model.
In this context, I’ve been playing with Google Docs, LibreOffice, and MS Word Online (didn’t have a copy of real MS Word around) to see how they behave. I was not able to find any kind of coherent behavior in the latter two (which doesn’t mean it isn’t there, just that I wasn’t able to figure out the model they use), and I often strongly disliked how they behaved, so for now I’m not using them as examples. Google Docs, on the other hand, does seem to follow a relatively clean and predictable model. As a starting point for a discussion on improving our copy/paste behavior, I’m going to describe what I believe that model is.
A Google Docs document appears to basically (with some exceptions, such as tables) be a flat list of blocks. Most blocks hold inline content, and each block has a number of properties, such as whether it is a list item, how deeply indented it is, how it is aligned, and so on. There are no such things as multiple paragraphs per list item, or even nested lists, but you can represent something like them by indenting paragraphs and lists below a list item.
The content of the clipboard is treated as a sequence of such blocks. The clipboard data saves the properties of the blocks in it, even if the selection was just a single word inside of a block.
When pasting, this appears to happen:
-
The content of the first clipboard block is inserted into the destination block. If that destination block is an empty plain paragraph with any special properties, it gets the properties of the pasted block.
-
Remaining pasted blocks, if any, are inserted after the destination block. If that block was a plain paragraph, they retain their properties, otherwise they take the properties of the destination block. If there was content after the selection, that content is appended to the last pasted block. [on closer look, this only appears to happen when they are all of the same type, if not, see below]
-
[added on edit] When pasting a range of blocks that don’t all have the same properties, the block’s properties seem to be preserved, even when pasting into a non-default block.
So pasting multiple bullet list blocks into a numbered list creates numbered list items, but pasting them into a plain paragraph creates bullet list items.
There are probably some special cases and exceptions that I didn’t describe, but this simple model seems to predict most of the editor’s behavior. So that’s a nice starting point! But the question is whether a model like that can be ported from a flat content model to a tree-shaped one.
So that’s what I’m thinking about now. Will add more posts in this thread when I come up with something. In the meantime, feedback and ideas are appreciated.