In particular, with lists, but no doubt this affects other types too. This makes envisioning a full solution difficult as I can't imagine all the different scenarios which a solution needs to cover.
There's not, as far as I can tell, 100% standard behavior across all editors on this, but we can definitely improve Slate's behavior to be more predictable for users anyway.
Here's how Google Docs handles an example for lists:
http://recordit.co/SEzxiNiodn
Here's how Slate handles it:
http://recordit.co/Gr9dTOaKHi
The fragments Slate decodes look like this:

The line where a fragment is encoded into the HTML on copy: https://github.com/ianstormtaylor/slate/blob/master/packages/slate-react/src/utils/clone-fragment.js#L33
First line where an encoded fragment is decoded (if it exists) on paste: https://github.com/ianstormtaylor/slate/blob/master/packages/slate-react/src/utils/get-event-transfer.js#L64 << This is probably the file we need to modify
It occurs to me we can check the types of the enclosing block for the fragment and for the paste location and avoid duplicating the block type, in this case numbered-list, if they match, but I'm not sure if this covers all use cases.
Can anyone think of a possible case this wouldn't work in? For me, tables come to mind, but if you try to paste table rows inside a table, you're gonna have a bad time. This seems beyond what Slate itself needs to handle, and an acceptable solution in my view should simply not interfere with someone else who wants to extend the behavior to handle tables.
This has become a pretty big problem for us.
It seems that when copying, all the blocks leading up to the block you've copied are cloned.
As an example, we use lists that can be nested. When copying text from a nested list, the full structure is copied with it.
- ul_list:
- list_item:
- paragraph: "some text"
- ul_list:
- list_item:
- paragraph: "This is to be copied"
The expectation would be either "This is to be copied" would get copied as text, or the single list_item gets copied.
Instead what we get is this in the copied fragment:
- ul_list:
- list_item:
- ul_list:
- list_item:
- paragraph: "This is to be copied"
Currently we are stripping much of the structure away to give us list_items, however this method is very fragile, and doesn't take into account copying of other types.
For instance, if you copy a list item in a table, then paste it, you get a table pasted with the list item in too.
I understand this is a very complicated problem to solve, but it would be very useful for plugins to have some way of telling cloneFragment and Insert* how to merge, and what kind of structural data is needed for cloning/inserting.
I think this might be related to https://github.com/ianstormtaylor/slate/pull/1366. We considered the <table> case and the <quote> case, but forgot about lists. I believe we used to have the exact same behavior as Google Docs, which is important here.
We might need to rollback that change, and have tables be something that is completely handled in userland as an edge case I think. (Or potentially with a future isAtomic property on nodes.)
But I'm down to accept a pure rollback of that logic, and delay figuring out a better table solution until a later pull request. If someone wants to help!
@ianstormtaylor I'm going on distance memories here and could be completely wrong, but I believe this has been an issue since at least January 2017 when I started using Slate. I've used most, but not all versions of Slate, and I think this has been an issue in all of them.
Like I said, could be mistaken about this.