Personal website
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, '&').replace(/</g, '<').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, '"') + '"';
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}());