1/*! angular-highlightjs 2version: 0.6.2 3build date: 2016-08-19 4author: Chih-Hsuan Fan 5https://github.com/pc035860/angular-highlightjs.git */ 6 7(function (root, factory) { 8 if (typeof exports === "object" || (typeof module === "object" && module.exports)) { 9 module.exports = factory(require("angular"), require("highlight.js")); 10 } else if (typeof define === "function" && define.amd) { 11 define(["angular", "hljs"], factory); 12 } else { 13 root.returnExports = factory(root.angular, root.hljs); 14 } 15}(this, function (angular, hljs) { 16 17/*global angular, hljs*/ 18 19/** 20 * returns a function to transform attrs to supported ones 21 * 22 * escape: 23 * hljs-escape or escape 24 * no-escape: 25 * hljs-no-escape or no-escape 26 * onhighlight: 27 * hljs-onhighlight or onhighlight 28 */ 29function attrGetter(attrs) { 30 return function (name) { 31 switch (name) { 32 case 'escape': 33 return angular.isDefined(attrs.hljsEscape) ? 34 attrs.hljsEscape : 35 attrs.escape; 36 37 case 'no-escape': 38 return angular.isDefined(attrs.hljsNoEscape) ? 39 attrs.hljsNoEscape : 40 attrs.noEscape; 41 42 case 'onhighlight': 43 return angular.isDefined(attrs.hljsOnhighlight) ? 44 attrs.hljsOnhighlight : 45 attrs.onhighlight; 46 } 47 }; 48} 49 50function shouldHighlightStatics(attrs) { 51 var should = true; 52 angular.forEach([ 53 'source', 'include' 54 ], function (name) { 55 if (attrs[name]) { 56 should = false; 57 } 58 }); 59 return should; 60} 61 62var ngModule = angular.module('hljs', []); 63 64/** 65 * hljsService service 66 */ 67ngModule.provider('hljsService', function () { 68 var _hljsOptions = {}; 69 70 return { 71 setOptions: function (options) { 72 angular.extend(_hljsOptions, options); 73 }, 74 getOptions: function () { 75 return angular.copy(_hljsOptions); 76 }, 77 $get: function () { 78 (hljs.configure || angular.noop)(_hljsOptions); 79 return hljs; 80 } 81 }; 82}); 83 84/** 85 * hljsCache service 86 */ 87ngModule.factory('hljsCache', ["$cacheFactory", function ($cacheFactory) { 88 return $cacheFactory('hljsCache'); 89}]); 90 91/** 92 * HljsCtrl controller 93 */ 94ngModule.controller('HljsCtrl', 95["hljsCache", "hljsService", "$interpolate", "$window", function HljsCtrl (hljsCache, hljsService, $interpolate, $window) { 96 var ctrl = this; 97 98 var _elm = null, 99 _lang = null, 100 _code = null, 101 _interpolateScope = false, 102 _stopInterpolateWatch = null, 103 _hlCb = null; 104 105 var RE_INTERPOLATION_STR = escapeRe($interpolate.startSymbol()) + 106 '((.|\\s)+?)' + escapeRe($interpolate.endSymbol()); 107 108 var INTERPOLATION_SYMBOL = 'â«'; 109 110 ctrl.init = function (codeElm) { 111 _elm = codeElm; 112 }; 113 114 ctrl.setInterpolateScope = function (scope) { 115 _interpolateScope = scope; 116 117 if (_code) { 118 ctrl.highlight(_code); 119 } 120 }; 121 122 ctrl.setLanguage = function (lang) { 123 _lang = lang; 124 125 if (_code) { 126 ctrl.highlight(_code); 127 } 128 }; 129 130 ctrl.highlightCallback = function (cb) { 131 _hlCb = cb; 132 }; 133 134 ctrl._highlight = function (code) { 135 if (!_elm) { 136 return; 137 } 138 139 var res, cacheKey, interpolateData; 140 141 _code = code; // preserve raw code 142 143 if (_interpolateScope) { 144 interpolateData = extractInterpolations(code); 145 code = interpolateData.code; 146 } 147 148 if (_lang) { 149 // cache key: language, scope, code 150 cacheKey = ctrl._cacheKey(_lang, !!_interpolateScope, code); 151 res = hljsCache.get(cacheKey); 152 153 if (!res) { 154 res = hljsService.highlight(_lang, hljsService.fixMarkup(code), true); 155 hljsCache.put(cacheKey, res); 156 } 157 } 158 else { 159 // cache key: scope, code 160 cacheKey = ctrl._cacheKey(!!_interpolateScope, code); 161 res = hljsCache.get(cacheKey); 162 163 if (!res) { 164 res = hljsService.highlightAuto(hljsService.fixMarkup(code)); 165 hljsCache.put(cacheKey, res); 166 } 167 } 168 169 code = res.value; 170 171 if (_interpolateScope) { 172 (_stopInterpolateWatch||angular.noop)(); 173 174 if (interpolateData) { 175 code = recoverInterpolations(code, interpolateData.tokens); 176 } 177 178 var interpolateFn = $interpolate(code); 179 _stopInterpolateWatch = _interpolateScope.$watch(interpolateFn, function (newVal, oldVal) { 180 if (newVal !== oldVal) { 181 _elm.html(newVal); 182 } 183 }); 184 _interpolateScope.$apply(); 185 _elm.html(interpolateFn(_interpolateScope)); 186 } 187 else { 188 _elm.html(code); 189 } 190 191 // language as class on the <code> tag 192 _elm.addClass(res.language); 193 194 if (_hlCb !== null && angular.isFunction(_hlCb)) { 195 _hlCb(); 196 } 197 }; 198 ctrl.highlight = debounce(ctrl._highlight, 17); 199 200 ctrl.clear = function () { 201 if (!_elm) { 202 return; 203 } 204 _code = null; 205 _elm.text(''); 206 }; 207 208 ctrl.release = function () { 209 _elm = null; 210 _interpolateScope = null; 211 (_stopInterpolateWatch||angular.noop)(); 212 _stopInterpolateWatch = null; 213 }; 214 215 ctrl._cacheKey = function () { 216 var args = Array.prototype.slice.call(arguments), 217 glue = "!angular-highlightjs!"; 218 return args.join(glue); 219 }; 220 221 222 // http://davidwalsh.name/function-debounce 223 function debounce(func, wait, immediate) { 224 var timeout; 225 return function() { 226 var context = this, args = arguments; 227 var later = function() { 228 timeout = null; 229 if (!immediate) {
230 func.apply(context, args); 231 } 232 }; 233 var callNow = immediate && !timeout; 234 $window.clearTimeout(timeout); 235 timeout = $window.setTimeout(later, wait); 236 if (callNow) { 237 func.apply(context, args); 238 } 239 }; 240 } 241 242 // Ref: http://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript 243 function escapeRe(text, asString) { 244 var replacement = asString ? "\\\\$&" : "\\$&"; 245 return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, replacement); 246 } 247 248 function extractInterpolations(code) { 249 var interpolateTokens = [], 250 re = new RegExp(RE_INTERPOLATION_STR, 'g'), 251 newCode = '', 252 lastIndex = 0, 253 arr; 254 255 while ((arr = re.exec(code)) !== null) { 256 newCode += code.substring(lastIndex, arr.index) + INTERPOLATION_SYMBOL; 257 lastIndex = arr.index + arr[0].length; 258 interpolateTokens.push(arr[0]); 259 } 260 261 newCode += code.substr(lastIndex); 262 263 return { 264 code: newCode, 265 tokens: interpolateTokens 266 }; 267 } 268 269 function recoverInterpolations(code, tokens) { 270 var re = new RegExp(INTERPOLATION_SYMBOL, 'g'), 271 newCode = '', 272 lastIndex = 0, 273 arr; 274 275 while ((arr = re.exec(code)) !== null) { 276 newCode += code.substring(lastIndex, arr.index ) + tokens.shift(); 277 lastIndex = arr.index + arr[0].length; 278 } 279 280 newCode += code.substr(lastIndex); 281 282 return newCode; 283 } 284}]); 285 286 287var hljsDir, interpolateDirFactory, languageDirFactory, sourceDirFactory, includeDirFactory; 288 289/** 290 * hljs directive 291 */ 292hljsDir = /*@ngInject*/ ["$parse", function ($parse) { 293 return { 294 restrict: 'EA', 295 controller: 'HljsCtrl', 296 compile: function(tElm, tAttrs, transclude) { 297 // get static code 298 // strip the starting "new line" character 299 var staticHTML = tElm[0].innerHTML.replace(/^(\r\n|\r|\n)/m, ''), 300 staticText = tElm[0].textContent.replace(/^(\r\n|\r|\n)/m, ''); 301 302 // put template 303 tElm.html('<pre><code class="hljs"></code></pre>'); 304 305 return function postLink(scope, iElm, iAttrs, ctrl) { 306 var escapeCheck; 307 308 var attrs = attrGetter(iAttrs); 309 310 if (angular.isDefined(attrs('escape'))) { 311 escapeCheck = $parse(attrs('escape')); 312 } else if (angular.isDefined(attrs('no-escape'))) { 313 escapeCheck = $parse('false'); 314 } 315 316 ctrl.init(iElm.find('code')); 317 318 if (attrs('onhighlight')) { 319 ctrl.highlightCallback(function () { 320 scope.$eval(attrs('onhighlight')); 321 }); 322 } 323 324 if ((staticHTML || staticText) && shouldHighlightStatics(iAttrs)) { 325 326 var code; 327 328 // Auto-escape check 329 // default to "true" 330 if (escapeCheck && !escapeCheck(scope)) { 331 code = staticText; 332 } 333 else { 334 code = staticHTML; 335 } 336 337 ctrl.highlight(code); 338 } 339 340 scope.$on('$destroy', function () { 341 ctrl.release(); 342 }); 343 }; 344 } 345 }; 346}]; 347 348/** 349 * language directive 350 */ 351languageDirFactory = function (dirName) { 352 return /*@ngInject*/ function () { 353 return { 354 require: '?hljs', 355 restrict: 'A', 356 link: function (scope, iElm, iAttrs, ctrl) { 357 if (!ctrl) { 358 return; 359 } 360 iAttrs.$observe(dirName, function (lang) { 361 if (angular.isDefined(lang)) { 362 ctrl.setLanguage(lang); 363 } 364 }); 365 } 366 }; 367 }; 368}; 369 370/** 371 * interpolate directive 372 */ 373interpolateDirFactory = function (dirName) { 374 /*@ngInject*/ 375 return function () { 376 return { 377 require: '?hljs', 378 restrict: 'A', 379 link: function (scope, iElm, iAttrs, ctrl) { 380 if (!ctrl) { 381 return; 382 } 383 scope.$watch(iAttrs[dirName], function (newVal, oldVal) { 384 if (newVal || newVal !== oldVal) { 385 ctrl.setInterpolateScope(newVal ? scope : null); 386 } 387 }); 388 } 389 }; 390 }; 391}; 392 393/** 394 * source directive 395 */ 396sourceDirFactory = function (dirName) { 397 return /*@ngInject*/ function () { 398 return { 399 require: '?hljs', 400 restrict: 'A', 401 link: function(scope, iElm, iAttrs, ctrl) { 402 if (!ctrl) { 403 return; 404 } 405 406 scope.$watch(iAttrs[dirName], function (newCode, oldCode) { 407 if (newCode) { 408 ctrl.highlight(newCode); 409 } 410 else { 411 ctrl.clear(); 412 } 413 }); 414 } 415 }; 416 }; 417}; 418 419/** 420 * include directive 421 */ 422includeDirFactory = function (dirName) { 423 return /*@ngInject*/ ["$http", "$templateCache", "$q", function ($http, $templateCache, $q) { 424 return { 425 require: '?hljs', 426 restrict: 'A', 427 compile: function(tElm, tAttrs, transclude) { 428 var srcExpr = tAttrs[dirName]; 429 430 return function postLink(scope, iElm, iAttrs, ctrl) { 431 var changeCounter = 0; 432 433 if (!ctrl) { 434 return; 435 } 436 437 scope.$watch(srcExpr, function (src) { 438 var thisChangeId = ++changeCounter; 439 440 if (src && angular.isString(src)) { 441 var templateCachePromise, dfd; 442 443 templateCachePromise = $templateCache.get(src); 444 if (!templateCachePromise) { 445 dfd = $q.defer(); 446 $http.get(src, { 447 cache: $templateCache, 448 transformResponse: function(data, headersGetter) { 449 // Return the raw string, so $http doesn't parse it 450 // if it's json. 451 return data; 452 } 453 }).success(function (code) { 454 if (thisChangeId !== changeCounter) { 455 return; 456 } 457 dfd.resolve(code); 458 }).error(function() { 459 if (thisChangeId === changeCounter) { 460 ctrl.clear(); 461 } 462 dfd.resolve(); 463 }); 464 templateCachePromise = dfd.promise; 465 } 466 467 $q.when(templateCachePromise) 468 .then(function (code) { 469 if (!code) { 470 return; 471 } 472 473 // $templateCache from $http 474 if (angular.isArray(code)) { 475 // 1.1.5 476 code = code[1]; 477 } 478 else if (angular.isObject(code)) { 479 // 1.0.7 480 code = code.data; 481 } 482 483 code = code.replace(/^(\r\n|\r|\n)/m, ''); 484 ctrl.highlight(code); 485 }); 486 } 487 else { 488 ctrl.clear(); 489 } 490 }); 491 }; 492 } 493 }; 494 }]; 495}; 496 497/** 498 * Add directives 499 */ 500(function (module) { 501 module.directive('hljs', hljsDir); 502 503 angular.forEach(['interpolate', 'hljsInterpolate', 'compile', 'hljsCompile'], function (name) { 504 module.directive(name, interpolateDirFactory(name)); 505 }); 506 507 angular.forEach(['language', 'hljsLanguage'], function (name) { 508 module.directive(name, languageDirFactory(name)); 509 }); 510 511 angular.forEach(['source', 'hljsSource'], function (name) { 512 module.directive(name, sourceDirFactory(name)); 513 }); 514 515 angular.forEach(['include', 'hljsInclude'], function (name) { 516 module.directive(name, includeDirFactory(name)); 517 }); 518})(ngModule); 519 520 return "hljs"; 521}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.