28

是否有一个 Angular JS 命令可以对文本进行 HTML 转义?我正在处理一个自定义指令,并且需要转义它生成的一些输出。

AngularJS sanitzer 在内部使用 encodeEntities 函数,但不公开它。我知道我可以复制该功能,但似乎应该有一个标准的方法来做到这一点。


用例:我有一个执行语言本地化的自定义指令。该指令使用数据文件中的键查找来查找语言文本。在某些情况下,允许此文本包含 HTML,和/或指令生成 HTML 以改进生成的视觉格式。此外,该指令将 Angular 表达式作为参数,并将它们用作字符串中标记的替换。我需要对这些参数进行编码,因为它们可能不是 HTML 安全的。

该指令被称为属性,例如i18n-html='welcome_text_html,1+1,user.name'. 然后该指令按照描述格式化字符串并用于element.html更新 DOM 节点。

4

9 回答 9

29

这个答案是关于转义,而不是清理HTML。有两种方法:

  1. 正如@maniekq 所提到的,如果您可以在 DOM 上工作,请执行以下操作:

    element.text( scope.myValue );
    
  2. 从此答案中,您可以使用mustache.js 中的此代码,例如创建一个角度过滤器:

    angular.module('myModule').filter('escapeHtml', function () {
    
        var entityMap = {
            "&": "&",
            "<": "&lt;",
            ">": "&gt;",
            '"': '&quot;',
            "'": '&#39;',
            "/": '&#x2F;'
        };
    
        return function(str) {
            return String(str).replace(/[&<>"'\/]/g, function (s) {
                return entityMap[s];
            });
        }
    });
    
于 2015-02-16T09:12:59.193 回答
2

消毒是一回事,但要显示所有字符而不是“执行”HTML 代码,我使用了“文本”函数来设置值。

在您的指令中,设置值,而不是编写:

element.html( scope.myValue );

写:

element.text( scope.myValue );
于 2014-07-28T23:58:58.653 回答
2

这个答案来自@mb21的。唯一改变的是使用$sce. ng-bind-html所以你可以在不触发的情况下使用这个过滤器Error: $sce:unsafe

angular
  .module('yourModule', [
    'ngSanitize'
  ])
  .filter('escapeHtml', function ($sce) {
    // Modified by Rockallite: Add $sce.trustAsHtml() to mute "Error: $sce:unsafe"
    // http://stackoverflow.com/a/32835368/2293304
    // http://stackoverflow.com/a/28537958/2293304
    // https://github.com/janl/mustache.js/blob/master/mustache.js#L82
    var entityMap = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        '"': '&quot;',
        "'": '&#39;',
        "/": '&#x2F;'
    };

    return function(str) {
      return $sce.trustAsHtml(String(str).replace(/[&<>"'\/]/g, function (s) {
          return entityMap[s];
      }));
    }
  });
于 2015-09-29T03:48:23.680 回答
1

转义 HTML 有两个不同的问题。第一个问题是需要对实体进行编码,第二个问题是需要信任结果,以便将数据用作 html 绑定。将以下代码添加到您的控制器中,可以使用 $sce 服务为这两个问题提供解决方案。

CoffeeScript 解决方案:

MyApp.controller('MyController', ['$scope','$sce',($scope,$sce) ->

  ###
  ...
  ###

  $scope.html5Entities = (value) ->
    value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, (i) ->
      '&#' + i.charCodeAt(0) + ';'
    )

  $scope.trustAsHtml = (value) ->
    $sce.trustAsHtml(value)

  ###
  ...
  ###

])    


Javascript解决方案:

MyApp.controller('MyController', ['$scope','$sce', function($scope,$sce) {

  /* ... */

  $scope.html5Entities = function(value) {
    return value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, function(i) {
          return '&#' + i.charCodeAt(0) + ';'
        })
  };

  $scope.trustAsHtml = function(value) {
     return $sce.trustAsHtml(value);
  };

  /* ... */

}]);


第一个函数html5Entities执行实际的实体编码,而第二个函数trustAsHtml将字符串标记为在 Angular 中用于 HTML 绑定是安全的。这两个版本都要求您的控制器中包含 $sce 服务。

示例用法:

<div ng-bind-html="trustAsHtml((html5Entities(product.title) | highlight: $select.search))"></div>

查看相关问题:

于 2015-02-17T01:31:05.640 回答
1

您可以像这样实现过滤器:

app.filter('escape', escape);

 function escape() {
    return function (html) {
      return angular.element('<pre/>').text(html).html();
    };
  }
于 2015-12-02T16:06:25.840 回答
0

在 AngularJS 中进行 HTML 清理有两种方法。第一个是使用 ngBindHtml 指令,第二个是使用 $sanitize 服务。

function MyCtrl ( $scope, $sanitize ) {
  $scope.rawHtml = "<div><script></script></div>";
  $scope.sanitizedHmtl = $sanitize( $scope.rawHtml );
}

那么这两个在功能上是等价的:

<div ng-bind-html="rawHtml"></div>
<div ng-bind-html-unsafe="sanitizedHtml"></div>

如果在指令中使用,如您的问题,您可以简单地插入经过清理的 HTML:

element.html( scope.sanitizedHtml );

但在大多数情况下,在编写指令时,您会在模板中使用它并使用 ngBindHtml,如上所述。但它适用于极端情况。

于 2013-01-25T02:16:45.120 回答
0

这不是直接的解决方案,但如果您深入研究 angular-sanitize 代码,您可以找到 function encodeEntities。这很好,但很私密。寻找它的用法,你会去htmlSanitizeWriter,然后去sanitizeText。它仍然是私有的,但用于 public filter linky

您可以明确使用linky并希望找不到任何链接,或者重新实现sanitizeTextencodeEntities集成您的服务。

于 2016-12-01T16:30:30.417 回答
-1

在 Angular 应用程序中使用的 HTML 模板文件中使用[innerHtml]速记标记。

下面显示的示例转义 wordpress 在从我的 WP API 检索到的 post_content 上生成的 HTML,因此 html 标记不会显示在浏览器中:

<div [innerHtml]="post.post_content" *ngIf="post && post.post_content"></div>

希望这可以帮助。

于 2019-08-29T12:29:46.107 回答
-2

您可以使用 ngSanitize 中的 encodeEntities() 函数来转义 & < > 等。

于 2014-03-03T10:03:47.870 回答