I am retrieving some textual data using JSON, this data includes text formatted with linebreaks. I would very much like to render those linebreaks to the user.
Question: What is the "correct" / "recommended" approach to achieve this?
Options I've tried:
<p>${myText}</p>
: Renders no linebreaks<pre>
: <p><pre>${myText}></pre></p>
: Renders linebreaks, but have all the known and loved issues with long <pre>
text, like horizontal scrolling in some browsers and suboptimal word breaking.<br>
tags: <p>${myText | textFormat}</p>
export class TextFormatValueConverter {
toView(value) {
return value.replace(new RegExp('\r?\n','g'), '<br>');
}
}
This does render <br>
tags, but the Aurelia binder escapes the tags and shows them as literal text to the user.
* Binding using the above converter and innerHTML: <p innerHTML.bind="myText | textFormat"></p>
: Renders ok but I'm worried that it might be vulnerable to exploits, as the texts comes from a legacy system that does not do any input sanitazion with regards to usage for the web.
What you're doing is correct. Binding to innerHTML
is sometimes necessary. The docs at aurelia.io include instructions for using a sanitization converter and a note about using a more complete implementation using the sanitize-html project.
That said, you can create a really light-weight custom attribute that does only what you need:
http://plnkr.co/edit/qykvo9PKAD0TawTlQ5sp?p=preview
preserve-breaks.js
import {inject} from 'aurelia-framework';
function htmlEncode(html) {
return document.createElement('a').appendChild(
document.createTextNode(html)).parentNode.innerHTML;
}
@inject(Element)
export class PreserveBreaksCustomAttribute {
constructor(element) {
this.element = element;
}
valueChanged() {
let html = htmlEncode(this.value);
html = html.replace(/\r/g, '').replace(/\n/g, '<br/>');
this.element.innerHTML = html;
}
}
app.js
export class App {
message = `this is my text
it has some line breaks
and some <script>evil javascript</script>
the line breaks were replaced with <br/> tags`;
}
app.html
<template>
<require from="./preserve-breaks"></require>
<div preserve-breaks.bind="message"></div>
</template>
The problem is that Aurelia renders your converted HTML as escaped tags. To get around this just use your RegExp function to convert to <br>
, then use innerHTML binding like so:
<p innerHTML.bind=“htmlText”>${myText}</p>
This will stop Aurelia from escaping the HTML. I see you're worried about using this approach, as you're afraid there could be bad HTML somewhere, but there's no other way to get around this as you can't tell Aurelia to only render specific tags.
If you're that concerned about the potential for bad HTML, why don't you write a piece of custom JS to unescape all the <br>
tags after page load? (Ugly as hell, but I can't see another way.)
I have found solution on Github :
usage of style="white-space: pre-wrap;"
on parent element fixes issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With