【问题标题】:AngularJS filter returning html as stringAngularJS过滤器将html作为字符串返回
【发布时间】:2013-07-07 19:44:28
【问题描述】:

我创建了一个 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 将被替换为 &amp;lt;a href="http://www.google.com" target="_blank"&amp;gt;http://google.com&amp;lt;/a&amp;gt;。这显然不是一个可点击的链接,这是我的目标。

我不确定为什么会这样。关于如何预防/修复它的任何想法?谢谢。

【问题讨论】:

  • 您可能想看看 AngularJS 在 ngSanitize 模块中提供的“linky”过滤器 (docs.angularjs.org/api/ngSanitize.filter:linky)——该过滤器可能已经满足您的需求,并且它的文档支持在有关 ng-bind-html / ng-bind-html-unsafe 指令的答案中提出的建议。

标签: javascript angularjs angularjs-filter


【解决方案1】:

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

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

【讨论】:

  • 不幸的是,新版本的 AngularJS 中没有这样的指令
  • 不建议使用ng-bind-html-unsafe,因为它会带来潜在的安全风险。我认为这是它被弃用的原因之一。
【解决方案2】:

你需要使用:

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

【讨论】:

    【解决方案3】:

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

    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! (??????)输出会弹道。大概这个问题与有多个匹配有关!

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多