AngularJS过滤器以字符串形式返回html

AngularJS filter returning html as string

本文关键字:返回 html 字符串 过滤器 AngularJS      更新时间:2023-09-26

我创建了一个AngularJS过滤器,可以根据数据中的地址自动创建可点击的链接。过滤器:

app.filter('parseUrl', function() {
    var  //URLs starting with http://, https://, or ftp://
        replacePattern1 = /('b(https?|ftp):'/'/[-A-Z0-9+&@#'/%?=~_|!:,.;]*[-A-Z0-9+&@#'/%=~_|])/gim,
        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        replacePattern2 = /(^|[^'/])(www'.['S]+('b|$))/gim,
        //Change email addresses to mailto:: links.
        replacePattern3 = /('w+@[a-zA-Z_]+?'.[a-zA-Z]{2,6})/gim;
        return function(text, target, otherProp) {        
            angular.forEach(text.match(replacePattern1), function(url) {
                text = text.replace(replacePattern1, "<a href='"$1'" target='"_blank'">$1</a>");
            });
            angular.forEach(text.match(replacePattern2), function(url) {
                text = text.replace(replacePattern2, "$1<a href='"http://$2'" target='"_blank'">$2</a>");
            });
            angular.forEach(text.match(replacePattern3), function(url) {
                text = text.replace(replacePattern3, "<a href='"mailto:$1'">$1</a>");
            });
            return text;        
        };
    });

以下是我如何称呼它(在一段中):

<p><strong>Details:</strong> {{event.description | parseUrl}}</p>

这可以正确地将纯文本链接替换为链接的代码。但是,它将其替换为纯文本形式的链接。例如,www.google.com将替换为&lt;a href="http://www.google.com" target="_blank"&gt;http://google.com&lt;/a&gt;。这显然不能成为一个可点击的链接,这是我的目标。

我不知道为什么会发生这种事。关于如何预防/修复它,有什么想法吗?谢谢

尝试使用ngBindHtmlUnsafe指令将过滤器生成的HTML应用为元素的实际innerHTML内容,如下所示:

<span ng-bind-html-unsafe="event.description | parseUrl"></span>

您需要使用其中一个:

  • ngBindHtml不安全
    如果您100%信任内容的来源
  • ngBindHtml
    如果你不信任内容的来源

使用表达式输出字符串将转义传递给它的任何html实体(符号,如<>&)

我使用这个过滤器有一段时间了,不知怎么的,我没有注意到它产生的灾难性结果。我在这里的修改版本:

filter('parseUrl', function($sce) {
var  //URLs starting with http://, https://, or ftp://
    replacePattern1 = /('b(https?|ftp):'/'/[-A-Z0-9+&@#'/%?=~_|!:,.;]*[-A-Z0-9+&@#'/%=~_|])/gim,
    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^'/])(www'.['S]+('b|$))/gim,
    //Change email addresses to mailto:: links.
    replacePattern3 = /('w+@[a-zA-Z_]+?'.[a-zA-Z]{2,6})/gim;
    return function(text, target, otherProp) {        
        text = (text + '').replace(/>/,"&gt;").replace(/</,"&lt;");
        text = (text + '').replace(/([^>'r'n]?)('r'n|'n'r|'r|'n)/g, '$1<br>$2');
        text = text.replace(replacePattern1, "<a href='"$1'" target='"_blank'">$1</a>");
        text = text.replace(replacePattern2, "<a href='"http://$2'" target='"_blank'">$2</a>");
        text = text.replace(replacePattern3, "<a href='"mailto:$1'">$1</a>");
        return $sce.trustAsHtml(text);
    };
});

请注意,它没有使用angular.forEach!(????)当它这样做的时候,产出会变得非常惊人。这个问题大概与多场比赛有关吧!