ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.71k stars 3.24k forks source link

Deserialized HTML list is not correctly inserted with insertFragment #639

Closed pavelvolek closed 7 years ago

pavelvolek commented 7 years ago

Deserializing a HTML snippet <ul><li>b</li><li>c</li></ul> and pasting it using insertFragment doesn't work as expected.

const { document } = serializer.deserialize('<ul><li>b</li><li>c</li></ul>');
state
  .transform()
  .insertFragment(document)
  .apply()

Seems that the HTML is correctly deserialized, but after inserting the fragment the first list item is pulled out of the list:

<li class="ListItem">
  <span data-key="9">
    <span data-offset-key="9-0">b</span>
  </span>
</li>
<ul class="List isUnordered">
  <li class="ListItem">
    <span data-key="11">
      <span data-offset-key="11-0">c</span>
    </span>
  </li>
</ul>

If the list is preceded for example by a paragraph (<p>a</p><ul><li>b</li><li>c</li></ul>), the fragment is inserted correctly.

Can be replicated in http://slatejs.org/#/paste-html.

kellyjosephprice commented 7 years ago

I spent some time looking at this, and I'm not sure how to proceed. insertFragment tries really hard to insert the first block as inline. That makes a lot of sense for text, but it's the wrong direction for actual blocks, ie ul's. So as to not break functionality, it seems it meet be worth it to add another transform like, insertFragmentAsBlock.

ianstormtaylor commented 7 years ago

The insertFragment behavior of melding the inlines is by design, but I think in this case you should be able to use insertBlock instead.