Handling unknown / unregistered node types
I searched in Google and in Issues but did not find unfortunately any discussion on this.
A usecase:
- import in a Lexical-based editor some markdown or serialized editor-state in JSON
- not all node types used are actually registered in the editor, so an error is thrown
Is there a way to configure Lexical to handle gracefully unknown node types?
I could imagine several meaningful strategies for different usecases:
- ignore/skip nodes with unknown node types
- render unknown node types as some opaque thing and preserve the original content in subsequent serializations (so that the unknown node can survive deserialization/serialization)
- import as a node of another type, e.g. import code node as paragraph node
The strategies (1) and (2) can be used in a quite generic way and not require much of additional configuration.
Some of my actual use cases:
-
E.g. in https://github.com/facebook/lexical/discussions/7177, I made a CLI tool to render some node types from a deserialized JSON, and it would be practical to be able to ignore/skip the unknown nodes (e.g. EmojiNode from the default document exported from Playground) or replace them with some special values like
<block of unknown node type 'this-that'>. -
For markdown specifically, I added markdown import in https://github.com/facebook/lexical/tree/main/examples/react-rich and trying to import some markdown using triple-backticks. But it throws because I have not registered yet the CodeNode from
lexical/code. But it could also be reasonable to import it as bare text/paragraph to display something reasonable and at least show the rest of the document
Thank you!
In general this doesn't really work and it's unlikely that anyone would want to spend time on this because serialized nodes aren't self-describing. Other than the type attribute the rest of the data could literally be anything and have any meaning. You can't really even know whether a node is a TextNode, DecoratorNode, or an ElementNode. There's also essentially no validation in the parsers from JSON right now so unless you also added some sort of schema validation for these guesses things would just crash or behave in unpredictable ways.
In other words, if you're planning to exchange random stuff between editors that are not explicitly designed to work together, then HTML is what you want to be using. Not JSON.
rest of the data could literally be anything and have any meaning.
What I'm proposing is to have a mechanism for handling unknown nodes in a custom way
Of course, one cannot do any editing/meaningful display of unknown nodes - but preserving the original representation for import-export roundtrip or allowing the user to delete these nodes should be possible (similar to how the editor displays "question-mark" icosn when a font does not know some unicode sequence encountered in text)
At least, allowing a hook to ignore/skip unknown nodes during deserialization from JSON / markdown parsing - should be possible. Maybe this type of handling / hooks exists already in Lexical?
if you're planning to exchange random stuff between editors that are not explicitly designed to work together, then HTML is what you want to be using. Not JSON.
JSON as representation has some advantages: it's extremely portable and is easy to manipulate/generate in other languages as a document representation and can have a more direct mapping to node types. So I think that having some deserialization hooks for unknown nodes is quite useful for both JSON and for Markdown.
It can also be useful in compatibility scenarios, when I saved to database a JSON with some node types which were later retired, so it's needed to do some custom transformations of them at deserialization time.
For HTML, is the need for hook/transforms why html: { export: ..., import: ...}, exists in EditorConfig?
Thank you!
The correct solution in the case when a node is retired or you don’t want to implement it for some reason is to create a node class with the same type that can import that data