Исключить текст HTML в директиве AngularJS

Есть ли команда angular JS, которая будет выполнять HTML-экранирование по тексту? Я обрабатываю пользовательскую директиву и нуждаюсь в том, чтобы скрыть некоторые из результатов, которые он генерирует.

Внутренне sanitzer AngularJS использует функцию encodeEntities, но не раскрывает ее. Я знаю, что я мог бы дублировать функцию, но похоже, что должен быть стандартный способ сделать это.


Пример использования. У меня есть настраиваемая директива, которая делает локализацию языка. Эта директива использует ключевой поиск из файла данных для поиска текста языка. В некоторых случаях этому тексту разрешено содержать HTML, и/или директива создает HTML для улучшения полученного визуального форматирования. Кроме того, эта директива принимает выражения angular как параметры и использует их как замену токенов в строках. Мне нужно кодировать эти параметры, так как они не могут быть безопасными для HTML.

Директива называется атрибутом, например i18n-html='welcome_text_html,1+1,user.name'. Затем директива форматирует строку, как описано, и использует element.html для обновления DOM node.

Ответ 1

Этот ответ посвящен экранированию, а не дезинфекции HTML. Существует два подхода:

  • Как уже упоминалось @maniekq, если вы можете работать с DOM, выполните:

    element.text( scope.myValue );
    
  • Из этого ответа вы можете использовать этот код из mustache.js и, например, создайте фильтр angular:

    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];
            });
        }
    });
    

Ответ 2

Вы можете реализовать фильтр следующим образом:

app.filter('escape', escape);

 function escape() {
    return function (html) {
      return angular.element('<pre/>').text(html).html();
    };
  }

Ответ 3

Санитирование - это одно, но для отображения всех символов, а не для "выполнения" HTML-кода, я использовал функцию "text" для установки значения.

В вашей директиве задайте значение вместо записи:

element.html( scope.myValue );

записи:

element.text( scope.myValue );

Ответ 4

Есть две отдельные проблемы с экранированием 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 Solution:

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>

См. связанные проблемы:

Ответ 5

Этот ответ получен из @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];
      }));
    }
  });

Ответ 6

Это не прямое решение, но если вы погрузитесь в код angular -sanitize, вы можете найти функцию encodeEntities. Это приятно, но конфиденциально. Если вы ищете его, вы перейдете к htmlSanitizeWriter, а затем к sanitizeText. Он по-прежнему закрыт, но используется в общедоступном фильтре linky.

Либо вы можете явно использовать linky и надеяться, что ссылки не будут найдены, или переопределите sanitizeText или encodeEntities int ваши сервисы.

Ответ 7

Используйте сокращенную метку [innerHtml] в файле шаблона HTML, который вы используете в своем приложении Angular.

Мой пример, показанный ниже, для экранирования HTML, сгенерированного wordpress на post_content, который извлекается из моего WP API, и поэтому html-теги не будут отображаться в браузере:

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

Надеюсь, это поможет.

Ответ 8

В 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, как указано выше. Но он работает для угловых случаев.

Ответ 9

Вы можете использовать функцию encodeEntities() в ngSanitize для выхода и < > и т.д.