Approaches:
- Monitor Lexical updates
- An (entity) node that extends LexicalTextNode
- A wrapper node on top of LexicalTextNode (like Comments)
Monitor Lexical updates
If I understand your problem correctly, that's the preferred approach.
editor.registerUpdateListener(({editorState, previousEditorState, dirtyLeaves, dirtyNodes}) => {
// You can diff editor state and each of the individual nodes that
// were modified (dirtyLeaves and dirtyNodes)
});
Note that a TextNode may contain multiple words.
Tradeoffs:
(+) It's neat. It works well with the existing Lexical nodes and doesn't modify the rendered DOM.
(-) Diffing nodes can be complicated.
An (entity) node that extends LexicalTextNode
Just like MentionNode you can have an Entity node that has your own data.
class MarkedNode extends TextNode {
__timestamps: {...};
setTimestamps() { this.getWritable().__timestamps = ... }
getTimestamps() { return this.__timestamps; }
}
Tradeoffs:
(+) It's easy to replace each word with a MarkedNode.
(-) Replacing TextNodes with your own custom nodes kills all the optimizations around TextNodes that are currently part of the reconciler (merging adjacent text nodes). Having multiple individual spans can also cause accessibility issues or other external plugins like Grammarly to misbehave and it can also drop the efficacy of other plugins that rely on TextNodes.
A wrapper node on top of LexicalTextNode (like Comments)
Just like the previous approach but instead of replacing TextNode, you create your own wrapper (Element) node on top. Given that diffing based on characters can be complicated and slow that is the approach we went for for the CommentPlugin.
Tradeoffs:
(+) It's easy to add custom wrapper nodes.
(-) It can still impact the overall app performance negatively. Overall, it's better than the previous approach because you don't override TextNode but shares most of the downsides.
What about TextNode marks?
First of all, a TextNode can contain multiple words. A mark on a TextNode can potentially refer to 1+ words.
Besides that, allowing arbitrary metadata on TextNodes means that it's hard to optimize later. For example, when merging nodes we look at the properties they have and only merge them whenever they share all properties (mode, details, style etc.). To preserve such optimization we would have to establish rules to determine whether two TextNodes nodes can indeed be merged.