Skip to content

Conversation

ellatrix
Copy link
Member

@ellatrix ellatrix commented Feb 9, 2019

Description

Fixes #12109. Alternative of #13606. See #13606 (comment).

How has this been tested?

Screenshots

Types of changes

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.

@gziolo gziolo added this to the 5.1 (Gutenberg) milestone Feb 11, 2019
@gziolo gziolo added [Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable [Type] Bug An existing feature does not function as intended labels Feb 11, 2019
@@ -68,7 +68,7 @@ export const settings = {
return (
<RichText
tagName="pre"
value={ content }
value={ content.replace( /\n/g, '<br>' ) }
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean we should do the opposite once onChange is called?
Are there other tags that needs to behave this way? Should this be a config of RichText?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, we don't need modify onChange. There are two possibilities: <br> and \n. In RichText \n is collapsed as it is normally in HTML, so it cannot handle it. I went for using <br> by default, but we could go for \n too, in which case we would need to onChange. RichText always outputs <br> for line breaks.

Yes, it could also be part of the RichText config. Something like collapseLineBreaks: false. Not sure if that's needed as it will be more of an exception and it can be resolved outside of RichText, keeping RichText free of more parameters.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it could also be part of the RichText config. Something like collapseLineBreaks: false.

Does it need to be configured? Or is it enough to infer by tagName === 'pre' ?

Copy link
Member

Choose a reason for hiding this comment

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

Why does RichText collapse HTML anyways? From the comment in filterString, it reads as though it's not strictly necessary, but more to the point of normalizing on an assumption it'd be treated as equivalent by the browser anyways. If so, wouldn't this pull request and corresponding issue contradict that assumption?

function filterString( string ) {
// Reduce any whitespace used for HTML formatting to one space
// character, because it will also be displayed as such by the browser.
return string.replace( /[\n\r\t]+/g, ' ' );
}

Copy link
Member Author

Choose a reason for hiding this comment

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

  • Without removing line breaks, the line breaks will be visible in RichText, just like <br>. So if you add a line break in the HTML editor, then switch back, the line break will remain visible.
  • If we were to keep textual line breaks, they'd interfere with the rich text value line breaks:
    • In HTML, \n means nothing, it's just for the formatting of HTML, <br> means line break.
    • In a rich text value, \n means line break.

So if we just leave \n, they'll all be serialised as line breaks.

Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

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

Works great in my tests and the approach is simple, I think we can use it 👍 I don't expect other blocks to need this kind of replacement so I think it is fine to leave this logic in the block.

Maybe we can add simple memoization to the replacement to avoid executing it on each block rerender even if nothing changed? A function wrapped around memize configured to one in the constructor would probably work great, but the replacement should also be a fast operation so in this case, memoization is not a must.

@ellatrix
Copy link
Member Author

@aduth What do you think about the memoization? I'm not sure if a simple replace needs it, but maybe it's slightly faster and worth it.

@aduth
Copy link
Member

aduth commented Feb 15, 2019

@aduth What do you think about the memoization? I'm not sure if a simple replace needs it, but maybe it's slightly faster and worth it.

Are you asking if it should be introduced? I see none currently.

I'd probably avoid it, or limit it to a maxSize of 1 to just avoid repeatedly calling it when the value doesn't change.

But I also think ideally the value sits at rest in the format we want it to be in, so that we don't need to apply formatting when rendering the value. I see @youknowriad mentioned onChange earlier, but it's not clear by that conversation that we shouldn't just be replacing newlines from content there and not at all as part of the value assignment.

Similar to what we do for the PostTitle component:

onChange( event ) {
const newTitle = event.target.value.replace( REGEXP_NEWLINES, ' ' );
this.props.onUpdate( newTitle );
}

@ellatrix
Copy link
Member Author

We don't want to change anything in the RichText output. Only to the input. Ideally, the replacing happens on attribute parsing, but there's no way for the block to interfere with it?

And yes, @jorgefilipecosta was thinking it would be good to introduce it. I'm not sure. I'd avoid it as well.

@ellatrix
Copy link
Member Author

Merging as it fixes the issue and adds a test. We can iterate on implementation if needed.

@gziolo
Copy link
Member

gziolo commented Feb 21, 2019

The test added in this PR is very unstable on Travis. See #14014.

youknowriad pushed a commit that referenced this pull request Mar 6, 2019
* Fix character newlines in pre

* Add e2e test
youknowriad pushed a commit that referenced this pull request Mar 6, 2019
* Fix character newlines in pre

* Add e2e test
@aduth aduth mentioned this pull request Mar 26, 2019
@EricForgy
Copy link

Out of curiosity, I'm a little lost, but did this change break multiline LaTeX equations? Ref #14564

@fransflippo
Copy link

Would this be included in WordPress 5.4.1? I'm experiencing this exact issue with preformatted blocks in WordPress 5.4.1, but I don't know how to tell which Gutenberg version it includes.

@fransflippo
Copy link

fransflippo commented May 13, 2020

Scratch that, it's not the exact same issue.

My issue is that adding a Gutenberg preformatted block with newlines cause those newlines to be converted into spaces when rendered to HTML.

Editor:

<pre class="wp-block-preformatted">Line 1
Line 2

Line 4 (previous line was empty)</pre>

HTML:

<pre class="wp-block-preformatted">Line 1 Line 2  Line 4 (previous line was empty)</pre>

Before I log a new issue, is anybody aware of this and can you reproduce it? Thanks.

@fransflippo
Copy link

If anybody runs into the same problem: newlines in the Tabbed Content block from the Ultimate Blocks plugin will be replaced by whitespace. So don't put preformatted or code blocks inside Tabbed Content blocks. (I'm using Tabby now for tabs which just doesn't have Gutenberg support atm, but the shortcodes work fine and it doesn't screw up my code blocks.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Converting a <pre> to blocks drops new lines
8 participants