basecamp / trix

A rich text editor for everyday writing
https://trix-editor.org/
MIT License
19.09k stars 1.12k forks source link

Trix adds newline after list #1085

Open n4nos opened 1 year ago

n4nos commented 1 year ago

If there is a list (ordered or unordered) at the end of the data, trix adds another <div><br></div> to the end. So if you submit the data and reopen the editor three times you have 3 extra lines in the data.

Steps to Reproduce
  1. Click in the editor and insert a list with text
  2. Submit the data and reopen it
  3. Now you have an extra newline at the end
  4. Repeat 2. for more extra lines
Details
n4nos commented 1 year ago

This problem is not limited to lists, it's the same with \, quoted Text and Links. If the content begins with normal Text, everything works as expected, but if it begins with a list, code, quote or link, it adds newlines to the content.

chadrschroeder commented 1 year ago

We ran into this too, where an extra newline was being added here.

shouldAddExtraNewlineElement looks for \n characters in the content to decide if it needs to add a <br>. This is necessary while someone is typing in the editor to get the appropriate behavior. But it can add unwanted extra <br> elements during the initial load from the hidden input element.

We were using Nokogiri to process the HTML before storage. Nokogiri can add newline characters by default because of the FORMAT flag in the default HTML save options:

For example, if the HTML that Trix passes down to the server is something like this:

html = "<div>X:<br><br></div><ul><li>Y</li><li>Z</li></ul>"

Running it through Nokogiri will add newlines:

doc = Nokogiri::HTML::DocumentFragment.parse(html)
# (Do other stuff to the doc here)
doc.to_html
 => "<div>X:<br><br>\n</div><ul>\n<li>Y</li>\n<li>Z</li>\n</ul>"

Then passing that to Trix will cause an extra <br> to be added:

"<div>X:<br><br><br></div><ul><li>Y</li><li>Z</li></ul>"

In our case, we were able to work around this by stripping out the \n characters before storage. One way to do this:

doc.to_html(save_with: Nokogiri::XML::Node::SaveOptions::AS_HTML)
 => "<div>X:<br><br></div><ul><li>Y</li><li>Z</li></ul>"