Render a String in HTML and Preserve Spaces and Linebreaks

Render a string in HTML and preserve spaces and linebreaks

Just style the content with white-space: pre-wrap;.

div {    white-space: pre-wrap;}
<div>This is some text   with some extra spacing    and afew newlines along with some trailing spaces             and five leading spaces thrown infor                                              goodmeasure                                              </div>

Secure string output and preserve spaces

I found a good solution based on your comments about CSS:

div:empty::before {
content: "\200b"; /* unicode zero width space character */
}

For pure whitespace output, there is a problem, but this does not affect my application.

How do I preserve line breaks when getting text from a textarea?

The easiest solution is to simply style the element you're inserting the text into with the following CSS property:

white-space: pre-wrap;

This property causes whitespace and newlines within the matching elements to be treated in the same way as inside a <textarea>. That is, consecutive whitespace is not collapsed, and lines are broken at explicit newlines (but are also wrapped automatically if they exceed the width of the element).

Given that several of the answers posted here so far have been vulnerable to HTML injection (e.g. because they assign unescaped user input to innerHTML) or otherwise buggy, let me give an example of how to do this safely and correctly, based on your original code:

document.getElementById('post-button').addEventListener('click', function () {  var post = document.createElement('p');  var postText = document.getElementById('post-text').value;  post.append(postText);  var card = document.createElement('div');  card.append(post);  var cardStack = document.getElementById('card-stack');  cardStack.prepend(card);});
#card-stack p {  background: #ddd;  white-space: pre-wrap;  /* <-- THIS PRESERVES THE LINE BREAKS */}textarea {  width: 100%;}
<textarea id="post-text" class="form-control" rows="8" placeholder="What's up?" required>Group Schedule:
Tuesday practice @ 5th floor (8pm - 11 pm)
Thursday practice @ 5th floor (8pm - 11 pm)
Sunday practice @ (9pm - 12 am)</textarea><br><input type="button" id="post-button" value="Post!"><div id="card-stack"></div>

Keep line breaks in HTML string

HTML, in general, uses br tags to denote a new line. A plain textarea tag does not use this, it uses whatever the user's system uses to denote a new line. This can vary by operating system.

Your simplest solution is to use CSS

<main role="main" class="container">
<p style="margin-bottom: 2rem;white-space:pre-wrap;">{{review.body}}</p>
</main>

This will maintain any "white space" formatting, including additional spaces.

If you want to actually replace the newline characters with br tags you can use the following regex

<main role="main" class="container">
<p style="margin-bottom: 2rem;" [innerHTML]="review.body.replace(/(?:\r\n|\r|\n)/g, '<br>')"></p>
</main>

Edit Thanks to ConnorsFan for the heads up on replace not working with interpolation.

Line break in HTML with '\n'

This is to show new line and return carriage in HTML, then you don't need to do it explicitly. You can do it in CSS by setting the white-space attribute pre-line value.

<span style="white-space: pre-line">@Model.CommentText</span>

Preserve line breaks in textarea

Generally you just need to add

  • white-space: pre-line; whitespace trimmed to single whitespace or

  • white-space: pre-wrap; all whitespace preserved

to the element's style (CSS), where you want your text rendered with line-breaks.

Why does the browser renders a newline as space?

Browsers condense multiple whitespace characters (including newlines) to a single space when rendering. The only exception is within <pre> elements or those that have the CSS property white-space set to pre or pre-wrap set. (Or in XHTML, the xml:space="preserve" attribute.)

Jinja render text in HTML preserving line breaks

All whitespace, including newlines, is turned into a single space in HTML.

Your options, from best to worst:

  1. Put white-space: pre-wrap; on the containing element. This tells HTML to show all whitespace exactly as it appears in the source, including newlines. (You could also use a <pre> tag, but that will also disable word-wrapping, which you probably don't want.)
  2. Treat the plain text as Markdown and throw a Markdown processor at it—one of the things Markdown does is wrap paragraphs in <p>.
  3. In Python-land, do .replace('\n', '<br>'). But this leaves you vulnerable to XSS because there might be other HTML-like junk in the string, and fixing that is a bit of a pain.

Convert (render) HTML to Text with correct line-breaks

The code below works correctly with the example provided, even deals with some weird stuff like <div><br></div>, there're still some things to improve, but the basic idea is there. See the comments.

public static string FormatLineBreaks(string html)
{
//first - remove all the existing '\n' from HTML
//they mean nothing in HTML, but break our logic
html = html.Replace("\r", "").Replace("\n", " ");

//now create an Html Agile Doc object
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);

//remove comments, head, style and script tags
foreach (HtmlNode node in doc.DocumentNode.SafeSelectNodes("//comment() | //script | //style | //head"))
{
node.ParentNode.RemoveChild(node);
}

//now remove all "meaningless" inline elements like "span"
foreach (HtmlNode node in doc.DocumentNode.SafeSelectNodes("//span | //label")) //add "b", "i" if required
{
node.ParentNode.ReplaceChild(HtmlNode.CreateNode(node.InnerHtml), node);
}

//block-elements - convert to line-breaks
foreach (HtmlNode node in doc.DocumentNode.SafeSelectNodes("//p | //div")) //you could add more tags here
{
//we add a "\n" ONLY if the node contains some plain text as "direct" child
//meaning - text is not nested inside children, but only one-level deep

//use XPath to find direct "text" in element
var txtNode = node.SelectSingleNode("text()");

//no "direct" text - NOT ADDDING the \n !!!!
if (txtNode == null || txtNode.InnerHtml.Trim() == "") continue;

//"surround" the node with line breaks
node.ParentNode.InsertBefore(doc.CreateTextNode("\r\n"), node);
node.ParentNode.InsertAfter(doc.CreateTextNode("\r\n"), node);
}

//todo: might need to replace multiple "\n\n" into one here, I'm still testing...

//now BR tags - simply replace with "\n" and forget
foreach (HtmlNode node in doc.DocumentNode.SafeSelectNodes("//br"))
node.ParentNode.ReplaceChild(doc.CreateTextNode("\r\n"), node);

//finally - return the text which will have our inserted line-breaks in it
return doc.DocumentNode.InnerText.Trim();

//todo - you should probably add "&code;" processing, to decode all the   and such
}

//here's the extension method I use
private static HtmlNodeCollection SafeSelectNodes(this HtmlNode node, string selector)
{
return (node.SelectNodes(selector) ?? new HtmlNodeCollection(node));
}


Related Topics



Leave a reply



Submit