Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #5620 Persist format at paragraph level for new line #5822

Merged
merged 29 commits into from
Apr 8, 2024

Conversation

Sahejkm
Copy link
Contributor

@Sahejkm Sahejkm commented Apr 4, 2024

  • The selection looses the format (bold,italic,etc) on tap of a new line
  • Update the paragraph node to persist the format which could be used to update the selection format on new paragraph creation
  • This fixes How to keep formatting between lines? #5620
    Before
Screen.Recording.2024-04-08.at.9.32.51.AM.mov

After:

Screen.Recording.2024-04-08.at.9.34.16.AM.mov

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 4, 2024
Copy link

vercel bot commented Apr 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
lexical ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 8, 2024 10:11am
lexical-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 8, 2024 10:11am

Copy link

github-actions bot commented Apr 4, 2024

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
packages/lexical/dist/Lexical.js 26.95 KB (+0.67% 🔺) 539 ms (+0.67% 🔺) 177 ms (+19.53% 🔺) 716 ms
packages/lexical-rich-text/dist/LexicalRichText.js 39.36 KB (+0.57% 🔺) 788 ms (+0.57% 🔺) 605 ms (+41.43% 🔺) 1.4 s
packages/lexical-plain-text/dist/LexicalPlainText.js 39.33 KB (+0.57% 🔺) 787 ms (+0.57% 🔺) 431 ms (-0.97% 🔽) 1.3 s

@Sahejkm Sahejkm changed the title #5620 Persist format at paragraph level for new line Fix #5620 Persist format at paragraph level for new line Apr 4, 2024
Copy link
Member

@zurfyx zurfyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, that's a hard one, some feedback:

Serialization

To support import/export we will need to add this new property onto the SerializedNode (defined above the class).

I don't think we need to handle HTML.

Updating after it's changed

The ParagraphNode currently doesn't update at all. The value is only set when creating the node. We will need to update that.

I believe a reconciler function nearby the direction logic should do the track to track the first node format.

Intentionally marked

Initially I thought we may need something like intentionally marked for selection. My hunch is that with the provided feedback I think we're good here. The selection toggle will flip when this happens and none of the other logic should override it.

But for some reason it currently doesn't work. We will need to investigate that.

(videos shows me trying to remove bold at the start of line, which currently is impossible)

Screen.Recording.2024-04-04.at.6.39.23.PM.mov

Similarly, what we should do is that when you change formatting on an empty paragraph node, we update the ParagraphNode styling.

Future work: new line after

It appears that there's a bug when the selection format carries over when deleting content.

Screen.Recording.2024-04-04.at.5.41.28.PM.mov

@@ -220,7 +221,12 @@ function $transferStartingElementPointToTextPoint(
const target = $isRootNode(element)
? $createParagraphNode().append(textNode)
: textNode;
textNode.setFormat(format);
const isParapgraphNode = $isParagraphNode(element);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const isParapgraphNode = $isParagraphNode(element);
const isParagraphNode = $isParagraphNode(element);

const newElement = $createParagraphNode();
if (rangeSelection != null) {
const isBackward = rangeSelection.isBackward();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be interesting to take this up separately #5825

const newElement = $createParagraphNode();
if (rangeSelection != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be null? The signature says otherwise

? this.$getParagaphNodeFromLastSelection(lastNode)
: null;
if (lastParagraphNode != null) {
newElement.setTextFormat(lastParagraphNode.getTextFormat());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this. Let's say that I have a paragraph marked as bold but none of the elements have bold now. I don't want to carry over the bold. In this case, I think we probably still want the selection if relevant

? rangeSelection.anchor
: rangeSelection.focus;
const lastNode = endPoint.getNode();
const lastParagraphNode = $isElementNode(lastNode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paragraph you're looking for is this, because we're inserting new after this paragraph

Comment on lines 224 to 229
const isParapgraphNode = $isParagraphNode(element);
textNode.setFormat(
format === 0 && isParapgraphNode && element.getChildren().length === 0
? element.getTextFormat()
: format,
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this logic into the selectionChange function? I was thinking that, just like when you put your caret inside a bold text the selection is bold, the same should be for an empty paragraph.

In this case, this logic should probably be the DFS backward we discussed. We might need to adjust the current heuristic. Or just handle the empty paragraph node case for now.

Copy link
Member

@zurfyx zurfyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! Can you add a couple more tests please?

  1. Toggle format with CMD + B at the start of a paragraph of different format, toggled format persists
  2. Removing all nodes of a paragraph with format and typing (I know that behavior doesn't resemble GDocs/Word but let's at least make sure it doesn't regress).

Can we follow up on the table formatting (in a separate PR)? Particularly persisting the format on creation and adding/removing rows and columns.

@nickschinestzki
Copy link

Does this fix also applies for styling? Like text color, font family, font size, etc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

How to keep formatting between lines?
5 participants