Angular2管道:输出原始HTML

50

我正在尝试创建一个Angular2自定义管道,用于输出原始HTML。我希望它能够将输入中的换行符简单地转换为HTML换行符。如何从angular2管道输出原始HTML?

以下是我的当前管道定义,但它会转义我不想要的HTML:

import {Pipe, PipeTransform} from '@angular/core';
/*
 * Converts newlines into html breaks
*/
@Pipe({ name: 'newline' })
export class NewlinePipe implements PipeTransform {
    transform(value: string, args: string[]): any {
        return value.replace(/(?:\r\n|\r|\n)/g, '<br />');
    }
}

编辑:由于这个问题似乎得到了很多关注和活动,所以我保留我的已接受答案,即使对于我特定的示例用例,css可能是更好的选择,而事实上这也是我所改变的。但我的实际问题是“如何从angular 2管道中输出原始html”,而不是“渲染换行的最佳方法”,这是已接受答案显示的内容。

请注意,在下面的评论中提到,如果您使用已接受答案中的方法,您需要确保不要呈现未经检查的用户输入,因为这可能会使您暴露于XSS漏洞。

9个回答

123

你也可以使用纯CSS

<span class="line-breaker">
{{text}}
</span>

.line-breaker {
  white-space: pre-line;
}

2
这应该是解决方案的理由,因为它易于使用且工作得非常好。 - Jonathan Corrin
1
如果你只需要换行符,就不需要使用不安全的HTML,这应该是被接受的答案。 - Ruan Mendes

62

答案(我在发布问题后找到)是不要更改管道定义中的任何内容,而是在使用管道时绑定到 [innerHtml]。

因此,请将其替换为:

<div class="panel-body">
    {{mycontent | newline}}
</div>

使用这个:

<div class="panel-body" [innerHtml]="myContent | newline">
</div>

虽然这种方法可能并不完美,但如果管道定义中能有一种方式来实现这一点就好了...

编辑:由于这个答案似乎引起了许多负面反应,我将其保留原样。针对我具体的示例用例,使用CSS可能会是更好的选择,而事实上也是我最终采用的方式。

但我的实际问题是“如何从Angular 2管道输出原始HTML”,而不是“渲染换行符的最佳方式”。这个答案展示了如何做到这一点。

需要注意的是,正如下面的评论所提到的,如果您使用此答案中的方法,则需要确保您不将未经检查的用户输入呈现为HTML代码,否则可能会打开XSS漏洞。


6
请勿使用已接受的解决方案,因为它会引入XSS漏洞。我的内容(myContent)中的任何HTML内容都不会被转义,将原样返回给用户。 - Bryan Burman
7
只有在用于呈现用户输入时才需要确保输入是“安全”的,此时您需要使用其他机制(例如服务器端)来确保输入的安全。 - mutex
12
为弥补XSS漏洞而点赞,该漏洞仅影响来自用户输入的HTML。有服务器端机制控制用户输入,此回答不会覆盖这些机制。 - JoeCool-Avismón
这真的是唯一的方法吗?对于我的需求来说,我还可以接受(在一系列标题中添加换行符 - 需要手动调整位置)。知道管道不是问题所在,而是使用它的方式很好。 - Simon_Weaver
3
已接受的解决方案没有问题。根据Angular文档所说,似乎不必担心XSS攻击,因为Angular会自动识别危险值并进行净化处理。https://angular.io/guide/security#sanitization-example - Mr. Mars

23
作为Toolkit所提供的CSS答案的一种变体,如果您希望空格被计入而不是被折叠,您可以使用以下代码。
HTML
<span class="line-breaker">
  {{text}}
</span>

CSS (层叠样式表)
.line-breaker {
  white-space: pre-wrap;
}
除了像一样显示换行和换行等内容之外,它所做的是将每个空格都显示为一个空格,而不是将多个空格折叠成一个空格。

normal

空格序列被折叠。源代码中的换行符与其他空格字符处理方式相同。必要时断行以填充行框。

nowrap

像normal一样折叠空白,但在源代码中禁止文本换行。

pre

保留空格序列。仅在源代码中的换行符和<br>元素处断行。

pre-wrap

保留空格序列。在换行符、<br>和必要时断行以填充行框。

pre-line

折叠空白序列。在换行符、<br>和必要时断行以填充行框。

来源:https://developer.mozilla.org/zh-CN/docs/Web/CSS/white-space

这是一个很棒的答案! - jvoigt

5

如果您在HTML中绑定TypeScript变量并且它包含'\n',则需要将其替换为<br/>,否则应该保留<br/>。

然而,字符串插值不会换行,您需要使用innerHtml绑定属性来实现:

<span [innerHtml]="stringVariableName"></span>

3
<p *ngFor="let myContent of myContents.split('\n')">{{ myContent }} </p>

这个东西将会执行相同的操作...

完美的 - 这对我起作用,而建议的管道则没有。我必须转义斜杠为 '\n',除此之外一切都很好。 - lordchancellor
简单却美丽 - Écio Silva

1
使用Angular指令。
import { Directive, ElementRef } from '@angular/core';

@Directive({
    selector: '[shareLineBreaker]',
})
export class LineBreakerDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style['white-space'] = 'pre-line'
    }
}

然后

<td shareLineBreaker>
                    {{data.users |  arraymap:'\n':'n':'l' }}
                </td>

1

这是我的看法,使用简单的管道

创建一个名为nl2pbr.pipe(代表:换行符转换为 p / br)的文件并将其放置在pipes文件夹中,以下是其内容:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'nl2pbr'
})
export class Nl2pbrPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    // return value.replace(/\n/g, '<br />');
    value = value.replace(/(?:\r\n\r\n|\r\r|\n\n)/g, '</p><p>');
    return '<p>' + value.replace(/(?:\r\n|\r|\n)/g, '<br>') + '</p>';
  }

/****************************
 * example useage
 * <div [innerHTML]="'testi\n\nng \n t/n/nest\n\b\ning' | translate | nl2pbr"></div>
 ****************************/

}

确保将管道添加到app.module中:
import { Nl2pbrPipe } from './pipes/`nl2pbr.pipe`';

Nl2pbrPipe添加到declarations: []中。

用法示例:

<div [innerHTML]="'hello\n\n this is a new paragraph\n and a new line' | translate | nl2pbr"></div>

输出结果为:

<p>hello</p>
<p>this is a new paragraph <br/> and a new line</p>

0

这个怎么样:

<pre>{{text}}</pre>

或者对于HTML:

<pre [innerHtml]="text"></pre>

我经常使用HTML的pre元素来表示预格式化文本。

另一个我经常用来格式化Json的技巧是:

<pre>{{jsonString | json}}</pre>

0
value.replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');

这对我有效


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