[RFC] [lexical] Bug Fix: don't set 'ltr' direction on node with no directioned text #7330
+96
−9
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
LexicalReconciler
tries to determine whether text should be LTR or RTL based on a regex.If a given block has no directioned text, then the
activeEditorDirection
is used. This more-or-less-global variable is set tonull
at the start of reconciliation but updated when a node with directioned text is encountered.That's fine when processing the whole tree: node get updated in reading order. However, if you process only some nodes in the tree, then you can end up changing the direction of a node in an unexpected way. This is shown in the third test case where marking the first and third nodes as dirty changes the direction of the latter to RTL.
Potential fixes
Don't set node direction to LTR if no directioned text
This makes it so that the node direction is more in sync with the
dir
property set in the DOM. Currently the reconciler clears thedir
property if direction is null OR if it's LTR and the node has no directioned text: https://github.com/facebook/lexical/blob/main/packages/lexical/src/LexicalReconciler.ts#L390-L395This approach is the one I've gone with in the current PR. The result is that the two editors have slightly different DOMs ('ltr' is removed in left editor but kept in right editor), however I don't think this is a huge issue. That said, a bunch of unit tests are failing.
Mark
__dir
as an excluded property for Yjs syncingBased on what the reconciler is doing, figuring out direction from the text content, arguably
__dir
is a derived node property in the same way that__cachedText
is on the root node: https://github.com/facebook/lexical/blob/main/packages/lexical-yjs/src/Utils.ts#L50-L54I tried adding
__dir
to the excluded list for element nodes and it was still only the Table test that needed updating.This feels like a reasonable approach to me, given
__dir
is derived state, however it would mean you could end up with two editors that display a given node with different directions. Take the example from the third test case - the two nodes were marked dirty but had no changes, so nothing would be synced to Lexical, so other editors would still havenull
as the direction for the third paragraph.Backtrack through the tree to determine
activeEditorDirection
This would be the most complete fix, however could be a significant change. Didn't want to go down this path without first discussing (and ruling out) the two options above.
The idea here would be to not use
activeEditorState
but instead look at the previous block node in the tree (direct sibling, or sibling of a parent) and use its direction, assuming you were processing a node with no directioned text. That should give the same result as processing the whole tree in order.Process the whole tree when reconciling direction
This would give consistent results and would be a small code change, but is a bad idea for obvious performance reasons.