at master 61 kB view raw
1/* PrismJS 1.30.0 2https://prismjs.com/download#themes=prism&plugins=custom-class+show-language+autoloader+toolbar+copy-to-clipboard */ 3/// <reference lib="WebWorker"/> 4 5var _self = (typeof window !== 'undefined') 6 ? window // if in browser 7 : ( 8 (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) 9 ? self // if in worker 10 : {} // if in node js 11 ); 12 13/** 14 * Prism: Lightweight, robust, elegant syntax highlighting 15 * 16 * @license MIT <https://opensource.org/licenses/MIT> 17 * @author Lea Verou <https://lea.verou.me> 18 * @namespace 19 * @public 20 */ 21var Prism = (function (_self) { 22 23 // Private helper vars 24 var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i; 25 var uniqueId = 0; 26 27 // The grammar object for plaintext 28 var plainTextGrammar = {}; 29 30 31 var _ = { 32 /** 33 * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the 34 * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load 35 * additional languages or plugins yourself. 36 * 37 * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. 38 * 39 * You obviously have to change this value before the automatic highlighting started. To do this, you can add an 40 * empty Prism object into the global scope before loading the Prism script like this: 41 * 42 * ```js 43 * window.Prism = window.Prism || {}; 44 * Prism.manual = true; 45 * // add a new <script> to load Prism's script 46 * ``` 47 * 48 * @default false 49 * @type {boolean} 50 * @memberof Prism 51 * @public 52 */ 53 manual: _self.Prism && _self.Prism.manual, 54 /** 55 * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses 56 * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your 57 * own worker, you don't want it to do this. 58 * 59 * By setting this value to `true`, Prism will not add its own listeners to the worker. 60 * 61 * You obviously have to change this value before Prism executes. To do this, you can add an 62 * empty Prism object into the global scope before loading the Prism script like this: 63 * 64 * ```js 65 * window.Prism = window.Prism || {}; 66 * Prism.disableWorkerMessageHandler = true; 67 * // Load Prism's script 68 * ``` 69 * 70 * @default false 71 * @type {boolean} 72 * @memberof Prism 73 * @public 74 */ 75 disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, 76 77 /** 78 * A namespace for utility methods. 79 * 80 * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may 81 * change or disappear at any time. 82 * 83 * @namespace 84 * @memberof Prism 85 */ 86 util: { 87 encode: function encode(tokens) { 88 if (tokens instanceof Token) { 89 return new Token(tokens.type, encode(tokens.content), tokens.alias); 90 } else if (Array.isArray(tokens)) { 91 return tokens.map(encode); 92 } else { 93 return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' '); 94 } 95 }, 96 97 /** 98 * Returns the name of the type of the given value. 99 * 100 * @param {any} o 101 * @returns {string} 102 * @example 103 * type(null) === 'Null' 104 * type(undefined) === 'Undefined' 105 * type(123) === 'Number' 106 * type('foo') === 'String' 107 * type(true) === 'Boolean' 108 * type([1, 2]) === 'Array' 109 * type({}) === 'Object' 110 * type(String) === 'Function' 111 * type(/abc+/) === 'RegExp' 112 */ 113 type: function (o) { 114 return Object.prototype.toString.call(o).slice(8, -1); 115 }, 116 117 /** 118 * Returns a unique number for the given object. Later calls will still return the same number. 119 * 120 * @param {Object} obj 121 * @returns {number} 122 */ 123 objId: function (obj) { 124 if (!obj['__id']) { 125 Object.defineProperty(obj, '__id', { value: ++uniqueId }); 126 } 127 return obj['__id']; 128 }, 129 130 /** 131 * Creates a deep clone of the given object. 132 * 133 * The main intended use of this function is to clone language definitions. 134 * 135 * @param {T} o 136 * @param {Record<number, any>} [visited] 137 * @returns {T} 138 * @template T 139 */ 140 clone: function deepClone(o, visited) { 141 visited = visited || {}; 142 143 var clone; var id; 144 switch (_.util.type(o)) { 145 case 'Object': 146 id = _.util.objId(o); 147 if (visited[id]) { 148 return visited[id]; 149 } 150 clone = /** @type {Record<string, any>} */ ({}); 151 visited[id] = clone; 152 153 for (var key in o) { 154 if (o.hasOwnProperty(key)) { 155 clone[key] = deepClone(o[key], visited); 156 } 157 } 158 159 return /** @type {any} */ (clone); 160 161 case 'Array': 162 id = _.util.objId(o); 163 if (visited[id]) { 164 return visited[id]; 165 } 166 clone = []; 167 visited[id] = clone; 168 169 (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) { 170 clone[i] = deepClone(v, visited); 171 }); 172 173 return /** @type {any} */ (clone); 174 175 default: 176 return o; 177 } 178 }, 179 180 /** 181 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class. 182 * 183 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned. 184 * 185 * @param {Element} element 186 * @returns {string} 187 */ 188 getLanguage: function (element) { 189 while (element) { 190 var m = lang.exec(element.className); 191 if (m) { 192 return m[1].toLowerCase(); 193 } 194 element = element.parentElement; 195 } 196 return 'none'; 197 }, 198 199 /** 200 * Sets the Prism `language-xxxx` class of the given element. 201 * 202 * @param {Element} element 203 * @param {string} language 204 * @returns {void} 205 */ 206 setLanguage: function (element, language) { 207 // remove all `language-xxxx` classes 208 // (this might leave behind a leading space) 209 element.className = element.className.replace(RegExp(lang, 'gi'), ''); 210 211 // add the new `language-xxxx` class 212 // (using `classList` will automatically clean up spaces for us) 213 element.classList.add('language-' + language); 214 }, 215 216 /** 217 * Returns the script element that is currently executing. 218 * 219 * This does __not__ work for line script element. 220 * 221 * @returns {HTMLScriptElement | null} 222 */ 223 currentScript: function () { 224 if (typeof document === 'undefined') { 225 return null; 226 } 227 if (document.currentScript && document.currentScript.tagName === 'SCRIPT' && 1 < 2 /* hack to trip TS' flow analysis */) { 228 return /** @type {any} */ (document.currentScript); 229 } 230 231 // IE11 workaround 232 // we'll get the src of the current script by parsing IE11's error stack trace 233 // this will not work for inline scripts 234 235 try { 236 throw new Error(); 237 } catch (err) { 238 // Get file src url from stack. Specifically works with the format of stack traces in IE. 239 // A stack will look like this: 240 // 241 // Error 242 // at _.util.currentScript (http://localhost/components/prism-core.js:119:5) 243 // at Global code (http://localhost/components/prism-core.js:606:1) 244 245 var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) || [])[1]; 246 if (src) { 247 var scripts = document.getElementsByTagName('script'); 248 for (var i in scripts) { 249 if (scripts[i].src == src) { 250 return scripts[i]; 251 } 252 } 253 } 254 return null; 255 } 256 }, 257 258 /** 259 * Returns whether a given class is active for `element`. 260 * 261 * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated 262 * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the 263 * given class is just the given class with a `no-` prefix. 264 * 265 * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is 266 * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its 267 * ancestors have the given class or the negated version of it, then the default activation will be returned. 268 * 269 * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated 270 * version of it, the class is considered active. 271 * 272 * @param {Element} element 273 * @param {string} className 274 * @param {boolean} [defaultActivation=false] 275 * @returns {boolean} 276 */ 277 isActive: function (element, className, defaultActivation) { 278 var no = 'no-' + className; 279 280 while (element) { 281 var classList = element.classList; 282 if (classList.contains(className)) { 283 return true; 284 } 285 if (classList.contains(no)) { 286 return false; 287 } 288 element = element.parentElement; 289 } 290 return !!defaultActivation; 291 } 292 }, 293 294 /** 295 * This namespace contains all currently loaded languages and the some helper functions to create and modify languages. 296 * 297 * @namespace 298 * @memberof Prism 299 * @public 300 */ 301 languages: { 302 /** 303 * The grammar for plain, unformatted text. 304 */ 305 plain: plainTextGrammar, 306 plaintext: plainTextGrammar, 307 text: plainTextGrammar, 308 txt: plainTextGrammar, 309 310 /** 311 * Creates a deep copy of the language with the given id and appends the given tokens. 312 * 313 * If a token in `redef` also appears in the copied language, then the existing token in the copied language 314 * will be overwritten at its original position. 315 * 316 * ## Best practices 317 * 318 * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language) 319 * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to 320 * understand the language definition because, normally, the order of tokens matters in Prism grammars. 321 * 322 * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. 323 * Furthermore, all non-overwriting tokens should be placed after the overwriting ones. 324 * 325 * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`. 326 * @param {Grammar} redef The new tokens to append. 327 * @returns {Grammar} The new language created. 328 * @public 329 * @example 330 * Prism.languages['css-with-colors'] = Prism.languages.extend('css', { 331 * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token 332 * // at its original position 333 * 'comment': { ... }, 334 * // CSS doesn't have a 'color' token, so this token will be appended 335 * 'color': /\b(?:red|green|blue)\b/ 336 * }); 337 */ 338 extend: function (id, redef) { 339 var lang = _.util.clone(_.languages[id]); 340 341 for (var key in redef) { 342 lang[key] = redef[key]; 343 } 344 345 return lang; 346 }, 347 348 /** 349 * Inserts tokens _before_ another token in a language definition or any other grammar. 350 * 351 * ## Usage 352 * 353 * This helper method makes it easy to modify existing languages. For example, the CSS language definition 354 * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded 355 * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the 356 * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do 357 * this: 358 * 359 * ```js 360 * Prism.languages.markup.style = { 361 * // token 362 * }; 363 * ``` 364 * 365 * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens 366 * before existing tokens. For the CSS example above, you would use it like this: 367 * 368 * ```js 369 * Prism.languages.insertBefore('markup', 'cdata', { 370 * 'style': { 371 * // token 372 * } 373 * }); 374 * ``` 375 * 376 * ## Special cases 377 * 378 * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar 379 * will be ignored. 380 * 381 * This behavior can be used to insert tokens after `before`: 382 * 383 * ```js 384 * Prism.languages.insertBefore('markup', 'comment', { 385 * 'comment': Prism.languages.markup.comment, 386 * // tokens after 'comment' 387 * }); 388 * ``` 389 * 390 * ## Limitations 391 * 392 * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object 393 * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave 394 * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily 395 * deleting properties which is necessary to insert at arbitrary positions. 396 * 397 * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object. 398 * Instead, it will create a new object and replace all references to the target object with the new one. This 399 * can be done without temporarily deleting properties, so the iteration order is well-defined. 400 * 401 * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if 402 * you hold the target object in a variable, then the value of the variable will not change. 403 * 404 * ```js 405 * var oldMarkup = Prism.languages.markup; 406 * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... }); 407 * 408 * assert(oldMarkup !== Prism.languages.markup); 409 * assert(newMarkup === Prism.languages.markup); 410 * ``` 411 * 412 * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the 413 * object to be modified. 414 * @param {string} before The key to insert before. 415 * @param {Grammar} insert An object containing the key-value pairs to be inserted. 416 * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the 417 * object to be modified. 418 * 419 * Defaults to `Prism.languages`. 420 * @returns {Grammar} The new grammar object. 421 * @public 422 */ 423 insertBefore: function (inside, before, insert, root) { 424 root = root || /** @type {any} */ (_.languages); 425 var grammar = root[inside]; 426 /** @type {Grammar} */ 427 var ret = {}; 428 429 for (var token in grammar) { 430 if (grammar.hasOwnProperty(token)) { 431 432 if (token == before) { 433 for (var newToken in insert) { 434 if (insert.hasOwnProperty(newToken)) { 435 ret[newToken] = insert[newToken]; 436 } 437 } 438 } 439 440 // Do not insert token which also occur in insert. See #1525 441 if (!insert.hasOwnProperty(token)) { 442 ret[token] = grammar[token]; 443 } 444 } 445 } 446 447 var old = root[inside]; 448 root[inside] = ret; 449 450 // Update references in other language definitions 451 _.languages.DFS(_.languages, function (key, value) { 452 if (value === old && key != inside) { 453 this[key] = ret; 454 } 455 }); 456 457 return ret; 458 }, 459 460 // Traverse a language definition with Depth First Search 461 DFS: function DFS(o, callback, type, visited) { 462 visited = visited || {}; 463 464 var objId = _.util.objId; 465 466 for (var i in o) { 467 if (o.hasOwnProperty(i)) { 468 callback.call(o, i, o[i], type || i); 469 470 var property = o[i]; 471 var propertyType = _.util.type(property); 472 473 if (propertyType === 'Object' && !visited[objId(property)]) { 474 visited[objId(property)] = true; 475 DFS(property, callback, null, visited); 476 } else if (propertyType === 'Array' && !visited[objId(property)]) { 477 visited[objId(property)] = true; 478 DFS(property, callback, i, visited); 479 } 480 } 481 } 482 } 483 }, 484 485 plugins: {}, 486 487 /** 488 * This is the most high-level function in Prism’s API. 489 * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on 490 * each one of them. 491 * 492 * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`. 493 * 494 * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}. 495 * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}. 496 * @memberof Prism 497 * @public 498 */ 499 highlightAll: function (async, callback) { 500 _.highlightAllUnder(document, async, callback); 501 }, 502 503 /** 504 * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls 505 * {@link Prism.highlightElement} on each one of them. 506 * 507 * The following hooks will be run: 508 * 1. `before-highlightall` 509 * 2. `before-all-elements-highlight` 510 * 3. All hooks of {@link Prism.highlightElement} for each element. 511 * 512 * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted. 513 * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers. 514 * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done. 515 * @memberof Prism 516 * @public 517 */ 518 highlightAllUnder: function (container, async, callback) { 519 var env = { 520 callback: callback, 521 container: container, 522 selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' 523 }; 524 525 _.hooks.run('before-highlightall', env); 526 527 env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector)); 528 529 _.hooks.run('before-all-elements-highlight', env); 530 531 for (var i = 0, element; (element = env.elements[i++]);) { 532 _.highlightElement(element, async === true, env.callback); 533 } 534 }, 535 536 /** 537 * Highlights the code inside a single element. 538 * 539 * The following hooks will be run: 540 * 1. `before-sanity-check` 541 * 2. `before-highlight` 542 * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`. 543 * 4. `before-insert` 544 * 5. `after-highlight` 545 * 6. `complete` 546 * 547 * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for 548 * the element's language. 549 * 550 * @param {Element} element The element containing the code. 551 * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier. 552 * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers 553 * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is 554 * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default). 555 * 556 * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for 557 * asynchronous highlighting to work. You can build your own bundle on the 558 * [Download page](https://prismjs.com/download.html). 559 * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done. 560 * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously. 561 * @memberof Prism 562 * @public 563 */ 564 highlightElement: function (element, async, callback) { 565 // Find language 566 var language = _.util.getLanguage(element); 567 var grammar = _.languages[language]; 568 569 // Set language on the element, if not present 570 _.util.setLanguage(element, language); 571 572 // Set language on the parent, for styling 573 var parent = element.parentElement; 574 if (parent && parent.nodeName.toLowerCase() === 'pre') { 575 _.util.setLanguage(parent, language); 576 } 577 578 var code = element.textContent; 579 580 var env = { 581 element: element, 582 language: language, 583 grammar: grammar, 584 code: code 585 }; 586 587 function insertHighlightedCode(highlightedCode) { 588 env.highlightedCode = highlightedCode; 589 590 _.hooks.run('before-insert', env); 591 592 env.element.innerHTML = env.highlightedCode; 593 594 _.hooks.run('after-highlight', env); 595 _.hooks.run('complete', env); 596 callback && callback.call(env.element); 597 } 598 599 _.hooks.run('before-sanity-check', env); 600 601 // plugins may change/add the parent/element 602 parent = env.element.parentElement; 603 if (parent && parent.nodeName.toLowerCase() === 'pre' && !parent.hasAttribute('tabindex')) { 604 parent.setAttribute('tabindex', '0'); 605 } 606 607 if (!env.code) { 608 _.hooks.run('complete', env); 609 callback && callback.call(env.element); 610 return; 611 } 612 613 _.hooks.run('before-highlight', env); 614 615 if (!env.grammar) { 616 insertHighlightedCode(_.util.encode(env.code)); 617 return; 618 } 619 620 if (async && _self.Worker) { 621 var worker = new Worker(_.filename); 622 623 worker.onmessage = function (evt) { 624 insertHighlightedCode(evt.data); 625 }; 626 627 worker.postMessage(JSON.stringify({ 628 language: env.language, 629 code: env.code, 630 immediateClose: true 631 })); 632 } else { 633 insertHighlightedCode(_.highlight(env.code, env.grammar, env.language)); 634 } 635 }, 636 637 /** 638 * Low-level function, only use if you know what you’re doing. It accepts a string of text as input 639 * and the language definitions to use, and returns a string with the HTML produced. 640 * 641 * The following hooks will be run: 642 * 1. `before-tokenize` 643 * 2. `after-tokenize` 644 * 3. `wrap`: On each {@link Token}. 645 * 646 * @param {string} text A string with the code to be highlighted. 647 * @param {Grammar} grammar An object containing the tokens to use. 648 * 649 * Usually a language definition like `Prism.languages.markup`. 650 * @param {string} language The name of the language definition passed to `grammar`. 651 * @returns {string} The highlighted HTML. 652 * @memberof Prism 653 * @public 654 * @example 655 * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript'); 656 */ 657 highlight: function (text, grammar, language) { 658 var env = { 659 code: text, 660 grammar: grammar, 661 language: language 662 }; 663 _.hooks.run('before-tokenize', env); 664 if (!env.grammar) { 665 throw new Error('The language "' + env.language + '" has no grammar.'); 666 } 667 env.tokens = _.tokenize(env.code, env.grammar); 668 _.hooks.run('after-tokenize', env); 669 return Token.stringify(_.util.encode(env.tokens), env.language); 670 }, 671 672 /** 673 * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input 674 * and the language definitions to use, and returns an array with the tokenized code. 675 * 676 * When the language definition includes nested tokens, the function is called recursively on each of these tokens. 677 * 678 * This method could be useful in other contexts as well, as a very crude parser. 679 * 680 * @param {string} text A string with the code to be highlighted. 681 * @param {Grammar} grammar An object containing the tokens to use. 682 * 683 * Usually a language definition like `Prism.languages.markup`. 684 * @returns {TokenStream} An array of strings and tokens, a token stream. 685 * @memberof Prism 686 * @public 687 * @example 688 * let code = `var foo = 0;`; 689 * let tokens = Prism.tokenize(code, Prism.languages.javascript); 690 * tokens.forEach(token => { 691 * if (token instanceof Prism.Token && token.type === 'number') { 692 * console.log(`Found numeric literal: ${token.content}`); 693 * } 694 * }); 695 */ 696 tokenize: function (text, grammar) { 697 var rest = grammar.rest; 698 if (rest) { 699 for (var token in rest) { 700 grammar[token] = rest[token]; 701 } 702 703 delete grammar.rest; 704 } 705 706 var tokenList = new LinkedList(); 707 addAfter(tokenList, tokenList.head, text); 708 709 matchGrammar(text, tokenList, grammar, tokenList.head, 0); 710 711 return toArray(tokenList); 712 }, 713 714 /** 715 * @namespace 716 * @memberof Prism 717 * @public 718 */ 719 hooks: { 720 all: {}, 721 722 /** 723 * Adds the given callback to the list of callbacks for the given hook. 724 * 725 * The callback will be invoked when the hook it is registered for is run. 726 * Hooks are usually directly run by a highlight function but you can also run hooks yourself. 727 * 728 * One callback function can be registered to multiple hooks and the same hook multiple times. 729 * 730 * @param {string} name The name of the hook. 731 * @param {HookCallback} callback The callback function which is given environment variables. 732 * @public 733 */ 734 add: function (name, callback) { 735 var hooks = _.hooks.all; 736 737 hooks[name] = hooks[name] || []; 738 739 hooks[name].push(callback); 740 }, 741 742 /** 743 * Runs a hook invoking all registered callbacks with the given environment variables. 744 * 745 * Callbacks will be invoked synchronously and in the order in which they were registered. 746 * 747 * @param {string} name The name of the hook. 748 * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered. 749 * @public 750 */ 751 run: function (name, env) { 752 var callbacks = _.hooks.all[name]; 753 754 if (!callbacks || !callbacks.length) { 755 return; 756 } 757 758 for (var i = 0, callback; (callback = callbacks[i++]);) { 759 callback(env); 760 } 761 } 762 }, 763 764 Token: Token 765 }; 766 _self.Prism = _; 767 768 769 // Typescript note: 770 // The following can be used to import the Token type in JSDoc: 771 // 772 // @typedef {InstanceType<import("./prism-core")["Token"]>} Token 773 774 /** 775 * Creates a new token. 776 * 777 * @param {string} type See {@link Token#type type} 778 * @param {string | TokenStream} content See {@link Token#content content} 779 * @param {string|string[]} [alias] The alias(es) of the token. 780 * @param {string} [matchedStr=""] A copy of the full string this token was created from. 781 * @class 782 * @global 783 * @public 784 */ 785 function Token(type, content, alias, matchedStr) { 786 /** 787 * The type of the token. 788 * 789 * This is usually the key of a pattern in a {@link Grammar}. 790 * 791 * @type {string} 792 * @see GrammarToken 793 * @public 794 */ 795 this.type = type; 796 /** 797 * The strings or tokens contained by this token. 798 * 799 * This will be a token stream if the pattern matched also defined an `inside` grammar. 800 * 801 * @type {string | TokenStream} 802 * @public 803 */ 804 this.content = content; 805 /** 806 * The alias(es) of the token. 807 * 808 * @type {string|string[]} 809 * @see GrammarToken 810 * @public 811 */ 812 this.alias = alias; 813 // Copy of the full string this token was created from 814 this.length = (matchedStr || '').length | 0; 815 } 816 817 /** 818 * A token stream is an array of strings and {@link Token Token} objects. 819 * 820 * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process 821 * them. 822 * 823 * 1. No adjacent strings. 824 * 2. No empty strings. 825 * 826 * The only exception here is the token stream that only contains the empty string and nothing else. 827 * 828 * @typedef {Array<string | Token>} TokenStream 829 * @global 830 * @public 831 */ 832 833 /** 834 * Converts the given token or token stream to an HTML representation. 835 * 836 * The following hooks will be run: 837 * 1. `wrap`: On each {@link Token}. 838 * 839 * @param {string | Token | TokenStream} o The token or token stream to be converted. 840 * @param {string} language The name of current language. 841 * @returns {string} The HTML representation of the token or token stream. 842 * @memberof Token 843 * @static 844 */ 845 Token.stringify = function stringify(o, language) { 846 if (typeof o == 'string') { 847 return o; 848 } 849 if (Array.isArray(o)) { 850 var s = ''; 851 o.forEach(function (e) { 852 s += stringify(e, language); 853 }); 854 return s; 855 } 856 857 var env = { 858 type: o.type, 859 content: stringify(o.content, language), 860 tag: 'span', 861 classes: ['token', o.type], 862 attributes: {}, 863 language: language 864 }; 865 866 var aliases = o.alias; 867 if (aliases) { 868 if (Array.isArray(aliases)) { 869 Array.prototype.push.apply(env.classes, aliases); 870 } else { 871 env.classes.push(aliases); 872 } 873 } 874 875 _.hooks.run('wrap', env); 876 877 var attributes = ''; 878 for (var name in env.attributes) { 879 attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"'; 880 } 881 882 return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>'; 883 }; 884 885 /** 886 * @param {RegExp} pattern 887 * @param {number} pos 888 * @param {string} text 889 * @param {boolean} lookbehind 890 * @returns {RegExpExecArray | null} 891 */ 892 function matchPattern(pattern, pos, text, lookbehind) { 893 pattern.lastIndex = pos; 894 var match = pattern.exec(text); 895 if (match && lookbehind && match[1]) { 896 // change the match to remove the text matched by the Prism lookbehind group 897 var lookbehindLength = match[1].length; 898 match.index += lookbehindLength; 899 match[0] = match[0].slice(lookbehindLength); 900 } 901 return match; 902 } 903 904 /** 905 * @param {string} text 906 * @param {LinkedList<string | Token>} tokenList 907 * @param {any} grammar 908 * @param {LinkedListNode<string | Token>} startNode 909 * @param {number} startPos 910 * @param {RematchOptions} [rematch] 911 * @returns {void} 912 * @private 913 * 914 * @typedef RematchOptions 915 * @property {string} cause 916 * @property {number} reach 917 */ 918 function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) { 919 for (var token in grammar) { 920 if (!grammar.hasOwnProperty(token) || !grammar[token]) { 921 continue; 922 } 923 924 var patterns = grammar[token]; 925 patterns = Array.isArray(patterns) ? patterns : [patterns]; 926 927 for (var j = 0; j < patterns.length; ++j) { 928 if (rematch && rematch.cause == token + ',' + j) { 929 return; 930 } 931 932 var patternObj = patterns[j]; 933 var inside = patternObj.inside; 934 var lookbehind = !!patternObj.lookbehind; 935 var greedy = !!patternObj.greedy; 936 var alias = patternObj.alias; 937 938 if (greedy && !patternObj.pattern.global) { 939 // Without the global flag, lastIndex won't work 940 var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0]; 941 patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g'); 942 } 943 944 /** @type {RegExp} */ 945 var pattern = patternObj.pattern || patternObj; 946 947 for ( // iterate the token list and keep track of the current token/string position 948 var currentNode = startNode.next, pos = startPos; 949 currentNode !== tokenList.tail; 950 pos += currentNode.value.length, currentNode = currentNode.next 951 ) { 952 953 if (rematch && pos >= rematch.reach) { 954 break; 955 } 956 957 var str = currentNode.value; 958 959 if (tokenList.length > text.length) { 960 // Something went terribly wrong, ABORT, ABORT! 961 return; 962 } 963 964 if (str instanceof Token) { 965 continue; 966 } 967 968 var removeCount = 1; // this is the to parameter of removeBetween 969 var match; 970 971 if (greedy) { 972 match = matchPattern(pattern, pos, text, lookbehind); 973 if (!match || match.index >= text.length) { 974 break; 975 } 976 977 var from = match.index; 978 var to = match.index + match[0].length; 979 var p = pos; 980 981 // find the node that contains the match 982 p += currentNode.value.length; 983 while (from >= p) { 984 currentNode = currentNode.next; 985 p += currentNode.value.length; 986 } 987 // adjust pos (and p) 988 p -= currentNode.value.length; 989 pos = p; 990 991 // the current node is a Token, then the match starts inside another Token, which is invalid 992 if (currentNode.value instanceof Token) { 993 continue; 994 } 995 996 // find the last node which is affected by this match 997 for ( 998 var k = currentNode; 999 k !== tokenList.tail && (p < to || typeof k.value === 'string'); 1000 k = k.next 1001 ) { 1002 removeCount++; 1003 p += k.value.length; 1004 } 1005 removeCount--; 1006 1007 // replace with the new match 1008 str = text.slice(pos, p); 1009 match.index -= pos; 1010 } else { 1011 match = matchPattern(pattern, 0, str, lookbehind); 1012 if (!match) { 1013 continue; 1014 } 1015 } 1016 1017 // eslint-disable-next-line no-redeclare 1018 var from = match.index; 1019 var matchStr = match[0]; 1020 var before = str.slice(0, from); 1021 var after = str.slice(from + matchStr.length); 1022 1023 var reach = pos + str.length; 1024 if (rematch && reach > rematch.reach) { 1025 rematch.reach = reach; 1026 } 1027 1028 var removeFrom = currentNode.prev; 1029 1030 if (before) { 1031 removeFrom = addAfter(tokenList, removeFrom, before); 1032 pos += before.length; 1033 } 1034 1035 removeRange(tokenList, removeFrom, removeCount); 1036 1037 var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr); 1038 currentNode = addAfter(tokenList, removeFrom, wrapped); 1039 1040 if (after) { 1041 addAfter(tokenList, currentNode, after); 1042 } 1043 1044 if (removeCount > 1) { 1045 // at least one Token object was removed, so we have to do some rematching 1046 // this can only happen if the current pattern is greedy 1047 1048 /** @type {RematchOptions} */ 1049 var nestedRematch = { 1050 cause: token + ',' + j, 1051 reach: reach 1052 }; 1053 matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch); 1054 1055 // the reach might have been extended because of the rematching 1056 if (rematch && nestedRematch.reach > rematch.reach) { 1057 rematch.reach = nestedRematch.reach; 1058 } 1059 } 1060 } 1061 } 1062 } 1063 } 1064 1065 /** 1066 * @typedef LinkedListNode 1067 * @property {T} value 1068 * @property {LinkedListNode<T> | null} prev The previous node. 1069 * @property {LinkedListNode<T> | null} next The next node. 1070 * @template T 1071 * @private 1072 */ 1073 1074 /** 1075 * @template T 1076 * @private 1077 */ 1078 function LinkedList() { 1079 /** @type {LinkedListNode<T>} */ 1080 var head = { value: null, prev: null, next: null }; 1081 /** @type {LinkedListNode<T>} */ 1082 var tail = { value: null, prev: head, next: null }; 1083 head.next = tail; 1084 1085 /** @type {LinkedListNode<T>} */ 1086 this.head = head; 1087 /** @type {LinkedListNode<T>} */ 1088 this.tail = tail; 1089 this.length = 0; 1090 } 1091 1092 /** 1093 * Adds a new node with the given value to the list. 1094 * 1095 * @param {LinkedList<T>} list 1096 * @param {LinkedListNode<T>} node 1097 * @param {T} value 1098 * @returns {LinkedListNode<T>} The added node. 1099 * @template T 1100 */ 1101 function addAfter(list, node, value) { 1102 // assumes that node != list.tail && values.length >= 0 1103 var next = node.next; 1104 1105 var newNode = { value: value, prev: node, next: next }; 1106 node.next = newNode; 1107 next.prev = newNode; 1108 list.length++; 1109 1110 return newNode; 1111 } 1112 /** 1113 * Removes `count` nodes after the given node. The given node will not be removed. 1114 * 1115 * @param {LinkedList<T>} list 1116 * @param {LinkedListNode<T>} node 1117 * @param {number} count 1118 * @template T 1119 */ 1120 function removeRange(list, node, count) { 1121 var next = node.next; 1122 for (var i = 0; i < count && next !== list.tail; i++) { 1123 next = next.next; 1124 } 1125 node.next = next; 1126 next.prev = node; 1127 list.length -= i; 1128 } 1129 /** 1130 * @param {LinkedList<T>} list 1131 * @returns {T[]} 1132 * @template T 1133 */ 1134 function toArray(list) { 1135 var array = []; 1136 var node = list.head.next; 1137 while (node !== list.tail) { 1138 array.push(node.value); 1139 node = node.next; 1140 } 1141 return array; 1142 } 1143 1144 1145 if (!_self.document) { 1146 if (!_self.addEventListener) { 1147 // in Node.js 1148 return _; 1149 } 1150 1151 if (!_.disableWorkerMessageHandler) { 1152 // In worker 1153 _self.addEventListener('message', function (evt) { 1154 var message = JSON.parse(evt.data); 1155 var lang = message.language; 1156 var code = message.code; 1157 var immediateClose = message.immediateClose; 1158 1159 _self.postMessage(_.highlight(code, _.languages[lang], lang)); 1160 if (immediateClose) { 1161 _self.close(); 1162 } 1163 }, false); 1164 } 1165 1166 return _; 1167 } 1168 1169 // Get current script and highlight 1170 var script = _.util.currentScript(); 1171 1172 if (script) { 1173 _.filename = script.src; 1174 1175 if (script.hasAttribute('data-manual')) { 1176 _.manual = true; 1177 } 1178 } 1179 1180 function highlightAutomaticallyCallback() { 1181 if (!_.manual) { 1182 _.highlightAll(); 1183 } 1184 } 1185 1186 if (!_.manual) { 1187 // If the document state is "loading", then we'll use DOMContentLoaded. 1188 // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the 1189 // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they 1190 // might take longer one animation frame to execute which can create a race condition where only some plugins have 1191 // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded. 1192 // See https://github.com/PrismJS/prism/issues/2102 1193 var readyState = document.readyState; 1194 if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) { 1195 document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback); 1196 } else { 1197 if (window.requestAnimationFrame) { 1198 window.requestAnimationFrame(highlightAutomaticallyCallback); 1199 } else { 1200 window.setTimeout(highlightAutomaticallyCallback, 16); 1201 } 1202 } 1203 } 1204 1205 return _; 1206 1207}(_self)); 1208 1209if (typeof module !== 'undefined' && module.exports) { 1210 module.exports = Prism; 1211} 1212 1213// hack for components to work correctly in node.js 1214if (typeof global !== 'undefined') { 1215 global.Prism = Prism; 1216} 1217 1218// some additional documentation/types 1219 1220/** 1221 * The expansion of a simple `RegExp` literal to support additional properties. 1222 * 1223 * @typedef GrammarToken 1224 * @property {RegExp} pattern The regular expression of the token. 1225 * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively) 1226 * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token. 1227 * @property {boolean} [greedy=false] Whether the token is greedy. 1228 * @property {string|string[]} [alias] An optional alias or list of aliases. 1229 * @property {Grammar} [inside] The nested grammar of this token. 1230 * 1231 * The `inside` grammar will be used to tokenize the text value of each token of this kind. 1232 * 1233 * This can be used to make nested and even recursive language definitions. 1234 * 1235 * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into 1236 * each another. 1237 * @global 1238 * @public 1239 */ 1240 1241/** 1242 * @typedef Grammar 1243 * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>} 1244 * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar. 1245 * @global 1246 * @public 1247 */ 1248 1249/** 1250 * A function which will invoked after an element was successfully highlighted. 1251 * 1252 * @callback HighlightCallback 1253 * @param {Element} element The element successfully highlighted. 1254 * @returns {void} 1255 * @global 1256 * @public 1257 */ 1258 1259/** 1260 * @callback HookCallback 1261 * @param {Object<string, any>} env The environment variables of the hook. 1262 * @returns {void} 1263 * @global 1264 * @public 1265 */ 1266; 1267(function () { 1268 1269 if (typeof Prism === 'undefined') { 1270 return; 1271 } 1272 1273 /** 1274 * @callback ClassMapper 1275 * @param {string} className 1276 * @param {string} language 1277 * @returns {string} 1278 * 1279 * @callback ClassAdder 1280 * @param {ClassAdderEnvironment} env 1281 * @returns {undefined | string | string[]} 1282 * 1283 * @typedef ClassAdderEnvironment 1284 * @property {string} language 1285 * @property {string} type 1286 * @property {string} content 1287 */ 1288 1289 // options 1290 1291 /** @type {ClassAdder | undefined} */ 1292 var adder; 1293 /** @type {ClassMapper | undefined} */ 1294 var mapper; 1295 /** @type {string} */ 1296 var prefixString = ''; 1297 1298 1299 /** 1300 * @param {string} className 1301 * @param {string} language 1302 */ 1303 function apply(className, language) { 1304 return prefixString + (mapper ? mapper(className, language) : className); 1305 } 1306 1307 1308 Prism.plugins.customClass = { 1309 /** 1310 * Sets the function which can be used to add custom aliases to any token. 1311 * 1312 * @param {ClassAdder} classAdder 1313 */ 1314 add: function (classAdder) { 1315 adder = classAdder; 1316 }, 1317 /** 1318 * Maps all class names using the given object or map function. 1319 * 1320 * This does not affect the prefix. 1321 * 1322 * @param {Object<string, string> | ClassMapper} classMapper 1323 */ 1324 map: function map(classMapper) { 1325 if (typeof classMapper === 'function') { 1326 mapper = classMapper; 1327 } else { 1328 mapper = function (className) { 1329 return classMapper[className] || className; 1330 }; 1331 } 1332 }, 1333 /** 1334 * Adds the given prefix to all class names. 1335 * 1336 * @param {string} string 1337 */ 1338 prefix: function prefix(string) { 1339 prefixString = string || ''; 1340 }, 1341 /** 1342 * Applies the current mapping and prefix to the given class name. 1343 * 1344 * @param {string} className A single class name. 1345 * @param {string} language The language of the code that contains this class name. 1346 * 1347 * If the language is unknown, pass `"none"`. 1348 */ 1349 apply: apply 1350 }; 1351 1352 Prism.hooks.add('wrap', function (env) { 1353 if (adder) { 1354 var result = adder({ 1355 content: env.content, 1356 type: env.type, 1357 language: env.language 1358 }); 1359 1360 if (Array.isArray(result)) { 1361 env.classes.push.apply(env.classes, result); 1362 } else if (result) { 1363 env.classes.push(result); 1364 } 1365 } 1366 1367 if (!mapper && !prefixString) { 1368 return; 1369 } 1370 1371 env.classes = env.classes.map(function (c) { 1372 return apply(c, env.language); 1373 }); 1374 }); 1375 1376}()); 1377 1378(function () { 1379 1380 if (typeof Prism === 'undefined' || typeof document === 'undefined') { 1381 return; 1382 } 1383 1384 var callbacks = []; 1385 var map = {}; 1386 var noop = function () {}; 1387 1388 Prism.plugins.toolbar = {}; 1389 1390 /** 1391 * @typedef ButtonOptions 1392 * @property {string} text The text displayed. 1393 * @property {string} [url] The URL of the link which will be created. 1394 * @property {Function} [onClick] The event listener for the `click` event of the created button. 1395 * @property {string} [className] The class attribute to include with element. 1396 */ 1397 1398 /** 1399 * Register a button callback with the toolbar. 1400 * 1401 * @param {string} key 1402 * @param {ButtonOptions|Function} opts 1403 */ 1404 var registerButton = Prism.plugins.toolbar.registerButton = function (key, opts) { 1405 var callback; 1406 1407 if (typeof opts === 'function') { 1408 callback = opts; 1409 } else { 1410 callback = function (env) { 1411 var element; 1412 1413 if (typeof opts.onClick === 'function') { 1414 element = document.createElement('button'); 1415 element.type = 'button'; 1416 element.addEventListener('click', function () { 1417 opts.onClick.call(this, env); 1418 }); 1419 } else if (typeof opts.url === 'string') { 1420 element = document.createElement('a'); 1421 element.href = opts.url; 1422 } else { 1423 element = document.createElement('span'); 1424 } 1425 1426 if (opts.className) { 1427 element.classList.add(opts.className); 1428 } 1429 1430 element.textContent = opts.text; 1431 1432 return element; 1433 }; 1434 } 1435 1436 if (key in map) { 1437 console.warn('There is a button with the key "' + key + '" registered already.'); 1438 return; 1439 } 1440 1441 callbacks.push(map[key] = callback); 1442 }; 1443 1444 /** 1445 * Returns the callback order of the given element. 1446 * 1447 * @param {HTMLElement} element 1448 * @returns {string[] | undefined} 1449 */ 1450 function getOrder(element) { 1451 while (element) { 1452 var order = element.getAttribute('data-toolbar-order'); 1453 if (order != null) { 1454 order = order.trim(); 1455 if (order.length) { 1456 return order.split(/\s*,\s*/g); 1457 } else { 1458 return []; 1459 } 1460 } 1461 element = element.parentElement; 1462 } 1463 } 1464 1465 /** 1466 * Post-highlight Prism hook callback. 1467 * 1468 * @param env 1469 */ 1470 var hook = Prism.plugins.toolbar.hook = function (env) { 1471 // Check if inline or actual code block (credit to line-numbers plugin) 1472 var pre = env.element.parentNode; 1473 if (!pre || !/pre/i.test(pre.nodeName)) { 1474 return; 1475 } 1476 1477 // Autoloader rehighlights, so only do this once. 1478 if (pre.parentNode.classList.contains('code-toolbar')) { 1479 return; 1480 } 1481 1482 // Create wrapper for <pre> to prevent scrolling toolbar with content 1483 var wrapper = document.createElement('div'); 1484 wrapper.classList.add('code-toolbar'); 1485 pre.parentNode.insertBefore(wrapper, pre); 1486 wrapper.appendChild(pre); 1487 1488 // Setup the toolbar 1489 var toolbar = document.createElement('div'); 1490 toolbar.classList.add('toolbar'); 1491 1492 // order callbacks 1493 var elementCallbacks = callbacks; 1494 var order = getOrder(env.element); 1495 if (order) { 1496 elementCallbacks = order.map(function (key) { 1497 return map[key] || noop; 1498 }); 1499 } 1500 1501 elementCallbacks.forEach(function (callback) { 1502 var element = callback(env); 1503 1504 if (!element) { 1505 return; 1506 } 1507 1508 var item = document.createElement('div'); 1509 item.classList.add('toolbar-item'); 1510 1511 item.appendChild(element); 1512 toolbar.appendChild(item); 1513 }); 1514 1515 // Add our toolbar to the currently created wrapper of <pre> tag 1516 wrapper.appendChild(toolbar); 1517 }; 1518 1519 registerButton('label', function (env) { 1520 var pre = env.element.parentNode; 1521 if (!pre || !/pre/i.test(pre.nodeName)) { 1522 return; 1523 } 1524 1525 if (!pre.hasAttribute('data-label')) { 1526 return; 1527 } 1528 1529 var element; var template; 1530 var text = pre.getAttribute('data-label'); 1531 try { 1532 // Any normal text will blow up this selector. 1533 template = document.querySelector('template#' + text); 1534 } catch (e) { /* noop */ } 1535 1536 if (template) { 1537 element = template.content; 1538 } else { 1539 if (pre.hasAttribute('data-url')) { 1540 element = document.createElement('a'); 1541 element.href = pre.getAttribute('data-url'); 1542 } else { 1543 element = document.createElement('span'); 1544 } 1545 1546 element.textContent = text; 1547 } 1548 1549 return element; 1550 }); 1551 1552 /** 1553 * Register the toolbar with Prism. 1554 */ 1555 Prism.hooks.add('complete', hook); 1556}()); 1557 1558(function () { 1559 1560 if (typeof Prism === 'undefined' || typeof document === 'undefined') { 1561 return; 1562 } 1563 1564 if (!Prism.plugins.toolbar) { 1565 console.warn('Show Languages plugin loaded before Toolbar plugin.'); 1566 1567 return; 1568 } 1569 1570 /* eslint-disable */ 1571 1572 // The languages map is built automatically with gulp 1573 var Languages = /*languages_placeholder[*/{ 1574 "none": "Plain text", 1575 "plain": "Plain text", 1576 "plaintext": "Plain text", 1577 "text": "Plain text", 1578 "txt": "Plain text", 1579 "html": "HTML", 1580 "xml": "XML", 1581 "svg": "SVG", 1582 "mathml": "MathML", 1583 "ssml": "SSML", 1584 "rss": "RSS", 1585 "css": "CSS", 1586 "clike": "C-like", 1587 "js": "JavaScript", 1588 "autohotkey": "AutoHotkey", 1589 "awk": "AWK", 1590 "gawk": "GAWK", 1591 "sh": "Shell", 1592 "csharp": "C#", 1593 "cs": "C#", 1594 "dotnet": "C#", 1595 "cpp": "C++", 1596 "css-extras": "CSS Extras", 1597 "csv": "CSV", 1598 "dockerfile": "Docker", 1599 "ejs": "EJS", 1600 "http": "HTTP", 1601 "ignore": ".ignore", 1602 "gitignore": ".gitignore", 1603 "hgignore": ".hgignore", 1604 "npmignore": ".npmignore", 1605 "javadoc": "JavaDoc", 1606 "javadoclike": "JavaDoc-like", 1607 "javastacktrace": "Java stack trace", 1608 "jsdoc": "JSDoc", 1609 "js-extras": "JS Extras", 1610 "json": "JSON", 1611 "webmanifest": "Web App Manifest", 1612 "json5": "JSON5", 1613 "jsstacktrace": "JS stack trace", 1614 "js-templates": "JS Templates", 1615 "kts": "Kotlin Script", 1616 "kt": "Kotlin", 1617 "md": "Markdown", 1618 "mongodb": "MongoDB", 1619 "pwsh": "PowerShell", 1620 "pwsh-mizumiya": "PowerShell with Mizumiya", 1621 "pwsh-functionsignature": "PowerShell function signature", 1622 "properties": ".properties", 1623 "py": "Python", 1624 "rb": "Ruby", 1625 "shell-session": "Shell session", 1626 "sh-session": "Shell session", 1627 "shellsession": "Shell session", 1628 "sql": "SQL", 1629 "systemd": "Systemd configuration file", 1630 "treeview": "Directory tree", 1631 "ts": "TypeScript", 1632 "tsconfig": "TSConfig", 1633 "uri": "URI", 1634 "url": "URL", 1635 "xml-doc": "XML doc (.net)", 1636 "yaml": "YAML", 1637 "yml": "YAML" 1638 }/*]*/; 1639 1640 /* eslint-enable */ 1641 1642 Prism.plugins.toolbar.registerButton('show-language', function (env) { 1643 var pre = env.element.parentNode; 1644 if (!pre || !/pre/i.test(pre.nodeName)) { 1645 return; 1646 } 1647 1648 /** 1649 * Tries to guess the name of a language given its id. 1650 * 1651 * @param {string} id The language id. 1652 * @returns {string} 1653 */ 1654 function guessTitle(id) { 1655 if (!id) { 1656 return id; 1657 } 1658 return (id.substring(0, 1).toUpperCase() + id.substring(1)).replace(/s(?=cript)/, 'S'); 1659 } 1660 1661 var language = pre.getAttribute('data-language') || Languages[env.language] || guessTitle(env.language); 1662 1663 if (!language) { 1664 return; 1665 } 1666 var element = document.createElement('span'); 1667 element.textContent = language; 1668 1669 return element; 1670 }); 1671 1672}()); 1673 1674(function () { 1675 1676 if (typeof Prism === 'undefined' || typeof document === 'undefined') { 1677 return; 1678 } 1679 1680 /* eslint-disable */ 1681 1682 /** 1683 * The dependencies map is built automatically with gulp. 1684 * 1685 * @type {Object<string, string | string[]>} 1686 */ 1687 var lang_dependencies = /*dependencies_placeholder[*/{ 1688 "javascript": "clike", 1689 "c": "clike", 1690 "csharp": "clike", 1691 "cpp": "c", 1692 "css-extras": "css", 1693 "ejs": [ 1694 "javascript", 1695 "markup-templating" 1696 ], 1697 "gradle": "clike", 1698 "java": "clike", 1699 "javadoc": [ 1700 "markup", 1701 "java", 1702 "javadoclike" 1703 ], 1704 "jsdoc": [ 1705 "javascript", 1706 "javadoclike", 1707 "typescript" 1708 ], 1709 "js-extras": "javascript", 1710 "json5": "json", 1711 "js-templates": "javascript", 1712 "kotlin": "clike", 1713 "markdown": "markup", 1714 "mongodb": "javascript", 1715 "plsql": "sql", 1716 "pwsh-mizumiya": "pwsh", 1717 "ruby": "clike", 1718 "shell-session": "bash", 1719 "typescript": "javascript", 1720 "xml-doc": "markup", 1721 }/*]*/; 1722 1723 var lang_aliases = /*aliases_placeholder[*/{ 1724 "html": "markup", 1725 "xml": "markup", 1726 "svg": "markup", 1727 "mathml": "markup", 1728 "ssml": "markup", 1729 "atom": "markup", 1730 "rss": "markup", 1731 "js": "javascript", 1732 "gawk": "awk", 1733 "sh": "bash", 1734 "shell": "bash", 1735 "cs": "csharp", 1736 "dotnet": "csharp", 1737 "dockerfile": "docker", 1738 "eta": "ejs", 1739 "gitignore": "ignore", 1740 "hgignore": "ignore", 1741 "npmignore": "ignore", 1742 "webmanifest": "json", 1743 "kt": "kotlin", 1744 "kts": "kotlin", 1745 "md": "markdown", 1746 "py": "python", 1747 "rb": "ruby", 1748 "sh-session": "shell-session", 1749 "shellsession": "shell-session", 1750 "url": "uri", 1751 "yml": "yaml" 1752 }/*]*/; 1753 1754 /* eslint-enable */ 1755 1756 /** 1757 * @typedef LangDataItem 1758 * @property {{ success?: () => void, error?: () => void }[]} callbacks 1759 * @property {boolean} [error] 1760 * @property {boolean} [loading] 1761 */ 1762 /** @type {Object<string, LangDataItem>} */ 1763 var lang_data = {}; 1764 1765 var ignored_language = 'none'; 1766 var languages_path = 'components/'; 1767 1768 var script = Prism.util.currentScript(); 1769 if (script) { 1770 var autoloaderFile = /\bplugins\/autoloader\/prism-autoloader\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i; 1771 var prismFile = /(^|\/)[\w-]+\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i; 1772 1773 var autoloaderPath = script.getAttribute('data-autoloader-path'); 1774 if (autoloaderPath != null) { 1775 // data-autoloader-path is set, so just use it 1776 languages_path = autoloaderPath.trim().replace(/\/?$/, '/'); 1777 } else { 1778 var src = script.src; 1779 if (autoloaderFile.test(src)) { 1780 // the script is the original autoloader script in the usual Prism project structure 1781 languages_path = src.replace(autoloaderFile, 'components/'); 1782 } else if (prismFile.test(src)) { 1783 // the script is part of a bundle like a custom prism.js from the download page 1784 languages_path = src.replace(prismFile, '$1components/'); 1785 } 1786 } 1787 } 1788 1789 var config = Prism.plugins.autoloader = { 1790 languages_path: languages_path, 1791 use_minified: true, 1792 loadLanguages: loadLanguages 1793 }; 1794 1795 1796 /** 1797 * Lazily loads an external script. 1798 * 1799 * @param {string} src 1800 * @param {() => void} [success] 1801 * @param {() => void} [error] 1802 */ 1803 function addScript(src, success, error) { 1804 var s = document.createElement('script'); 1805 s.src = src; 1806 s.async = true; 1807 s.onload = function () { 1808 document.body.removeChild(s); 1809 success && success(); 1810 }; 1811 s.onerror = function () { 1812 document.body.removeChild(s); 1813 error && error(); 1814 }; 1815 document.body.appendChild(s); 1816 } 1817 1818 /** 1819 * Returns all additional dependencies of the given element defined by the `data-dependencies` attribute. 1820 * 1821 * @param {Element} element 1822 * @returns {string[]} 1823 */ 1824 function getDependencies(element) { 1825 var deps = (element.getAttribute('data-dependencies') || '').trim(); 1826 if (!deps) { 1827 var parent = element.parentElement; 1828 if (parent && parent.tagName.toLowerCase() === 'pre') { 1829 deps = (parent.getAttribute('data-dependencies') || '').trim(); 1830 } 1831 } 1832 return deps ? deps.split(/\s*,\s*/g) : []; 1833 } 1834 1835 /** 1836 * Returns whether the given language is currently loaded. 1837 * 1838 * @param {string} lang 1839 * @returns {boolean} 1840 */ 1841 function isLoaded(lang) { 1842 if (lang.indexOf('!') >= 0) { 1843 // forced reload 1844 return false; 1845 } 1846 1847 lang = lang_aliases[lang] || lang; // resolve alias 1848 1849 if (lang in Prism.languages) { 1850 // the given language is already loaded 1851 return true; 1852 } 1853 1854 // this will catch extensions like CSS extras that don't add a grammar to Prism.languages 1855 var data = lang_data[lang]; 1856 return data && !data.error && data.loading === false; 1857 } 1858 1859 /** 1860 * Returns the path to a grammar, using the language_path and use_minified config keys. 1861 * 1862 * @param {string} lang 1863 * @returns {string} 1864 */ 1865 function getLanguagePath(lang) { 1866 return config.languages_path + 'prism-' + lang + (config.use_minified ? '.min' : '') + '.js'; 1867 } 1868 1869 /** 1870 * Loads all given grammars concurrently. 1871 * 1872 * @param {string[]|string} languages 1873 * @param {(languages: string[]) => void} [success] 1874 * @param {(language: string) => void} [error] This callback will be invoked on the first language to fail. 1875 */ 1876 function loadLanguages(languages, success, error) { 1877 if (typeof languages === 'string') { 1878 languages = [languages]; 1879 } 1880 1881 var total = languages.length; 1882 var completed = 0; 1883 var failed = false; 1884 1885 if (total === 0) { 1886 if (success) { 1887 setTimeout(success, 0); 1888 } 1889 return; 1890 } 1891 1892 function successCallback() { 1893 if (failed) { 1894 return; 1895 } 1896 completed++; 1897 if (completed === total) { 1898 success && success(languages); 1899 } 1900 } 1901 1902 languages.forEach(function (lang) { 1903 loadLanguage(lang, successCallback, function () { 1904 if (failed) { 1905 return; 1906 } 1907 failed = true; 1908 error && error(lang); 1909 }); 1910 }); 1911 } 1912 1913 /** 1914 * Loads a grammar with its dependencies. 1915 * 1916 * @param {string} lang 1917 * @param {() => void} [success] 1918 * @param {() => void} [error] 1919 */ 1920 function loadLanguage(lang, success, error) { 1921 var force = lang.indexOf('!') >= 0; 1922 1923 lang = lang.replace('!', ''); 1924 lang = lang_aliases[lang] || lang; 1925 1926 function load() { 1927 var data = lang_data[lang]; 1928 if (!data) { 1929 data = lang_data[lang] = { 1930 callbacks: [] 1931 }; 1932 } 1933 data.callbacks.push({ 1934 success: success, 1935 error: error 1936 }); 1937 1938 if (!force && isLoaded(lang)) { 1939 // the language is already loaded and we aren't forced to reload 1940 languageCallback(lang, 'success'); 1941 } else if (!force && data.error) { 1942 // the language failed to load before and we don't reload 1943 languageCallback(lang, 'error'); 1944 } else if (force || !data.loading) { 1945 // the language isn't currently loading and/or we are forced to reload 1946 data.loading = true; 1947 data.error = false; 1948 1949 addScript(getLanguagePath(lang), function () { 1950 data.loading = false; 1951 languageCallback(lang, 'success'); 1952 1953 }, function () { 1954 data.loading = false; 1955 data.error = true; 1956 languageCallback(lang, 'error'); 1957 }); 1958 } 1959 } 1960 1961 var dependencies = lang_dependencies[lang]; 1962 if (dependencies && dependencies.length) { 1963 loadLanguages(dependencies, load, error); 1964 } else { 1965 load(); 1966 } 1967 } 1968 1969 /** 1970 * Runs all callbacks of the given type for the given language. 1971 * 1972 * @param {string} lang 1973 * @param {"success" | "error"} type 1974 */ 1975 function languageCallback(lang, type) { 1976 if (lang_data[lang]) { 1977 var callbacks = lang_data[lang].callbacks; 1978 for (var i = 0, l = callbacks.length; i < l; i++) { 1979 var callback = callbacks[i][type]; 1980 if (callback) { 1981 setTimeout(callback, 0); 1982 } 1983 } 1984 callbacks.length = 0; 1985 } 1986 } 1987 1988 Prism.hooks.add('complete', function (env) { 1989 var element = env.element; 1990 var language = env.language; 1991 if (!element || !language || language === ignored_language) { 1992 return; 1993 } 1994 1995 var deps = getDependencies(element); 1996 if (/^diff-./i.test(language)) { 1997 // the "diff-xxxx" format is used by the Diff Highlight plugin 1998 deps.push('diff'); 1999 deps.push(language.substr('diff-'.length)); 2000 } else { 2001 deps.push(language); 2002 } 2003 2004 if (!deps.every(isLoaded)) { 2005 // the language or some dependencies aren't loaded 2006 loadLanguages(deps, function () { 2007 Prism.highlightElement(element); 2008 }); 2009 } 2010 }); 2011 2012}()); 2013 2014(function () { 2015 2016 if (typeof Prism === 'undefined' || typeof document === 'undefined') { 2017 return; 2018 } 2019 2020 if (!Prism.plugins.toolbar) { 2021 console.warn('Copy to Clipboard plugin loaded before Toolbar plugin.'); 2022 2023 return; 2024 } 2025 2026 /** 2027 * When the given elements is clicked by the user, the given text will be copied to clipboard. 2028 * 2029 * @param {HTMLElement} element 2030 * @param {CopyInfo} copyInfo 2031 * 2032 * @typedef CopyInfo 2033 * @property {() => string} getText 2034 * @property {() => void} success 2035 * @property {(reason: unknown) => void} error 2036 */ 2037 function registerClipboard(element, copyInfo) { 2038 element.addEventListener('click', function () { 2039 copyTextToClipboard(copyInfo); 2040 }); 2041 } 2042 2043 // https://stackoverflow.com/a/30810322/7595472 2044 2045 /** @param {CopyInfo} copyInfo */ 2046 function fallbackCopyTextToClipboard(copyInfo) { 2047 var textArea = document.createElement('textarea'); 2048 textArea.value = copyInfo.getText(); 2049 2050 // Avoid scrolling to bottom 2051 textArea.style.top = '0'; 2052 textArea.style.left = '0'; 2053 textArea.style.position = 'fixed'; 2054 2055 document.body.appendChild(textArea); 2056 textArea.focus(); 2057 textArea.select(); 2058 2059 try { 2060 var successful = document.execCommand('copy'); 2061 setTimeout(function () { 2062 if (successful) { 2063 copyInfo.success(); 2064 } else { 2065 copyInfo.error(); 2066 } 2067 }, 1); 2068 } catch (err) { 2069 setTimeout(function () { 2070 copyInfo.error(err); 2071 }, 1); 2072 } 2073 2074 document.body.removeChild(textArea); 2075 } 2076 /** @param {CopyInfo} copyInfo */ 2077 function copyTextToClipboard(copyInfo) { 2078 if (navigator.clipboard) { 2079 navigator.clipboard.writeText(copyInfo.getText()).then(copyInfo.success, function () { 2080 // try the fallback in case `writeText` didn't work 2081 fallbackCopyTextToClipboard(copyInfo); 2082 }); 2083 } else { 2084 fallbackCopyTextToClipboard(copyInfo); 2085 } 2086 } 2087 2088 /** 2089 * Selects the text content of the given element. 2090 * 2091 * @param {Element} element 2092 */ 2093 function selectElementText(element) { 2094 // https://stackoverflow.com/a/20079910/7595472 2095 window.getSelection().selectAllChildren(element); 2096 } 2097 2098 /** 2099 * Traverses up the DOM tree to find data attributes that override the default plugin settings. 2100 * 2101 * @param {Element} startElement An element to start from. 2102 * @returns {Settings} The plugin settings. 2103 * @typedef {Record<"copy" | "copy-error" | "copy-success" | "copy-timeout", string | number>} Settings 2104 */ 2105 function getSettings(startElement) { 2106 /** @type {Settings} */ 2107 var settings = { 2108 'copy': 'Copy', 2109 'copy-error': 'Press Ctrl+C to copy', 2110 'copy-success': 'Copied!', 2111 'copy-timeout': 5000 2112 }; 2113 2114 var prefix = 'data-prismjs-'; 2115 for (var key in settings) { 2116 var attr = prefix + key; 2117 var element = startElement; 2118 while (element && !element.hasAttribute(attr)) { 2119 element = element.parentElement; 2120 } 2121 if (element) { 2122 settings[key] = element.getAttribute(attr); 2123 } 2124 } 2125 return settings; 2126 } 2127 2128 Prism.plugins.toolbar.registerButton('copy-to-clipboard', function (env) { 2129 var element = env.element; 2130 2131 var settings = getSettings(element); 2132 2133 var linkCopy = document.createElement('button'); 2134 linkCopy.className = 'copy-to-clipboard-button'; 2135 linkCopy.setAttribute('type', 'button'); 2136 var linkSpan = document.createElement('span'); 2137 linkCopy.appendChild(linkSpan); 2138 2139 setState('copy'); 2140 2141 registerClipboard(linkCopy, { 2142 getText: function () { 2143 return element.textContent; 2144 }, 2145 success: function () { 2146 setState('copy-success'); 2147 2148 resetText(); 2149 }, 2150 error: function () { 2151 setState('copy-error'); 2152 2153 setTimeout(function () { 2154 selectElementText(element); 2155 }, 1); 2156 2157 resetText(); 2158 } 2159 }); 2160 2161 return linkCopy; 2162 2163 function resetText() { 2164 setTimeout(function () { setState('copy'); }, settings['copy-timeout']); 2165 } 2166 2167 /** @param {"copy" | "copy-error" | "copy-success"} state */ 2168 function setState(state) { 2169 linkSpan.textContent = settings[state]; 2170 linkCopy.setAttribute('data-copy-state', state); 2171 } 2172 }); 2173}()); 2174 2175(function () { 2176 if (typeof Prism === 'undefined') { 2177 return; 2178 } 2179 2180 Prism.languages.treeview = { 2181 'treeview-part': { 2182 pattern: /^.+/m, 2183 inside: { 2184 'entry-line': [ 2185 { 2186 pattern: /\|-- |├── /, 2187 alias: 'line-h' 2188 }, 2189 { 2190 pattern: /\| {3}|│ {3}/, 2191 alias: 'line-v' 2192 }, 2193 { 2194 pattern: /`-- |└── /, 2195 alias: 'line-v-last' 2196 }, 2197 { 2198 pattern: / {4}/, 2199 alias: 'line-v-gap' 2200 } 2201 ], 2202 'entry-name': { 2203 pattern: /.*\S.*/, 2204 inside: { 2205 // symlink 2206 'operator': / -> /, 2207 } 2208 } 2209 } 2210 } 2211 }; 2212 2213 Prism.hooks.add('wrap', function (env) { 2214 if (env.language === 'treeview' && env.type === 'entry-name') { 2215 var classes = env.classes; 2216 2217 var folderPattern = /(^|[^\\])\/\s*$/; 2218 if (folderPattern.test(env.content)) { // dir 2219 // remove trailing / 2220 env.content = env.content.replace(folderPattern, '$1'); 2221 classes.push('dir'); 2222 } else { // file 2223 // remove trailing file marker 2224 env.content = env.content.replace(/(^|[^\\])[=*|]\s*$/, '$1'); 2225 } 2226 2227 if (env.content[0] === '.') { 2228 classes.push('dotfile'); 2229 } 2230 } 2231 }); 2232}());