this is what I have:
"de-de": "This is a description for Process\r\nHere is no line break"
I want to replace the \r\n with an <br>
tag
This is what I am trying:
<p
v-if="process.description"
v-html="process.description.replace('\r\n', '<br >')"
>
</p>
This works, but if I use v-html
, there are security warnings in case of XSS vulnerabilities. So v-html isn't the solution ether.
Someone an idea?
CodePudding user response:
As you said, You are getting description
text straight from an API that means it's not directly coming from a user input. In that case you are good to go with v-html
.
But if you still concern about the XSS vulnerability by using v-html
, then you can do this with the help of v-for
and splitting a string.
Live Demo :
new Vue({
el: '#app',
data: {
description: 'This is a description for Process\r\nHere is no line break'
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<span v-for="(line, index) of description.split('\r\n')" :key="index">
{{ line }}<br/>
</span>
</div>
CodePudding user response:
Use Vue's built-in security
It's an interesting problem, but there is a simple solution that leverages Vue's built-in security.
If we split the description at carriage returns we can then use v-for
with a template to output each text fragment appended with a <br>
break.
<p v-if="process.description">
<template v-for="line in process.description?.split('\r\n')">
{{line}}<br>
</template>
</p>
Which produces rendered output:
<p >
This is a description for Process<br>
Here is no line break<br>
</p>
Further Reading
Snippet
For this test, a XSS alert has been embedded in the description. Vue escapes the alert and displays it as text. Yet, if we were to use v-html to render the description it would trigger the XSS alert.
const {
createApp
} = Vue
createApp({
data() {
return {
process: {
description: 'This is a description for Process\r\nHere is no line break\r\n<svg/onload=alert("XSS")>'
}
}
}
}).mount('#app')
body {
font-family: sans-serif;
}
.description {
border: 1px solid blue;
border-radius: 0.5rem;
padding: 1rem;
}
<div id="app">
<p v-if="process.description">
<template v-for="line in process.description?.split('\r\n')">
{{line}}<br>
</template>
</p>
<!-- v-html will trigger a XSS alert
<div v-html="process.description"></div>
-->
<!-- v-text will NOT trigger XSS alert, but no line breaks
<div v-text="process.description"></div>
-->
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
CodePudding user response:
I think you should put your string in a <pre>
tag instead https://www.w3schools.com/tags/tag_pre.asp .
<pre>
respects line breaks etc and will avoid you doing replacement hacks.