vendor: 36,603 bytes, lines 1-1207
1/// <reference lib="WebWorker"/> 2 3var _self = (typeof window !== 'undefined') 4 ? window // if in browser 5 : ( 6 (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) 7 ? self // if in worker 8 : {} // if in node js 9 ); 10 11/** 12 * Prism: Lightweight, robust, elegant syntax highlighting 13 * 14 * @license MIT <https://opensource.org/licenses/MIT> 15 * @author Lea Verou <https://lea.verou.me> 16 * @namespace 17 * @public 18 */ 19var Prism = (function (_self) { 20 21 // Private helper vars 22 var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i; 23 var uniqueId = 0; 24 25 // The grammar object for plaintext 26 var plainTextGrammar = {}; 27 28 29 var _ = { 30 /** 31 * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the 32 * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load 33 * additional languages or plugins yourself. 34 * 35 * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. 36 * 37 * You obviously have to change this value before the automatic highlighting started. To do this, you can add an 38 * empty Prism object into the global scope before loading the Prism script like this: 39 * 40 * ```js 41 * window.Prism = window.Prism || {}; 42 * Prism.manual = true; 43 * // add a new <script> to load Prism's script 44 * ``` 45 * 46 * @default false 47 * @type {boolean} 48 * @memberof Prism 49 * @public 50 */ 51 manual: _self.Prism && _self.Prism.manual, 52 /** 53 * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses 54 * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your 55 * own worker, you don't want it to do this. 56 * 57 * By setting this value to `true`, Prism will not add its own listeners to the worker. 58 * 59 * You obviously have to change this value before Prism executes. To do this, you can add an 60 * empty Prism object into the global scope before loading the Prism script like this: 61 * 62 * ```js 63 * window.Prism = window.Prism || {}; 64 * Prism.disableWorkerMessageHandler = true; 65 * // Load Prism's script 66 * ``` 67 * 68 * @default false 69 * @type {boolean} 70 * @memberof Prism 71 * @public 72 */ 73 disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, 74 75 /** 76 * A namespace for utility methods. 77 * 78 * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may 79 * change or disappear at any time. 80 * 81 * @namespace 82 * @memberof Prism 83 */ 84 util: { 85 encode: function encode(tokens) { 86 if (tokens instanceof Token) { 87 return new Token(tokens.type, encode(tokens.content), tokens.alias); 88 } else if (Array.isArray(tokens)) { 89 return tokens.map(encode); 90 } else { 91 return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); 92 } 93 }, 94 95 /** 96 * Returns the name of the type of the given value. 97 * 98 * @param {any} o 99 * @returns {string} 100 * @example 101 * type(null) === 'Null' 102 * type(undefined) === 'Undefined' 103 * type(123) === 'Number' 104 * type('foo') === 'String' 105 * type(true) === 'Boolean' 106 * type([1, 2]) === 'Array' 107 * type({}) === 'Object' 108 * type(String) === 'Function' 109 * type(/abc+/) === 'RegExp' 110 */ 111 type: function (o) { 112 return Object.prototype.toString.call(o).slice(8, -1); 113 }, 114 115 /** 116 * Returns a unique number for the given object. Later calls will still return the same number. 117 * 118 * @param {Object} obj 119 * @returns {number} 120 */ 121 objId: function (obj) { 122 if (!obj['__id']) { 123 Object.defineProperty(obj, '__id', { value: ++uniqueId }); 124 } 125 return obj['__id']; 126 }, 127 128 /** 129 * Creates a deep clone of the given object. 130 * 131 * The main intended use of this function is to clone language definitions. 132 * 133 * @param {T} o 134 * @param {Record<number, any>} [visited] 135 * @returns {T} 136 * @template T 137 */ 138 clone: function deepClone(o, visited) { 139 visited = visited || {}; 140 141 var clone; var id; 142 switch (_.util.type(o)) { 143 case 'Object': 144 id = _.util.objId(o); 145 if (visited[id]) { 146 return visited[id]; 147 } 148 clone = /** @type {Record<string, any>} */ ({}); 149 visited[id] = clone; 150 151 for (var key in o) { 152 if (o.hasOwnProperty(key)) { 153 clone[key] = deepClone(o[key], visited); 154 } 155 } 156 157 return /** @type {any} */ (clone); 158 159 case 'Array': 160 id = _.util.objId(o); 161 if (visited[id]) { 162 return visited[id]; 163 } 164 clone = []; 165 visited[id] = clone; 166 167 (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) { 168 clone[i] = deepClone(v, visited); 169 }); 170 171 return /** @type {any} */ (clone); 172 173 default: 174 return o; 175 } 176 }, 177 178 /** 179 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class. 180 * 181 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned. 182 * 183 * @param {Element} element 184 * @returns {string} 185 */ 186 getLanguage: function (element) { 187 while (element) { 188 var m = lang.exec(element.className); 189 if (m) { 190 return m[1].toLowerCase(); 191 } 192 element = element.parentElement; 193 } 194 return 'none'; 195 }, 196 197 /** 198 * Sets the Prism `language-xxxx` class of the given element. 199 * 200 * @param {Element} element 201 * @param {string} language 202 * @returns {void} 203 */ 204 setLanguage: function (element, language) { 205 // remove all `language-xxxx` classes 206 // (this might leave behind a leading space) 207 element.className = element.className.replace(RegExp(lang, 'gi'), ''); 208 209 // add the new `language-xxxx` class 210 // (using `classList` will automatically clean up spaces for us) 211 element.classList.add('language-' + language); 212 }, 213 214 /** 215 * Returns the script element that is currently executing. 216 * 217 * This does __not__ work for line script element. 218 * 219 * @returns {HTMLScriptElement | null} 220 */ 221 currentScript: function () { 222 if (typeof document === 'undefined') { 223 return null; 224 } 225 if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) { 226 return /** @type {any} */ (document.currentScript); 227 } 228 229 // IE11 workaround 230 // we'll get the src of the current script by parsing IE11's error stack trace 231 // this will not work for inline scripts 232 233 try { 234 throw new Error(); 235 } catch (err) { 236 // Get file src url from stack. Specifically works with the format of stack traces in IE. 237 // A stack will look like this: 238 // 239 // Error 240 // at _.util.currentScript (http://localhost/components/prism-core.js:119:5) 241 // at Global code (http://localhost/components/prism-core.js:606:1) 242 243 var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) || [])[1]; 244 if (src) { 245 var scripts = document.getElementsByTagName('script'); 246 for (var i in scripts) { 247 if (scripts[i].src == src) { 248 return scripts[i]; 249 } 250 } 251 } 252 return null; 253 } 254 }, 255 256 /** 257 * Returns whether a given class is active for `element`. 258 * 259 * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated 260 * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the 261 * given class is just the given class with a `no-` prefix. 262 * 263 * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is 264 * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its 265 * ancestors have the given class or the negated version of it, then the default activation will be returned. 266 * 267 * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated 268 * version of it, the class is considered active. 269 * 270 * @param {Element} element 271 * @param {string} className 272 * @param {boolean} [defaultActivation=false] 273 * @returns {boolean} 274 */ 275 isActive: function (element, className, defaultActivation) { 276 var no = 'no-' + className; 277 278 while (element) { 279 var classList = element.classList; 280 if (classList.contains(className)) { 281 return true; 282 } 283 if (classList.contains(no)) { 284 return false; 285 } 286 element = element.parentElement; 287 } 288 return !!defaultActivation; 289 } 290 }, 291 292 /** 293 * This namespace contains all currently loaded languages and the some helper functions to create and modify languages. 294 * 295 * @namespace 296 * @memberof Prism 297 * @public 298 */ 299 languages: { 300 /** 301 * The grammar for plain, unformatted text. 302 */ 303 plain: plainTextGrammar, 304 plaintext: plainTextGrammar, 305 text: plainTextGrammar, 306 txt: plainTextGrammar, 307 308 /** 309 * Creates a deep copy of the language with the given id and appends the given tokens. 310 * 311 * If a token in `redef` also appears in the copied language, then the existing token in the copied language 312 * will be overwritten at its original position. 313 * 314 * ## Best practices 315 * 316 * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language) 317 * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to 318 * understand the language definition because, normally, the order of tokens matters in Prism grammars. 319 * 320 * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. 321 * Furthermore, all non-overwriting tokens should be placed after the overwriting ones. 322 * 323 * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`. 324 * @param {Grammar} redef The new tokens to append. 325 * @returns {Grammar} The new language created. 326 * @public 327 * @example 328 * Prism.languages['css-with-colors'] = Prism.languages.extend('css', { 329 * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token 330 * // at its original position 331 * 'comment': { ... }, 332 * // CSS doesn't have a 'color' token, so this token will be appended 333 * 'color': /\b(?:red|green|blue)\b/ 334 * }); 335 */ 336 extend: function (id, redef) { 337 var lang = _.util.clone(_.languages[id]); 338 339 for (var key in redef) { 340 lang[key] = redef[key]; 341 } 342 343 return lang; 344 }, 345 346 /** 347 * Inserts tokens _before_ another token in a language definition or any other grammar. 348 * 349 * ## Usage 350 * 351 * This helper method makes it easy to modify existing languages. For example, the CSS language definition 352 * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded 353 * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the 354 * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do 355 * this: 356 * 357 * ```js 358 * Prism.languages.markup.style = { 359 * // token 360 * }; 361 * ``` 362 * 363 * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens 364 * before existing tokens. For the CSS example above, you would use it like this: 365 * 366 * ```js 367 * Prism.languages.insertBefore('markup', 'cdata', { 368 * 'style': { 369 * // token 370 * } 371 * }); 372 * ``` 373 * 374 * ## Special cases 375 * 376 * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar 377 * will be ignored. 378 * 379 * This behavior can be used to insert tokens after `before`: 380 * 381 * ```js 382 * Prism.languages.insertBefore('markup', 'comment', { 383 * 'comment': Prism.languages.markup.comment, 384 * // tokens after 'comment' 385 * }); 386 * ``` 387 * 388 * ## Limitations 389 * 390 * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object 391 * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave 392 * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily 393 * deleting properties which is necessary to insert at arbitrary positions. 394 * 395 * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object. 396 * Instead, it will create a new object and replace all references to the target object with the new one. This 397 * can be done without temporarily deleting properties, so the iteration order is well-defined. 398 * 399 * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if 400 * you hold the target object in a variable, then the value of the variable will not change. 401 * 402 * ```js 403 * var oldMarkup = Prism.languages.markup; 404 * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... }); 405 * 406 * assert(oldMarkup !== Prism.languages.markup); 407 * assert(newMarkup === Prism.languages.markup); 408 * ``` 409 * 410 * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the 411 * object to be modified. 412 * @param {string} before The key to insert before. 413 * @param {Grammar} insert An object containing the key-value pairs to be inserted. 414 * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the 415 * object to be modified. 416 * 417 * Defaults to `Prism.languages`. 418 * @returns {Grammar} The new grammar object. 419 * @public 420 */ 421 insertBefore: function (inside, before, insert, root) { 422 root = root || /** @type {any} */ (_.languages); 423 var grammar = root[inside]; 424 /** @type {Grammar} */ 425 var ret = {}; 426 427 for (var token in grammar) { 428 if (grammar.hasOwnProperty(token)) { 429 430 if (token == before) { 431 for (var newToken in insert) { 432 if (insert.hasOwnProperty(newToken)) { 433 ret[newToken] = insert[newToken]; 434 } 435 } 436 } 437 438 // Do not insert token which also occur in insert. See #1525 439 if (!insert.hasOwnProperty(token)) { 440 ret[token] = grammar[token]; 441 } 442 } 443 } 444 445 var old = root[inside]; 446 root[inside] = ret; 447 448 // Update references in other language definitions 449 _.languages.DFS(_.languages, function (key, value) { 450 if (value === old && key != inside) { 451 this[key] = ret; 452 } 453 }); 454 455 return ret; 456 }, 457 458 // Traverse a language definition with Depth First Search 459 DFS: function DFS(o, callback, type, visited) { 460 visited = visited || {}; 461 462 var objId = _.util.objId; 463 464 for (var i in o) { 465 if (o.hasOwnProperty(i)) { 466 callback.call(o, i, o[i], type || i); 467 468 var property = o[i]; 469 var propertyType = _.util.type(property); 470 471 if (propertyType === 'Object' && !visited[objId(property)]) { 472 visited[objId(property)] = true; 473 DFS(property, callback, null, visited); 474 } else if (propertyType === 'Array' && !visited[objId(property)]) { 475 visited[objId(property)] = true; 476 DFS(property, callback, i, visited); 477 } 478 } 479 } 480 } 481 }, 482 483 plugins: {}, 484 485 /** 486 * This is the most high-level function in Prismâs API. 487 * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on 488 * each one of them. 489 * 490 * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`. 491 * 492 * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}. 493 * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}. 494 * @memberof Prism 495 * @public 496 */ 497 highlightAll: function (async, callback) { 498 _.highlightAllUnder(document, async, callback); 499 }, 500 501 /** 502 * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls 503 * {@link Prism.highlightElement} on each one of them. 504 * 505 * The following hooks will be run: 506 * 1. `before-highlightall` 507 * 2. `before-all-elements-highlight` 508 * 3. All hooks of {@link Prism.highlightElement} for each element. 509 * 510 * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted. 511 * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers. 512 * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done. 513 * @memberof Prism 514 * @public 515 */ 516 highlightAllUnder: function (container, async, callback) { 517 var env = { 518 callback: callback, 519 container: container, 520 selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' 521 }; 522 523 _.hooks.run('before-highlightall', env); 524 525 env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector)); 526 527 _.hooks.run('before-all-elements-highlight', env); 528 529 for (var i = 0, element; (element = env.elements[i++]);) { 530 _.highlightElement(element, async === true, env.callback); 531 } 532 }, 533 534 /** 535 * Highlights the code inside a single element. 536 * 537 * The following hooks will be run: 538 * 1. `before-sanity-check` 539 * 2. `before-highlight` 540 * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`. 541 * 4. `before-insert` 542 * 5. `after-highlight` 543 * 6. `complete` 544 * 545 * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for 546 * the element's language. 547 * 548 * @param {Element} element The element containing the code. 549 * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier. 550 * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers 551 * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is 552 * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default). 553 * 554 * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for 555 * asynchronous highlighting to work. You can build your own bundle on the 556 * [Download page](https://prismjs.com/download.html). 557 * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done. 558 * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously. 559 * @memberof Prism 560 * @public 561 */ 562 highlightElement: function (element, async, callback) { 563 // Find language 564 var language = _.util.getLanguage(element); 565 var grammar = _.languages[language]; 566 567 // Set language on the element, if not present 568 _.util.setLanguage(element, language); 569 570 // Set language on the parent, for styling 571 var parent = element.parentElement; 572 if (parent && parent.nodeName.toLowerCase() === 'pre') { 573 _.util.setLanguage(parent, language); 574 } 575 576 var code = element.textContent; 577 578 var env = { 579 element: element, 580 language: language, 581 grammar: grammar, 582 code: code 583 }; 584 585 function insertHighlightedCode(highlightedCode) { 586 env.highlightedCode = highlightedCode; 587 588 _.hooks.run('before-insert', env); 589 590 env.element.innerHTML = env.highlightedCode; 591 592 _.hooks.run('after-highlight', env); 593 _.hooks.run('complete', env); 594 callback && callback.call(env.element); 595 } 596 597 _.hooks.run('before-sanity-check', env); 598 599 // plugins may change/add the parent/element 600 parent = env.element.parentElement; 601 if (parent && parent.nodeName.toLowerCase() === 'pre' && !parent.hasAttribute('tabindex')) { 602 parent.setAttribute('tabindex', '0'); 603 } 604 605 if (!env.code) { 606 _.hooks.run('complete', env); 607 callback && callback.call(env.element); 608 return; 609 } 610 611 _.hooks.run('before-highlight', env); 612 613 if (!env.grammar) { 614 insertHighlightedCode(_.util.encode(env.code)); 615 return; 616 } 617 618 if (async && _self.Worker) { 619 var worker = new Worker(_.filename); 620 621 worker.onmessage = function (evt) { 622 insertHighlightedCode(evt.data); 623 }; 624 625 worker.postMessage(JSON.stringify({ 626 language: env.language, 627 code: env.code, 628 immediateClose: true 629 })); 630 } else { 631 insertHighlightedCode(_.highlight(env.code, env.grammar, env.language)); 632 } 633 }, 634 635 /** 636 * Low-level function, only use if you know what youâre doing. It accepts a string of text as input 637 * and the language definitions to use, and returns a string with the HTML produced. 638 * 639 * The following hooks will be run: 640 * 1. `before-tokenize` 641 * 2. `after-tokenize` 642 * 3. `wrap`: On each {@link Token}. 643 * 644 * @param {string} text A string with the code to be highlighted. 645 * @param {Grammar} grammar An object containing the tokens to use. 646 * 647 * Usually a language definition like `Prism.languages.markup`. 648 * @param {string} language The name of the language definition passed to `grammar`. 649 * @returns {string} The highlighted HTML. 650 * @memberof Prism 651 * @public 652 * @example 653 * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript'); 654 */ 655 highlight: function (text, grammar, language) { 656 var env = { 657 code: text, 658 grammar: grammar, 659 language: language 660 }; 661 _.hooks.run('before-tokenize', env); 662 if (!env.grammar) { 663 throw new Error('The language "' + env.language + '" has no grammar.'); 664 } 665 env.tokens = _.tokenize(env.code, env.grammar); 666 _.hooks.run('after-tokenize', env); 667 return Token.stringify(_.util.encode(env.tokens), env.language); 668 }, 669 670 /** 671 * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input 672 * and the language definitions to use, and returns an array with the tokenized code. 673 * 674 * When the language definition includes nested tokens, the function is called recursively on each of these tokens. 675 * 676 * This method could be useful in other contexts as well, as a very crude parser. 677 * 678 * @param {string} text A string with the code to be highlighted. 679 * @param {Grammar} grammar An object containing the tokens to use. 680 * 681 * Usually a language definition like `Prism.languages.markup`. 682 * @returns {TokenStream} An array of strings and tokens, a token stream. 683 * @memberof Prism 684 * @public 685 * @example 686 * let code = `var foo = 0;`; 687 * let tokens = Prism.tokenize(code, Prism.languages.javascript); 688 * tokens.forEach(token => { 689 * if (token instanceof Prism.Token && token.type === 'number') { 690 * console.log(`Found numeric literal: ${token.content}`); 691 * } 692 * }); 693 */ 694 tokenize: function (text, grammar) { 695 var rest = grammar.rest; 696 if (rest) { 697 for (var token in rest) { 698 grammar[token] = rest[token]; 699 } 700 701 delete grammar.rest; 702 } 703 704 var tokenList = new LinkedList(); 705 addAfter(tokenList, tokenList.head, text); 706 707 matchGrammar(text, tokenList, grammar, tokenList.head, 0); 708 709 return toArray(tokenList); 710 }, 711 712 /** 713 * @namespace 714 * @memberof Prism 715 * @public 716 */ 717 hooks: { 718 all: {}, 719 720 /** 721 * Adds the given callback to the list of callbacks for the given hook. 722 * 723 * The callback will be invoked when the hook it is registered for is run. 724 * Hooks are usually directly run by a highlight function but you can also run hooks yourself. 725 * 726 * One callback function can be registered to multiple hooks and the same hook multiple times. 727 * 728 * @param {string} name The name of the hook. 729 * @param {HookCallback} callback The callback function which is given environment variables. 730 * @public 731 */ 732 add: function (name, callback) { 733 var hooks = _.hooks.all; 734 735 hooks[name] = hooks[name] || []; 736 737 hooks[name].push(callback); 738 }, 739 740 /** 741 * Runs a hook invoking all registered callbacks with the given environment variables. 742 * 743 * Callbacks will be invoked synchronously and in the order in which they were registered. 744 * 745 * @param {string} name The name of the hook. 746 * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered. 747 * @public 748 */ 749 run: function (name, env) { 750 var callbacks = _.hooks.all[name]; 751 752 if (!callbacks || !callbacks.length) { 753 return; 754 } 755 756 for (var i = 0, callback; (callback = callbacks[i++]);) { 757 callback(env); 758 } 759 } 760 }, 761 762 Token: Token 763 }; 764 _self.Prism = _; 765 766 767 // Typescript note: 768 // The following can be used to import the Token type in JSDoc: 769 // 770 // @typedef {InstanceType<import("./prism-core")["Token"]>} Token 771 772 /** 773 * Creates a new token. 774 * 775 * @param {string} type See {@link Token#type type} 776 * @param {string | TokenStream} content See {@link Token#content content} 777 * @param {string|string[]} [alias] The alias(es) of the token. 778 * @param {string} [matchedStr=""] A copy of the full string this token was created from. 779 * @class 780 * @global 781 * @public 782 */ 783 function Token(type, content, alias, matchedStr) { 784 /** 785 * The type of the token. 786 * 787 * This is usually the key of a pattern in a {@link Grammar}. 788 * 789 * @type {string} 790 * @see GrammarToken 791 * @public 792 */ 793 this.type = type; 794 /** 795 * The strings or tokens contained by this token. 796 * 797 * This will be a token stream if the pattern matched also defined an `inside` grammar. 798 * 799 * @type {string | TokenStream} 800 * @public 801 */ 802 this.content = content; 803 /** 804 * The alias(es) of the token. 805 * 806 * @type {string|string[]} 807 * @see GrammarToken 808 * @public 809 */ 810 this.alias = alias; 811 // Copy of the full string this token was created from 812 this.length = (matchedStr || '').length | 0; 813 } 814 815 /** 816 * A token stream is an array of strings and {@link Token Token} objects. 817 * 818 * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process 819 * them. 820 * 821 * 1. No adjacent strings. 822 * 2. No empty strings. 823 * 824 * The only exception here is the token stream that only contains the empty string and nothing else. 825 * 826 * @typedef {Array<string | Token>} TokenStream 827 * @global 828 * @public 829 */ 830 831 /** 832 * Converts the given token or token stream to an HTML representation. 833 * 834 * The following hooks will be run: 835 * 1. `wrap`: On each {@link Token}. 836 * 837 * @param {string | Token | TokenStream} o The token or token stream to be converted. 838 * @param {string} language The name of current language. 839 * @returns {string} The HTML representation of the token or token stream. 840 * @memberof Token 841 * @static 842 */ 843 Token.stringify = function stringify(o, language) { 844 if (typeof o == 'string') { 845 return o; 846 } 847 if (Array.isArray(o)) { 848 var s = ''; 849 o.forEach(function (e) { 850 s += stringify(e, language); 851 }); 852 return s; 853 } 854 855 var env = { 856 type: o.type, 857 content: stringify(o.content, language), 858 tag: 'span', 859 classes: ['token', o.type], 860 attributes: {}, 861 language: language 862 }; 863 864 var aliases = o.alias; 865 if (aliases) { 866 if (Array.isArray(aliases)) { 867 Array.prototype.push.apply(env.classes, aliases); 868 } else { 869 env.classes.push(aliases); 870 } 871 } 872 873 _.hooks.run('wrap', env); 874 875 var attributes = ''; 876 for (var name in env.attributes) { 877 attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"'; 878 } 879 880 return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>'; 881 }; 882 883 /** 884 * @param {RegExp} pattern 885 * @param {number} pos 886 * @param {string} text 887 * @param {boolean} lookbehind 888 * @returns {RegExpExecArray | null} 889 */ 890 function matchPattern(pattern, pos, text, lookbehind) { 891 pattern.lastIndex = pos; 892 var match = pattern.exec(text); 893 if (match && lookbehind && match[1]) { 894 // change the match to remove the text matched by the Prism lookbehind group 895 var lookbehindLength = match[1].length; 896 match.index += lookbehindLength; 897 match[0] = match[0].slice(lookbehindLength); 898 } 899 return match; 900 } 901 902 /** 903 * @param {string} text 904 * @param {LinkedList<string | Token>} tokenList 905 * @param {any} grammar 906 * @param {LinkedListNode<string | Token>} startNode 907 * @param {number} startPos 908 * @param {RematchOptions} [rematch] 909 * @returns {void} 910 * @private 911 * 912 * @typedef RematchOptions 913 * @property {string} cause 914 * @property {number} reach 915 */ 916 function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) { 917 for (var token in grammar) { 918 if (!grammar.hasOwnProperty(token) || !grammar[token]) { 919 continue; 920 } 921 922 var patterns = grammar[token]; 923 patterns = Array.isArray(patterns) ? patterns : [patterns]; 924 925 for (var j = 0; j < patterns.length; ++j) { 926 if (rematch && rematch.cause == token + ',' + j) { 927 return; 928 } 929 930 var patternObj = patterns[j]; 931 var inside = patternObj.inside; 932 var lookbehind = !!patternObj.lookbehind; 933 var greedy = !!patternObj.greedy; 934 var alias = patternObj.alias; 935 936 if (greedy && !patternObj.pattern.global) { 937 // Without the global flag, lastIndex won't work 938 var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0]; 939 patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g'); 940 } 941 942 /** @type {RegExp} */ 943 var pattern = patternObj.pattern || patternObj; 944 945 for ( // iterate the token list and keep track of the current token/string position 946 var currentNode = startNode.next, pos = startPos; 947 currentNode !== tokenList.tail; 948 pos += currentNode.value.length, currentNode = currentNode.next 949 ) { 950 951 if (rematch && pos >= rematch.reach) { 952 break; 953 } 954 955 var str = currentNode.value; 956 957 if (tokenList.length > text.length) { 958 // Something went terribly wrong, ABORT, ABORT! 959 return; 960 } 961 962 if (str instanceof Token) { 963 continue; 964 } 965 966 var removeCount = 1; // this is the to parameter of removeBetween 967 var match; 968 969 if (greedy) { 970 match = matchPattern(pattern, pos, text, lookbehind); 971 if (!match || match.index >= text.length) { 972 break; 973 } 974 975 var from = match.index; 976 var to = match.index + match[0].length; 977 var p = pos; 978 979 // find the node that contains the match 980 p += currentNode.value.length; 981 while (from >= p) { 982 currentNode = currentNode.next; 983 p += currentNode.value.length; 984 } 985 // adjust pos (and p) 986 p -= currentNode.value.length; 987 pos = p; 988 989 // the current node is a Token, then the match starts inside another Token, which is invalid 990 if (currentNode.value instanceof Token) { 991 continue; 992 } 993 994 // find the last node which is affected by this match 995 for ( 996 var k = currentNode; 997 k !== tokenList.tail && (p < to || typeof k.value === 'string'); 998 k = k.next 999 ) { 1000 removeCount++; 1001 p += k.value.length; 1002 } 1003 removeCount--; 1004 1005 // replace with the new match 1006 str = text.slice(pos, p); 1007 match.index -= pos; 1008 } else { 1009 match = matchPattern(pattern, 0, str, lookbehind); 1010 if (!match) { 1011 continue; 1012 } 1013 } 1014 1015 // eslint-disable-next-line no-redeclare 1016 var from = match.index; 1017 var matchStr = match[0]; 1018 var before = str.slice(0, from); 1019 var after = str.slice(from + matchStr.length); 1020 1021 var reach = pos + str.length; 1022 if (rematch && reach > rematch.reach) { 1023 rematch.reach = reach; 1024 } 1025 1026 var removeFrom = currentNode.prev; 1027 1028 if (before) { 1029 removeFrom = addAfter(tokenList, removeFrom, before); 1030 pos += before.length; 1031 } 1032 1033 removeRange(tokenList, removeFrom, removeCount); 1034 1035 var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr); 1036 currentNode = addAfter(tokenList, removeFrom, wrapped); 1037 1038 if (after) { 1039 addAfter(tokenList, currentNode, after); 1040 } 1041 1042 if (removeCount > 1) { 1043 // at least one Token object was removed, so we have to do some rematching 1044 // this can only happen if the current pattern is greedy 1045 1046 /** @type {RematchOptions} */ 1047 var nestedRematch = { 1048 cause: token + ',' + j, 1049 reach: reach 1050 }; 1051 matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch); 1052 1053 // the reach might have been extended because of the rematching 1054 if (rematch && nestedRematch.reach > rematch.reach) { 1055 rematch.reach = nestedRematch.reach; 1056 } 1057 } 1058 } 1059 } 1060 } 1061 } 1062 1063 /** 1064 * @typedef LinkedListNode 1065 * @property {T} value 1066 * @property {LinkedListNode<T> | null} prev The previous node. 1067 * @property {LinkedListNode<T> | null} next The next node. 1068 * @template T 1069 * @private 1070 */ 1071 1072 /** 1073 * @template T 1074 * @private 1075 */ 1076 function LinkedList() { 1077 /** @type {LinkedListNode<T>} */ 1078 var head = { value: null, prev: null, next: null }; 1079 /** @type {LinkedListNode<T>} */ 1080 var tail = { value: null, prev: head, next: null }; 1081 head.next = tail; 1082 1083 /** @type {LinkedListNode<T>} */ 1084 this.head = head; 1085 /** @type {LinkedListNode<T>} */ 1086 this.tail = tail; 1087 this.length = 0; 1088 } 1089 1090 /** 1091 * Adds a new node with the given value to the list. 1092 * 1093 * @param {LinkedList<T>} list 1094 * @param {LinkedListNode<T>} node 1095 * @param {T} value 1096 * @returns {LinkedListNode<T>} The added node. 1097 * @template T 1098 */ 1099 function addAfter(list, node, value) { 1100 // assumes that node != list.tail && values.length >= 0 1101 var next = node.next; 1102 1103 var newNode = { value: value, prev: node, next: next }; 1104 node.next = newNode; 1105 next.prev = newNode; 1106 list.length++; 1107 1108 return newNode; 1109 } 1110 /** 1111 * Removes `count` nodes after the given node. The given node will not be removed. 1112 * 1113 * @param {LinkedList<T>} list 1114 * @param {LinkedListNode<T>} node 1115 * @param {number} count 1116 * @template T 1117 */ 1118 function removeRange(list, node, count) { 1119 var next = node.next; 1120 for (var i = 0; i < count && next !== list.tail; i++) { 1121 next = next.next; 1122 } 1123 node.next = next; 1124 next.prev = node; 1125 list.length -= i; 1126 } 1127 /** 1128 * @param {LinkedList<T>} list 1129 * @returns {T[]} 1130 * @template T 1131 */ 1132 function toArray(list) { 1133 var array = []; 1134 var node = list.head.next; 1135 while (node !== list.tail) { 1136 array.push(node.value); 1137 node = node.next; 1138 } 1139 return array; 1140 } 1141 1142 1143 if (!_self.document) { 1144 if (!_self.addEventListener) { 1145 // in Node.js 1146 return _; 1147 } 1148 1149 if (!_.disableWorkerMessageHandler) { 1150 // In worker 1151 _self.addEventListener('message', function (evt) { 1152 var message = JSON.parse(evt.data); 1153 var lang = message.language; 1154 var code = message.code; 1155 var immediateClose = message.immediateClose; 1156 1157 _self.postMessage(_.highlight(code, _.languages[lang], lang)); 1158 if (immediateClose) { 1159 _self.close(); 1160 } 1161 }, false); 1162 } 1163 1164 return _; 1165 } 1166 1167 // Get current script and highlight 1168 var script = _.util.currentScript(); 1169 1170 if (script) { 1171 _.filename = script.src; 1172 1173 if (script.hasAttribute('data-manual')) { 1174 _.manual = true; 1175 } 1176 } 1177 1178 function highlightAutomaticallyCallback() { 1179 if (!_.manual) { 1180 _.highlightAll(); 1181 } 1182 } 1183 1184 if (!_.manual) { 1185 // If the document state is "loading", then we'll use DOMContentLoaded. 1186 // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the 1187 // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they 1188 // might take longer one animation frame to execute which can create a race condition where only some plugins have 1189 // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded. 1190 // See https://github.com/PrismJS/prism/issues/2102 1191 var readyState = document.readyState; 1192 if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) { 1193 document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback); 1194 } else { 1195 if (window.requestAnimationFrame) { 1196 window.requestAnimationFrame(highlightAutomaticallyCallback); 1197 } else { 1198 window.setTimeout(highlightAutomaticallyCallback, 16); 1199 } 1200 } 1201 } 1202 1203 return _; 1204 1205}(_self)); 1206 1207if (
1207typeof module !== 'undefined' && module.exports) { 1208 module.exports = Prism; 1209} 1210 1211// hack for components to work correctly in node.js 1212if (typeof global !== 'undefined') { 1213 global.Prism = Prism; 1214} 1215 1216// some additional documentation/types 1217 1218/** 1219 * The expansion of a simple `RegExp` literal to support additional properties. 1220 * 1221 * @typedef GrammarToken 1222 * @property {RegExp} pattern The regular expression of the token. 1223 * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively) 1224 * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token. 1225 * @property {boolean} [greedy=false] Whether the token is greedy. 1226 * @property {string|string[]} [alias] An optional alias or list of aliases. 1227 * @property {Grammar} [inside] The nested grammar of this token. 1228 * 1229 * The `inside` grammar will be used to tokenize the text value of each token of this kind. 1230 * 1231 * This can be used to make nested and even recursive language definitions. 1232 * 1233 * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into 1234 * each another. 1235 * @global 1236 * @public 1237 */ 1238 1239/** 1240 * @typedef Grammar 1241 * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>} 1242 * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar. 1243 * @global 1244 * @public 1245 */ 1246 1247/** 1248 * A function which will invoked after an element was successfully highlighted. 1249 * 1250 * @callback HighlightCallback 1251 * @param {Element} element The element successfully highlighted. 1252 * @returns {void} 1253 * @global 1254 * @public 1255 */ 1256 1257/** 1258 * @callback HookCallback 1259 * @param {Object<string, any>} env The environment variables of the hook. 1260 * @returns {void} 1261 * @global 1262 * @public 1263 */
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.