trustashtml - Escape dal testo HTML in una direttiva AngularJS



ng-bind-html (6)

È possibile implementare il filtro in questo modo:

app.filter('escape', escape);

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

https://src-bin.com

Esiste un comando JS angolare che eseguirà l'escape dell'HTML sul testo? Sto elaborando una direttiva personalizzata e ho bisogno di sfuggire ad alcuni degli output che genera.

Internamente il sanitzer AngularJS utilizza una funzione encodeEntities, ma non la espone. So che potrei duplicare la funzione, ma sembra che ci dovrebbe essere un modo standard per farlo.

Caso d'uso : ho una direttiva personalizzata che localizza la lingua. Questa direttiva utilizza una ricerca chiave da un file di dati per trovare il testo della lingua. In alcuni casi questo testo può contenere HTML e / o la direttiva produce HTML per migliorare la formattazione visiva risultante. Inoltre questa direttiva prende le espressioni angolari come parametri e li usa come sostituti dei token nelle stringhe. Ho bisogno di codificare questi parametri in quanto potrebbero non essere HTML sicuri.

La direttiva viene chiamata come attributo, ad esempio i18n-html='welcome_text_html,1+1,user.name' . La direttiva quindi formatta la stringa come descritto e utilizza element.html per aggiornare il nodo DOM.


Answer #1

Ci sono due problemi separati con l'escape dell'HTML. Il primo problema è che le entità devono essere codificate e il secondo problema è che il risultato deve essere considerato attendibile in modo che i dati possano essere utilizzati come associazioni html. L'aggiunta del seguente codice al / i tuo / i controller / i fornisce una soluzione per entrambi i problemi usando il servizio $ sce.

Soluzione 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)

  ###
  ...
  ###

])    


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

  /* ... */

}]);


La prima funzione html5Entities esegue l'effettiva codifica dell'entità, mentre la seconda funzione trustAsHtml contrassegna una stringa come sicura da utilizzare in Angular per i collegamenti HTML. Entrambe le versioni richiedono che il servizio $ sce sia incluso nel controller.

Esempio di utilizzo:

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

Vedi problemi correlati:


Answer #2

La sanitizzazione è una cosa, ma per visualizzare tutti i caratteri e non "eseguire" il codice HTML ho usato la funzione "testo" per impostare il valore.

Nella tua direttiva, per impostare il valore, invece di scrivere:

element.html( scope.myValue );

Scrivi:

element.text( scope.myValue );

Answer #3

Non è la soluzione lineare, ma se ti encodeEntities codice angolare-igienizzante, potresti trovare function encodeEntities . È carino ma privato. In cerca di htmlSanitizeWriter , vai su htmlSanitizeWriter e poi su sanitizeText . È ancora privato ma usato in linky pubblico.

O puoi usare esplicitamente linky e sperare che non vengano trovati collegamenti, o reimplementare sanitizeText o encodeEntities tuoi servizi.


Answer #4

Questa risposta deriva da @ mb21 . L'unica cosa che viene cambiata è l'utilizzo di $sce . Quindi puoi usare questo filtro in ng-bind-html , senza attivare Error: $sce:unsafe .

angular
  .module('yourModule', [
    'ngSanitize'
  ])
  .filter('escapeHtml', function ($sce) {
    // Modified by Rockallite: Add $sce.trustAsHtml() to mute "Error: $sce:unsafe"
    // http://.com/a/32835368/2293304
    // http://.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];
      }));
    }
  });

Answer #5

Questa risposta riguarda la fuga , non la disinfezione dell'HTML. Ci sono due approcci:

  1. Come menzionato da @maniekq, se puoi lavorare sul DOM, fai:

    element.text( scope.myValue );
  2. Da questa risposta , è possibile utilizzare questo codice da mustache.js e, ad esempio, creare un filtro angolare:

    angular.module('myModule').filter('escapeHtml', function () {
    
        var entityMap = {
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            '"': '&quot;',
            "'": '&#39;',
            "/": '&#x2F;'
        };
    
        return function(str) {
            return String(str).replace(/[&<>"'\/]/g, function (s) {
                return entityMap[s];
            });
        }
    });




angularjs