facebook / lexical

Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.
https://lexical.dev
MIT License
17.37k stars 1.43k forks source link

Bug: Collapsible container is not properly deserialized #5910

Closed AndyBaird closed 1 week ago

AndyBaird commented 2 weeks ago

I've integrated a lexical editor into my app along with the ability to create collapsible containers, similar to what's demonstrated in the lexical playground. To store this on the backend, I need to serialize the collapsible container (convert it into plain HTML using $generateHtmlFromNodes). When I retrieve it for editing, I need to deserialize it (using $generateNodesFromDOM) from plain HTML back into lexical nodes.

However, during deserialization, the correct HTML markup isn't injected into the editor. It fails to maintain the structure for the collapsible container with details and summary tags, instead transforming it into <p> tags with only text.

Lexical version: 0.14.5

It should output: `

Test title
  <div class="Collapsible__content">
    <p class="editor-paragraph" dir="ltr">
      <span style="white-space: pre-wrap;">This is test description</span>
    </p>
  </div>
</details>`

However the output is: `

Test title

This is test description

`
etrepum commented 2 weeks ago

Generally the best way to store and retrieve Lexical nodes with full fidelity is to use the JSON rather than HTML.

That said, the playground code doesn't look like it would behave this way, since exportDOM does return a details element, importDOM handles it, and I don't see any other node at a glance that would override it. Can you post a reproduction of this happening (e.g. codesandbox, github, stackblitz, etc)?

AndyBaird commented 2 weeks ago

I've made some updates and want to update the output from $generateHtmlFromNodes to the following:

<p class="PlaygroundEditorTheme__paragraph"><br></p><details open="true"><summary><p class="PlaygroundEditorTheme__paragraph" dir="ltr"><span style="white-space: pre-wrap;">testing</span></p></summary><div data-lexical-collapsible-content="true"><p class="PlaygroundEditorTheme__paragraph" dir="ltr"><span style="white-space: pre-wrap;">test</span></p><p class="PlaygroundEditorTheme__paragraph" dir="ltr"><br></p></div></details><p class="PlaygroundEditorTheme__paragraph"><br></p>

The tags for details and summary are included, however the classes that the CollapsibleContainerNode applies are being omitted when using the $generateHtmlFromNodes method.

AndyBaird commented 2 weeks ago

This is reproducible in the playground itself, in the screenshot, exportDOM does not include the classes from CollapsibleContainerNode e.g. Collapsible__container and Collapsible__title

Screenshot 2024-04-17 at 2 44 37 PM
etrepum commented 2 weeks ago

Most of the nodes in Lexical use CSS only for display, and export is designed not to use them for clipboard interoperability with other tools. If you want to export the css you'd want to copy over most of createDOM to exportDOM.

etrepum commented 2 weeks ago

If you did want the HTML from the editor as-rendered for whatever reason, you wouldn't use a Lexical API to do that (beyond maybe getting the reference to the node with editor.getRootElement()). Just get the innerHTML of your contentEditable and call it a day.

AndyBaird commented 1 week ago

Thanks for the feedback. Getting the innerHTML of contentEditable was the easiest approach for our use case. Thanks