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

Bug: Additional break line when initializing or copy/pasting in the editor with break lines #3677

Closed
mariofpalb opened this issue Jan 5, 2023 · 19 comments · Fixed by #4467
Closed

Comments

@mariofpalb
Copy link

mariofpalb commented Jan 5, 2023

When I initialize the Lexical editor from an DOM like <p><br></p>, passing through generateNodesFromDOM and inserting the generated nodes to the editor, it imports it with an additional break line like <p><br><br></p>. This makes the editor have more break lines than expected. It is also curious that both
count as one character if I delete them and count the characters.

@zeitstein mentioned in a discord chat that when trying to pass a single <p></p> without break lines, it also imports it with an additional break line like <p><br></p>. They also mention that that this PR can be related -> #3581 (thanks for rising this up in the discord chat, here is the full thread: https://discord.com/channels/953974421008293909/1060331843578249376)

I also managed to reproduce it when copying some text with break lines from the Notes Application from my Mac.

Lexical version: 0.7.6

Steps To Reproduce

  1. Write something like this (with some break lines) in a Note in the Mac Notes Application:
First line



Fifth line
  1. Copy the five lines (or the block of text you have written) and paste it in the lexical playground editor
  2. You can find that there are more than 5 lines in this particular case.

image


Here is an example of the InitialState plugin to initialize the editor from a preview HTML string (not sure why is duplicating the text in the codesandbox, in my code only runs once): https://codesandbox.io/s/break-line-example-w1ic2x?file=/src/plugins/InitialState.js

The current behavior

When copying or initializing some text with break lines, it duplicates them, making the text different from the expected one.

The expected behavior

When copying or initializing some text with break lines, the number of break lines is exactly the same as the one inserted in the editor.

@chalecki
Copy link

I'm facing the same issue. I've noticed $generateNodesFromDOM is adding an extra <br /> tag for each "empty" paragraph. If you put any character, eg. period or even empty space - the problem does not exist

@rabishah
Copy link

Facing the same issue, exactly as @chalecki .

@willwang888
Copy link
Contributor

Facing the same issue!

@chalecki
Copy link

I think it was introduced in #590 in commit f38d4d5 .

Commenting on this line https://github.com/facebook/lexical/blob/main/packages/lexical/src/LexicalReconciler.ts#L324 does the trick I think but I lack knowledge on the overall flow so would be best to hear from @trueadm more on this behavior

@almazkaliyev
Copy link

maybe this can helps u

const removeLineBreaks = (inputHtml: string): string => {
  let copy = inputHtml
  copy = copy.replaceAll('<br>', '')
  return copy
}

const onChange = (_: EditorState, editorInstance: LexicalEditor) => {
  editorInstance.update(() => {
    const generatedHtml = $generateHtmlFromNodes(editorInstance, null)
    let resultHtmlString = wrapTables(generatedHtml)
    resultHtmlString = removeLineBreaks(generatedHtml)
    setHtml(resultHtmlString)
  })
}

@mariofpalb
Copy link
Author

@almazkaliyev the point is not to remove every <br> from the generated HTML, I want to keep the exact number of break lines from a copy/paste and when initialising the editor with some previous HTML saved from the database.

@thegreatercurve thegreatercurve self-assigned this Jan 31, 2023
@sagarchoudhary96
Copy link

@thegreatercurve do we have any updates for the fix for this issue ?

@obinmatt
Copy link

@thegreatercurve any updates? 😄

@oleksandr-danylchenko
Copy link

oleksandr-danylchenko commented Mar 15, 2023

Having the same issue. An empty text field has the <p><br></p by default

Rich text field $generateHtmlFromNodes result
image image

@ferugi
Copy link

ferugi commented Apr 12, 2023

I've found that a single empty paragraph converted to HTML with $generateHtmlFromNodes will result in <p><br></p>.
However when converting back from HTML to Lexical nodes with $generateNodesFromDOM and then updating the contents of the editor's root node, I end up with the following HTML in the ContentEditable element: <p><br><br></p>.

sagzy added a commit to TryGhost/Koenig that referenced this issue Apr 13, 2023
refs TryGhost/Product#2992

- at the moment, there are some open issues at Lexical with line breaks
  - facebook/lexical#2807
  - facebook/lexical#3677
- this commit fixes our workaround in `generateEditorState` for nested editors. We actively remove any additional spaces or line breaks before inserting them
sagzy added a commit to TryGhost/Koenig that referenced this issue Apr 13, 2023
refs TryGhost/Product#2992

- at the moment, there are some open issues at Lexical with line breaks
  - facebook/lexical#2807
  - facebook/lexical#3677
- this commit fixes our workaround in `generateEditorState` for nested editors. We actively remove any additional spaces or line breaks before inserting them
@keithhackbarth
Copy link

@oleksandr-danylchenko and @ferugi - I am experiencing both of your observations reproducibly as well.
@thegreatercurve - Let me know if anything we can do to help (ie test cases, repo steps, etc.)

@rjullian
Copy link

rjullian commented May 9, 2023

I'm facing a similar issue and would really appreciate any updates on the progress made toward resolving it. Thanks.

@alexz-spotnana
Copy link

alexz-spotnana commented May 12, 2023

This is my function to initialize the editor state from HTML. Since the lexical's renderer adds additional
tags, this function does the opposite – decreases the number of
tags by 1 in the parsed DOM and then parses DOM to nodes and inserts them into the editor.

const parser = new DOMParser();
const dom = parser.parseFromString(initialHtml, 'text/html');

const elementsWithBr = dom.querySelectorAll('*:not(br) > br');
for (let i = 0; i < elementsWithBr.length; i += 1) {
  const brElement = elementsWithBr[i];
  const parentElement = brElement.parentNode;
  const lastBr = parentElement?.querySelectorAll('br:last-child')[0];
  if (lastBr === brElement) {
    parentElement?.removeChild(brElement);
  }
}

const nodes = $generateNodesFromDOM(editor, dom);

$getRoot().select();
$insertNodes(nodes);

Does work for me, but checked on some basic HTML fragments that fit my needs.

@gajanan999
Copy link

HI ,

I am facing this issue still in version 0.12.0

@kazimirchuk
Copy link
Contributor

Facing the same issue version 0.12.4

@rtrevisanlectra
Copy link

Hello, same issue in version 0.13.1

@mustafamoe
Copy link

Same issue in version 0.13.1

@dpr10
Copy link

dpr10 commented Apr 2, 2024

Hello, I'm having the same issue but found a workaround, if you clear the editor before the insertion, the line break is removed.

$getRoot().clear();
$getRoot().select();
$insertNodes(nodes);

@Michael7141
Copy link

Hello, I'm having the same issue but found a workaround, if you clear the editor before the insertion, the line break is removed.

$getRoot().clear();
$getRoot().select();
$insertNodes(nodes);

bless your soul;
cuz u set mine on fire

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.