如何在Aurelia中将换行符渲染为<br>标签

6
我正在使用JSON检索一些文本数据,其中包括带有换行符格式的文本。我非常希望将这些换行符呈现给用户。
问题:如何“正确”/“推荐”的方法实现此目标?
我尝试过以下选项: - 普通绑定:<p>${myText}</p>:不呈现换行符。 - 使用 <pre> 标签:<p><pre>${myText}></pre></p>:渲染出换行符,但存在已知的问题,如在某些浏览器中水平滚动和单词换行不理想等。 - 使用值转换器普通绑定,将换行符替换为<br>标签:<p>${myText | textFormat}</p>
export class TextFormatValueConverter {
  toView(value) {
    return value.replace(new RegExp('\r?\n','g'), '<br>');
  }
}

这确实会呈现<br>标签,但Aurelia绑定器会转义这些标签,并将它们显示为文本。使用上述转换器和innerHTML进行绑定:<p innerHTML.bind="myText | textFormat"></p>:渲染正常,但我担心它可能容易受到攻击,因为文本来自不执行与Web使用相关的任何输入净化处理的旧系统。

那么 sanitize-html 转换器怎么样? - dfsq
谢谢 :) 我之前不知道那个。所以一个可能的解决方案是通过卫生器进行管道处理,或者只需扩展自己的转换器以包括卫生。我确实相信一些卫生纳入了 innerHtml 绑定中(看着你上面链接的代码,似乎仅停止了脚本,我认为 innerHtml 默认保护免受此类攻击(虽然可能是错误的)。我还不太了解是否从脚本标签中进行保护就足够好还是应该考虑更多的保护... - Vidar
请参见"问题标题应该包含“标签”吗?",在这个问题中达成的共识是“不应该”! - user57508
1
@AndreasNiedermair 有时候当他们让问题更清晰时,他们应该这样做。这是其中之一。 - Jeremy Danyow
@JeremyDanyow 这并不是应该使用标签的情况,相反,应该以完整的句子作为标题的目标... 标签从来都不是解决问题的途径! - user57508
3个回答

4
您正在做正确的事情。有时需要绑定到innerHTML。在aurelia.io的文档中包括使用清理转换器的说明以及有关使用sanitize-html项目的更完整实现的注释。
话虽如此,您可以创建一个非常轻量级的自定义属性,仅执行所需操作: 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>

这能否作为自定义元素来完成呢?<my-p-newline-replacer>${myText}</my-p-newline-replacer>或者这样做会带来很多开销吗? - Vidar
考虑到这一点,属性非常有意义,因为它可以在不同的元素上重复使用。 - Vidar
正确- 对于这样的情况,属性更加灵活,但自定义元素也可以使用。 - Jeremy Danyow
更好的正则表达式应该是:html.replace(/(?:\r\n|\r|\n)/g, '<br />'); - Tarps

2

问题在于Aurelia将您转换后的HTML呈现为转义标记。要解决这个问题,只需使用您的RegExp函数将其转换为<br>,然后像这样使用innerHTML绑定:

<p innerHTML.bind=“htmlText”>${myText}</p>

这将停止Aurelia对HTML的转义。我看到你担心使用这种方法,因为你担心可能会有不良的HTML代码存在,但是没有其他方法可以解决这个问题,因为你无法告诉Aurelia仅渲染特定的标签。
如果你非常担心潜在的不良HTML代码,为什么不编写一个自定义JS代码,在页面加载后取消转义所有的<br>标签呢?(虽然很丑陋,但我看不到其他方法。)

有没有可能使用一个函数,将所有标签替换为安全标签,并将BR转换回不安全的标签,然后将其绑定到innerHTML。这基本上就解决了,对吧?(我没有Aurelia经验) - DoXicK
为什么要点踩?被接受的答案完全实现了我的建议,但是保留了回车符而不是使用未转义的内容。 - Chuck Le Butt
没有线索,不是我干的...猜测发帖人很恶意 :-/ - DoXicK

1
我找到了一个解决方案在Github上: 在父元素使用style="white-space: pre-wrap;"可以解决问题。

这个贴子值得更多的投票 - 这只是一条CSS语句,而且完美地解决了 OP 所提出的问题。 (也许这是显而易见的,但请注意您需要将 <p>${myText}</p> 放在一行上 - 如果您尝试将 ${myText} 移动到新行,则 HTML 文档中的所有缩进也会显示在页面上。) - AnorZaken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接