Syntaxe Dynamique Highlighting avec AngularJS et Highlight.js

Je crée un site qui illustre des vulnérabilités d'applications courantes telles que l'injection SQL. J'utilise AngularJS et highlight.js pour créer des exemples interactifs.

Comment puis-je faire AngularJS et highlight.js mettre à jour mes extraits de code?

Exemple

Ce Fiddle démontre comment la saisie de ' OR 1=1 -- dans le champ Email peut changer le comportement prévu de la requête si l'entrée de l'utilisateur n'est pas validée ou désinfectée.

 SELECT * FROM dbo.Users WHERE Email='{{email}}' AND Password='{{password}}' 

Lorsqu'un utilisateur entre une adresse e-mail et un mot de passe, Angular met à jour la requête. Cependant, la mise en surbrillance de la syntaxe ne se met pas à jour.

 SELECT * FROM dbo.Users WHERE Email='[email protected]' AND Password='' 

J'ai essayé de réinitialiser hljs, mais quand je fais des arrêts angulaires, je met à jour la requête.

 hljs.initHighlighting.called = false; hljs.initHighlighting(); 

Application

 <script> var app = angular.module("app", ['hljs']); app.controller("controller", function($scope) { $scope.email = "[email protected]"; $scope.password = ""; }) </script> <div ng-app="app" ng-controller="controller"> <div> <div class="row"> <div class="col-sm-4">Email <input type="text" class="form-control" ng-model="email"> </div> <div class="col-sm-4">Password <input type="text" class="form-control" ng-model="password"> </div> </div> <br> <div hljs include="'compile-me'" compile="true" language="sql"></div> </div> <script type="text/ng-template" id="compile-me"> SELECT * FROM dbo.Users WHERE Email = '{{email}}' AND Password = '{{password}}' </script> </div> 

Dans le jsfiddle que vous avez fourni, vous utilisez angular-highlightjs qui, dans votre cas, est fondamentalement:

  1. Obtient le modèle que vous avez fourni include directive s'applique
  2. Appelle l'API de la bibliothèque highlightjs sur le modèle qui produit un balisage HTML avec des éléments en surbrillance ayant un style correct pour une langue particulière
  3. Le balisage HTML en surbrillance est transmis à angularjs $compile

Par la suite, aucun déréglementement n'a lieu, en particulier même lorsque le contenu interpolé change.

Une façon de le résoudre est d'utiliser la directive source partir de angular-highlightjs qui est observée, mais je pense qu'il est plus simple de créer une directive personnalisée.

Le tour consiste ici à interpoler manuellement et à mettre en surbrillance le contenu. J'ai mis à jour votre violon avec une directive simpliste qui présente l'idée:

 app.directive('highlight', function($interpolate, $window){ return { restrict: 'EA', scope: true, compile: function (tElem, tAttrs) { var interpolateFn = $interpolate(tElem.html(), true); tElem.html(''); // stop automatic intepolation return function(scope, elem, attrs){ scope.$watch(interpolateFn, function (value) { elem.html(hljs.highlight('sql',value).value); }); } } }; }); 

Une façon plus simple que je viens de trouver est d'utiliser un filtre:

 app.filter('highlight', function($sce) { return function(input, lang) { if (lang && input) return hljs.highlight(lang, input).value; return input; } }).filter('unsafe', function($sce) { return $sce.trustAsHtml; }) 

Ensuite, vous pouvez dire:

 <pre><code ng-bind-html="someScopeVariable | highlight | unsafe"></code></pre> 

Le $ sce doit être injecté dans votre application et indique à Angular d'afficher le HTML brut – que vous en faites confiance.