Исключить текст 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 = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
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 = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
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 для выхода и < > и т.д.