From ecb0aec3e40e9e2c76a2e28e9a9f1c413ada4391 Mon Sep 17 00:00:00 2001 From: pc035860 Date: Sat, 1 Nov 2014 18:50:43 +0800 Subject: [PATCH 1/4] Opt-out the auto-escape of code in pure `hljs` directive with `no-escape` or `escape="{expression}"`. Close #33 --- angular-highlightjs.js | 28 ++++++++++++++++++++++++---- angular-highlightjs.min.js | 12 ++++++------ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/angular-highlightjs.js b/angular-highlightjs.js index add8c30..a3d4857 100644 --- a/angular-highlightjs.js +++ b/angular-highlightjs.js @@ -115,18 +115,25 @@ function HljsCtrl (hljsCache, hljsService) { compile: function(tElm, tAttrs, transclude) { // get static code // strip the starting "new line" character - var staticCode = tElm[0].innerHTML.replace(/^(\r\n|\r|\n)/m, ''); + var staticHTML = tElm[0].innerHTML.replace(/^(\r\n|\r|\n)/m, ''), + staticText = tElm[0].textContent.replace(/^(\r\n|\r|\n)/m, ''); // put template tElm.html('
'); return function postLink(scope, iElm, iAttrs, ctrl) { - var compileCheck; + var compileCheck, escapeCheck; if (angular.isDefined(iAttrs.compile)) { compileCheck = $parse(iAttrs.compile); } + if (angular.isDefined(iAttrs.escape)) { + escapeCheck = $parse(iAttrs.escape); + } else if (angular.isDefined(iAttrs.noEscape)) { + escapeCheck = $parse('false'); + } + ctrl.init(iElm.find('code')); if (iAttrs.onhighlight) { @@ -135,8 +142,21 @@ function HljsCtrl (hljsCache, hljsService) { }); } - if (staticCode) { - ctrl.highlight(staticCode); + if ((staticHTML || staticText) && + angular.isUndefined(iAttrs.source) && angular.isUndefined(iAttrs.include)) { + + var code; + + // Auto-escape check + // default to "true" + if (escapeCheck && !escapeCheck(scope)) { + code = staticText; + } + else { + code = staticHTML; + } + + ctrl.highlight(code); // Check if the highlight result needs to be compiled if (compileCheck && compileCheck(scope)) { diff --git a/angular-highlightjs.min.js b/angular-highlightjs.min.js index 289ab8b..7e1d1a0 100644 --- a/angular-highlightjs.min.js +++ b/angular-highlightjs.min.js @@ -1,6 +1,6 @@ -/*! angular-highlightjs -version: 0.3.1 -build date: 2014-10-21 -author: Robin Fan -https://github.com/pc035860/angular-highlightjs.git */ -angular.module("hljs",[]).provider("hljsService",function(){var a={};return{setOptions:function(b){angular.extend(a,b)},getOptions:function(){return angular.copy(a)},$get:["$window",function(b){return(b.hljs.configure||angular.noop)(a),b.hljs}]}}).factory("hljsCache",["$cacheFactory",function(a){return a("hljsCache")}]).controller("HljsCtrl",["hljsCache","hljsService",function(a,b){var c=this,d=null,e=null,f=null,g=null;c.init=function(a){d=a},c.setLanguage=function(a){e=a,f&&c.highlight(f)},c.highlightCallback=function(a){g=a},c.highlight=function(h){if(d){var i,j;f=h,e?(j=c._cacheKey(e,f),i=a.get(j),i||(i=b.highlight(e,b.fixMarkup(f),!0),a.put(j,i))):(j=c._cacheKey(f),i=a.get(j),i||(i=b.highlightAuto(b.fixMarkup(f)),a.put(j,i))),d.html(i.value),d.addClass(i.language),null!==g&&angular.isFunction(g)&&g()}},c.clear=function(){d&&(f=null,d.text(""))},c.release=function(){d=null},c._cacheKey=function(){var a=Array.prototype.slice.call(arguments),b="!angular-highlightjs!";return a.join(b)}}]).directive("hljs",["$compile","$parse",function(a,b){return{restrict:"EA",controller:"HljsCtrl",compile:function(c){var d=c[0].innerHTML.replace(/^(\r\n|\r|\n)/m,"");return c.html('
'),function(c,e,f,g){var h;angular.isDefined(f.compile)&&(h=b(f.compile)),g.init(e.find("code")),f.onhighlight&&g.highlightCallback(function(){c.$eval(f.onhighlight)}),d&&(g.highlight(d),h&&h(c)&&a(e.find("code").contents())(c)),c.$on("$destroy",function(){g.release()})}}}}]).directive("language",[function(){return{require:"hljs",restrict:"A",link:function(a,b,c,d){c.$observe("language",function(a){angular.isDefined(a)&&d.setLanguage(a)})}}}]).directive("source",["$compile","$parse",function(a,b){return{require:"hljs",restrict:"A",link:function(c,d,e,f){var g;angular.isDefined(e.compile)&&(g=b(e.compile)),c.$watch(e.source,function(b){b?(f.highlight(b),g&&g(c)&&a(d.find("code").contents())(c)):f.clear()})}}}]).directive("include",["$http","$templateCache","$q","$compile","$parse",function(a,b,c,d,e){return{require:"hljs",restrict:"A",compile:function(f,g){var h=g.include;return function(f,g,i,j){var k,l=0;angular.isDefined(i.compile)&&(k=e(i.compile)),f.$watch(h,function(e){var h=++l;if(e&&angular.isString(e)){var i,m;i=b.get(e),i||(m=c.defer(),a.get(e,{cache:b,transformResponse:function(a){return a}}).success(function(a){h===l&&m.resolve(a)}).error(function(){h===l&&j.clear(),m.resolve()}),i=m.promise),c.when(i).then(function(a){a&&(angular.isArray(a)?a=a[1]:angular.isObject(a)&&(a=a.data),a=a.replace(/^(\r\n|\r|\n)/m,""),j.highlight(a),k&&k(f)&&d(g.find("code").contents())(f))})}else j.clear()})}}}}]); \ No newline at end of file +/*! angular-highlightjs +version: 0.3.1 +build date: 2014-11-01 +author: Robin Fan +https://github.com/pc035860/angular-highlightjs.git */ +angular.module("hljs",[]).provider("hljsService",function(){var a={};return{setOptions:function(b){angular.extend(a,b)},getOptions:function(){return angular.copy(a)},$get:["$window",function(b){return(b.hljs.configure||angular.noop)(a),b.hljs}]}}).factory("hljsCache",["$cacheFactory",function(a){return a("hljsCache")}]).controller("HljsCtrl",["hljsCache","hljsService",function(a,b){var c=this,d=null,e=null,f=null,g=null;c.init=function(a){d=a},c.setLanguage=function(a){e=a,f&&c.highlight(f)},c.highlightCallback=function(a){g=a},c.highlight=function(h){if(d){var i,j;f=h,e?(j=c._cacheKey(e,f),i=a.get(j),i||(i=b.highlight(e,b.fixMarkup(f),!0),a.put(j,i))):(j=c._cacheKey(f),i=a.get(j),i||(i=b.highlightAuto(b.fixMarkup(f)),a.put(j,i))),d.html(i.value),d.addClass(i.language),null!==g&&angular.isFunction(g)&&g()}},c.clear=function(){d&&(f=null,d.text(""))},c.release=function(){d=null},c._cacheKey=function(){var a=Array.prototype.slice.call(arguments),b="!angular-highlightjs!";return a.join(b)}}]).directive("hljs",["$compile","$parse",function(a,b){return{restrict:"EA",controller:"HljsCtrl",compile:function(c){var d=c[0].innerHTML.replace(/^(\r\n|\r|\n)/m,""),e=c[0].textContent.replace(/^(\r\n|\r|\n)/m,"");return c.html('
'),function(c,f,g,h){var i,j;if(angular.isDefined(g.compile)&&(i=b(g.compile)),angular.isDefined(g.escape)?j=b(g.escape):angular.isDefined(g.noEscape)&&(j=b("false")),h.init(f.find("code")),g.onhighlight&&h.highlightCallback(function(){c.$eval(g.onhighlight)}),(d||e)&&angular.isUndefined(g.source)&&angular.isUndefined(g.include)){var k;k=j&&!j(c)?e:d,h.highlight(k),i&&i(c)&&a(f.find("code").contents())(c)}c.$on("$destroy",function(){h.release()})}}}}]).directive("language",[function(){return{require:"hljs",restrict:"A",link:function(a,b,c,d){c.$observe("language",function(a){angular.isDefined(a)&&d.setLanguage(a)})}}}]).directive("source",["$compile","$parse",function(a,b){return{require:"hljs",restrict:"A",link:function(c,d,e,f){var g;angular.isDefined(e.compile)&&(g=b(e.compile)),c.$watch(e.source,function(b){b?(f.highlight(b),g&&g(c)&&a(d.find("code").contents())(c)):f.clear()})}}}]).directive("include",["$http","$templateCache","$q","$compile","$parse",function(a,b,c,d,e){return{require:"hljs",restrict:"A",compile:function(f,g){var h=g.include;return function(f,g,i,j){var k,l=0;angular.isDefined(i.compile)&&(k=e(i.compile)),f.$watch(h,function(e){var h=++l;if(e&&angular.isString(e)){var i,m;i=b.get(e),i||(m=c.defer(),a.get(e,{cache:b,transformResponse:function(a){return a}}).success(function(a){h===l&&m.resolve(a)}).error(function(){h===l&&j.clear(),m.resolve()}),i=m.promise),c.when(i).then(function(a){a&&(angular.isArray(a)?a=a[1]:angular.isObject(a)&&(a=a.data),a=a.replace(/^(\r\n|\r|\n)/m,""),j.highlight(a),k&&k(f)&&d(g.find("code").contents())(f))})}else j.clear()})}}}}]); \ No newline at end of file From 76c90443bddab945b8e4f28405804ec0ce668364 Mon Sep 17 00:00:00 2001 From: pc035860 Date: Sun, 2 Nov 2014 14:42:12 +0800 Subject: [PATCH 2/4] Bump version 0.3.2 --- angular-highlightjs.min.js | 4 ++-- bower.json | 2 +- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/angular-highlightjs.min.js b/angular-highlightjs.min.js index 7e1d1a0..50a015e 100644 --- a/angular-highlightjs.min.js +++ b/angular-highlightjs.min.js @@ -1,6 +1,6 @@ /*! angular-highlightjs -version: 0.3.1 -build date: 2014-11-01 +version: 0.3.2 +build date: 2014-11-02 author: Robin Fan https://github.com/pc035860/angular-highlightjs.git */ angular.module("hljs",[]).provider("hljsService",function(){var a={};return{setOptions:function(b){angular.extend(a,b)},getOptions:function(){return angular.copy(a)},$get:["$window",function(b){return(b.hljs.configure||angular.noop)(a),b.hljs}]}}).factory("hljsCache",["$cacheFactory",function(a){return a("hljsCache")}]).controller("HljsCtrl",["hljsCache","hljsService",function(a,b){var c=this,d=null,e=null,f=null,g=null;c.init=function(a){d=a},c.setLanguage=function(a){e=a,f&&c.highlight(f)},c.highlightCallback=function(a){g=a},c.highlight=function(h){if(d){var i,j;f=h,e?(j=c._cacheKey(e,f),i=a.get(j),i||(i=b.highlight(e,b.fixMarkup(f),!0),a.put(j,i))):(j=c._cacheKey(f),i=a.get(j),i||(i=b.highlightAuto(b.fixMarkup(f)),a.put(j,i))),d.html(i.value),d.addClass(i.language),null!==g&&angular.isFunction(g)&&g()}},c.clear=function(){d&&(f=null,d.text(""))},c.release=function(){d=null},c._cacheKey=function(){var a=Array.prototype.slice.call(arguments),b="!angular-highlightjs!";return a.join(b)}}]).directive("hljs",["$compile","$parse",function(a,b){return{restrict:"EA",controller:"HljsCtrl",compile:function(c){var d=c[0].innerHTML.replace(/^(\r\n|\r|\n)/m,""),e=c[0].textContent.replace(/^(\r\n|\r|\n)/m,"");return c.html('
'),function(c,f,g,h){var i,j;if(angular.isDefined(g.compile)&&(i=b(g.compile)),angular.isDefined(g.escape)?j=b(g.escape):angular.isDefined(g.noEscape)&&(j=b("false")),h.init(f.find("code")),g.onhighlight&&h.highlightCallback(function(){c.$eval(g.onhighlight)}),(d||e)&&angular.isUndefined(g.source)&&angular.isUndefined(g.include)){var k;k=j&&!j(c)?e:d,h.highlight(k),i&&i(c)&&a(f.find("code").contents())(c)}c.$on("$destroy",function(){h.release()})}}}}]).directive("language",[function(){return{require:"hljs",restrict:"A",link:function(a,b,c,d){c.$observe("language",function(a){angular.isDefined(a)&&d.setLanguage(a)})}}}]).directive("source",["$compile","$parse",function(a,b){return{require:"hljs",restrict:"A",link:function(c,d,e,f){var g;angular.isDefined(e.compile)&&(g=b(e.compile)),c.$watch(e.source,function(b){b?(f.highlight(b),g&&g(c)&&a(d.find("code").contents())(c)):f.clear()})}}}]).directive("include",["$http","$templateCache","$q","$compile","$parse",function(a,b,c,d,e){return{require:"hljs",restrict:"A",compile:function(f,g){var h=g.include;return function(f,g,i,j){var k,l=0;angular.isDefined(i.compile)&&(k=e(i.compile)),f.$watch(h,function(e){var h=++l;if(e&&angular.isString(e)){var i,m;i=b.get(e),i||(m=c.defer(),a.get(e,{cache:b,transformResponse:function(a){return a}}).success(function(a){h===l&&m.resolve(a)}).error(function(){h===l&&j.clear(),m.resolve()}),i=m.promise),c.when(i).then(function(a){a&&(angular.isArray(a)?a=a[1]:angular.isObject(a)&&(a=a.data),a=a.replace(/^(\r\n|\r|\n)/m,""),j.highlight(a),k&&k(f)&&d(g.find("code").contents())(f))})}else j.clear()})}}}}]); \ No newline at end of file diff --git a/bower.json b/bower.json index e1c7b3f..2c1d9cd 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-highlightjs", - "version": "0.3.1", + "version": "0.3.2", "description": "AngularJS directive for syntax highlighting with highlight.js.", "main": "angular-highlightjs.js", "ignore": [ diff --git a/package.json b/package.json index 6dba7d6..feefa87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-highlightjs", - "version": "0.3.1", + "version": "0.3.2", "description": "AngularJS directive for syntax highlighting with highlight.js", "main": "index.js", "directories": {}, From 33bad79054762b0c57ded21ad3204aa67168aae0 Mon Sep 17 00:00:00 2001 From: pc035860 Date: Sun, 2 Nov 2014 14:42:36 +0800 Subject: [PATCH 3/4] Example update - Add `escape="false"` and `no-escape` notes - Change nav item names --- example/index.html | 14 +++++++------- example/partials/hljs.html | 27 ++++++++++++++++++++++++++- example/scripts/controllers.js | 6 ++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/example/index.html b/example/index.html index 38fe842..f044197 100644 --- a/example/index.html +++ b/example/index.html @@ -4,15 +4,15 @@ angular-highlightjs examples - - + + - + - - - + + + @@ -30,7 +30,7 @@ diff --git a/example/partials/hljs.html b/example/partials/hljs.html index 27a3e30..53831a8 100644 --- a/example/partials/hljs.html +++ b/example/partials/hljs.html @@ -8,12 +8,15 @@

hljs

  • Can't preserve whitespaces inside HTML tag. Take a peek at the page source with "show source" on the top-right corner.
  • +
  • + Limitations above are not applicable when the auto-escape feature is off. With escape="false" or no-escape. +

  • -HTML +HTML (ref: ngSelect example)

    @@ -35,6 +38,28 @@

    hljs

    +HTML without auto-escape (ref: ngSelect example) +
    +<!-- setup selection display/input input:text --> +<p class="lead"> + selection: <input type="text" ng-model="selection"> +</p> + +<!-- bind scope.selection to ngSelect model --> +<div class="row example" ng-select="selection"> + <div class="col-xs-12"> + + <!-- five images with number as option value --> + <!-- add "selected" class on option selected --> + <img class="img-polaroid img-circle" + ng-repeat="num in [1, 2, 3, 4, 5] track by $id($index)" + ng-src="http://lorempixel.com/100/100/sports/{{ num }}" + ng-select-option="{{ num }}" + select-class="{'selected': $optSelected}"> + </div> +</div> +
    + Django templates (ref: highlight.js demo page)
    {% if articles|length %} diff --git a/example/scripts/controllers.js b/example/scripts/controllers.js index de9a3f0..b6e84b2 100644 --- a/example/scripts/controllers.js +++ b/example/scripts/controllers.js @@ -11,6 +11,12 @@ function ExampleCtrl($scope, $location, $templateCache, exampleRoutes) { $scope.source = null; $scope.subSource = null; + $scope.getNavName = function (link) { + if (link.indexOf('hljs-') < 0) { + return 'basic'; + } + return link.substr(1).replace('hljs-', ''); + }; $scope.toggleSource = function (target) { target = target || 'source'; From 3f216ef06a60f6362feee77a8856d8d57c6f1006 Mon Sep 17 00:00:00 2001 From: pc035860 Date: Sun, 2 Nov 2014 14:54:59 +0800 Subject: [PATCH 4/4] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f662df..3e3f433 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ Follow the instructions [here](http://softwaremaniacs.org/soft/highlight/en/down Using a prebuilt version of highlight.js hosted at Yandex here. ```html - - + + ``` Include `angular-highlightjs` module script with AngularJS script on your page. ```html - + ``` @@ -63,6 +63,8 @@ myApp.config(function (hljsServiceProvider) { ### hljs This is a required directive. Without any other supportive directives, it provides basic inline highlight function. For better understanding, some notes about using it are specified in the live example page. +The directive automatically escapes its content HTML entities by default. Can be turned off with explicitly configuration `escape="{expression evaled to false}"` or `no-escape`, and **they're only applicable for "just-`hljs`" usage**. + [Live example](http://pc035860.github.io/angular-highlightjs/example/#/hljs) ```html @@ -71,6 +73,11 @@ This is a required directive. Without any other supportive directives, it provid
    + + +
    +<!-- put your codes here --> +
    ``` #### source (optional)