admin管理员组

文章数量:1129469

I'm creating a note app where users can add a note by entering multiline text in a textarea. When I save the note in Firebase it is being saved with newline (\n) characters which I want to visualize.

Therefore, I wrote a filter that replaces these characters with <br /> and that works great.
Though, now I need to render my data using {{{note.content}}} and a user can inject HTML, CSS, and JS that will be executed.
Should I use something like DOMPurify to validate the content or is there a way to safely render newline characters?

I'm creating a note app where users can add a note by entering multiline text in a textarea. When I save the note in Firebase it is being saved with newline (\n) characters which I want to visualize.

Therefore, I wrote a filter that replaces these characters with <br /> and that works great.
Though, now I need to render my data using {{{note.content}}} and a user can inject HTML, CSS, and JS that will be executed.
Should I use something like DOMPurify to validate the content or is there a way to safely render newline characters?

Share Improve this question edited Sep 26, 2018 at 21:08 Krzysiek 8,3556 gold badges40 silver badges39 bronze badges asked Apr 19, 2016 at 21:16 SwimburgerSwimburger 7,1446 gold badges40 silver badges67 bronze badges
Add a comment  | 

10 Answers 10

Reset to default 276

As @shelvacu said the <pre> html tag preserves whitespaces.

However using it has one serious disadvantage: the tag itself inherits plenty of unnecessary styling from CSS frameworks that are used in project (e.g. Bootstrap).

To preserve whitespaces and avoid inheriting any unnecessary styles use:

<span style="white-space: pre;">Some whitespaced content</span>

what will act exacly like the <pre> tag.

Be aware that white-space: pre remains text 'as it is' - if you would like to have additional line break when it's necessary use: white-space: pre-wrap.

See: w3schools.com CSS white-space Property

Wrap the content in a pre element.

A <pre> element will preserve whitespace within it, eg:

This is followed by a newline,
not that you can tell
<br />
<br />
<pre>You can see the newline after me!
Woohoo!</pre>

Will result in:

This is followed by a newline, not that you can tell

You can see the newline after me!
Woohoo!

This way, you do not need to do any filtering of newlines.

Use white-space: pre-line; CSS property.

As write in Mozzila Doc for pre-line value:

Sequences of white space are collapsed. Lines are broken at newline characters, at <br>, and as necessary to fill line boxes.

After actually describing my problem I got the idea the use the pre-tag which is for preformatted text. This tag will respect '\t\n' characters and render the text correctly out of the box! Though the sentences don't get broken automatically and overflow the width. With some CSS I was able to get the same behaviour that other elements have.

html:

{{note.content}}

css:

.note pre {
  white-space: pre-wrap; 
  word-wrap: break-word;
  font-family: inherit;
}

Hope this would add value to new visitors.

Input from User.

I am big line with lots and lots of text which would make me not fit.

Line two ✌ 
Line three

Best Approach for output

<span style="white-space: pre-line">Your Content</span>

Problems with other approach

<span style="white-space: pre">Your Content</span>

Will result in addition of a scroll on y-axis

Reference & More details: https://css-tricks.com/almanac/properties/w/whitespace

i'm not really a fan of pre (except in debugging!) so here is another way to deal with this using v-for. this makes it easier to tweak formatting (eg, maybe you want to use a list or something else that is not span and br)

<span
   v-for="(line,lineNumber) of stringWithNewlines.split('\n')" 
   v-bind:key="lineNumber" >
  {{ line }}<br/>
</span>

The first thing you can do is split up the string and then replace all \n with <br /> tag.

replace(/\n/g, '<br />')

you can use Computed Properties and then use value v-html in DOM:

computed: {
    content () {
        return this.note.content.replace(/\n/g, '<br />')
    },
}

then:

<span v-html="content"></span>

Before using v-html, you have to make sure that the element which you escape is sanitized in case you allow user input, otherwise you expose your app to xss vulnerabilities.

More info Vue.js ref

The other way or better way to prevent xss attack that you can do is using the white-space CSS property and set it to either pre-wrap or pre-line.

.css-fix {
    white-space: pre-wrap; /* or pre-line */
}

These two make sure that the text wraps when line breaks are in the content, and pre-line specifically collapses multiple whitespaces into one.

I'm able to make it work with backticks (`)

<pre>{{textRenderedAsItIs}}</pre>

data():{
  return{
    textRenderedAsItIs:`Hello
                        World`
   }
}

Convert \n to

if (this.content.my_val && this.content.my_val !== '') {
    return this.content.my_val.replace(/\n/g, '<br />')
}

you can use v-html

<span v-html="yourContent"></span>

 

data():{
  return{
    yourContent: "Line 1 <br> Line 2"
   }
}

本文标签: javascriptRendering newline character in VueJSStack Overflow