UNPKG

284 kBJavaScriptView Raw
1(function () {
2 /**
3 * Create a cached version of a pure function.
4 * @param {*} fn The function call to be cached
5 * @void
6 */
7
8 function cached(fn) {
9 var cache = Object.create(null);
10 return function(str) {
11 var key = isPrimitive(str) ? str : JSON.stringify(str);
12 var hit = cache[key];
13 return hit || (cache[key] = fn(str));
14 };
15 }
16
17 /**
18 * Hyphenate a camelCase string.
19 */
20 var hyphenate = cached(function (str) {
21 return str.replace(/([A-Z])/g, function (m) { return '-' + m.toLowerCase(); });
22 });
23
24 var hasOwn = Object.prototype.hasOwnProperty;
25
26 /**
27 * Simple Object.assign polyfill
28 * @param {Object} to The object to be merged with
29 * @returns {Object} The merged object
30 */
31 var merge =
32 Object.assign ||
33 function(to) {
34 var arguments$1 = arguments;
35
36 for (var i = 1; i < arguments.length; i++) {
37 var from = Object(arguments$1[i]);
38
39 for (var key in from) {
40 if (hasOwn.call(from, key)) {
41 to[key] = from[key];
42 }
43 }
44 }
45
46 return to;
47 };
48
49 /**
50 * Check if value is primitive
51 * @param {*} value Checks if a value is primitive
52 * @returns {Boolean} Result of the check
53 */
54 function isPrimitive(value) {
55 return typeof value === 'string' || typeof value === 'number';
56 }
57
58 /**
59 * Performs no operation.
60 * @void
61 */
62 function noop() {}
63
64 /**
65 * Check if value is function
66 * @param {*} obj Any javascript object
67 * @returns {Boolean} True if the passed-in value is a function
68 */
69 function isFn(obj) {
70 return typeof obj === 'function';
71 }
72
73 /**
74 * Check if url is external
75 * @param {String} string url
76 * @returns {Boolean} True if the passed-in url is external
77 */
78 function isExternal(url) {
79 var match = url.match(
80 /^([^:/?#]+:)?(?:\/{2,}([^/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/
81 );
82
83 if (
84 typeof match[1] === 'string' &&
85 match[1].length > 0 &&
86 match[1].toLowerCase() !== location.protocol
87 ) {
88 return true;
89 }
90 if (
91 typeof match[2] === 'string' &&
92 match[2].length > 0 &&
93 match[2].replace(
94 new RegExp(
95 ':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$'
96 ),
97 ''
98 ) !== location.host
99 ) {
100 return true;
101 }
102 return false;
103 }
104
105 var inBrowser = !false;
106
107 var isMobile = document.body.clientWidth <= 600;
108
109 /**
110 * @see https://github.com/MoOx/pjax/blob/master/lib/is-supported.js
111 */
112 var supportsPushState =
113
114 (function() {
115 // Borrowed wholesale from https://github.com/defunkt/jquery-pjax
116 return (
117 window.history &&
118 window.history.pushState &&
119 window.history.replaceState &&
120 // PushState isn’t reliable on iOS until 5.
121 !navigator.userAgent.match(
122 /((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/
123 )
124 );
125 })();
126
127 var cacheNode = {};
128
129 /**
130 * Get Node
131 * @param {String|Element} el A DOM element
132 * @param {Boolean} noCache Flag to use or not use the cache
133 * @return {Element} The found node element
134 */
135 function getNode(el, noCache) {
136 if ( noCache === void 0 ) noCache = false;
137
138 if (typeof el === 'string') {
139 if (typeof window.Vue !== 'undefined') {
140 return find(el);
141 }
142
143 el = noCache ? find(el) : cacheNode[el] || (cacheNode[el] = find(el));
144 }
145
146 return el;
147 }
148
149 var $ = document;
150
151 var body = $.body;
152
153 var head = $.head;
154
155 /**
156 * Find elements
157 * @param {String|Element} el The root element where to perform the search from
158 * @param {Element} node The query
159 * @returns {Element} The found DOM element
160 * @example
161 * find('nav') => document.querySelector('nav')
162 * find(nav, 'a') => nav.querySelector('a')
163 */
164 function find(el, node) {
165 return node ? el.querySelector(node) : $.querySelector(el);
166 }
167
168 /**
169 * Find all elements
170 * @param {String|Element} el The root element where to perform the search from
171 * @param {Element} node The query
172 * @returns {Array<Element>} An array of DOM elements
173 * @example
174 * findAll('a') => [].slice.call(document.querySelectorAll('a'))
175 * findAll(nav, 'a') => [].slice.call(nav.querySelectorAll('a'))
176 */
177 function findAll(el, node) {
178 return [].slice.call(
179 node ? el.querySelectorAll(node) : $.querySelectorAll(el)
180 );
181 }
182
183 function create(node, tpl) {
184 node = $.createElement(node);
185 if (tpl) {
186 node.innerHTML = tpl;
187 }
188
189 return node;
190 }
191
192 function appendTo(target, el) {
193 return target.appendChild(el);
194 }
195
196 function before(target, el) {
197 return target.insertBefore(el, target.children[0]);
198 }
199
200 function on(el, type, handler) {
201 isFn(type)
202 ? window.addEventListener(el, type)
203 : el.addEventListener(type, handler);
204 }
205
206 function off(el, type, handler) {
207 isFn(type)
208 ? window.removeEventListener(el, type)
209 : el.removeEventListener(type, handler);
210 }
211
212 /**
213 * Toggle class
214 * @param {String|Element} el The element that needs the class to be toggled
215 * @param {Element} type The type of action to be performed on the classList (toggle by default)
216 * @param {String} val Name of the class to be toggled
217 * @void
218 * @example
219 * toggleClass(el, 'active') => el.classList.toggle('active')
220 * toggleClass(el, 'add', 'active') => el.classList.add('active')
221 */
222 function toggleClass(el, type, val) {
223 el && el.classList[val ? type : 'toggle'](val || type);
224 }
225
226 function style(content) {
227 appendTo(head, create('style', content));
228 }
229
230 /**
231 * Fork https://github.com/bendrucker/document-ready/blob/master/index.js
232 * @param {Function} callback The callbacack to be called when the page is loaded
233 * @returns {Number|void} If the page is already laoded returns the result of the setTimeout callback,
234 * otherwise it only attaches the callback to the DOMContentLoaded event
235 */
236 function documentReady(callback, doc) {
237 if ( doc === void 0 ) doc = document;
238
239 var state = doc.readyState;
240
241 if (state === 'complete' || state === 'interactive') {
242 return setTimeout(callback, 0);
243 }
244
245 doc.addEventListener('DOMContentLoaded', callback);
246 }
247
248 var dom = /*#__PURE__*/Object.freeze({
249 __proto__: null,
250 getNode: getNode,
251 $: $,
252 body: body,
253 head: head,
254 find: find,
255 findAll: findAll,
256 create: create,
257 appendTo: appendTo,
258 before: before,
259 on: on,
260 off: off,
261 toggleClass: toggleClass,
262 style: style,
263 documentReady: documentReady
264 });
265
266 var decode = decodeURIComponent;
267 var encode = encodeURIComponent;
268
269 function parseQuery(query) {
270 var res = {};
271
272 query = query.trim().replace(/^(\?|#|&)/, '');
273
274 if (!query) {
275 return res;
276 }
277
278 // Simple parse
279 query.split('&').forEach(function(param) {
280 var parts = param.replace(/\+/g, ' ').split('=');
281
282 res[parts[0]] = parts[1] && decode(parts[1]);
283 });
284
285 return res;
286 }
287
288 function stringifyQuery(obj, ignores) {
289 if ( ignores === void 0 ) ignores = [];
290
291 var qs = [];
292
293 for (var key in obj) {
294 if (ignores.indexOf(key) > -1) {
295 continue;
296 }
297
298 qs.push(
299 obj[key]
300 ? ((encode(key)) + "=" + (encode(obj[key]))).toLowerCase()
301 : encode(key)
302 );
303 }
304
305 return qs.length ? ("?" + (qs.join('&'))) : '';
306 }
307
308 var isAbsolutePath = cached(function (path) {
309 return /(:|(\/{2}))/g.test(path);
310 });
311
312 var removeParams = cached(function (path) {
313 return path.split(/[?#]/)[0];
314 });
315
316 var getParentPath = cached(function (path) {
317 if (/\/$/g.test(path)) {
318 return path;
319 }
320
321 var matchingParts = path.match(/(\S*\/)[^/]+$/);
322 return matchingParts ? matchingParts[1] : '';
323 });
324
325 var cleanPath = cached(function (path) {
326 return path.replace(/^\/+/, '/').replace(/([^:])\/{2,}/g, '$1/');
327 });
328
329 var resolvePath = cached(function (path) {
330 var segments = path.replace(/^\//, '').split('/');
331 var resolved = [];
332 for (var i = 0, len = segments.length; i < len; i++) {
333 var segment = segments[i];
334 if (segment === '..') {
335 resolved.pop();
336 } else if (segment !== '.') {
337 resolved.push(segment);
338 }
339 }
340
341 return '/' + resolved.join('/');
342 });
343
344 /**
345 * Normalises the URI path to handle the case where Docsify is
346 * hosted off explicit files, i.e. /index.html. This function
347 * eliminates any path segments that contain `#` fragments.
348 *
349 * This is used to map browser URIs to markdown file sources.
350 *
351 * For example:
352 *
353 * http://example.org/base/index.html#/blah
354 *
355 * would be mapped to:
356 *
357 * http://example.org/base/blah.md.
358 *
359 * See here for more information:
360 *
361 * https://github.com/docsifyjs/docsify/pull/1372
362 *
363 * @param {string} path The URI path to normalise
364 * @return {string} { path, query }
365 */
366
367 function normaliseFragment(path) {
368 return path
369 .split('/')
370 .filter(function (p) { return p.indexOf('#') === -1; })
371 .join('/');
372 }
373
374 function getPath() {
375 var args = [], len = arguments.length;
376 while ( len-- ) args[ len ] = arguments[ len ];
377
378 return cleanPath(args.map(normaliseFragment).join('/'));
379 }
380
381 var replaceSlug = cached(function (path) {
382 return path.replace('#', '?id=');
383 });
384
385 function endsWith(str, suffix) {
386 return str.indexOf(suffix, str.length - suffix.length) !== -1;
387 }
388
389 var cached$1 = {};
390
391 function getAlias(path, alias, last) {
392 var match = Object.keys(alias).filter(function (key) {
393 var re = cached$1[key] || (cached$1[key] = new RegExp(("^" + key + "$")));
394 return re.test(path) && path !== last;
395 })[0];
396
397 return match
398 ? getAlias(path.replace(cached$1[match], alias[match]), alias, path)
399 : path;
400 }
401
402 function getFileName(path, ext) {
403 return new RegExp(("\\.(" + (ext.replace(/^\./, '')) + "|html)$"), 'g').test(path)
404 ? path
405 : /\/$/g.test(path)
406 ? (path + "README" + ext)
407 : ("" + path + ext);
408 }
409
410 var History = function History(config) {
411 this.config = config;
412 };
413
414 History.prototype.getBasePath = function getBasePath () {
415 return this.config.basePath;
416 };
417
418 History.prototype.getFile = function getFile (path, isRelative) {
419 if ( path === void 0 ) path = this.getCurrentPath();
420
421 var ref = this;
422 var config = ref.config;
423 var base = this.getBasePath();
424 var ext = typeof config.ext === 'string' ? config.ext : '.md';
425
426 path = config.alias ? getAlias(path, config.alias) : path;
427 path = getFileName(path, ext);
428 path = path === ("/README" + ext) ? config.homepage || path : path;
429 path = isAbsolutePath(path) ? path : getPath(base, path);
430
431 if (isRelative) {
432 path = path.replace(new RegExp(("^" + base)), '');
433 }
434
435 return path;
436 };
437
438 History.prototype.onchange = function onchange (cb) {
439 if ( cb === void 0 ) cb = noop;
440
441 cb();
442 };
443
444 History.prototype.getCurrentPath = function getCurrentPath () {};
445
446 History.prototype.normalize = function normalize () {};
447
448 History.prototype.parse = function parse () {};
449
450 History.prototype.toURL = function toURL (path, params, currentRoute) {
451 var local = currentRoute && path[0] === '#';
452 var route = this.parse(replaceSlug(path));
453
454 route.query = merge({}, route.query, params);
455 path = route.path + stringifyQuery(route.query);
456 path = path.replace(/\.md(\?)|\.md$/, '$1');
457
458 if (local) {
459 var idIndex = currentRoute.indexOf('?');
460 path =
461 (idIndex > 0 ? currentRoute.substring(0, idIndex) : currentRoute) +
462 path;
463 }
464
465 if (this.config.relativePath && path.indexOf('/') !== 0) {
466 var currentDir = currentRoute.substring(
467 0,
468 currentRoute.lastIndexOf('/') + 1
469 );
470 return cleanPath(resolvePath(currentDir + path));
471 }
472
473 return cleanPath('/' + path);
474 };
475
476 function replaceHash(path) {
477 var i = location.href.indexOf('#');
478 location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path);
479 }
480 var HashHistory = /*@__PURE__*/(function (History) {
481 function HashHistory(config) {
482 History.call(this, config);
483 this.mode = 'hash';
484 }
485
486 if ( History ) HashHistory.__proto__ = History;
487 HashHistory.prototype = Object.create( History && History.prototype );
488 HashHistory.prototype.constructor = HashHistory;
489
490 HashHistory.prototype.getBasePath = function getBasePath () {
491 var path = window.location.pathname || '';
492 var base = this.config.basePath;
493
494 // This handles the case where Docsify is served off an
495 // explicit file path, i.e.`/base/index.html#/blah`. This
496 // prevents the `/index.html` part of the URI from being
497 // remove during routing.
498 // See here: https://github.com/docsifyjs/docsify/pull/1372
499 var basePath = endsWith(path, '.html')
500 ? path + '#/' + base
501 : path + '/' + base;
502 return /^(\/|https?:)/g.test(base) ? base : cleanPath(basePath);
503 };
504
505 HashHistory.prototype.getCurrentPath = function getCurrentPath () {
506 // We can't use location.hash here because it's not
507 // consistent across browsers - Firefox will pre-decode it!
508 var href = location.href;
509 var index = href.indexOf('#');
510 return index === -1 ? '' : href.slice(index + 1);
511 };
512
513 /** @param {((params: {source: TODO}) => void)} [cb] */
514 HashHistory.prototype.onchange = function onchange (cb) {
515 if ( cb === void 0 ) cb = noop;
516
517 // The hashchange event does not tell us if it originated from
518 // a clicked link or by moving back/forward in the history;
519 // therefore we set a `navigating` flag when a link is clicked
520 // to be able to tell these two scenarios apart
521 var navigating = false;
522
523 on('click', function (e) {
524 var el = e.target.tagName === 'A' ? e.target : e.target.parentNode;
525
526 if (el && el.tagName === 'A' && !/_blank/.test(el.target)) {
527 navigating = true;
528 }
529 });
530
531 on('hashchange', function (e) {
532 var source = navigating ? 'navigate' : 'history';
533 navigating = false;
534 cb({ event: e, source: source });
535 });
536 };
537
538 HashHistory.prototype.normalize = function normalize () {
539 var path = this.getCurrentPath();
540
541 path = replaceSlug(path);
542
543 if (path.charAt(0) === '/') {
544 return replaceHash(path);
545 }
546
547 replaceHash('/' + path);
548 };
549
550 /**
551 * Parse the url
552 * @param {string} [path=location.herf] URL to be parsed
553 * @return {object} { path, query }
554 */
555 HashHistory.prototype.parse = function parse (path) {
556 if ( path === void 0 ) path = location.href;
557
558 var query = '';
559
560 var hashIndex = path.indexOf('#');
561 if (hashIndex >= 0) {
562 path = path.slice(hashIndex + 1);
563 }
564
565 var queryIndex = path.indexOf('?');
566 if (queryIndex >= 0) {
567 query = path.slice(queryIndex + 1);
568 path = path.slice(0, queryIndex);
569 }
570
571 return {
572 path: path,
573 file: this.getFile(path, true),
574 query: parseQuery(query),
575 };
576 };
577
578 HashHistory.prototype.toURL = function toURL (path, params, currentRoute) {
579 return '#' + History.prototype.toURL.call(this, path, params, currentRoute);
580 };
581
582 return HashHistory;
583 }(History));
584
585 /** @typedef {any} TODO */
586
587 var HTML5History = /*@__PURE__*/(function (History) {
588 function HTML5History(config) {
589 History.call(this, config);
590 this.mode = 'history';
591 }
592
593 if ( History ) HTML5History.__proto__ = History;
594 HTML5History.prototype = Object.create( History && History.prototype );
595 HTML5History.prototype.constructor = HTML5History;
596
597 HTML5History.prototype.getCurrentPath = function getCurrentPath () {
598 var base = this.getBasePath();
599 var path = window.location.pathname;
600
601 if (base && path.indexOf(base) === 0) {
602 path = path.slice(base.length);
603 }
604
605 return (path || '/') + window.location.search + window.location.hash;
606 };
607
608 HTML5History.prototype.onchange = function onchange (cb) {
609 var this$1 = this;
610 if ( cb === void 0 ) cb = noop;
611
612 on('click', function (e) {
613 var el = e.target.tagName === 'A' ? e.target : e.target.parentNode;
614
615 if (el && el.tagName === 'A' && !/_blank/.test(el.target)) {
616 e.preventDefault();
617 var url = el.href;
618 // solve history.pushState cross-origin issue
619 if (this$1.config.crossOriginLinks.indexOf(url) !== -1) {
620 window.open(url, '_self');
621 } else {
622 window.history.pushState({ key: url }, '', url);
623 }
624 cb({ event: e, source: 'navigate' });
625 }
626 });
627
628 on('popstate', function (e) {
629 cb({ event: e, source: 'history' });
630 });
631 };
632
633 /**
634 * Parse the url
635 * @param {string} [path=location.href] URL to be parsed
636 * @return {object} { path, query }
637 */
638 HTML5History.prototype.parse = function parse (path) {
639 if ( path === void 0 ) path = location.href;
640
641 var query = '';
642
643 var queryIndex = path.indexOf('?');
644 if (queryIndex >= 0) {
645 query = path.slice(queryIndex + 1);
646 path = path.slice(0, queryIndex);
647 }
648
649 var base = getPath(location.origin);
650 var baseIndex = path.indexOf(base);
651
652 if (baseIndex > -1) {
653 path = path.slice(baseIndex + base.length);
654 }
655
656 return {
657 path: path,
658 file: this.getFile(path),
659 query: parseQuery(query),
660 };
661 };
662
663 return HTML5History;
664 }(History));
665
666 /**
667 * @typedef {{
668 * path?: string
669 * }} Route
670 */
671
672 /** @type {Route} */
673 var lastRoute = {};
674
675 /** @typedef {import('../Docsify').Constructor} Constructor */
676
677 /**
678 * @template {!Constructor} T
679 * @param {T} Base - The class to extend
680 */
681 function Router(Base) {
682 return /*@__PURE__*/(function (Base) {
683 function Router() {
684 var args = [], len = arguments.length;
685 while ( len-- ) args[ len ] = arguments[ len ];
686
687 Base.apply(this, args);
688
689 this.route = {};
690 }
691
692 if ( Base ) Router.__proto__ = Base;
693 Router.prototype = Object.create( Base && Base.prototype );
694 Router.prototype.constructor = Router;
695
696 Router.prototype.updateRender = function updateRender () {
697 this.router.normalize();
698 this.route = this.router.parse();
699 body.setAttribute('data-page', this.route.file);
700 };
701
702 Router.prototype.initRouter = function initRouter () {
703 var this$1 = this;
704
705 var config = this.config;
706 var mode = config.routerMode || 'hash';
707 var router;
708
709 if (mode === 'history' && supportsPushState) {
710 router = new HTML5History(config);
711 } else {
712 router = new HashHistory(config);
713 }
714
715 this.router = router;
716 this.updateRender();
717 lastRoute = this.route;
718
719 // eslint-disable-next-line no-unused-vars
720 router.onchange(function (params) {
721 this$1.updateRender();
722 this$1._updateRender();
723
724 if (lastRoute.path === this$1.route.path) {
725 this$1.$resetEvents(params.source);
726 return;
727 }
728
729 this$1.$fetch(noop, this$1.$resetEvents.bind(this$1, params.source));
730 lastRoute = this$1.route;
731 });
732 };
733
734 return Router;
735 }(Base));
736 }
737
738 var RGX = /([^{]*?)\w(?=\})/g;
739
740 var MAP = {
741 YYYY: 'getFullYear',
742 YY: 'getYear',
743 MM: function (d) {
744 return d.getMonth() + 1;
745 },
746 DD: 'getDate',
747 HH: 'getHours',
748 mm: 'getMinutes',
749 ss: 'getSeconds',
750 fff: 'getMilliseconds'
751 };
752
753 function tinydate (str, custom) {
754 var parts=[], offset=0;
755
756 str.replace(RGX, function (key, _, idx) {
757 // save preceding string
758 parts.push(str.substring(offset, idx - 1));
759 offset = idx += key.length + 1;
760 // save function
761 parts.push(custom && custom[key] || function (d) {
762 return ('00' + (typeof MAP[key] === 'string' ? d[MAP[key]]() : MAP[key](d))).slice(-key.length);
763 });
764 });
765
766 if (offset !== str.length) {
767 parts.push(str.substring(offset));
768 }
769
770 return function (arg) {
771 var out='', i=0, d=arg||new Date();
772 for (; i<parts.length; i++) {
773 out += (typeof parts[i]==='string') ? parts[i] : parts[i](d);
774 }
775 return out;
776 };
777 }
778
779 /*! @license DOMPurify 2.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.1/LICENSE */
780
781 function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
782
783 var hasOwnProperty = Object.hasOwnProperty,
784 setPrototypeOf = Object.setPrototypeOf,
785 isFrozen = Object.isFrozen,
786 getPrototypeOf = Object.getPrototypeOf,
787 getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
788 var freeze = Object.freeze,
789 seal = Object.seal,
790 create$1 = Object.create; // eslint-disable-line import/no-mutable-exports
791
792 var _ref = typeof Reflect !== 'undefined' && Reflect,
793 apply = _ref.apply,
794 construct = _ref.construct;
795
796 if (!apply) {
797 apply = function apply(fun, thisValue, args) {
798 return fun.apply(thisValue, args);
799 };
800 }
801
802 if (!freeze) {
803 freeze = function freeze(x) {
804 return x;
805 };
806 }
807
808 if (!seal) {
809 seal = function seal(x) {
810 return x;
811 };
812 }
813
814 if (!construct) {
815 construct = function construct(Func, args) {
816 return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))();
817 };
818 }
819
820 var arrayForEach = unapply(Array.prototype.forEach);
821 var arrayPop = unapply(Array.prototype.pop);
822 var arrayPush = unapply(Array.prototype.push);
823
824 var stringToLowerCase = unapply(String.prototype.toLowerCase);
825 var stringMatch = unapply(String.prototype.match);
826 var stringReplace = unapply(String.prototype.replace);
827 var stringIndexOf = unapply(String.prototype.indexOf);
828 var stringTrim = unapply(String.prototype.trim);
829
830 var regExpTest = unapply(RegExp.prototype.test);
831
832 var typeErrorCreate = unconstruct(TypeError);
833
834 function unapply(func) {
835 return function (thisArg) {
836 var arguments$1 = arguments;
837
838 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
839 args[_key - 1] = arguments$1[_key];
840 }
841
842 return apply(func, thisArg, args);
843 };
844 }
845
846 function unconstruct(func) {
847 return function () {
848 var arguments$1 = arguments;
849
850 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
851 args[_key2] = arguments$1[_key2];
852 }
853
854 return construct(func, args);
855 };
856 }
857
858 /* Add properties to a lookup table */
859 function addToSet(set, array) {
860 if (setPrototypeOf) {
861 // Make 'in' and truthy checks like Boolean(set.constructor)
862 // independent of any properties defined on Object.prototype.
863 // Prevent prototype setters from intercepting set as a this value.
864 setPrototypeOf(set, null);
865 }
866
867 var l = array.length;
868 while (l--) {
869 var element = array[l];
870 if (typeof element === 'string') {
871 var lcElement = stringToLowerCase(element);
872 if (lcElement !== element) {
873 // Config presets (e.g. tags.js, attrs.js) are immutable.
874 if (!isFrozen(array)) {
875 array[l] = lcElement;
876 }
877
878 element = lcElement;
879 }
880 }
881
882 set[element] = true;
883 }
884
885 return set;
886 }
887
888 /* Shallow clone an object */
889 function clone(object) {
890 var newObject = create$1(null);
891
892 var property = void 0;
893 for (property in object) {
894 if (apply(hasOwnProperty, object, [property])) {
895 newObject[property] = object[property];
896 }
897 }
898
899 return newObject;
900 }
901
902 /* IE10 doesn't support __lookupGetter__ so lets'
903 * simulate it. It also automatically checks
904 * if the prop is function or getter and behaves
905 * accordingly. */
906 function lookupGetter(object, prop) {
907 while (object !== null) {
908 var desc = getOwnPropertyDescriptor(object, prop);
909 if (desc) {
910 if (desc.get) {
911 return unapply(desc.get);
912 }
913
914 if (typeof desc.value === 'function') {
915 return unapply(desc.value);
916 }
917 }
918
919 object = getPrototypeOf(object);
920 }
921
922 function fallbackValue(element) {
923 console.warn('fallback value for', element);
924 return null;
925 }
926
927 return fallbackValue;
928 }
929
930 var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
931
932 // SVG
933 var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
934
935 var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
936
937 // List of SVG elements that are disallowed by default.
938 // We still need to know them so that we can do namespace
939 // checks properly in case one wants to add them to
940 // allow-list.
941 var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'feimage', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
942
943 var mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
944
945 // Similarly to SVG, we want to know all MathML elements,
946 // even those that we disallow by default.
947 var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
948
949 var text = freeze(['#text']);
950
951 var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
952
953 var svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
954
955 var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
956
957 var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
958
959 // eslint-disable-next-line unicorn/better-regex
960 var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
961 var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
962 var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
963 var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
964 var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
965 );
966 var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
967 var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
968 );
969
970 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
971
972 function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
973
974 var getGlobal = function getGlobal() {
975 return typeof window === 'undefined' ? null : window;
976 };
977
978 /**
979 * Creates a no-op policy for internal use only.
980 * Don't export this function outside this module!
981 * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
982 * @param {Document} document The document object (to determine policy name suffix)
983 * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
984 * are not supported).
985 */
986 var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
987 if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
988 return null;
989 }
990
991 // Allow the callers to control the unique policy name
992 // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
993 // Policy creation with duplicate names throws in Trusted Types.
994 var suffix = null;
995 var ATTR_NAME = 'data-tt-policy-suffix';
996 if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
997 suffix = document.currentScript.getAttribute(ATTR_NAME);
998 }
999
1000 var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
1001
1002 try {
1003 return trustedTypes.createPolicy(policyName, {
1004 createHTML: function createHTML(html$$1) {
1005 return html$$1;
1006 }
1007 });
1008 } catch (_) {
1009 // Policy creation failed (most likely another DOMPurify script has
1010 // already run). Skip creating the policy, as this will only cause errors
1011 // if TT are enforced.
1012 console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
1013 return null;
1014 }
1015 };
1016
1017 function createDOMPurify() {
1018 var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
1019
1020 var DOMPurify = function DOMPurify(root) {
1021 return createDOMPurify(root);
1022 };
1023
1024 /**
1025 * Version label, exposed for easier checks
1026 * if DOMPurify is up to date or not
1027 */
1028 DOMPurify.version = '2.3.1';
1029
1030 /**
1031 * Array of elements that DOMPurify removed during sanitation.
1032 * Empty if nothing was removed.
1033 */
1034 DOMPurify.removed = [];
1035
1036 if (!window || !window.document || window.document.nodeType !== 9) {
1037 // Not running in a browser, provide a factory function
1038 // so that you can pass your own Window
1039 DOMPurify.isSupported = false;
1040
1041 return DOMPurify;
1042 }
1043
1044 var originalDocument = window.document;
1045
1046 var document = window.document;
1047 var DocumentFragment = window.DocumentFragment,
1048 HTMLTemplateElement = window.HTMLTemplateElement,
1049 Node = window.Node,
1050 Element = window.Element,
1051 NodeFilter = window.NodeFilter,
1052 _window$NamedNodeMap = window.NamedNodeMap,
1053 NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
1054 Text = window.Text,
1055 Comment = window.Comment,
1056 DOMParser = window.DOMParser,
1057 trustedTypes = window.trustedTypes;
1058
1059
1060 var ElementPrototype = Element.prototype;
1061
1062 var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
1063 var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
1064 var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
1065 var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
1066
1067 // As per issue #47, the web-components registry is inherited by a
1068 // new document created via createHTMLDocument. As per the spec
1069 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
1070 // a new empty registry is used when creating a template contents owner
1071 // document, so we use that as our parent document to ensure nothing
1072 // is inherited.
1073 if (typeof HTMLTemplateElement === 'function') {
1074 var template = document.createElement('template');
1075 if (template.content && template.content.ownerDocument) {
1076 document = template.content.ownerDocument;
1077 }
1078 }
1079
1080 var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
1081 var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : '';
1082
1083 var _document = document,
1084 implementation = _document.implementation,
1085 createNodeIterator = _document.createNodeIterator,
1086 createDocumentFragment = _document.createDocumentFragment,
1087 getElementsByTagName = _document.getElementsByTagName;
1088 var importNode = originalDocument.importNode;
1089
1090
1091 var documentMode = {};
1092 try {
1093 documentMode = clone(document).documentMode ? document.documentMode : {};
1094 } catch (_) {}
1095
1096 var hooks = {};
1097
1098 /**
1099 * Expose whether this browser supports running the full DOMPurify.
1100 */
1101 DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
1102
1103 var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
1104 ERB_EXPR$$1 = ERB_EXPR,
1105 DATA_ATTR$$1 = DATA_ATTR,
1106 ARIA_ATTR$$1 = ARIA_ATTR,
1107 IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
1108 ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
1109 var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
1110
1111 /**
1112 * We consider the elements and attributes below to be safe. Ideally
1113 * don't add any new ones but feel free to remove unwanted ones.
1114 */
1115
1116 /* allowed element names */
1117
1118 var ALLOWED_TAGS = null;
1119 var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(html), _toConsumableArray$1(svg), _toConsumableArray$1(svgFilters), _toConsumableArray$1(mathMl), _toConsumableArray$1(text)));
1120
1121 /* Allowed attribute names */
1122 var ALLOWED_ATTR = null;
1123 var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
1124
1125 /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
1126 var FORBID_TAGS = null;
1127
1128 /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
1129 var FORBID_ATTR = null;
1130
1131 /* Decide if ARIA attributes are okay */
1132 var ALLOW_ARIA_ATTR = true;
1133
1134 /* Decide if custom data attributes are okay */
1135 var ALLOW_DATA_ATTR = true;
1136
1137 /* Decide if unknown protocols are okay */
1138 var ALLOW_UNKNOWN_PROTOCOLS = false;
1139
1140 /* Output should be safe for common template engines.
1141 * This means, DOMPurify removes data attributes, mustaches and ERB
1142 */
1143 var SAFE_FOR_TEMPLATES = false;
1144
1145 /* Decide if document with <html>... should be returned */
1146 var WHOLE_DOCUMENT = false;
1147
1148 /* Track whether config is already set on this instance of DOMPurify. */
1149 var SET_CONFIG = false;
1150
1151 /* Decide if all elements (e.g. style, script) must be children of
1152 * document.body. By default, browsers might move them to document.head */
1153 var FORCE_BODY = false;
1154
1155 /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
1156 * string (or a TrustedHTML object if Trusted Types are supported).
1157 * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
1158 */
1159 var RETURN_DOM = false;
1160
1161 /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
1162 * string (or a TrustedHTML object if Trusted Types are supported) */
1163 var RETURN_DOM_FRAGMENT = false;
1164
1165 /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
1166 * `Node` is imported into the current `Document`. If this flag is not enabled the
1167 * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
1168 * DOMPurify.
1169 *
1170 * This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`
1171 * might cause XSS from attacks hidden in closed shadowroots in case the browser
1172 * supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/
1173 */
1174 var RETURN_DOM_IMPORT = true;
1175
1176 /* Try to return a Trusted Type object instead of a string, return a string in
1177 * case Trusted Types are not supported */
1178 var RETURN_TRUSTED_TYPE = false;
1179
1180 /* Output should be free from DOM clobbering attacks? */
1181 var SANITIZE_DOM = true;
1182
1183 /* Keep element content when removing element? */
1184 var KEEP_CONTENT = true;
1185
1186 /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
1187 * of importing it into a new Document and returning a sanitized copy */
1188 var IN_PLACE = false;
1189
1190 /* Allow usage of profiles like html, svg and mathMl */
1191 var USE_PROFILES = {};
1192
1193 /* Tags to ignore content of when KEEP_CONTENT is true */
1194 var FORBID_CONTENTS = null;
1195 var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
1196
1197 /* Tags that are safe for data: URIs */
1198 var DATA_URI_TAGS = null;
1199 var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
1200
1201 /* Attributes safe for values like "javascript:" */
1202 var URI_SAFE_ATTRIBUTES = null;
1203 var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
1204
1205 var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
1206 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
1207 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
1208 /* Document namespace */
1209 var NAMESPACE = HTML_NAMESPACE;
1210 var IS_EMPTY_INPUT = false;
1211
1212 /* Keep a reference to config to pass to hooks */
1213 var CONFIG = null;
1214
1215 /* Ideally, do not touch anything below this line */
1216 /* ______________________________________________ */
1217
1218 var formElement = document.createElement('form');
1219
1220 /**
1221 * _parseConfig
1222 *
1223 * @param {Object} cfg optional config literal
1224 */
1225 // eslint-disable-next-line complexity
1226 var _parseConfig = function _parseConfig(cfg) {
1227 if (CONFIG && CONFIG === cfg) {
1228 return;
1229 }
1230
1231 /* Shield configuration object from tampering */
1232 if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
1233 cfg = {};
1234 }
1235
1236 /* Shield configuration object from prototype pollution */
1237 cfg = clone(cfg);
1238
1239 /* Set configuration parameters */
1240 ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
1241 ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
1242 URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
1243 DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
1244 FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
1245 FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
1246 FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
1247 USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
1248 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
1249 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
1250 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
1251 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
1252 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
1253 RETURN_DOM = cfg.RETURN_DOM || false; // Default false
1254 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
1255 RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true
1256 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
1257 FORCE_BODY = cfg.FORCE_BODY || false; // Default false
1258 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
1259 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
1260 IN_PLACE = cfg.IN_PLACE || false; // Default false
1261 IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
1262 NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
1263 if (SAFE_FOR_TEMPLATES) {
1264 ALLOW_DATA_ATTR = false;
1265 }
1266
1267 if (RETURN_DOM_FRAGMENT) {
1268 RETURN_DOM = true;
1269 }
1270
1271 /* Parse profile info */
1272 if (USE_PROFILES) {
1273 ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(text)));
1274 ALLOWED_ATTR = [];
1275 if (USE_PROFILES.html === true) {
1276 addToSet(ALLOWED_TAGS, html);
1277 addToSet(ALLOWED_ATTR, html$1);
1278 }
1279
1280 if (USE_PROFILES.svg === true) {
1281 addToSet(ALLOWED_TAGS, svg);
1282 addToSet(ALLOWED_ATTR, svg$1);
1283 addToSet(ALLOWED_ATTR, xml);
1284 }
1285
1286 if (USE_PROFILES.svgFilters === true) {
1287 addToSet(ALLOWED_TAGS, svgFilters);
1288 addToSet(ALLOWED_ATTR, svg$1);
1289 addToSet(ALLOWED_ATTR, xml);
1290 }
1291
1292 if (USE_PROFILES.mathMl === true) {
1293 addToSet(ALLOWED_TAGS, mathMl);
1294 addToSet(ALLOWED_ATTR, mathMl$1);
1295 addToSet(ALLOWED_ATTR, xml);
1296 }
1297 }
1298
1299 /* Merge configuration parameters */
1300 if (cfg.ADD_TAGS) {
1301 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
1302 ALLOWED_TAGS = clone(ALLOWED_TAGS);
1303 }
1304
1305 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
1306 }
1307
1308 if (cfg.ADD_ATTR) {
1309 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
1310 ALLOWED_ATTR = clone(ALLOWED_ATTR);
1311 }
1312
1313 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
1314 }
1315
1316 if (cfg.ADD_URI_SAFE_ATTR) {
1317 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
1318 }
1319
1320 if (cfg.FORBID_CONTENTS) {
1321 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
1322 FORBID_CONTENTS = clone(FORBID_CONTENTS);
1323 }
1324
1325 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
1326 }
1327
1328 /* Add #text in case KEEP_CONTENT is set to true */
1329 if (KEEP_CONTENT) {
1330 ALLOWED_TAGS['#text'] = true;
1331 }
1332
1333 /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
1334 if (WHOLE_DOCUMENT) {
1335 addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
1336 }
1337
1338 /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
1339 if (ALLOWED_TAGS.table) {
1340 addToSet(ALLOWED_TAGS, ['tbody']);
1341 delete FORBID_TAGS.tbody;
1342 }
1343
1344 // Prevent further manipulation of configuration.
1345 // Not available in IE8, Safari 5, etc.
1346 if (freeze) {
1347 freeze(cfg);
1348 }
1349
1350 CONFIG = cfg;
1351 };
1352
1353 var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
1354
1355 var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
1356
1357 /* Keep track of all possible SVG and MathML tags
1358 * so that we can perform the namespace checks
1359 * correctly. */
1360 var ALL_SVG_TAGS = addToSet({}, svg);
1361 addToSet(ALL_SVG_TAGS, svgFilters);
1362 addToSet(ALL_SVG_TAGS, svgDisallowed);
1363
1364 var ALL_MATHML_TAGS = addToSet({}, mathMl);
1365 addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
1366
1367 /**
1368 *
1369 *
1370 * @param {Element} element a DOM element whose namespace is being checked
1371 * @returns {boolean} Return false if the element has a
1372 * namespace that a spec-compliant parser would never
1373 * return. Return true otherwise.
1374 */
1375 var _checkValidNamespace = function _checkValidNamespace(element) {
1376 var parent = getParentNode(element);
1377
1378 // In JSDOM, if we're inside shadow DOM, then parentNode
1379 // can be null. We just simulate parent in this case.
1380 if (!parent || !parent.tagName) {
1381 parent = {
1382 namespaceURI: HTML_NAMESPACE,
1383 tagName: 'template'
1384 };
1385 }
1386
1387 var tagName = stringToLowerCase(element.tagName);
1388 var parentTagName = stringToLowerCase(parent.tagName);
1389
1390 if (element.namespaceURI === SVG_NAMESPACE) {
1391 // The only way to switch from HTML namespace to SVG
1392 // is via <svg>. If it happens via any other tag, then
1393 // it should be killed.
1394 if (parent.namespaceURI === HTML_NAMESPACE) {
1395 return tagName === 'svg';
1396 }
1397
1398 // The only way to switch from MathML to SVG is via
1399 // svg if parent is either <annotation-xml> or MathML
1400 // text integration points.
1401 if (parent.namespaceURI === MATHML_NAMESPACE) {
1402 return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
1403 }
1404
1405 // We only allow elements that are defined in SVG
1406 // spec. All others are disallowed in SVG namespace.
1407 return Boolean(ALL_SVG_TAGS[tagName]);
1408 }
1409
1410 if (element.namespaceURI === MATHML_NAMESPACE) {
1411 // The only way to switch from HTML namespace to MathML
1412 // is via <math>. If it happens via any other tag, then
1413 // it should be killed.
1414 if (parent.namespaceURI === HTML_NAMESPACE) {
1415 return tagName === 'math';
1416 }
1417
1418 // The only way to switch from SVG to MathML is via
1419 // <math> and HTML integration points
1420 if (parent.namespaceURI === SVG_NAMESPACE) {
1421 return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
1422 }
1423
1424 // We only allow elements that are defined in MathML
1425 // spec. All others are disallowed in MathML namespace.
1426 return Boolean(ALL_MATHML_TAGS[tagName]);
1427 }
1428
1429 if (element.namespaceURI === HTML_NAMESPACE) {
1430 // The only way to switch from SVG to HTML is via
1431 // HTML integration points, and from MathML to HTML
1432 // is via MathML text integration points
1433 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
1434 return false;
1435 }
1436
1437 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
1438 return false;
1439 }
1440
1441 // Certain elements are allowed in both SVG and HTML
1442 // namespace. We need to specify them explicitly
1443 // so that they don't get erronously deleted from
1444 // HTML namespace.
1445 var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
1446
1447 // We disallow tags that are specific for MathML
1448 // or SVG and should never appear in HTML namespace
1449 return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);
1450 }
1451
1452 // The code should never reach this place (this means
1453 // that the element somehow got namespace that is not
1454 // HTML, SVG or MathML). Return false just in case.
1455 return false;
1456 };
1457
1458 /**
1459 * _forceRemove
1460 *
1461 * @param {Node} node a DOM node
1462 */
1463 var _forceRemove = function _forceRemove(node) {
1464 arrayPush(DOMPurify.removed, { element: node });
1465 try {
1466 // eslint-disable-next-line unicorn/prefer-dom-node-remove
1467 node.parentNode.removeChild(node);
1468 } catch (_) {
1469 try {
1470 node.outerHTML = emptyHTML;
1471 } catch (_) {
1472 node.remove();
1473 }
1474 }
1475 };
1476
1477 /**
1478 * _removeAttribute
1479 *
1480 * @param {String} name an Attribute name
1481 * @param {Node} node a DOM node
1482 */
1483 var _removeAttribute = function _removeAttribute(name, node) {
1484 try {
1485 arrayPush(DOMPurify.removed, {
1486 attribute: node.getAttributeNode(name),
1487 from: node
1488 });
1489 } catch (_) {
1490 arrayPush(DOMPurify.removed, {
1491 attribute: null,
1492 from: node
1493 });
1494 }
1495
1496 node.removeAttribute(name);
1497
1498 // We void attribute values for unremovable "is"" attributes
1499 if (name === 'is' && !ALLOWED_ATTR[name]) {
1500 if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
1501 try {
1502 _forceRemove(node);
1503 } catch (_) {}
1504 } else {
1505 try {
1506 node.setAttribute(name, '');
1507 } catch (_) {}
1508 }
1509 }
1510 };
1511
1512 /**
1513 * _initDocument
1514 *
1515 * @param {String} dirty a string of dirty markup
1516 * @return {Document} a DOM, filled with the dirty markup
1517 */
1518 var _initDocument = function _initDocument(dirty) {
1519 /* Create a HTML document */
1520 var doc = void 0;
1521 var leadingWhitespace = void 0;
1522
1523 if (FORCE_BODY) {
1524 dirty = '<remove></remove>' + dirty;
1525 } else {
1526 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
1527 var matches = stringMatch(dirty, /^[\r\n\t ]+/);
1528 leadingWhitespace = matches && matches[0];
1529 }
1530
1531 var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
1532 /*
1533 * Use the DOMParser API by default, fallback later if needs be
1534 * DOMParser not work for svg when has multiple root element.
1535 */
1536 if (NAMESPACE === HTML_NAMESPACE) {
1537 try {
1538 doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
1539 } catch (_) {}
1540 }
1541
1542 /* Use createHTMLDocument in case DOMParser is not available */
1543 if (!doc || !doc.documentElement) {
1544 doc = implementation.createDocument(NAMESPACE, 'template', null);
1545 try {
1546 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
1547 } catch (_) {
1548 // Syntax error if dirtyPayload is invalid xml
1549 }
1550 }
1551
1552 var body = doc.body || doc.documentElement;
1553
1554 if (dirty && leadingWhitespace) {
1555 body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
1556 }
1557
1558 /* Work on whole document or just its body */
1559 if (NAMESPACE === HTML_NAMESPACE) {
1560 return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
1561 }
1562
1563 return WHOLE_DOCUMENT ? doc.documentElement : body;
1564 };
1565
1566 /**
1567 * _createIterator
1568 *
1569 * @param {Document} root document/fragment to create iterator for
1570 * @return {Iterator} iterator instance
1571 */
1572 var _createIterator = function _createIterator(root) {
1573 return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
1574 };
1575
1576 /**
1577 * _isClobbered
1578 *
1579 * @param {Node} elm element to check for clobbering attacks
1580 * @return {Boolean} true if clobbered, false if safe
1581 */
1582 var _isClobbered = function _isClobbered(elm) {
1583 if (elm instanceof Text || elm instanceof Comment) {
1584 return false;
1585 }
1586
1587 if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function') {
1588 return true;
1589 }
1590
1591 return false;
1592 };
1593
1594 /**
1595 * _isNode
1596 *
1597 * @param {Node} obj object to check whether it's a DOM node
1598 * @return {Boolean} true is object is a DOM node
1599 */
1600 var _isNode = function _isNode(object) {
1601 return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? object instanceof Node : object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
1602 };
1603
1604 /**
1605 * _executeHook
1606 * Execute user configurable hooks
1607 *
1608 * @param {String} entryPoint Name of the hook's entry point
1609 * @param {Node} currentNode node to work on with the hook
1610 * @param {Object} data additional hook parameters
1611 */
1612 var _executeHook = function _executeHook(entryPoint, currentNode, data) {
1613 if (!hooks[entryPoint]) {
1614 return;
1615 }
1616
1617 arrayForEach(hooks[entryPoint], function (hook) {
1618 hook.call(DOMPurify, currentNode, data, CONFIG);
1619 });
1620 };
1621
1622 /**
1623 * _sanitizeElements
1624 *
1625 * @protect nodeName
1626 * @protect textContent
1627 * @protect removeChild
1628 *
1629 * @param {Node} currentNode to check for permission to exist
1630 * @return {Boolean} true if node was killed, false if left alive
1631 */
1632 var _sanitizeElements = function _sanitizeElements(currentNode) {
1633 var content = void 0;
1634
1635 /* Execute a hook if present */
1636 _executeHook('beforeSanitizeElements', currentNode, null);
1637
1638 /* Check if element is clobbered or can clobber */
1639 if (_isClobbered(currentNode)) {
1640 _forceRemove(currentNode);
1641 return true;
1642 }
1643
1644 /* Check if tagname contains Unicode */
1645 if (stringMatch(currentNode.nodeName, /[\u0080-\uFFFF]/)) {
1646 _forceRemove(currentNode);
1647 return true;
1648 }
1649
1650 /* Now let's check the element's type and name */
1651 var tagName = stringToLowerCase(currentNode.nodeName);
1652
1653 /* Execute a hook if present */
1654 _executeHook('uponSanitizeElement', currentNode, {
1655 tagName: tagName,
1656 allowedTags: ALLOWED_TAGS
1657 });
1658
1659 /* Detect mXSS attempts abusing namespace confusion */
1660 if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
1661 _forceRemove(currentNode);
1662 return true;
1663 }
1664
1665 /* Mitigate a problem with templates inside select */
1666 if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
1667 _forceRemove(currentNode);
1668 return true;
1669 }
1670
1671 /* Remove element if anything forbids its presence */
1672 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1673 /* Keep content except for bad-listed elements */
1674 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1675 var parentNode = getParentNode(currentNode) || currentNode.parentNode;
1676 var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
1677
1678 if (childNodes && parentNode) {
1679 var childCount = childNodes.length;
1680
1681 for (var i = childCount - 1; i >= 0; --i) {
1682 parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
1683 }
1684 }
1685 }
1686
1687 _forceRemove(currentNode);
1688 return true;
1689 }
1690
1691 /* Check whether element has a valid namespace */
1692 if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
1693 _forceRemove(currentNode);
1694 return true;
1695 }
1696
1697 if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
1698 _forceRemove(currentNode);
1699 return true;
1700 }
1701
1702 /* Sanitize element content to be template-safe */
1703 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1704 /* Get the element's text content */
1705 content = currentNode.textContent;
1706 content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
1707 content = stringReplace(content, ERB_EXPR$$1, ' ');
1708 if (currentNode.textContent !== content) {
1709 arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
1710 currentNode.textContent = content;
1711 }
1712 }
1713
1714 /* Execute a hook if present */
1715 _executeHook('afterSanitizeElements', currentNode, null);
1716
1717 return false;
1718 };
1719
1720 /**
1721 * _isValidAttribute
1722 *
1723 * @param {string} lcTag Lowercase tag name of containing element.
1724 * @param {string} lcName Lowercase attribute name.
1725 * @param {string} value Attribute value.
1726 * @return {Boolean} Returns true if `value` is valid, otherwise false.
1727 */
1728 // eslint-disable-next-line complexity
1729 var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1730 /* Make sure attribute cannot clobber */
1731 if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1732 return false;
1733 }
1734
1735 /* Allow valid data-* attributes: At least one character after "-"
1736 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1737 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1738 We don't need to check the value; it's always URI safe. */
1739 if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1740 return false;
1741
1742 /* Check value is safe. First, is attr inert? If so, is safe */
1743 } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
1744 return false;
1745 }
1746
1747 return true;
1748 };
1749
1750 /**
1751 * _sanitizeAttributes
1752 *
1753 * @protect attributes
1754 * @protect nodeName
1755 * @protect removeAttribute
1756 * @protect setAttribute
1757 *
1758 * @param {Node} currentNode to sanitize
1759 */
1760 var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1761 var attr = void 0;
1762 var value = void 0;
1763 var lcName = void 0;
1764 var l = void 0;
1765 /* Execute a hook if present */
1766 _executeHook('beforeSanitizeAttributes', currentNode, null);
1767
1768 var attributes = currentNode.attributes;
1769
1770 /* Check if we have attributes; if not we might have a text node */
1771
1772 if (!attributes) {
1773 return;
1774 }
1775
1776 var hookEvent = {
1777 attrName: '',
1778 attrValue: '',
1779 keepAttr: true,
1780 allowedAttributes: ALLOWED_ATTR
1781 };
1782 l = attributes.length;
1783
1784 /* Go backwards over all attributes; safely remove bad ones */
1785 while (l--) {
1786 attr = attributes[l];
1787 var _attr = attr,
1788 name = _attr.name,
1789 namespaceURI = _attr.namespaceURI;
1790
1791 value = stringTrim(attr.value);
1792 lcName = stringToLowerCase(name);
1793
1794 /* Execute a hook if present */
1795 hookEvent.attrName = lcName;
1796 hookEvent.attrValue = value;
1797 hookEvent.keepAttr = true;
1798 hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1799 _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1800 value = hookEvent.attrValue;
1801 /* Did the hooks approve of the attribute? */
1802 if (hookEvent.forceKeepAttr) {
1803 continue;
1804 }
1805
1806 /* Remove attribute */
1807 _removeAttribute(name, currentNode);
1808
1809 /* Did the hooks approve of the attribute? */
1810 if (!hookEvent.keepAttr) {
1811 continue;
1812 }
1813
1814 /* Work around a security issue in jQuery 3.0 */
1815 if (regExpTest(/\/>/i, value)) {
1816 _removeAttribute(name, currentNode);
1817 continue;
1818 }
1819
1820 /* Sanitize attribute content to be template-safe */
1821 if (SAFE_FOR_TEMPLATES) {
1822 value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
1823 value = stringReplace(value, ERB_EXPR$$1, ' ');
1824 }
1825
1826 /* Is `value` valid for this attribute? */
1827 var lcTag = currentNode.nodeName.toLowerCase();
1828 if (!_isValidAttribute(lcTag, lcName, value)) {
1829 continue;
1830 }
1831
1832 /* Handle invalid data-* attribute set by try-catching it */
1833 try {
1834 if (namespaceURI) {
1835 currentNode.setAttributeNS(namespaceURI, name, value);
1836 } else {
1837 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1838 currentNode.setAttribute(name, value);
1839 }
1840
1841 arrayPop(DOMPurify.removed);
1842 } catch (_) {}
1843 }
1844
1845 /* Execute a hook if present */
1846 _executeHook('afterSanitizeAttributes', currentNode, null);
1847 };
1848
1849 /**
1850 * _sanitizeShadowDOM
1851 *
1852 * @param {DocumentFragment} fragment to iterate over recursively
1853 */
1854 var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1855 var shadowNode = void 0;
1856 var shadowIterator = _createIterator(fragment);
1857
1858 /* Execute a hook if present */
1859 _executeHook('beforeSanitizeShadowDOM', fragment, null);
1860
1861 while (shadowNode = shadowIterator.nextNode()) {
1862 /* Execute a hook if present */
1863 _executeHook('uponSanitizeShadowNode', shadowNode, null);
1864
1865 /* Sanitize tags and elements */
1866 if (_sanitizeElements(shadowNode)) {
1867 continue;
1868 }
1869
1870 /* Deep shadow DOM detected */
1871 if (shadowNode.content instanceof DocumentFragment) {
1872 _sanitizeShadowDOM(shadowNode.content);
1873 }
1874
1875 /* Check attributes, sanitize if necessary */
1876 _sanitizeAttributes(shadowNode);
1877 }
1878
1879 /* Execute a hook if present */
1880 _executeHook('afterSanitizeShadowDOM', fragment, null);
1881 };
1882
1883 /**
1884 * Sanitize
1885 * Public method providing core sanitation functionality
1886 *
1887 * @param {String|Node} dirty string or DOM node
1888 * @param {Object} configuration object
1889 */
1890 // eslint-disable-next-line complexity
1891 DOMPurify.sanitize = function (dirty, cfg) {
1892 var body = void 0;
1893 var importedNode = void 0;
1894 var currentNode = void 0;
1895 var oldNode = void 0;
1896 var returnNode = void 0;
1897 /* Make sure we have a string to sanitize.
1898 DO NOT return early, as this will return the wrong type if
1899 the user has requested a DOM object rather than a string */
1900 IS_EMPTY_INPUT = !dirty;
1901 if (IS_EMPTY_INPUT) {
1902 dirty = '<!-->';
1903 }
1904
1905 /* Stringify, in case dirty is an object */
1906 if (typeof dirty !== 'string' && !_isNode(dirty)) {
1907 // eslint-disable-next-line no-negated-condition
1908 if (typeof dirty.toString !== 'function') {
1909 throw typeErrorCreate('toString is not a function');
1910 } else {
1911 dirty = dirty.toString();
1912 if (typeof dirty !== 'string') {
1913 throw typeErrorCreate('dirty is not a string, aborting');
1914 }
1915 }
1916 }
1917
1918 /* Check we can run. Otherwise fall back or ignore */
1919 if (!DOMPurify.isSupported) {
1920 if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1921 if (typeof dirty === 'string') {
1922 return window.toStaticHTML(dirty);
1923 }
1924
1925 if (_isNode(dirty)) {
1926 return window.toStaticHTML(dirty.outerHTML);
1927 }
1928 }
1929
1930 return dirty;
1931 }
1932
1933 /* Assign config vars */
1934 if (!SET_CONFIG) {
1935 _parseConfig(cfg);
1936 }
1937
1938 /* Clean up removed elements */
1939 DOMPurify.removed = [];
1940
1941 /* Check if dirty is correctly typed for IN_PLACE */
1942 if (typeof dirty === 'string') {
1943 IN_PLACE = false;
1944 }
1945
1946 if (IN_PLACE) ; else if (dirty instanceof Node) {
1947 /* If dirty is a DOM element, append to an empty document to avoid
1948 elements being stripped by the parser */
1949 body = _initDocument('<!---->');
1950 importedNode = body.ownerDocument.importNode(dirty, true);
1951 if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1952 /* Node is already a body, use as is */
1953 body = importedNode;
1954 } else if (importedNode.nodeName === 'HTML') {
1955 body = importedNode;
1956 } else {
1957 // eslint-disable-next-line unicorn/prefer-dom-node-append
1958 body.appendChild(importedNode);
1959 }
1960 } else {
1961 /* Exit directly if we have nothing to do */
1962 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
1963 // eslint-disable-next-line unicorn/prefer-includes
1964 dirty.indexOf('<') === -1) {
1965 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1966 }
1967
1968 /* Initialize the document to work on */
1969 body = _initDocument(dirty);
1970
1971 /* Check we have a DOM node from the data */
1972 if (!body) {
1973 return RETURN_DOM ? null : emptyHTML;
1974 }
1975 }
1976
1977 /* Remove first element node (ours) if FORCE_BODY is set */
1978 if (body && FORCE_BODY) {
1979 _forceRemove(body.firstChild);
1980 }
1981
1982 /* Get node iterator */
1983 var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1984
1985 /* Now start iterating over the created document */
1986 while (currentNode = nodeIterator.nextNode()) {
1987 /* Fix IE's strange behavior with manipulated textNodes #89 */
1988 if (currentNode.nodeType === 3 && currentNode === oldNode) {
1989 continue;
1990 }
1991
1992 /* Sanitize tags and elements */
1993 if (_sanitizeElements(currentNode)) {
1994 continue;
1995 }
1996
1997 /* Shadow DOM detected, sanitize it */
1998 if (currentNode.content instanceof DocumentFragment) {
1999 _sanitizeShadowDOM(currentNode.content);
2000 }
2001
2002 /* Check attributes, sanitize if necessary */
2003 _sanitizeAttributes(currentNode);
2004
2005 oldNode = currentNode;
2006 }
2007
2008 oldNode = null;
2009
2010 /* If we sanitized `dirty` in-place, return it. */
2011 if (IN_PLACE) {
2012 return dirty;
2013 }
2014
2015 /* Return sanitized string or DOM */
2016 if (RETURN_DOM) {
2017 if (RETURN_DOM_FRAGMENT) {
2018 returnNode = createDocumentFragment.call(body.ownerDocument);
2019
2020 while (body.firstChild) {
2021 // eslint-disable-next-line unicorn/prefer-dom-node-append
2022 returnNode.appendChild(body.firstChild);
2023 }
2024 } else {
2025 returnNode = body;
2026 }
2027
2028 if (RETURN_DOM_IMPORT) {
2029 /*
2030 AdoptNode() is not used because internal state is not reset
2031 (e.g. the past names map of a HTMLFormElement), this is safe
2032 in theory but we would rather not risk another attack vector.
2033 The state that is cloned by importNode() is explicitly defined
2034 by the specs.
2035 */
2036 returnNode = importNode.call(originalDocument, returnNode, true);
2037 }
2038
2039 return returnNode;
2040 }
2041
2042 var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
2043
2044 /* Sanitize final string template-safe */
2045 if (SAFE_FOR_TEMPLATES) {
2046 serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
2047 serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
2048 }
2049
2050 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
2051 };
2052
2053 /**
2054 * Public method to set the configuration once
2055 * setConfig
2056 *
2057 * @param {Object} cfg configuration object
2058 */
2059 DOMPurify.setConfig = function (cfg) {
2060 _parseConfig(cfg);
2061 SET_CONFIG = true;
2062 };
2063
2064 /**
2065 * Public method to remove the configuration
2066 * clearConfig
2067 *
2068 */
2069 DOMPurify.clearConfig = function () {
2070 CONFIG = null;
2071 SET_CONFIG = false;
2072 };
2073
2074 /**
2075 * Public method to check if an attribute value is valid.
2076 * Uses last set config, if any. Otherwise, uses config defaults.
2077 * isValidAttribute
2078 *
2079 * @param {string} tag Tag name of containing element.
2080 * @param {string} attr Attribute name.
2081 * @param {string} value Attribute value.
2082 * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
2083 */
2084 DOMPurify.isValidAttribute = function (tag, attr, value) {
2085 /* Initialize shared config vars if necessary. */
2086 if (!CONFIG) {
2087 _parseConfig({});
2088 }
2089
2090 var lcTag = stringToLowerCase(tag);
2091 var lcName = stringToLowerCase(attr);
2092 return _isValidAttribute(lcTag, lcName, value);
2093 };
2094
2095 /**
2096 * AddHook
2097 * Public method to add DOMPurify hooks
2098 *
2099 * @param {String} entryPoint entry point for the hook to add
2100 * @param {Function} hookFunction function to execute
2101 */
2102 DOMPurify.addHook = function (entryPoint, hookFunction) {
2103 if (typeof hookFunction !== 'function') {
2104 return;
2105 }
2106
2107 hooks[entryPoint] = hooks[entryPoint] || [];
2108 arrayPush(hooks[entryPoint], hookFunction);
2109 };
2110
2111 /**
2112 * RemoveHook
2113 * Public method to remove a DOMPurify hook at a given entryPoint
2114 * (pops it from the stack of hooks if more are present)
2115 *
2116 * @param {String} entryPoint entry point for the hook to remove
2117 */
2118 DOMPurify.removeHook = function (entryPoint) {
2119 if (hooks[entryPoint]) {
2120 arrayPop(hooks[entryPoint]);
2121 }
2122 };
2123
2124 /**
2125 * RemoveHooks
2126 * Public method to remove all DOMPurify hooks at a given entryPoint
2127 *
2128 * @param {String} entryPoint entry point for the hooks to remove
2129 */
2130 DOMPurify.removeHooks = function (entryPoint) {
2131 if (hooks[entryPoint]) {
2132 hooks[entryPoint] = [];
2133 }
2134 };
2135
2136 /**
2137 * RemoveAllHooks
2138 * Public method to remove all DOMPurify hooks
2139 *
2140 */
2141 DOMPurify.removeAllHooks = function () {
2142 hooks = {};
2143 };
2144
2145 return DOMPurify;
2146 }
2147
2148 var purify = createDOMPurify();
2149
2150 var barEl;
2151 var timeId;
2152
2153 /**
2154 * Init progress component
2155 */
2156 function init() {
2157 var div = create('div');
2158
2159 div.classList.add('progress');
2160 appendTo(body, div);
2161 barEl = div;
2162 }
2163
2164 /**
2165 * Render progress bar
2166 */
2167 function progressbar(ref) {
2168 var loaded = ref.loaded;
2169 var total = ref.total;
2170 var step = ref.step;
2171
2172 var num;
2173
2174 !barEl && init();
2175
2176 if (step) {
2177 num = parseInt(barEl.style.width || 0, 10) + step;
2178 num = num > 80 ? 80 : num;
2179 } else {
2180 num = Math.floor((loaded / total) * 100);
2181 }
2182
2183 barEl.style.opacity = 1;
2184 barEl.style.width = num >= 95 ? '100%' : num + '%';
2185
2186 if (num >= 95) {
2187 clearTimeout(timeId);
2188 // eslint-disable-next-line no-unused-vars
2189 timeId = setTimeout(function (_) {
2190 barEl.style.opacity = 0;
2191 barEl.style.width = '0%';
2192 }, 200);
2193 }
2194 }
2195
2196 /* eslint-disable no-unused-vars */
2197
2198 var cache = {};
2199
2200 /**
2201 * Ajax GET implmentation
2202 * @param {string} url Resource URL
2203 * @param {boolean} [hasBar=false] Has progress bar
2204 * @param {String[]} headers Array of headers
2205 * @return {Promise} Promise response
2206 */
2207 function get(url, hasBar, headers) {
2208 if ( hasBar === void 0 ) hasBar = false;
2209 if ( headers === void 0 ) headers = {};
2210
2211 var xhr = new XMLHttpRequest();
2212 var on = function() {
2213 xhr.addEventListener.apply(xhr, arguments);
2214 };
2215
2216 var cached = cache[url];
2217
2218 if (cached) {
2219 return { then: function (cb) { return cb(cached.content, cached.opt); }, abort: noop };
2220 }
2221
2222 xhr.open('GET', url);
2223 for (var i in headers) {
2224 if (hasOwn.call(headers, i)) {
2225 xhr.setRequestHeader(i, headers[i]);
2226 }
2227 }
2228
2229 xhr.send();
2230
2231 return {
2232 then: function(success, error) {
2233 if ( error === void 0 ) error = noop;
2234
2235 if (hasBar) {
2236 var id = setInterval(
2237 function (_) { return progressbar({
2238 step: Math.floor(Math.random() * 5 + 1),
2239 }); },
2240 500
2241 );
2242
2243 on('progress', progressbar);
2244 on('loadend', function (evt) {
2245 progressbar(evt);
2246 clearInterval(id);
2247 });
2248 }
2249
2250 on('error', error);
2251 on('load', function (ref) {
2252 var target = ref.target;
2253
2254 if (target.status >= 400) {
2255 error(target);
2256 } else {
2257 var result = (cache[url] = {
2258 content: target.response,
2259 opt: {
2260 updatedAt: xhr.getResponseHeader('last-modified'),
2261 },
2262 });
2263
2264 success(result.content, result.opt);
2265 }
2266 });
2267 },
2268 abort: function (_) { return xhr.readyState !== 4 && xhr.abort(); },
2269 };
2270 }
2271
2272 function replaceVar(block, color) {
2273 block.innerHTML = block.innerHTML.replace(
2274 /var\(\s*--theme-color.*?\)/g,
2275 color
2276 );
2277 }
2278
2279 function cssVars(color) {
2280 // Variable support
2281 if (window.CSS && window.CSS.supports && window.CSS.supports('(--v:red)')) {
2282 return;
2283 }
2284
2285 var styleBlocks = findAll('style:not(.inserted),link');
2286 [].forEach.call(styleBlocks, function (block) {
2287 if (block.nodeName === 'STYLE') {
2288 replaceVar(block, color);
2289 } else if (block.nodeName === 'LINK') {
2290 var href = block.getAttribute('href');
2291
2292 if (!/\.css$/.test(href)) {
2293 return;
2294 }
2295
2296 get(href).then(function (res) {
2297 var style = create('style', res);
2298
2299 head.appendChild(style);
2300 replaceVar(style, color);
2301 });
2302 }
2303 });
2304 }
2305
2306 /* eslint-disable no-unused-vars */
2307
2308 var title = $.title;
2309 /**
2310 * Toggle button
2311 * @param {Element} el Button to be toggled
2312 * @void
2313 */
2314 function btn(el) {
2315 var toggle = function (_) { return body.classList.toggle('close'); };
2316
2317 el = getNode(el);
2318 if (el === null || el === undefined) {
2319 return;
2320 }
2321
2322 on(el, 'click', function (e) {
2323 e.stopPropagation();
2324 toggle();
2325 });
2326
2327 isMobile &&
2328 on(
2329 body,
2330 'click',
2331 function (_) { return body.classList.contains('close') && toggle(); }
2332 );
2333 }
2334
2335 function collapse(el) {
2336 el = getNode(el);
2337 if (el === null || el === undefined) {
2338 return;
2339 }
2340
2341 on(el, 'click', function (ref) {
2342 var target = ref.target;
2343
2344 if (
2345 target.nodeName === 'A' &&
2346 target.nextSibling &&
2347 target.nextSibling.classList &&
2348 target.nextSibling.classList.contains('app-sub-sidebar')
2349 ) {
2350 toggleClass(target.parentNode, 'collapse');
2351 }
2352 });
2353 }
2354
2355 function sticky() {
2356 var cover = getNode('section.cover');
2357 if (!cover) {
2358 return;
2359 }
2360
2361 var coverHeight = cover.getBoundingClientRect().height;
2362
2363 if (window.pageYOffset >= coverHeight || cover.classList.contains('hidden')) {
2364 toggleClass(body, 'add', 'sticky');
2365 } else {
2366 toggleClass(body, 'remove', 'sticky');
2367 }
2368 }
2369
2370 /**
2371 * Get and active link
2372 * @param {Object} router Router
2373 * @param {String|Element} el Target element
2374 * @param {Boolean} isParent Active parent
2375 * @param {Boolean} autoTitle Automatically set title
2376 * @return {Element} Active element
2377 */
2378 function getAndActive(router, el, isParent, autoTitle) {
2379 el = getNode(el);
2380 var links = [];
2381 if (el !== null && el !== undefined) {
2382 links = findAll(el, 'a');
2383 }
2384
2385 var hash = decodeURI(router.toURL(router.getCurrentPath()));
2386 var target;
2387
2388 links
2389 .sort(function (a, b) { return b.href.length - a.href.length; })
2390 .forEach(function (a) {
2391 var href = decodeURI(a.getAttribute('href'));
2392 var node = isParent ? a.parentNode : a;
2393
2394 a.title = a.title || a.innerText;
2395
2396 if (hash.indexOf(href) === 0 && !target) {
2397 target = a;
2398 toggleClass(node, 'add', 'active');
2399 } else {
2400 toggleClass(node, 'remove', 'active');
2401 }
2402 });
2403
2404 if (autoTitle) {
2405 $.title = target
2406 ? target.title || ((target.innerText) + " - " + title)
2407 : title;
2408 }
2409
2410 return target;
2411 }
2412
2413 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
2414
2415 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2416
2417 var SingleTweener = function () {
2418 function SingleTweener() {
2419 var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2420
2421 _classCallCheck(this, SingleTweener);
2422
2423 this.start = opts.start;
2424 this.end = opts.end;
2425 this.decimal = opts.decimal;
2426 }
2427
2428 _createClass(SingleTweener, [{
2429 key: "getIntermediateValue",
2430 value: function getIntermediateValue(tick) {
2431 if (this.decimal) {
2432 return tick;
2433 } else {
2434 return Math.round(tick);
2435 }
2436 }
2437 }, {
2438 key: "getFinalValue",
2439 value: function getFinalValue() {
2440 return this.end;
2441 }
2442 }]);
2443
2444 return SingleTweener;
2445 }();
2446
2447 var _createClass$1 = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) { descriptor.writable = true; } Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) { defineProperties(Constructor.prototype, protoProps); } if (staticProps) { defineProperties(Constructor, staticProps); } return Constructor; }; }();
2448
2449 function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2450
2451 var Tweezer = function () {
2452 function Tweezer() {
2453 var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2454
2455 _classCallCheck$1(this, Tweezer);
2456
2457 this.duration = opts.duration || 1000;
2458 this.ease = opts.easing || this._defaultEase;
2459 this.tweener = opts.tweener || new SingleTweener(opts);
2460 this.start = this.tweener.start;
2461 this.end = this.tweener.end;
2462
2463 this.frame = null;
2464 this.next = null;
2465 this.isRunning = false;
2466 this.events = {};
2467 this.direction = this.start < this.end ? 'up' : 'down';
2468 }
2469
2470 _createClass$1(Tweezer, [{
2471 key: 'begin',
2472 value: function begin() {
2473 if (!this.isRunning && this.next !== this.end) {
2474 this.frame = window.requestAnimationFrame(this._tick.bind(this));
2475 }
2476 return this;
2477 }
2478 }, {
2479 key: 'stop',
2480 value: function stop() {
2481 window.cancelAnimationFrame(this.frame);
2482 this.isRunning = false;
2483 this.frame = null;
2484 this.timeStart = null;
2485 this.next = null;
2486 return this;
2487 }
2488 }, {
2489 key: 'on',
2490 value: function on(name, handler) {
2491 this.events[name] = this.events[name] || [];
2492 this.events[name].push(handler);
2493 return this;
2494 }
2495 }, {
2496 key: '_emit',
2497 value: function _emit(name, val) {
2498 var _this = this;
2499
2500 var e = this.events[name];
2501 e && e.forEach(function (handler) {
2502 return handler.call(_this, val);
2503 });
2504 }
2505 }, {
2506 key: '_tick',
2507 value: function _tick(currentTime) {
2508 this.isRunning = true;
2509
2510 var lastTick = this.next || this.start;
2511
2512 if (!this.timeStart) { this.timeStart = currentTime; }
2513 this.timeElapsed = currentTime - this.timeStart;
2514 this.next = this.ease(this.timeElapsed, this.start, this.end - this.start, this.duration);
2515
2516 if (this._shouldTick(lastTick)) {
2517 this._emit('tick', this.tweener.getIntermediateValue(this.next));
2518 this.frame = window.requestAnimationFrame(this._tick.bind(this));
2519 } else {
2520 this._emit('tick', this.tweener.getFinalValue());
2521 this._emit('done', null);
2522 }
2523 }
2524 }, {
2525 key: '_shouldTick',
2526 value: function _shouldTick(lastTick) {
2527 return {
2528 up: this.next < this.end && lastTick <= this.next,
2529 down: this.next > this.end && lastTick >= this.next
2530 }[this.direction];
2531 }
2532 }, {
2533 key: '_defaultEase',
2534 value: function _defaultEase(t, b, c, d) {
2535 if ((t /= d / 2) < 1) { return c / 2 * t * t + b; }
2536 return -c / 2 * (--t * (t - 2) - 1) + b;
2537 }
2538 }]);
2539
2540 return Tweezer;
2541 }();
2542
2543 var currentScript = document.currentScript;
2544
2545 /** @param {import('./Docsify').Docsify} vm */
2546 function config(vm) {
2547 var config = merge(
2548 {
2549 el: '#app',
2550 repo: '',
2551 maxLevel: 6,
2552 subMaxLevel: 0,
2553 loadSidebar: null,
2554 loadNavbar: null,
2555 homepage: 'README.md',
2556 coverpage: '',
2557 basePath: '',
2558 auto2top: false,
2559 name: '',
2560 themeColor: '',
2561 nameLink: window.location.pathname,
2562 autoHeader: false,
2563 executeScript: null,
2564 noEmoji: false,
2565 ga: '',
2566 ext: '.md',
2567 mergeNavbar: false,
2568 formatUpdated: '',
2569 // This config for the links inside markdown
2570 externalLinkTarget: '_blank',
2571 // This config for the corner
2572 cornerExternalLinkTarget: '_blank',
2573 externalLinkRel: 'noopener',
2574 routerMode: 'hash',
2575 noCompileLinks: [],
2576 crossOriginLinks: [],
2577 relativePath: false,
2578 topMargin: 0,
2579 },
2580 typeof window.$docsify === 'function'
2581 ? window.$docsify(vm)
2582 : window.$docsify
2583 );
2584
2585 var script =
2586 currentScript ||
2587 [].slice
2588 .call(document.getElementsByTagName('script'))
2589 .filter(function (n) { return /docsify\./.test(n.src); })[0];
2590
2591 if (script) {
2592 for (var prop in config) {
2593 if (hasOwn.call(config, prop)) {
2594 var val = script.getAttribute('data-' + hyphenate(prop));
2595
2596 if (isPrimitive(val)) {
2597 config[prop] = val === '' ? true : val;
2598 }
2599 }
2600 }
2601 }
2602
2603 if (config.loadSidebar === true) {
2604 config.loadSidebar = '_sidebar' + config.ext;
2605 }
2606
2607 if (config.loadNavbar === true) {
2608 config.loadNavbar = '_navbar' + config.ext;
2609 }
2610
2611 if (config.coverpage === true) {
2612 config.coverpage = '_coverpage' + config.ext;
2613 }
2614
2615 if (config.repo === true) {
2616 config.repo = '';
2617 }
2618
2619 if (config.name === true) {
2620 config.name = '';
2621 }
2622
2623 window.$docsify = config;
2624
2625 return config;
2626 }
2627
2628 var nav = {};
2629 var hoverOver = false;
2630 var scroller = null;
2631 var enableScrollEvent = true;
2632 var coverHeight = 0;
2633
2634 function scrollTo(el, offset) {
2635 if ( offset === void 0 ) offset = 0;
2636
2637 if (scroller) {
2638 scroller.stop();
2639 }
2640
2641 enableScrollEvent = false;
2642 scroller = new Tweezer({
2643 start: window.pageYOffset,
2644 end:
2645 Math.round(el.getBoundingClientRect().top) + window.pageYOffset - offset,
2646 duration: 500,
2647 })
2648 .on('tick', function (v) { return window.scrollTo(0, v); })
2649 .on('done', function () {
2650 enableScrollEvent = true;
2651 scroller = null;
2652 })
2653 .begin();
2654 }
2655
2656 function highlight(path) {
2657 if (!enableScrollEvent) {
2658 return;
2659 }
2660
2661 var sidebar = getNode('.sidebar');
2662 var anchors = findAll('.anchor');
2663 var wrap = find(sidebar, '.sidebar-nav');
2664 var active = find(sidebar, 'li.active');
2665 var doc = document.documentElement;
2666 var top = ((doc && doc.scrollTop) || document.body.scrollTop) - coverHeight;
2667 var last;
2668
2669 for (var i = 0, len = anchors.length; i < len; i += 1) {
2670 var node = anchors[i];
2671
2672 if (node.offsetTop > top) {
2673 if (!last) {
2674 last = node;
2675 }
2676
2677 break;
2678 } else {
2679 last = node;
2680 }
2681 }
2682
2683 if (!last) {
2684 return;
2685 }
2686
2687 var li = nav[getNavKey(path, last.getAttribute('data-id'))];
2688
2689 if (!li || li === active) {
2690 return;
2691 }
2692
2693 active && active.classList.remove('active');
2694 li.classList.add('active');
2695 active = li;
2696
2697 // Scroll into view
2698 // https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297
2699 if (!hoverOver && body.classList.contains('sticky')) {
2700 var height = sidebar.clientHeight;
2701 var curOffset = 0;
2702 var cur = active.offsetTop + active.clientHeight + 40;
2703 var isInView =
2704 active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height;
2705 var notThan = cur - curOffset < height;
2706
2707 sidebar.scrollTop = isInView
2708 ? wrap.scrollTop
2709 : notThan
2710 ? curOffset
2711 : cur - height;
2712 }
2713 }
2714
2715 function getNavKey(path, id) {
2716 return ((decodeURIComponent(path)) + "?id=" + (decodeURIComponent(id)));
2717 }
2718
2719 function scrollActiveSidebar(router) {
2720 var cover = find('.cover.show');
2721 coverHeight = cover ? cover.offsetHeight : 0;
2722
2723 var sidebar = getNode('.sidebar');
2724 var lis = [];
2725 if (sidebar !== null && sidebar !== undefined) {
2726 lis = findAll(sidebar, 'li');
2727 }
2728
2729 for (var i = 0, len = lis.length; i < len; i += 1) {
2730 var li = lis[i];
2731 var a = li.querySelector('a');
2732 if (!a) {
2733 continue;
2734 }
2735
2736 var href = a.getAttribute('href');
2737
2738 if (href !== '/') {
2739 var ref = router.parse(href);
2740 var id = ref.query.id;
2741 var path$1 = ref.path;
2742 if (id) {
2743 href = getNavKey(path$1, id);
2744 }
2745 }
2746
2747 if (href) {
2748 nav[decodeURIComponent(href)] = li;
2749 }
2750 }
2751
2752 if (isMobile) {
2753 return;
2754 }
2755
2756 var path = removeParams(router.getCurrentPath());
2757 off('scroll', function () { return highlight(path); });
2758 on('scroll', function () { return highlight(path); });
2759 on(sidebar, 'mouseover', function () {
2760 hoverOver = true;
2761 });
2762 on(sidebar, 'mouseleave', function () {
2763 hoverOver = false;
2764 });
2765 }
2766
2767 function scrollIntoView(path, id) {
2768 if (!id) {
2769 return;
2770 }
2771 var topMargin = config().topMargin;
2772 var section = find('#' + id);
2773 section && scrollTo(section, topMargin);
2774
2775 var li = nav[getNavKey(path, id)];
2776 var sidebar = getNode('.sidebar');
2777 var active = find(sidebar, 'li.active');
2778 active && active.classList.remove('active');
2779 li && li.classList.add('active');
2780 }
2781
2782 var scrollEl = $.scrollingElement || $.documentElement;
2783
2784 function scroll2Top(offset) {
2785 if ( offset === void 0 ) offset = 0;
2786
2787 scrollEl.scrollTop = offset === true ? 0 : Number(offset);
2788 }
2789
2790 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
2791
2792 function createCommonjsModule(fn, module) {
2793 return module = { exports: {} }, fn(module, module.exports), module.exports;
2794 }
2795
2796 var defaults = createCommonjsModule(function (module) {
2797 function getDefaults() {
2798 return {
2799 baseUrl: null,
2800 breaks: false,
2801 gfm: true,
2802 headerIds: true,
2803 headerPrefix: '',
2804 highlight: null,
2805 langPrefix: 'language-',
2806 mangle: true,
2807 pedantic: false,
2808 renderer: null,
2809 sanitize: false,
2810 sanitizer: null,
2811 silent: false,
2812 smartLists: false,
2813 smartypants: false,
2814 tokenizer: null,
2815 walkTokens: null,
2816 xhtml: false
2817 };
2818 }
2819
2820 function changeDefaults(newDefaults) {
2821 module.exports.defaults = newDefaults;
2822 }
2823
2824 module.exports = {
2825 defaults: getDefaults(),
2826 getDefaults: getDefaults,
2827 changeDefaults: changeDefaults
2828 };
2829 });
2830 var defaults_1 = defaults.defaults;
2831 var defaults_2 = defaults.getDefaults;
2832 var defaults_3 = defaults.changeDefaults;
2833
2834 /**
2835 * Helpers
2836 */
2837 var escapeTest = /[&<>"']/;
2838 var escapeReplace = /[&<>"']/g;
2839 var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
2840 var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
2841 var escapeReplacements = {
2842 '&': '&amp;',
2843 '<': '&lt;',
2844 '>': '&gt;',
2845 '"': '&quot;',
2846 "'": '&#39;'
2847 };
2848 var getEscapeReplacement = function (ch) { return escapeReplacements[ch]; };
2849 function escape(html, encode) {
2850 if (encode) {
2851 if (escapeTest.test(html)) {
2852 return html.replace(escapeReplace, getEscapeReplacement);
2853 }
2854 } else {
2855 if (escapeTestNoEncode.test(html)) {
2856 return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
2857 }
2858 }
2859
2860 return html;
2861 }
2862
2863 var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
2864
2865 function unescape(html) {
2866 // explicitly match decimal, hex, and named HTML entities
2867 return html.replace(unescapeTest, function (_, n) {
2868 n = n.toLowerCase();
2869 if (n === 'colon') { return ':'; }
2870 if (n.charAt(0) === '#') {
2871 return n.charAt(1) === 'x'
2872 ? String.fromCharCode(parseInt(n.substring(2), 16))
2873 : String.fromCharCode(+n.substring(1));
2874 }
2875 return '';
2876 });
2877 }
2878
2879 var caret = /(^|[^\[])\^/g;
2880 function edit(regex, opt) {
2881 regex = regex.source || regex;
2882 opt = opt || '';
2883 var obj = {
2884 replace: function (name, val) {
2885 val = val.source || val;
2886 val = val.replace(caret, '$1');
2887 regex = regex.replace(name, val);
2888 return obj;
2889 },
2890 getRegex: function () {
2891 return new RegExp(regex, opt);
2892 }
2893 };
2894 return obj;
2895 }
2896
2897 var nonWordAndColonTest = /[^\w:]/g;
2898 var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
2899 function cleanUrl(sanitize, base, href) {
2900 if (sanitize) {
2901 var prot;
2902 try {
2903 prot = decodeURIComponent(unescape(href))
2904 .replace(nonWordAndColonTest, '')
2905 .toLowerCase();
2906 } catch (e) {
2907 return null;
2908 }
2909 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
2910 return null;
2911 }
2912 }
2913 if (base && !originIndependentUrl.test(href)) {
2914 href = resolveUrl(base, href);
2915 }
2916 try {
2917 href = encodeURI(href).replace(/%25/g, '%');
2918 } catch (e) {
2919 return null;
2920 }
2921 return href;
2922 }
2923
2924 var baseUrls = {};
2925 var justDomain = /^[^:]+:\/*[^/]*$/;
2926 var protocol = /^([^:]+:)[\s\S]*$/;
2927 var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
2928
2929 function resolveUrl(base, href) {
2930 if (!baseUrls[' ' + base]) {
2931 // we can ignore everything in base after the last slash of its path component,
2932 // but we might need to add _that_
2933 // https://tools.ietf.org/html/rfc3986#section-3
2934 if (justDomain.test(base)) {
2935 baseUrls[' ' + base] = base + '/';
2936 } else {
2937 baseUrls[' ' + base] = rtrim(base, '/', true);
2938 }
2939 }
2940 base = baseUrls[' ' + base];
2941 var relativeBase = base.indexOf(':') === -1;
2942
2943 if (href.substring(0, 2) === '//') {
2944 if (relativeBase) {
2945 return href;
2946 }
2947 return base.replace(protocol, '$1') + href;
2948 } else if (href.charAt(0) === '/') {
2949 if (relativeBase) {
2950 return href;
2951 }
2952 return base.replace(domain, '$1') + href;
2953 } else {
2954 return base + href;
2955 }
2956 }
2957
2958 var noopTest = { exec: function noopTest() {} };
2959
2960 function merge$1(obj) {
2961 var arguments$1 = arguments;
2962
2963 var i = 1,
2964 target,
2965 key;
2966
2967 for (; i < arguments.length; i++) {
2968 target = arguments$1[i];
2969 for (key in target) {
2970 if (Object.prototype.hasOwnProperty.call(target, key)) {
2971 obj[key] = target[key];
2972 }
2973 }
2974 }
2975
2976 return obj;
2977 }
2978
2979 function splitCells(tableRow, count) {
2980 // ensure that every cell-delimiting pipe has a space
2981 // before it to distinguish it from an escaped pipe
2982 var row = tableRow.replace(/\|/g, function (match, offset, str) {
2983 var escaped = false,
2984 curr = offset;
2985 while (--curr >= 0 && str[curr] === '\\') { escaped = !escaped; }
2986 if (escaped) {
2987 // odd number of slashes means | is escaped
2988 // so we leave it alone
2989 return '|';
2990 } else {
2991 // add space before unescaped |
2992 return ' |';
2993 }
2994 }),
2995 cells = row.split(/ \|/);
2996 var i = 0;
2997
2998 if (cells.length > count) {
2999 cells.splice(count);
3000 } else {
3001 while (cells.length < count) { cells.push(''); }
3002 }
3003
3004 for (; i < cells.length; i++) {
3005 // leading or trailing whitespace is ignored per the gfm spec
3006 cells[i] = cells[i].trim().replace(/\\\|/g, '|');
3007 }
3008 return cells;
3009 }
3010
3011 // Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
3012 // /c*$/ is vulnerable to REDOS.
3013 // invert: Remove suffix of non-c chars instead. Default falsey.
3014 function rtrim(str, c, invert) {
3015 var l = str.length;
3016 if (l === 0) {
3017 return '';
3018 }
3019
3020 // Length of suffix matching the invert condition.
3021 var suffLen = 0;
3022
3023 // Step left until we fail to match the invert condition.
3024 while (suffLen < l) {
3025 var currChar = str.charAt(l - suffLen - 1);
3026 if (currChar === c && !invert) {
3027 suffLen++;
3028 } else if (currChar !== c && invert) {
3029 suffLen++;
3030 } else {
3031 break;
3032 }
3033 }
3034
3035 return str.substr(0, l - suffLen);
3036 }
3037
3038 function findClosingBracket(str, b) {
3039 if (str.indexOf(b[1]) === -1) {
3040 return -1;
3041 }
3042 var l = str.length;
3043 var level = 0,
3044 i = 0;
3045 for (; i < l; i++) {
3046 if (str[i] === '\\') {
3047 i++;
3048 } else if (str[i] === b[0]) {
3049 level++;
3050 } else if (str[i] === b[1]) {
3051 level--;
3052 if (level < 0) {
3053 return i;
3054 }
3055 }
3056 }
3057 return -1;
3058 }
3059
3060 function checkSanitizeDeprecation(opt) {
3061 if (opt && opt.sanitize && !opt.silent) {
3062 console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
3063 }
3064 }
3065
3066 // copied from https://stackoverflow.com/a/5450113/806777
3067 function repeatString(pattern, count) {
3068 if (count < 1) {
3069 return '';
3070 }
3071 var result = '';
3072 while (count > 1) {
3073 if (count & 1) {
3074 result += pattern;
3075 }
3076 count >>= 1;
3077 pattern += pattern;
3078 }
3079 return result + pattern;
3080 }
3081
3082 var helpers = {
3083 escape: escape,
3084 unescape: unescape,
3085 edit: edit,
3086 cleanUrl: cleanUrl,
3087 resolveUrl: resolveUrl,
3088 noopTest: noopTest,
3089 merge: merge$1,
3090 splitCells: splitCells,
3091 rtrim: rtrim,
3092 findClosingBracket: findClosingBracket,
3093 checkSanitizeDeprecation: checkSanitizeDeprecation,
3094 repeatString: repeatString
3095 };
3096
3097 var defaults$1 = defaults.defaults;
3098
3099 var rtrim$1 = helpers.rtrim;
3100 var splitCells$1 = helpers.splitCells;
3101 var escape$1 = helpers.escape;
3102 var findClosingBracket$1 = helpers.findClosingBracket;
3103
3104 function outputLink(cap, link, raw) {
3105 var href = link.href;
3106 var title = link.title ? escape$1(link.title) : null;
3107 var text = cap[1].replace(/\\([\[\]])/g, '$1');
3108
3109 if (cap[0].charAt(0) !== '!') {
3110 return {
3111 type: 'link',
3112 raw: raw,
3113 href: href,
3114 title: title,
3115 text: text
3116 };
3117 } else {
3118 return {
3119 type: 'image',
3120 raw: raw,
3121 href: href,
3122 title: title,
3123 text: escape$1(text)
3124 };
3125 }
3126 }
3127
3128 function indentCodeCompensation(raw, text) {
3129 var matchIndentToCode = raw.match(/^(\s+)(?:```)/);
3130
3131 if (matchIndentToCode === null) {
3132 return text;
3133 }
3134
3135 var indentToCode = matchIndentToCode[1];
3136
3137 return text
3138 .split('\n')
3139 .map(function (node) {
3140 var matchIndentInNode = node.match(/^\s+/);
3141 if (matchIndentInNode === null) {
3142 return node;
3143 }
3144
3145 var indentInNode = matchIndentInNode[0];
3146
3147 if (indentInNode.length >= indentToCode.length) {
3148 return node.slice(indentToCode.length);
3149 }
3150
3151 return node;
3152 })
3153 .join('\n');
3154 }
3155
3156 /**
3157 * Tokenizer
3158 */
3159 var Tokenizer = /*@__PURE__*/(function () {
3160 function Tokenizer(options) {
3161 this.options = options || defaults$1;
3162 }
3163
3164 Tokenizer.prototype.space = function space (src) {
3165 var cap = this.rules.block.newline.exec(src);
3166 if (cap) {
3167 if (cap[0].length > 1) {
3168 return {
3169 type: 'space',
3170 raw: cap[0]
3171 };
3172 }
3173 return { raw: '\n' };
3174 }
3175 };
3176
3177 Tokenizer.prototype.code = function code (src, tokens) {
3178 var cap = this.rules.block.code.exec(src);
3179 if (cap) {
3180 var lastToken = tokens[tokens.length - 1];
3181 // An indented code block cannot interrupt a paragraph.
3182 if (lastToken && lastToken.type === 'paragraph') {
3183 return {
3184 raw: cap[0],
3185 text: cap[0].trimRight()
3186 };
3187 }
3188
3189 var text = cap[0].replace(/^ {1,4}/gm, '');
3190 return {
3191 type: 'code',
3192 raw: cap[0],
3193 codeBlockStyle: 'indented',
3194 text: !this.options.pedantic
3195 ? rtrim$1(text, '\n')
3196 : text
3197 };
3198 }
3199 };
3200
3201 Tokenizer.prototype.fences = function fences (src) {
3202 var cap = this.rules.block.fences.exec(src);
3203 if (cap) {
3204 var raw = cap[0];
3205 var text = indentCodeCompensation(raw, cap[3] || '');
3206
3207 return {
3208 type: 'code',
3209 raw: raw,
3210 lang: cap[2] ? cap[2].trim() : cap[2],
3211 text: text
3212 };
3213 }
3214 };
3215
3216 Tokenizer.prototype.heading = function heading (src) {
3217 var cap = this.rules.block.heading.exec(src);
3218 if (cap) {
3219 var text = cap[2].trim();
3220
3221 // remove trailing #s
3222 if (/#$/.test(text)) {
3223 var trimmed = rtrim$1(text, '#');
3224 if (this.options.pedantic) {
3225 text = trimmed.trim();
3226 } else if (!trimmed || / $/.test(trimmed)) {
3227 // CommonMark requires space before trailing #s
3228 text = trimmed.trim();
3229 }
3230 }
3231
3232 return {
3233 type: 'heading',
3234 raw: cap[0],
3235 depth: cap[1].length,
3236 text: text
3237 };
3238 }
3239 };
3240
3241 Tokenizer.prototype.nptable = function nptable (src) {
3242 var cap = this.rules.block.nptable.exec(src);
3243 if (cap) {
3244 var item = {
3245 type: 'table',
3246 header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
3247 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
3248 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [],
3249 raw: cap[0]
3250 };
3251
3252 if (item.header.length === item.align.length) {
3253 var l = item.align.length;
3254 var i;
3255 for (i = 0; i < l; i++) {
3256 if (/^ *-+: *$/.test(item.align[i])) {
3257 item.align[i] = 'right';
3258 } else if (/^ *:-+: *$/.test(item.align[i])) {
3259 item.align[i] = 'center';
3260 } else if (/^ *:-+ *$/.test(item.align[i])) {
3261 item.align[i] = 'left';
3262 } else {
3263 item.align[i] = null;
3264 }
3265 }
3266
3267 l = item.cells.length;
3268 for (i = 0; i < l; i++) {
3269 item.cells[i] = splitCells$1(item.cells[i], item.header.length);
3270 }
3271
3272 return item;
3273 }
3274 }
3275 };
3276
3277 Tokenizer.prototype.hr = function hr (src) {
3278 var cap = this.rules.block.hr.exec(src);
3279 if (cap) {
3280 return {
3281 type: 'hr',
3282 raw: cap[0]
3283 };
3284 }
3285 };
3286
3287 Tokenizer.prototype.blockquote = function blockquote (src) {
3288 var cap = this.rules.block.blockquote.exec(src);
3289 if (cap) {
3290 var text = cap[0].replace(/^ *> ?/gm, '');
3291
3292 return {
3293 type: 'blockquote',
3294 raw: cap[0],
3295 text: text
3296 };
3297 }
3298 };
3299
3300 Tokenizer.prototype.list = function list (src) {
3301 var cap = this.rules.block.list.exec(src);
3302 if (cap) {
3303 var raw = cap[0];
3304 var bull = cap[2];
3305 var isordered = bull.length > 1;
3306
3307 var list = {
3308 type: 'list',
3309 raw: raw,
3310 ordered: isordered,
3311 start: isordered ? +bull.slice(0, -1) : '',
3312 loose: false,
3313 items: []
3314 };
3315
3316 // Get each top-level item.
3317 var itemMatch = cap[0].match(this.rules.block.item);
3318
3319 var next = false,
3320 item,
3321 space,
3322 bcurr,
3323 bnext,
3324 addBack,
3325 loose,
3326 istask,
3327 ischecked;
3328
3329 var l = itemMatch.length;
3330 bcurr = this.rules.block.listItemStart.exec(itemMatch[0]);
3331 for (var i = 0; i < l; i++) {
3332 item = itemMatch[i];
3333 raw = item;
3334
3335 // Determine whether the next list item belongs here.
3336 // Backpedal if it does not belong in this list.
3337 if (i !== l - 1) {
3338 bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
3339 if (
3340 !this.options.pedantic
3341 ? bnext[1].length > bcurr[0].length || bnext[1].length > 3
3342 : bnext[1].length > bcurr[1].length
3343 ) {
3344 // nested list
3345 itemMatch.splice(i, 2, itemMatch[i] + '\n' + itemMatch[i + 1]);
3346 i--;
3347 l--;
3348 continue;
3349 } else {
3350 if (
3351 // different bullet style
3352 !this.options.pedantic || this.options.smartLists
3353 ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1]
3354 : isordered === (bnext[2].length === 1)
3355 ) {
3356 addBack = itemMatch.slice(i + 1).join('\n');
3357 list.raw = list.raw.substring(0, list.raw.length - addBack.length);
3358 i = l - 1;
3359 }
3360 }
3361 bcurr = bnext;
3362 }
3363
3364 // Remove the list item's bullet
3365 // so it is seen as the next token.
3366 space = item.length;
3367 item = item.replace(/^ *([*+-]|\d+[.)]) ?/, '');
3368
3369 // Outdent whatever the
3370 // list item contains. Hacky.
3371 if (~item.indexOf('\n ')) {
3372 space -= item.length;
3373 item = !this.options.pedantic
3374 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
3375 : item.replace(/^ {1,4}/gm, '');
3376 }
3377
3378 // Determine whether item is loose or not.
3379 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
3380 // for discount behavior.
3381 loose = next || /\n\n(?!\s*$)/.test(item);
3382 if (i !== l - 1) {
3383 next = item.charAt(item.length - 1) === '\n';
3384 if (!loose) { loose = next; }
3385 }
3386
3387 if (loose) {
3388 list.loose = true;
3389 }
3390
3391 // Check for task list items
3392 if (this.options.gfm) {
3393 istask = /^\[[ xX]\] /.test(item);
3394 ischecked = undefined;
3395 if (istask) {
3396 ischecked = item[1] !== ' ';
3397 item = item.replace(/^\[[ xX]\] +/, '');
3398 }
3399 }
3400
3401 list.items.push({
3402 type: 'list_item',
3403 raw: raw,
3404 task: istask,
3405 checked: ischecked,
3406 loose: loose,
3407 text: item
3408 });
3409 }
3410
3411 return list;
3412 }
3413 };
3414
3415 Tokenizer.prototype.html = function html (src) {
3416 var cap = this.rules.block.html.exec(src);
3417 if (cap) {
3418 return {
3419 type: this.options.sanitize
3420 ? 'paragraph'
3421 : 'html',
3422 raw: cap[0],
3423 pre: !this.options.sanitizer
3424 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
3425 text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0]
3426 };
3427 }
3428 };
3429
3430 Tokenizer.prototype.def = function def (src) {
3431 var cap = this.rules.block.def.exec(src);
3432 if (cap) {
3433 if (cap[3]) { cap[3] = cap[3].substring(1, cap[3].length - 1); }
3434 var tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
3435 return {
3436 tag: tag,
3437 raw: cap[0],
3438 href: cap[2],
3439 title: cap[3]
3440 };
3441 }
3442 };
3443
3444 Tokenizer.prototype.table = function table (src) {
3445 var cap = this.rules.block.table.exec(src);
3446 if (cap) {
3447 var item = {
3448 type: 'table',
3449 header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
3450 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
3451 cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
3452 };
3453
3454 if (item.header.length === item.align.length) {
3455 item.raw = cap[0];
3456
3457 var l = item.align.length;
3458 var i;
3459 for (i = 0; i < l; i++) {
3460 if (/^ *-+: *$/.test(item.align[i])) {
3461 item.align[i] = 'right';
3462 } else if (/^ *:-+: *$/.test(item.align[i])) {
3463 item.align[i] = 'center';
3464 } else if (/^ *:-+ *$/.test(item.align[i])) {
3465 item.align[i] = 'left';
3466 } else {
3467 item.align[i] = null;
3468 }
3469 }
3470
3471 l = item.cells.length;
3472 for (i = 0; i < l; i++) {
3473 item.cells[i] = splitCells$1(
3474 item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
3475 item.header.length);
3476 }
3477
3478 return item;
3479 }
3480 }
3481 };
3482
3483 Tokenizer.prototype.lheading = function lheading (src) {
3484 var cap = this.rules.block.lheading.exec(src);
3485 if (cap) {
3486 return {
3487 type: 'heading',
3488 raw: cap[0],
3489 depth: cap[2].charAt(0) === '=' ? 1 : 2,
3490 text: cap[1]
3491 };
3492 }
3493 };
3494
3495 Tokenizer.prototype.paragraph = function paragraph (src) {
3496 var cap = this.rules.block.paragraph.exec(src);
3497 if (cap) {
3498 return {
3499 type: 'paragraph',
3500 raw: cap[0],
3501 text: cap[1].charAt(cap[1].length - 1) === '\n'
3502 ? cap[1].slice(0, -1)
3503 : cap[1]
3504 };
3505 }
3506 };
3507
3508 Tokenizer.prototype.text = function text (src, tokens) {
3509 var cap = this.rules.block.text.exec(src);
3510 if (cap) {
3511 var lastToken = tokens[tokens.length - 1];
3512 if (lastToken && lastToken.type === 'text') {
3513 return {
3514 raw: cap[0],
3515 text: cap[0]
3516 };
3517 }
3518
3519 return {
3520 type: 'text',
3521 raw: cap[0],
3522 text: cap[0]
3523 };
3524 }
3525 };
3526
3527 Tokenizer.prototype.escape = function escape$1$1 (src) {
3528 var cap = this.rules.inline.escape.exec(src);
3529 if (cap) {
3530 return {
3531 type: 'escape',
3532 raw: cap[0],
3533 text: escape$1(cap[1])
3534 };
3535 }
3536 };
3537
3538 Tokenizer.prototype.tag = function tag (src, inLink, inRawBlock) {
3539 var cap = this.rules.inline.tag.exec(src);
3540 if (cap) {
3541 if (!inLink && /^<a /i.test(cap[0])) {
3542 inLink = true;
3543 } else if (inLink && /^<\/a>/i.test(cap[0])) {
3544 inLink = false;
3545 }
3546 if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
3547 inRawBlock = true;
3548 } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
3549 inRawBlock = false;
3550 }
3551
3552 return {
3553 type: this.options.sanitize
3554 ? 'text'
3555 : 'html',
3556 raw: cap[0],
3557 inLink: inLink,
3558 inRawBlock: inRawBlock,
3559 text: this.options.sanitize
3560 ? (this.options.sanitizer
3561 ? this.options.sanitizer(cap[0])
3562 : escape$1(cap[0]))
3563 : cap[0]
3564 };
3565 }
3566 };
3567
3568 Tokenizer.prototype.link = function link (src) {
3569 var cap = this.rules.inline.link.exec(src);
3570 if (cap) {
3571 var trimmedUrl = cap[2].trim();
3572 if (!this.options.pedantic && /^</.test(trimmedUrl)) {
3573 // commonmark requires matching angle brackets
3574 if (!(/>$/.test(trimmedUrl))) {
3575 return;
3576 }
3577
3578 // ending angle bracket cannot be escaped
3579 var rtrimSlash = rtrim$1(trimmedUrl.slice(0, -1), '\\');
3580 if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
3581 return;
3582 }
3583 } else {
3584 // find closing parenthesis
3585 var lastParenIndex = findClosingBracket$1(cap[2], '()');
3586 if (lastParenIndex > -1) {
3587 var start = cap[0].indexOf('!') === 0 ? 5 : 4;
3588 var linkLen = start + cap[1].length + lastParenIndex;
3589 cap[2] = cap[2].substring(0, lastParenIndex);
3590 cap[0] = cap[0].substring(0, linkLen).trim();
3591 cap[3] = '';
3592 }
3593 }
3594 var href = cap[2];
3595 var title = '';
3596 if (this.options.pedantic) {
3597 // split pedantic href and title
3598 var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
3599
3600 if (link) {
3601 href = link[1];
3602 title = link[3];
3603 }
3604 } else {
3605 title = cap[3] ? cap[3].slice(1, -1) : '';
3606 }
3607
3608 href = href.trim();
3609 if (/^</.test(href)) {
3610 if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {
3611 // pedantic allows starting angle bracket without ending angle bracket
3612 href = href.slice(1);
3613 } else {
3614 href = href.slice(1, -1);
3615 }
3616 }
3617 return outputLink(cap, {
3618 href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
3619 title: title ? title.replace(this.rules.inline._escapes, '$1') : title
3620 }, cap[0]);
3621 }
3622 };
3623
3624 Tokenizer.prototype.reflink = function reflink (src, links) {
3625 var cap;
3626 if ((cap = this.rules.inline.reflink.exec(src))
3627 || (cap = this.rules.inline.nolink.exec(src))) {
3628 var link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
3629 link = links[link.toLowerCase()];
3630 if (!link || !link.href) {
3631 var text = cap[0].charAt(0);
3632 return {
3633 type: 'text',
3634 raw: text,
3635 text: text
3636 };
3637 }
3638 return outputLink(cap, link, cap[0]);
3639 }
3640 };
3641
3642 Tokenizer.prototype.strong = function strong (src, maskedSrc, prevChar) {
3643 if ( prevChar === void 0 ) prevChar = '';
3644
3645 var match = this.rules.inline.strong.start.exec(src);
3646
3647 if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
3648 maskedSrc = maskedSrc.slice(-1 * src.length);
3649 var endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd;
3650
3651 endReg.lastIndex = 0;
3652
3653 var cap;
3654 while ((match = endReg.exec(maskedSrc)) != null) {
3655 cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3));
3656 if (cap) {
3657 return {
3658 type: 'strong',
3659 raw: src.slice(0, cap[0].length),
3660 text: src.slice(2, cap[0].length - 2)
3661 };
3662 }
3663 }
3664 }
3665 };
3666
3667 Tokenizer.prototype.em = function em (src, maskedSrc, prevChar) {
3668 if ( prevChar === void 0 ) prevChar = '';
3669
3670 var match = this.rules.inline.em.start.exec(src);
3671
3672 if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
3673 maskedSrc = maskedSrc.slice(-1 * src.length);
3674 var endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd;
3675
3676 endReg.lastIndex = 0;
3677
3678 var cap;
3679 while ((match = endReg.exec(maskedSrc)) != null) {
3680 cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2));
3681 if (cap) {
3682 return {
3683 type: 'em',
3684 raw: src.slice(0, cap[0].length),
3685 text: src.slice(1, cap[0].length - 1)
3686 };
3687 }
3688 }
3689 }
3690 };
3691
3692 Tokenizer.prototype.codespan = function codespan (src) {
3693 var cap = this.rules.inline.code.exec(src);
3694 if (cap) {
3695 var text = cap[2].replace(/\n/g, ' ');
3696 var hasNonSpaceChars = /[^ ]/.test(text);
3697 var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
3698 if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
3699 text = text.substring(1, text.length - 1);
3700 }
3701 text = escape$1(text, true);
3702 return {
3703 type: 'codespan',
3704 raw: cap[0],
3705 text: text
3706 };
3707 }
3708 };
3709
3710 Tokenizer.prototype.br = function br (src) {
3711 var cap = this.rules.inline.br.exec(src);
3712 if (cap) {
3713 return {
3714 type: 'br',
3715 raw: cap[0]
3716 };
3717 }
3718 };
3719
3720 Tokenizer.prototype.del = function del (src) {
3721 var cap = this.rules.inline.del.exec(src);
3722 if (cap) {
3723 return {
3724 type: 'del',
3725 raw: cap[0],
3726 text: cap[2]
3727 };
3728 }
3729 };
3730
3731 Tokenizer.prototype.autolink = function autolink (src, mangle) {
3732 var cap = this.rules.inline.autolink.exec(src);
3733 if (cap) {
3734 var text, href;
3735 if (cap[2] === '@') {
3736 text = escape$1(this.options.mangle ? mangle(cap[1]) : cap[1]);
3737 href = 'mailto:' + text;
3738 } else {
3739 text = escape$1(cap[1]);
3740 href = text;
3741 }
3742
3743 return {
3744 type: 'link',
3745 raw: cap[0],
3746 text: text,
3747 href: href,
3748 tokens: [
3749 {
3750 type: 'text',
3751 raw: text,
3752 text: text
3753 }
3754 ]
3755 };
3756 }
3757 };
3758
3759 Tokenizer.prototype.url = function url (src, mangle) {
3760 var cap;
3761 if (cap = this.rules.inline.url.exec(src)) {
3762 var text, href;
3763 if (cap[2] === '@') {
3764 text = escape$1(this.options.mangle ? mangle(cap[0]) : cap[0]);
3765 href = 'mailto:' + text;
3766 } else {
3767 // do extended autolink path validation
3768 var prevCapZero;
3769 do {
3770 prevCapZero = cap[0];
3771 cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
3772 } while (prevCapZero !== cap[0]);
3773 text = escape$1(cap[0]);
3774 if (cap[1] === 'www.') {
3775 href = 'http://' + text;
3776 } else {
3777 href = text;
3778 }
3779 }
3780 return {
3781 type: 'link',
3782 raw: cap[0],
3783 text: text,
3784 href: href,
3785 tokens: [
3786 {
3787 type: 'text',
3788 raw: text,
3789 text: text
3790 }
3791 ]
3792 };
3793 }
3794 };
3795
3796 Tokenizer.prototype.inlineText = function inlineText (src, inRawBlock, smartypants) {
3797 var cap = this.rules.inline.text.exec(src);
3798 if (cap) {
3799 var text;
3800 if (inRawBlock) {
3801 text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0];
3802 } else {
3803 text = escape$1(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
3804 }
3805 return {
3806 type: 'text',
3807 raw: cap[0],
3808 text: text
3809 };
3810 }
3811 };
3812
3813 return Tokenizer;
3814 }());
3815
3816 var noopTest$1 = helpers.noopTest;
3817 var edit$1 = helpers.edit;
3818 var merge$2 = helpers.merge;
3819
3820 /**
3821 * Block-Level Grammar
3822 */
3823 var block = {
3824 newline: /^(?: *(?:\n|$))+/,
3825 code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
3826 fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
3827 hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
3828 heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
3829 blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
3830 list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,
3831 html: '^ {0,3}(?:' // optional indentation
3832 + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
3833 + '|comment[^\\n]*(\\n+|$)' // (2)
3834 + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
3835 + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
3836 + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
3837 + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
3838 + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
3839 + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
3840 + ')',
3841 def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
3842 nptable: noopTest$1,
3843 table: noopTest$1,
3844 lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
3845 // regex template, placeholders will be replaced according to different paragraph
3846 // interruption rules of commonmark and the original markdown spec:
3847 _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
3848 text: /^[^\n]+/
3849 };
3850
3851 block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
3852 block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
3853 block.def = edit$1(block.def)
3854 .replace('label', block._label)
3855 .replace('title', block._title)
3856 .getRegex();
3857
3858 block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
3859 block.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/;
3860 block.item = edit$1(block.item, 'gm')
3861 .replace(/bull/g, block.bullet)
3862 .getRegex();
3863
3864 block.listItemStart = edit$1(/^( *)(bull)/)
3865 .replace('bull', block.bullet)
3866 .getRegex();
3867
3868 block.list = edit$1(block.list)
3869 .replace(/bull/g, block.bullet)
3870 .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
3871 .replace('def', '\\n+(?=' + block.def.source + ')')
3872 .getRegex();
3873
3874 block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
3875 + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
3876 + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
3877 + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
3878 + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
3879 + '|track|ul';
3880 block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
3881 block.html = edit$1(block.html, 'i')
3882 .replace('comment', block._comment)
3883 .replace('tag', block._tag)
3884 .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
3885 .getRegex();
3886
3887 block.paragraph = edit$1(block._paragraph)
3888 .replace('hr', block.hr)
3889 .replace('heading', ' {0,3}#{1,6} ')
3890 .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
3891 .replace('blockquote', ' {0,3}>')
3892 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
3893 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
3894 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
3895 .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
3896 .getRegex();
3897
3898 block.blockquote = edit$1(block.blockquote)
3899 .replace('paragraph', block.paragraph)
3900 .getRegex();
3901
3902 /**
3903 * Normal Block Grammar
3904 */
3905
3906 block.normal = merge$2({}, block);
3907
3908 /**
3909 * GFM Block Grammar
3910 */
3911
3912 block.gfm = merge$2({}, block.normal, {
3913 nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
3914 + ' {0,3}([-:]+ *\\|[-| :]*)' // Align
3915 + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells
3916 table: '^ *\\|(.+)\\n' // Header
3917 + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
3918 + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
3919 });
3920
3921 block.gfm.nptable = edit$1(block.gfm.nptable)
3922 .replace('hr', block.hr)
3923 .replace('heading', ' {0,3}#{1,6} ')
3924 .replace('blockquote', ' {0,3}>')
3925 .replace('code', ' {4}[^\\n]')
3926 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
3927 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
3928 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
3929 .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
3930 .getRegex();
3931
3932 block.gfm.table = edit$1(block.gfm.table)
3933 .replace('hr', block.hr)
3934 .replace('heading', ' {0,3}#{1,6} ')
3935 .replace('blockquote', ' {0,3}>')
3936 .replace('code', ' {4}[^\\n]')
3937 .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
3938 .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
3939 .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
3940 .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
3941 .getRegex();
3942
3943 /**
3944 * Pedantic grammar (original John Gruber's loose markdown specification)
3945 */
3946
3947 block.pedantic = merge$2({}, block.normal, {
3948 html: edit$1(
3949 '^ *(?:comment *(?:\\n|\\s*$)'
3950 + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
3951 + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
3952 .replace('comment', block._comment)
3953 .replace(/tag/g, '(?!(?:'
3954 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
3955 + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
3956 + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
3957 .getRegex(),
3958 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
3959 heading: /^(#{1,6})(.*)(?:\n+|$)/,
3960 fences: noopTest$1, // fences not supported
3961 paragraph: edit$1(block.normal._paragraph)
3962 .replace('hr', block.hr)
3963 .replace('heading', ' *#{1,6} *[^\n]')
3964 .replace('lheading', block.lheading)
3965 .replace('blockquote', ' {0,3}>')
3966 .replace('|fences', '')
3967 .replace('|list', '')
3968 .replace('|html', '')
3969 .getRegex()
3970 });
3971
3972 /**
3973 * Inline-Level Grammar
3974 */
3975 var inline = {
3976 escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
3977 autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
3978 url: noopTest$1,
3979 tag: '^comment'
3980 + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
3981 + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
3982 + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
3983 + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
3984 + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
3985 link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
3986 reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
3987 nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
3988 reflinkSearch: 'reflink|nolink(?!\\()',
3989 strong: {
3990 start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
3991 middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
3992 endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
3993 endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
3994 },
3995 em: {
3996 start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
3997 middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
3998 endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
3999 endUnd: /[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
4000 },
4001 code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
4002 br: /^( {2,}|\\)\n(?!\s*$)/,
4003 del: noopTest$1,
4004 text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
4005 punctuation: /^([\s*punctuation])/
4006 };
4007
4008 // list of punctuation marks from common mark spec
4009 // without * and _ to workaround cases with double emphasis
4010 inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
4011 inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
4012
4013 // sequences em should skip over [title](link), `code`, <html>
4014 inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
4015 inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
4016
4017 inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex();
4018
4019 inline.em.start = edit$1(inline.em.start)
4020 .replace(/punctuation/g, inline._punctuation)
4021 .getRegex();
4022
4023 inline.em.middle = edit$1(inline.em.middle)
4024 .replace(/punctuation/g, inline._punctuation)
4025 .replace(/overlapSkip/g, inline._overlapSkip)
4026 .getRegex();
4027
4028 inline.em.endAst = edit$1(inline.em.endAst, 'g')
4029 .replace(/punctuation/g, inline._punctuation)
4030 .getRegex();
4031
4032 inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
4033 .replace(/punctuation/g, inline._punctuation)
4034 .getRegex();
4035
4036 inline.strong.start = edit$1(inline.strong.start)
4037 .replace(/punctuation/g, inline._punctuation)
4038 .getRegex();
4039
4040 inline.strong.middle = edit$1(inline.strong.middle)
4041 .replace(/punctuation/g, inline._punctuation)
4042 .replace(/overlapSkip/g, inline._overlapSkip)
4043 .getRegex();
4044
4045 inline.strong.endAst = edit$1(inline.strong.endAst, 'g')
4046 .replace(/punctuation/g, inline._punctuation)
4047 .getRegex();
4048
4049 inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g')
4050 .replace(/punctuation/g, inline._punctuation)
4051 .getRegex();
4052
4053 inline.blockSkip = edit$1(inline._blockSkip, 'g')
4054 .getRegex();
4055
4056 inline.overlapSkip = edit$1(inline._overlapSkip, 'g')
4057 .getRegex();
4058
4059 inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
4060
4061 inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
4062 inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
4063 inline.autolink = edit$1(inline.autolink)
4064 .replace('scheme', inline._scheme)
4065 .replace('email', inline._email)
4066 .getRegex();
4067
4068 inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
4069
4070 inline.tag = edit$1(inline.tag)
4071 .replace('comment', inline._comment)
4072 .replace('attribute', inline._attribute)
4073 .getRegex();
4074
4075 inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
4076 inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
4077 inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
4078
4079 inline.link = edit$1(inline.link)
4080 .replace('label', inline._label)
4081 .replace('href', inline._href)
4082 .replace('title', inline._title)
4083 .getRegex();
4084
4085 inline.reflink = edit$1(inline.reflink)
4086 .replace('label', inline._label)
4087 .getRegex();
4088
4089 inline.reflinkSearch = edit$1(inline.reflinkSearch, 'g')
4090 .replace('reflink', inline.reflink)
4091 .replace('nolink', inline.nolink)
4092 .getRegex();
4093
4094 /**
4095 * Normal Inline Grammar
4096 */
4097
4098 inline.normal = merge$2({}, inline);
4099
4100 /**
4101 * Pedantic Inline Grammar
4102 */
4103
4104 inline.pedantic = merge$2({}, inline.normal, {
4105 strong: {
4106 start: /^__|\*\*/,
4107 middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
4108 endAst: /\*\*(?!\*)/g,
4109 endUnd: /__(?!_)/g
4110 },
4111 em: {
4112 start: /^_|\*/,
4113 middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
4114 endAst: /\*(?!\*)/g,
4115 endUnd: /_(?!_)/g
4116 },
4117 link: edit$1(/^!?\[(label)\]\((.*?)\)/)
4118 .replace('label', inline._label)
4119 .getRegex(),
4120 reflink: edit$1(/^!?\[(label)\]\s*\[([^\]]*)\]/)
4121 .replace('label', inline._label)
4122 .getRegex()
4123 });
4124
4125 /**
4126 * GFM Inline Grammar
4127 */
4128
4129 inline.gfm = merge$2({}, inline.normal, {
4130 escape: edit$1(inline.escape).replace('])', '~|])').getRegex(),
4131 _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
4132 url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
4133 _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
4134 del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
4135 text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
4136 });
4137
4138 inline.gfm.url = edit$1(inline.gfm.url, 'i')
4139 .replace('email', inline.gfm._extended_email)
4140 .getRegex();
4141 /**
4142 * GFM + Line Breaks Inline Grammar
4143 */
4144
4145 inline.breaks = merge$2({}, inline.gfm, {
4146 br: edit$1(inline.br).replace('{2,}', '*').getRegex(),
4147 text: edit$1(inline.gfm.text)
4148 .replace('\\b_', '\\b_| {2,}\\n')
4149 .replace(/\{2,\}/g, '*')
4150 .getRegex()
4151 });
4152
4153 var rules = {
4154 block: block,
4155 inline: inline
4156 };
4157
4158 var defaults$2 = defaults.defaults;
4159
4160 var block$1 = rules.block;
4161 var inline$1 = rules.inline;
4162
4163 var repeatString$1 = helpers.repeatString;
4164
4165 /**
4166 * smartypants text replacement
4167 */
4168 function smartypants(text) {
4169 return text
4170 // em-dashes
4171 .replace(/---/g, '\u2014')
4172 // en-dashes
4173 .replace(/--/g, '\u2013')
4174 // opening singles
4175 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
4176 // closing singles & apostrophes
4177 .replace(/'/g, '\u2019')
4178 // opening doubles
4179 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
4180 // closing doubles
4181 .replace(/"/g, '\u201d')
4182 // ellipses
4183 .replace(/\.{3}/g, '\u2026');
4184 }
4185
4186 /**
4187 * mangle email addresses
4188 */
4189 function mangle(text) {
4190 var out = '',
4191 i,
4192 ch;
4193
4194 var l = text.length;
4195 for (i = 0; i < l; i++) {
4196 ch = text.charCodeAt(i);
4197 if (Math.random() > 0.5) {
4198 ch = 'x' + ch.toString(16);
4199 }
4200 out += '&#' + ch + ';';
4201 }
4202
4203 return out;
4204 }
4205
4206 /**
4207 * Block Lexer
4208 */
4209 var Lexer = /*@__PURE__*/(function () {
4210 function Lexer(options) {
4211 this.tokens = [];
4212 this.tokens.links = Object.create(null);
4213 this.options = options || defaults$2;
4214 this.options.tokenizer = this.options.tokenizer || new Tokenizer();
4215 this.tokenizer = this.options.tokenizer;
4216 this.tokenizer.options = this.options;
4217
4218 var rules = {
4219 block: block$1.normal,
4220 inline: inline$1.normal
4221 };
4222
4223 if (this.options.pedantic) {
4224 rules.block = block$1.pedantic;
4225 rules.inline = inline$1.pedantic;
4226 } else if (this.options.gfm) {
4227 rules.block = block$1.gfm;
4228 if (this.options.breaks) {
4229 rules.inline = inline$1.breaks;
4230 } else {
4231 rules.inline = inline$1.gfm;
4232 }
4233 }
4234 this.tokenizer.rules = rules;
4235 }
4236
4237 var staticAccessors = { rules: { configurable: true } };
4238
4239 /**
4240 * Expose Rules
4241 */
4242 staticAccessors.rules.get = function () {
4243 return {
4244 block: block$1,
4245 inline: inline$1
4246 };
4247 };
4248
4249 /**
4250 * Static Lex Method
4251 */
4252 Lexer.lex = function lex (src, options) {
4253 var lexer = new Lexer(options);
4254 return lexer.lex(src);
4255 };
4256
4257 /**
4258 * Static Lex Inline Method
4259 */
4260 Lexer.lexInline = function lexInline (src, options) {
4261 var lexer = new Lexer(options);
4262 return lexer.inlineTokens(src);
4263 };
4264
4265 /**
4266 * Preprocessing
4267 */
4268 Lexer.prototype.lex = function lex (src) {
4269 src = src
4270 .replace(/\r\n|\r/g, '\n')
4271 .replace(/\t/g, ' ');
4272
4273 this.blockTokens(src, this.tokens, true);
4274
4275 this.inline(this.tokens);
4276
4277 return this.tokens;
4278 };
4279
4280 /**
4281 * Lexing
4282 */
4283 Lexer.prototype.blockTokens = function blockTokens (src, tokens, top) {
4284 if ( tokens === void 0 ) tokens = [];
4285 if ( top === void 0 ) top = true;
4286
4287 if (this.options.pedantic) {
4288 src = src.replace(/^ +$/gm, '');
4289 }
4290 var token, i, l, lastToken;
4291
4292 while (src) {
4293 // newline
4294 if (token = this.tokenizer.space(src)) {
4295 src = src.substring(token.raw.length);
4296 if (token.type) {
4297 tokens.push(token);
4298 }
4299 continue;
4300 }
4301
4302 // code
4303 if (token = this.tokenizer.code(src, tokens)) {
4304 src = src.substring(token.raw.length);
4305 if (token.type) {
4306 tokens.push(token);
4307 } else {
4308 lastToken = tokens[tokens.length - 1];
4309 lastToken.raw += '\n' + token.raw;
4310 lastToken.text += '\n' + token.text;
4311 }
4312 continue;
4313 }
4314
4315 // fences
4316 if (token = this.tokenizer.fences(src)) {
4317 src = src.substring(token.raw.length);
4318 tokens.push(token);
4319 continue;
4320 }
4321
4322 // heading
4323 if (token = this.tokenizer.heading(src)) {
4324 src = src.substring(token.raw.length);
4325 tokens.push(token);
4326 continue;
4327 }
4328
4329 // table no leading pipe (gfm)
4330 if (token = this.tokenizer.nptable(src)) {
4331 src = src.substring(token.raw.length);
4332 tokens.push(token);
4333 continue;
4334 }
4335
4336 // hr
4337 if (token = this.tokenizer.hr(src)) {
4338 src = src.substring(token.raw.length);
4339 tokens.push(token);
4340 continue;
4341 }
4342
4343 // blockquote
4344 if (token = this.tokenizer.blockquote(src)) {
4345 src = src.substring(token.raw.length);
4346 token.tokens = this.blockTokens(token.text, [], top);
4347 tokens.push(token);
4348 continue;
4349 }
4350
4351 // list
4352 if (token = this.tokenizer.list(src)) {
4353 src = src.substring(token.raw.length);
4354 l = token.items.length;
4355 for (i = 0; i < l; i++) {
4356 token.items[i].tokens = this.blockTokens(token.items[i].text, [], false);
4357 }
4358 tokens.push(token);
4359 continue;
4360 }
4361
4362 // html
4363 if (token = this.tokenizer.html(src)) {
4364 src = src.substring(token.raw.length);
4365 tokens.push(token);
4366 continue;
4367 }
4368
4369 // def
4370 if (top && (token = this.tokenizer.def(src))) {
4371 src = src.substring(token.raw.length);
4372 if (!this.tokens.links[token.tag]) {
4373 this.tokens.links[token.tag] = {
4374 href: token.href,
4375 title: token.title
4376 };
4377 }
4378 continue;
4379 }
4380
4381 // table (gfm)
4382 if (token = this.tokenizer.table(src)) {
4383 src = src.substring(token.raw.length);
4384 tokens.push(token);
4385 continue;
4386 }
4387
4388 // lheading
4389 if (token = this.tokenizer.lheading(src)) {
4390 src = src.substring(token.raw.length);
4391 tokens.push(token);
4392 continue;
4393 }
4394
4395 // top-level paragraph
4396 if (top && (token = this.tokenizer.paragraph(src))) {
4397 src = src.substring(token.raw.length);
4398 tokens.push(token);
4399 continue;
4400 }
4401
4402 // text
4403 if (token = this.tokenizer.text(src, tokens)) {
4404 src = src.substring(token.raw.length);
4405 if (token.type) {
4406 tokens.push(token);
4407 } else {
4408 lastToken = tokens[tokens.length - 1];
4409 lastToken.raw += '\n' + token.raw;
4410 lastToken.text += '\n' + token.text;
4411 }
4412 continue;
4413 }
4414
4415 if (src) {
4416 var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4417 if (this.options.silent) {
4418 console.error(errMsg);
4419 break;
4420 } else {
4421 throw new Error(errMsg);
4422 }
4423 }
4424 }
4425
4426 return tokens;
4427 };
4428
4429 Lexer.prototype.inline = function inline (tokens) {
4430 var i,
4431 j,
4432 k,
4433 l2,
4434 row,
4435 token;
4436
4437 var l = tokens.length;
4438 for (i = 0; i < l; i++) {
4439 token = tokens[i];
4440 switch (token.type) {
4441 case 'paragraph':
4442 case 'text':
4443 case 'heading': {
4444 token.tokens = [];
4445 this.inlineTokens(token.text, token.tokens);
4446 break;
4447 }
4448 case 'table': {
4449 token.tokens = {
4450 header: [],
4451 cells: []
4452 };
4453
4454 // header
4455 l2 = token.header.length;
4456 for (j = 0; j < l2; j++) {
4457 token.tokens.header[j] = [];
4458 this.inlineTokens(token.header[j], token.tokens.header[j]);
4459 }
4460
4461 // cells
4462 l2 = token.cells.length;
4463 for (j = 0; j < l2; j++) {
4464 row = token.cells[j];
4465 token.tokens.cells[j] = [];
4466 for (k = 0; k < row.length; k++) {
4467 token.tokens.cells[j][k] = [];
4468 this.inlineTokens(row[k], token.tokens.cells[j][k]);
4469 }
4470 }
4471
4472 break;
4473 }
4474 case 'blockquote': {
4475 this.inline(token.tokens);
4476 break;
4477 }
4478 case 'list': {
4479 l2 = token.items.length;
4480 for (j = 0; j < l2; j++) {
4481 this.inline(token.items[j].tokens);
4482 }
4483 break;
4484 }
4485 }
4486 }
4487
4488 return tokens;
4489 };
4490
4491 /**
4492 * Lexing/Compiling
4493 */
4494 Lexer.prototype.inlineTokens = function inlineTokens (src, tokens, inLink, inRawBlock) {
4495 if ( tokens === void 0 ) tokens = [];
4496 if ( inLink === void 0 ) inLink = false;
4497 if ( inRawBlock === void 0 ) inRawBlock = false;
4498
4499 var token;
4500
4501 // String with links masked to avoid interference with em and strong
4502 var maskedSrc = src;
4503 var match;
4504 var keepPrevChar, prevChar;
4505
4506 // Mask out reflinks
4507 if (this.tokens.links) {
4508 var links = Object.keys(this.tokens.links);
4509 if (links.length > 0) {
4510 while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
4511 if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
4512 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
4513 }
4514 }
4515 }
4516 }
4517 // Mask out other blocks
4518 while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
4519 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
4520 }
4521
4522 while (src) {
4523 if (!keepPrevChar) {
4524 prevChar = '';
4525 }
4526 keepPrevChar = false;
4527 // escape
4528 if (token = this.tokenizer.escape(src)) {
4529 src = src.substring(token.raw.length);
4530 tokens.push(token);
4531 continue;
4532 }
4533
4534 // tag
4535 if (token = this.tokenizer.tag(src, inLink, inRawBlock)) {
4536 src = src.substring(token.raw.length);
4537 inLink = token.inLink;
4538 inRawBlock = token.inRawBlock;
4539 tokens.push(token);
4540 continue;
4541 }
4542
4543 // link
4544 if (token = this.tokenizer.link(src)) {
4545 src = src.substring(token.raw.length);
4546 if (token.type === 'link') {
4547 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
4548 }
4549 tokens.push(token);
4550 continue;
4551 }
4552
4553 // reflink, nolink
4554 if (token = this.tokenizer.reflink(src, this.tokens.links)) {
4555 src = src.substring(token.raw.length);
4556 if (token.type === 'link') {
4557 token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
4558 }
4559 tokens.push(token);
4560 continue;
4561 }
4562
4563 // strong
4564 if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
4565 src = src.substring(token.raw.length);
4566 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
4567 tokens.push(token);
4568 continue;
4569 }
4570
4571 // em
4572 if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
4573 src = src.substring(token.raw.length);
4574 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
4575 tokens.push(token);
4576 continue;
4577 }
4578
4579 // code
4580 if (token = this.tokenizer.codespan(src)) {
4581 src = src.substring(token.raw.length);
4582 tokens.push(token);
4583 continue;
4584 }
4585
4586 // br
4587 if (token = this.tokenizer.br(src)) {
4588 src = src.substring(token.raw.length);
4589 tokens.push(token);
4590 continue;
4591 }
4592
4593 // del (gfm)
4594 if (token = this.tokenizer.del(src)) {
4595 src = src.substring(token.raw.length);
4596 token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
4597 tokens.push(token);
4598 continue;
4599 }
4600
4601 // autolink
4602 if (token = this.tokenizer.autolink(src, mangle)) {
4603 src = src.substring(token.raw.length);
4604 tokens.push(token);
4605 continue;
4606 }
4607
4608 // url (gfm)
4609 if (!inLink && (token = this.tokenizer.url(src, mangle))) {
4610 src = src.substring(token.raw.length);
4611 tokens.push(token);
4612 continue;
4613 }
4614
4615 // text
4616 if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
4617 src = src.substring(token.raw.length);
4618 prevChar = token.raw.slice(-1);
4619 keepPrevChar = true;
4620 tokens.push(token);
4621 continue;
4622 }
4623
4624 if (src) {
4625 var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4626 if (this.options.silent) {
4627 console.error(errMsg);
4628 break;
4629 } else {
4630 throw new Error(errMsg);
4631 }
4632 }
4633 }
4634
4635 return tokens;
4636 };
4637
4638 Object.defineProperties( Lexer, staticAccessors );
4639
4640 return Lexer;
4641 }());
4642
4643 var defaults$3 = defaults.defaults;
4644
4645 var cleanUrl$1 = helpers.cleanUrl;
4646 var escape$2 = helpers.escape;
4647
4648 /**
4649 * Renderer
4650 */
4651 var Renderer = /*@__PURE__*/(function () {
4652 function Renderer(options) {
4653 this.options = options || defaults$3;
4654 }
4655
4656 Renderer.prototype.code = function code (code$1, infostring, escaped) {
4657 var lang = (infostring || '').match(/\S*/)[0];
4658 if (this.options.highlight) {
4659 var out = this.options.highlight(code$1, lang);
4660 if (out != null && out !== code$1) {
4661 escaped = true;
4662 code$1 = out;
4663 }
4664 }
4665
4666 code$1 = code$1.replace(/\n$/, '') + '\n';
4667
4668 if (!lang) {
4669 return '<pre><code>'
4670 + (escaped ? code$1 : escape$2(code$1, true))
4671 + '</code></pre>\n';
4672 }
4673
4674 return '<pre><code class="'
4675 + this.options.langPrefix
4676 + escape$2(lang, true)
4677 + '">'
4678 + (escaped ? code$1 : escape$2(code$1, true))
4679 + '</code></pre>\n';
4680 };
4681
4682 Renderer.prototype.blockquote = function blockquote (quote) {
4683 return '<blockquote>\n' + quote + '</blockquote>\n';
4684 };
4685
4686 Renderer.prototype.html = function html (html$1) {
4687 return html$1;
4688 };
4689
4690 Renderer.prototype.heading = function heading (text, level, raw, slugger) {
4691 if (this.options.headerIds) {
4692 return '<h'
4693 + level
4694 + ' id="'
4695 + this.options.headerPrefix
4696 + slugger.slug(raw)
4697 + '">'
4698 + text
4699 + '</h'
4700 + level
4701 + '>\n';
4702 }
4703 // ignore IDs
4704 return '<h' + level + '>' + text + '</h' + level + '>\n';
4705 };
4706
4707 Renderer.prototype.hr = function hr () {
4708 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
4709 };
4710
4711 Renderer.prototype.list = function list (body, ordered, start) {
4712 var type = ordered ? 'ol' : 'ul',
4713 startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
4714 return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
4715 };
4716
4717 Renderer.prototype.listitem = function listitem (text) {
4718 return '<li>' + text + '</li>\n';
4719 };
4720
4721 Renderer.prototype.checkbox = function checkbox (checked) {
4722 return '<input '
4723 + (checked ? 'checked="" ' : '')
4724 + 'disabled="" type="checkbox"'
4725 + (this.options.xhtml ? ' /' : '')
4726 + '> ';
4727 };
4728
4729 Renderer.prototype.paragraph = function paragraph (text) {
4730 return '<p>' + text + '</p>\n';
4731 };
4732
4733 Renderer.prototype.table = function table (header, body) {
4734 if (body) { body = '<tbody>' + body + '</tbody>'; }
4735
4736 return '<table>\n'
4737 + '<thead>\n'
4738 + header
4739 + '</thead>\n'
4740 + body
4741 + '</table>\n';
4742 };
4743
4744 Renderer.prototype.tablerow = function tablerow (content) {
4745 return '<tr>\n' + content + '</tr>\n';
4746 };
4747
4748 Renderer.prototype.tablecell = function tablecell (content, flags) {
4749 var type = flags.header ? 'th' : 'td';
4750 var tag = flags.align
4751 ? '<' + type + ' align="' + flags.align + '">'
4752 : '<' + type + '>';
4753 return tag + content + '</' + type + '>\n';
4754 };
4755
4756 // span level renderer
4757 Renderer.prototype.strong = function strong (text) {
4758 return '<strong>' + text + '</strong>';
4759 };
4760
4761 Renderer.prototype.em = function em (text) {
4762 return '<em>' + text + '</em>';
4763 };
4764
4765 Renderer.prototype.codespan = function codespan (text) {
4766 return '<code>' + text + '</code>';
4767 };
4768
4769 Renderer.prototype.br = function br () {
4770 return this.options.xhtml ? '<br/>' : '<br>';
4771 };
4772
4773 Renderer.prototype.del = function del (text) {
4774 return '<del>' + text + '</del>';
4775 };
4776
4777 Renderer.prototype.link = function link (href, title, text) {
4778 href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href);
4779 if (href === null) {
4780 return text;
4781 }
4782 var out = '<a href="' + escape$2(href) + '"';
4783 if (title) {
4784 out += ' title="' + title + '"';
4785 }
4786 out += '>' + text + '</a>';
4787 return out;
4788 };
4789
4790 Renderer.prototype.image = function image (href, title, text) {
4791 href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href);
4792 if (href === null) {
4793 return text;
4794 }
4795
4796 var out = '<img src="' + href + '" alt="' + text + '"';
4797 if (title) {
4798 out += ' title="' + title + '"';
4799 }
4800 out += this.options.xhtml ? '/>' : '>';
4801 return out;
4802 };
4803
4804 Renderer.prototype.text = function text (text$1) {
4805 return text$1;
4806 };
4807
4808 return Renderer;
4809 }());
4810
4811 /**
4812 * TextRenderer
4813 * returns only the textual part of the token
4814 */
4815 var TextRenderer = /*@__PURE__*/(function () {
4816 function TextRenderer () {}
4817
4818 TextRenderer.prototype.strong = function strong (text) {
4819 return text;
4820 };
4821
4822 TextRenderer.prototype.em = function em (text) {
4823 return text;
4824 };
4825
4826 TextRenderer.prototype.codespan = function codespan (text) {
4827 return text;
4828 };
4829
4830 TextRenderer.prototype.del = function del (text) {
4831 return text;
4832 };
4833
4834 TextRenderer.prototype.html = function html (text) {
4835 return text;
4836 };
4837
4838 TextRenderer.prototype.text = function text (text$1) {
4839 return text$1;
4840 };
4841
4842 TextRenderer.prototype.link = function link (href, title, text) {
4843 return '' + text;
4844 };
4845
4846 TextRenderer.prototype.image = function image (href, title, text) {
4847 return '' + text;
4848 };
4849
4850 TextRenderer.prototype.br = function br () {
4851 return '';
4852 };
4853
4854 return TextRenderer;
4855 }());
4856
4857 /**
4858 * Slugger generates header id
4859 */
4860 var Slugger = /*@__PURE__*/(function () {
4861 function Slugger() {
4862 this.seen = {};
4863 }
4864
4865 Slugger.prototype.serialize = function serialize (value) {
4866 return value
4867 .toLowerCase()
4868 .trim()
4869 // remove html tags
4870 .replace(/<[!\/a-z].*?>/ig, '')
4871 // remove unwanted chars
4872 .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
4873 .replace(/\s/g, '-');
4874 };
4875
4876 /**
4877 * Finds the next safe (unique) slug to use
4878 */
4879 Slugger.prototype.getNextSafeSlug = function getNextSafeSlug (originalSlug, isDryRun) {
4880 var slug = originalSlug;
4881 var occurenceAccumulator = 0;
4882 if (this.seen.hasOwnProperty(slug)) {
4883 occurenceAccumulator = this.seen[originalSlug];
4884 do {
4885 occurenceAccumulator++;
4886 slug = originalSlug + '-' + occurenceAccumulator;
4887 } while (this.seen.hasOwnProperty(slug));
4888 }
4889 if (!isDryRun) {
4890 this.seen[originalSlug] = occurenceAccumulator;
4891 this.seen[slug] = 0;
4892 }
4893 return slug;
4894 };
4895
4896 /**
4897 * Convert string to unique id
4898 * @param {object} options
4899 * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
4900 */
4901 Slugger.prototype.slug = function slug (value, options) {
4902 if ( options === void 0 ) options = {};
4903
4904 var slug = this.serialize(value);
4905 return this.getNextSafeSlug(slug, options.dryrun);
4906 };
4907
4908 return Slugger;
4909 }());
4910
4911 var defaults$4 = defaults.defaults;
4912
4913 var unescape$1 = helpers.unescape;
4914
4915 /**
4916 * Parsing & Compiling
4917 */
4918 var Parser = /*@__PURE__*/(function () {
4919 function Parser(options) {
4920 this.options = options || defaults$4;
4921 this.options.renderer = this.options.renderer || new Renderer();
4922 this.renderer = this.options.renderer;
4923 this.renderer.options = this.options;
4924 this.textRenderer = new TextRenderer();
4925 this.slugger = new Slugger();
4926 }
4927
4928 /**
4929 * Static Parse Method
4930 */
4931 Parser.parse = function parse (tokens, options) {
4932 var parser = new Parser(options);
4933 return parser.parse(tokens);
4934 };
4935
4936 /**
4937 * Static Parse Inline Method
4938 */
4939 Parser.parseInline = function parseInline (tokens, options) {
4940 var parser = new Parser(options);
4941 return parser.parseInline(tokens);
4942 };
4943
4944 /**
4945 * Parse Loop
4946 */
4947 Parser.prototype.parse = function parse (tokens, top) {
4948 if ( top === void 0 ) top = true;
4949
4950 var out = '',
4951 i,
4952 j,
4953 k,
4954 l2,
4955 l3,
4956 row,
4957 cell,
4958 header,
4959 body,
4960 token,
4961 ordered,
4962 start,
4963 loose,
4964 itemBody,
4965 item,
4966 checked,
4967 task,
4968 checkbox;
4969
4970 var l = tokens.length;
4971 for (i = 0; i < l; i++) {
4972 token = tokens[i];
4973 switch (token.type) {
4974 case 'space': {
4975 continue;
4976 }
4977 case 'hr': {
4978 out += this.renderer.hr();
4979 continue;
4980 }
4981 case 'heading': {
4982 out += this.renderer.heading(
4983 this.parseInline(token.tokens),
4984 token.depth,
4985 unescape$1(this.parseInline(token.tokens, this.textRenderer)),
4986 this.slugger);
4987 continue;
4988 }
4989 case 'code': {
4990 out += this.renderer.code(token.text,
4991 token.lang,
4992 token.escaped);
4993 continue;
4994 }
4995 case 'table': {
4996 header = '';
4997
4998 // header
4999 cell = '';
5000 l2 = token.header.length;
5001 for (j = 0; j < l2; j++) {
5002 cell += this.renderer.tablecell(
5003 this.parseInline(token.tokens.header[j]),
5004 { header: true, align: token.align[j] }
5005 );
5006 }
5007 header += this.renderer.tablerow(cell);
5008
5009 body = '';
5010 l2 = token.cells.length;
5011 for (j = 0; j < l2; j++) {
5012 row = token.tokens.cells[j];
5013
5014 cell = '';
5015 l3 = row.length;
5016 for (k = 0; k < l3; k++) {
5017 cell += this.renderer.tablecell(
5018 this.parseInline(row[k]),
5019 { header: false, align: token.align[k] }
5020 );
5021 }
5022
5023 body += this.renderer.tablerow(cell);
5024 }
5025 out += this.renderer.table(header, body);
5026 continue;
5027 }
5028 case 'blockquote': {
5029 body = this.parse(token.tokens);
5030 out += this.renderer.blockquote(body);
5031 continue;
5032 }
5033 case 'list': {
5034 ordered = token.ordered;
5035 start = token.start;
5036 loose = token.loose;
5037 l2 = token.items.length;
5038
5039 body = '';
5040 for (j = 0; j < l2; j++) {
5041 item = token.items[j];
5042 checked = item.checked;
5043 task = item.task;
5044
5045 itemBody = '';
5046 if (item.task) {
5047 checkbox = this.renderer.checkbox(checked);
5048 if (loose) {
5049 if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
5050 item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
5051 if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
5052 item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
5053 }
5054 } else {
5055 item.tokens.unshift({
5056 type: 'text',
5057 text: checkbox
5058 });
5059 }
5060 } else {
5061 itemBody += checkbox;
5062 }
5063 }
5064
5065 itemBody += this.parse(item.tokens, loose);
5066 body += this.renderer.listitem(itemBody, task, checked);
5067 }
5068
5069 out += this.renderer.list(body, ordered, start);
5070 continue;
5071 }
5072 case 'html': {
5073 // TODO parse inline content if parameter markdown=1
5074 out += this.renderer.html(token.text);
5075 continue;
5076 }
5077 case 'paragraph': {
5078 out += this.renderer.paragraph(this.parseInline(token.tokens));
5079 continue;
5080 }
5081 case 'text': {
5082 body = token.tokens ? this.parseInline(token.tokens) : token.text;
5083 while (i + 1 < l && tokens[i + 1].type === 'text') {
5084 token = tokens[++i];
5085 body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
5086 }
5087 out += top ? this.renderer.paragraph(body) : body;
5088 continue;
5089 }
5090 default: {
5091 var errMsg = 'Token with "' + token.type + '" type was not found.';
5092 if (this.options.silent) {
5093 console.error(errMsg);
5094 return;
5095 } else {
5096 throw new Error(errMsg);
5097 }
5098 }
5099 }
5100 }
5101
5102 return out;
5103 };
5104
5105 /**
5106 * Parse Inline Tokens
5107 */
5108 Parser.prototype.parseInline = function parseInline (tokens, renderer) {
5109 renderer = renderer || this.renderer;
5110 var out = '',
5111 i,
5112 token;
5113
5114 var l = tokens.length;
5115 for (i = 0; i < l; i++) {
5116 token = tokens[i];
5117 switch (token.type) {
5118 case 'escape': {
5119 out += renderer.text(token.text);
5120 break;
5121 }
5122 case 'html': {
5123 out += renderer.html(token.text);
5124 break;
5125 }
5126 case 'link': {
5127 out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
5128 break;
5129 }
5130 case 'image': {
5131 out += renderer.image(token.href, token.title, token.text);
5132 break;
5133 }
5134 case 'strong': {
5135 out += renderer.strong(this.parseInline(token.tokens, renderer));
5136 break;
5137 }
5138 case 'em': {
5139 out += renderer.em(this.parseInline(token.tokens, renderer));
5140 break;
5141 }
5142 case 'codespan': {
5143 out += renderer.codespan(token.text);
5144 break;
5145 }
5146 case 'br': {
5147 out += renderer.br();
5148 break;
5149 }
5150 case 'del': {
5151 out += renderer.del(this.parseInline(token.tokens, renderer));
5152 break;
5153 }
5154 case 'text': {
5155 out += renderer.text(token.text);
5156 break;
5157 }
5158 default: {
5159 var errMsg = 'Token with "' + token.type + '" type was not found.';
5160 if (this.options.silent) {
5161 console.error(errMsg);
5162 return;
5163 } else {
5164 throw new Error(errMsg);
5165 }
5166 }
5167 }
5168 }
5169 return out;
5170 };
5171
5172 return Parser;
5173 }());
5174
5175 var merge$3 = helpers.merge;
5176 var checkSanitizeDeprecation$1 = helpers.checkSanitizeDeprecation;
5177 var escape$3 = helpers.escape;
5178
5179 var getDefaults = defaults.getDefaults;
5180 var changeDefaults = defaults.changeDefaults;
5181 var defaults$5 = defaults.defaults;
5182
5183 /**
5184 * Marked
5185 */
5186 function marked(src, opt, callback) {
5187 // throw error in case of non string input
5188 if (typeof src === 'undefined' || src === null) {
5189 throw new Error('marked(): input parameter is undefined or null');
5190 }
5191 if (typeof src !== 'string') {
5192 throw new Error('marked(): input parameter is of type '
5193 + Object.prototype.toString.call(src) + ', string expected');
5194 }
5195
5196 if (typeof opt === 'function') {
5197 callback = opt;
5198 opt = null;
5199 }
5200
5201 opt = merge$3({}, marked.defaults, opt || {});
5202 checkSanitizeDeprecation$1(opt);
5203
5204 if (callback) {
5205 var highlight = opt.highlight;
5206 var tokens;
5207
5208 try {
5209 tokens = Lexer.lex(src, opt);
5210 } catch (e) {
5211 return callback(e);
5212 }
5213
5214 var done = function(err) {
5215 var out;
5216
5217 if (!err) {
5218 try {
5219 out = Parser.parse(tokens, opt);
5220 } catch (e) {
5221 err = e;
5222 }
5223 }
5224
5225 opt.highlight = highlight;
5226
5227 return err
5228 ? callback(err)
5229 : callback(null, out);
5230 };
5231
5232 if (!highlight || highlight.length < 3) {
5233 return done();
5234 }
5235
5236 delete opt.highlight;
5237
5238 if (!tokens.length) { return done(); }
5239
5240 var pending = 0;
5241 marked.walkTokens(tokens, function(token) {
5242 if (token.type === 'code') {
5243 pending++;
5244 setTimeout(function () {
5245 highlight(token.text, token.lang, function(err, code) {
5246 if (err) {
5247 return done(err);
5248 }
5249 if (code != null && code !== token.text) {
5250 token.text = code;
5251 token.escaped = true;
5252 }
5253
5254 pending--;
5255 if (pending === 0) {
5256 done();
5257 }
5258 });
5259 }, 0);
5260 }
5261 });
5262
5263 if (pending === 0) {
5264 done();
5265 }
5266
5267 return;
5268 }
5269
5270 try {
5271 var tokens$1 = Lexer.lex(src, opt);
5272 if (opt.walkTokens) {
5273 marked.walkTokens(tokens$1, opt.walkTokens);
5274 }
5275 return Parser.parse(tokens$1, opt);
5276 } catch (e) {
5277 e.message += '\nPlease report this to https://github.com/markedjs/marked.';
5278 if (opt.silent) {
5279 return '<p>An error occurred:</p><pre>'
5280 + escape$3(e.message + '', true)
5281 + '</pre>';
5282 }
5283 throw e;
5284 }
5285 }
5286
5287 /**
5288 * Options
5289 */
5290
5291 marked.options =
5292 marked.setOptions = function(opt) {
5293 merge$3(marked.defaults, opt);
5294 changeDefaults(marked.defaults);
5295 return marked;
5296 };
5297
5298 marked.getDefaults = getDefaults;
5299
5300 marked.defaults = defaults$5;
5301
5302 /**
5303 * Use Extension
5304 */
5305
5306 marked.use = function(extension) {
5307 var opts = merge$3({}, extension);
5308 if (extension.renderer) {
5309 var renderer = marked.defaults.renderer || new Renderer();
5310 var loop = function ( prop ) {
5311 var prevRenderer = renderer[prop];
5312 renderer[prop] = function () {
5313 var args = [], len = arguments.length;
5314 while ( len-- ) args[ len ] = arguments[ len ];
5315
5316 var ret = extension.renderer[prop].apply(renderer, args);
5317 if (ret === false) {
5318 ret = prevRenderer.apply(renderer, args);
5319 }
5320 return ret;
5321 };
5322 };
5323
5324 for (var prop in extension.renderer) loop( prop );
5325 opts.renderer = renderer;
5326 }
5327 if (extension.tokenizer) {
5328 var tokenizer = marked.defaults.tokenizer || new Tokenizer();
5329 var loop$1 = function ( prop ) {
5330 var prevTokenizer = tokenizer[prop$1];
5331 tokenizer[prop$1] = function () {
5332 var args = [], len = arguments.length;
5333 while ( len-- ) args[ len ] = arguments[ len ];
5334
5335 var ret = extension.tokenizer[prop$1].apply(tokenizer, args);
5336 if (ret === false) {
5337 ret = prevTokenizer.apply(tokenizer, args);
5338 }
5339 return ret;
5340 };
5341 };
5342
5343 for (var prop$1 in extension.tokenizer) loop$1( prop );
5344 opts.tokenizer = tokenizer;
5345 }
5346 if (extension.walkTokens) {
5347 var walkTokens = marked.defaults.walkTokens;
5348 opts.walkTokens = function (token) {
5349 extension.walkTokens(token);
5350 if (walkTokens) {
5351 walkTokens(token);
5352 }
5353 };
5354 }
5355 marked.setOptions(opts);
5356 };
5357
5358 /**
5359 * Run callback for every token
5360 */
5361
5362 marked.walkTokens = function(tokens, callback) {
5363 for (var i$3 = 0, list$3 = tokens; i$3 < list$3.length; i$3 += 1) {
5364 var token = list$3[i$3];
5365
5366 callback(token);
5367 switch (token.type) {
5368 case 'table': {
5369 for (var i = 0, list = token.tokens.header; i < list.length; i += 1) {
5370 var cell = list[i];
5371
5372 marked.walkTokens(cell, callback);
5373 }
5374 for (var i$2 = 0, list$2 = token.tokens.cells; i$2 < list$2.length; i$2 += 1) {
5375 var row = list$2[i$2];
5376
5377 for (var i$1 = 0, list$1 = row; i$1 < list$1.length; i$1 += 1) {
5378 var cell$1 = list$1[i$1];
5379
5380 marked.walkTokens(cell$1, callback);
5381 }
5382 }
5383 break;
5384 }
5385 case 'list': {
5386 marked.walkTokens(token.items, callback);
5387 break;
5388 }
5389 default: {
5390 if (token.tokens) {
5391 marked.walkTokens(token.tokens, callback);
5392 }
5393 }
5394 }
5395 }
5396 };
5397
5398 /**
5399 * Parse Inline
5400 */
5401 marked.parseInline = function(src, opt) {
5402 // throw error in case of non string input
5403 if (typeof src === 'undefined' || src === null) {
5404 throw new Error('marked.parseInline(): input parameter is undefined or null');
5405 }
5406 if (typeof src !== 'string') {
5407 throw new Error('marked.parseInline(): input parameter is of type '
5408 + Object.prototype.toString.call(src) + ', string expected');
5409 }
5410
5411 opt = merge$3({}, marked.defaults, opt || {});
5412 checkSanitizeDeprecation$1(opt);
5413
5414 try {
5415 var tokens = Lexer.lexInline(src, opt);
5416 if (opt.walkTokens) {
5417 marked.walkTokens(tokens, opt.walkTokens);
5418 }
5419 return Parser.parseInline(tokens, opt);
5420 } catch (e) {
5421 e.message += '\nPlease report this to https://github.com/markedjs/marked.';
5422 if (opt.silent) {
5423 return '<p>An error occurred:</p><pre>'
5424 + escape$3(e.message + '', true)
5425 + '</pre>';
5426 }
5427 throw e;
5428 }
5429 };
5430
5431 /**
5432 * Expose
5433 */
5434
5435 marked.Parser = Parser;
5436 marked.parser = Parser.parse;
5437
5438 marked.Renderer = Renderer;
5439 marked.TextRenderer = TextRenderer;
5440
5441 marked.Lexer = Lexer;
5442 marked.lexer = Lexer.lex;
5443
5444 marked.Tokenizer = Tokenizer;
5445
5446 marked.Slugger = Slugger;
5447
5448 marked.parse = marked;
5449
5450 var marked_1 = marked;
5451
5452 /**
5453 * Render github corner
5454 * @param {Object} data URL for the View Source on Github link
5455 * @param {String} cornerExternalLinkTarge value of the target attribute of the link
5456 * @return {String} SVG element as string
5457 */
5458 function corner(data, cornerExternalLinkTarge) {
5459 if (!data) {
5460 return '';
5461 }
5462
5463 if (!/\/\//.test(data)) {
5464 data = 'https://github.com/' + data;
5465 }
5466
5467 data = data.replace(/^git\+/, '');
5468 // Double check
5469 cornerExternalLinkTarge = cornerExternalLinkTarge || '_blank';
5470
5471 return (
5472 "<a href=\"" + data + "\" target=\"" + cornerExternalLinkTarge + "\" class=\"github-corner\" aria-label=\"View source on Github\">" +
5473 '<svg viewBox="0 0 250 250" aria-hidden="true">' +
5474 '<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>' +
5475 '<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>' +
5476 '<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>' +
5477 '</svg>' +
5478 '</a>'
5479 );
5480 }
5481
5482 /**
5483 * Renders main content
5484 * @param {Object} config Configuration object
5485 * @returns {String} HTML of the main content
5486 */
5487 function main(config) {
5488 var name = config.name ? config.name : '';
5489
5490 var aside =
5491 '<button class="sidebar-toggle" aria-label="Menu">' +
5492 '<div class="sidebar-toggle-button">' +
5493 '<span></span><span></span><span></span>' +
5494 '</div>' +
5495 '</button>' +
5496 '<aside class="sidebar">' +
5497 (config.name
5498 ? ("<h1 class=\"app-name\"><a class=\"app-name-link\" data-nosearch>" + (config.logo ? ("<img alt=\"" + name + "\" src=" + (config.logo) + ">") : name) + "</a></h1>")
5499 : '') +
5500 '<div class="sidebar-nav"><!--sidebar--></div>' +
5501 '</aside>';
5502 return (
5503 "<main>" + aside +
5504 '<section class="content">' +
5505 '<article class="markdown-section" id="main"><!--main--></article>' +
5506 '</section>' +
5507 '</main>'
5508 );
5509 }
5510
5511 /**
5512 * Cover Page
5513 * @returns {String} Cover page
5514 */
5515 function cover() {
5516 var SL = ', 100%, 85%';
5517 var bgc =
5518 'linear-gradient(to left bottom, ' +
5519 "hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 0%," +
5520 "hsl(" + (Math.floor(Math.random() * 255) + SL) + ") 100%)";
5521
5522 return (
5523 "<section class=\"cover show\" style=\"background: " + bgc + "\">" +
5524 '<div class="mask"></div>' +
5525 '<div class="cover-main"><!--cover--></div>' +
5526 '</section>'
5527 );
5528 }
5529
5530 /**
5531 * Render tree
5532 * @param {Array} toc Array of TOC section links
5533 * @param {String} tpl TPL list
5534 * @return {String} Rendered tree
5535 */
5536 function tree(toc, tpl) {
5537 if ( tpl === void 0 ) tpl = '<ul class="app-sub-sidebar">{inner}</ul>';
5538
5539 if (!toc || !toc.length) {
5540 return '';
5541 }
5542
5543 var innerHTML = '';
5544 toc.forEach(function (node) {
5545 var title = node.title.replace(/(<([^>]+)>)/g, '');
5546 innerHTML += "<li><a class=\"section-link\" href=\"" + (node.slug) + "\" title=\"" + title + "\">" + (node.title) + "</a></li>";
5547 if (node.children) {
5548 innerHTML += tree(node.children, tpl);
5549 }
5550 });
5551 return tpl.replace('{inner}', innerHTML);
5552 }
5553
5554 function helper(className, content) {
5555 return ("<p class=\"" + className + "\">" + (content.slice(5).trim()) + "</p>");
5556 }
5557
5558 function theme(color) {
5559 return ("<style>:root{--theme-color: " + color + ";}</style>");
5560 }
5561
5562 /**
5563 * Gen toc tree
5564 * @link https://github.com/killercup/grock/blob/5280ae63e16c5739e9233d9009bc235ed7d79a50/styles/solarized/assets/js/behavior.coffee#L54-L81
5565 * @param {Array} toc List of TOC elements
5566 * @param {Number} maxLevel Deep level
5567 * @return {Array} Headlines
5568 */
5569 function genTree(toc, maxLevel) {
5570 var headlines = [];
5571 var last = {};
5572
5573 toc.forEach(function (headline) {
5574 var level = headline.level || 1;
5575 var len = level - 1;
5576
5577 if (level > maxLevel) {
5578 return;
5579 }
5580
5581 if (last[len]) {
5582 last[len].children = (last[len].children || []).concat(headline);
5583 } else {
5584 headlines.push(headline);
5585 }
5586
5587 last[level] = headline;
5588 });
5589
5590 return headlines;
5591 }
5592
5593 var cache$1 = {};
5594 var re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g;
5595
5596 function lower(string) {
5597 return string.toLowerCase();
5598 }
5599
5600 function slugify(str) {
5601 if (typeof str !== 'string') {
5602 return '';
5603 }
5604
5605 var slug = str
5606 .trim()
5607 .replace(/[A-Z]+/g, lower)
5608 .replace(/<[^>]+>/g, '')
5609 .replace(re, '')
5610 .replace(/\s/g, '-')
5611 .replace(/-+/g, '-')
5612 .replace(/^(\d)/, '_$1');
5613 var count = cache$1[slug];
5614
5615 count = hasOwn.call(cache$1, slug) ? count + 1 : 0;
5616 cache$1[slug] = count;
5617
5618 if (count) {
5619 slug = slug + '-' + count;
5620 }
5621
5622 return slug;
5623 }
5624
5625 slugify.clear = function() {
5626 cache$1 = {};
5627 };
5628
5629 function replace(m, $1) {
5630 return (
5631 '<img class="emoji" src="https://github.githubassets.com/images/icons/emoji/' +
5632 $1 +
5633 '.png" alt="' +
5634 $1 +
5635 '" />'
5636 );
5637 }
5638
5639 function emojify(text) {
5640 return text
5641 .replace(/:\+1:/g, ':thumbsup:')
5642 .replace(/:-1:/g, ':thumbsdown:')
5643 .replace(/<(pre|template|code)[^>]*?>[\s\S]+?<\/(pre|template|code)>/g, function (m) { return m.replace(/:/g, '__colon__'); }
5644 )
5645 .replace(/:(\w+?):/gi, ( window.emojify) || replace)
5646 .replace(/__colon__/g, ':');
5647 }
5648
5649 /**
5650 * Converts a colon formatted string to a object with properties.
5651 *
5652 * This is process a provided string and look for any tokens in the format
5653 * of `:name[=value]` and then convert it to a object and return.
5654 * An example of this is ':include :type=code :fragment=demo' is taken and
5655 * then converted to:
5656 *
5657 * ```
5658 * {
5659 * include: '',
5660 * type: 'code',
5661 * fragment: 'demo'
5662 * }
5663 * ```
5664 *
5665 * @param {string} str The string to parse.
5666 *
5667 * @return {object} The original string and parsed object, { str, config }.
5668 */
5669 function getAndRemoveConfig(str) {
5670 if ( str === void 0 ) str = '';
5671
5672 var config = {};
5673
5674 if (str) {
5675 str = str
5676 .replace(/^('|")/, '')
5677 .replace(/('|")$/, '')
5678 .replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g, function (m, key, value) {
5679 if (key.indexOf(':') === -1) {
5680 config[key] = (value && value.replace(/&quot;/g, '')) || true;
5681 return '';
5682 }
5683
5684 return m;
5685 })
5686 .trim();
5687 }
5688
5689 return { str: str, config: config };
5690 }
5691
5692 /**
5693 * Remove the <a> tag from sidebar when the header with link, details see issue 1069
5694 * @param {string} str The string to deal with.
5695 *
5696 * @return {string} str The string after delete the <a> element.
5697 */
5698 function removeAtag(str) {
5699 if ( str === void 0 ) str = '';
5700
5701 return str.replace(/(<\/?a.*?>)/gi, '');
5702 }
5703
5704 var imageCompiler = function (ref) {
5705 var renderer = ref.renderer;
5706 var contentBase = ref.contentBase;
5707 var router = ref.router;
5708
5709 return (renderer.image = function (href, title, text) {
5710 var url = href;
5711 var attrs = [];
5712
5713 var ref = getAndRemoveConfig(title);
5714 var str = ref.str;
5715 var config = ref.config;
5716 title = str;
5717
5718 if (config['no-zoom']) {
5719 attrs.push('data-no-zoom');
5720 }
5721
5722 if (title) {
5723 attrs.push(("title=\"" + title + "\""));
5724 }
5725
5726 if (config.size) {
5727 var ref$1 = config.size.split('x');
5728 var width = ref$1[0];
5729 var height = ref$1[1];
5730 if (height) {
5731 attrs.push(("width=\"" + width + "\" height=\"" + height + "\""));
5732 } else {
5733 attrs.push(("width=\"" + width + "\""));
5734 }
5735 }
5736
5737 if (config.class) {
5738 attrs.push(("class=\"" + (config.class) + "\""));
5739 }
5740
5741 if (config.id) {
5742 attrs.push(("id=\"" + (config.id) + "\""));
5743 }
5744
5745 if (!isAbsolutePath(href)) {
5746 url = getPath(contentBase, getParentPath(router.getCurrentPath()), href);
5747 }
5748
5749 if (attrs.length > 0) {
5750 return ("<img src=\"" + url + "\" data-origin=\"" + href + "\" alt=\"" + text + "\" " + (attrs.join(
5751 ' '
5752 )) + " />");
5753 }
5754
5755 return ("<img src=\"" + url + "\" data-origin=\"" + href + "\" alt=\"" + text + "\"" + attrs + ">");
5756 });
5757 };
5758
5759 var prism = createCommonjsModule(function (module) {
5760 /* **********************************************
5761 Begin prism-core.js
5762 ********************************************** */
5763
5764 /// <reference lib="WebWorker"/>
5765
5766 var _self = (typeof window !== 'undefined')
5767 ? window // if in browser
5768 : (
5769 (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
5770 ? self // if in worker
5771 : {} // if in node js
5772 );
5773
5774 /**
5775 * Prism: Lightweight, robust, elegant syntax highlighting
5776 *
5777 * @license MIT <https://opensource.org/licenses/MIT>
5778 * @author Lea Verou <https://lea.verou.me>
5779 * @namespace
5780 * @public
5781 */
5782 var Prism = (function (_self){
5783
5784 // Private helper vars
5785 var lang = /\blang(?:uage)?-([\w-]+)\b/i;
5786 var uniqueId = 0;
5787
5788
5789 var _ = {
5790 /**
5791 * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the
5792 * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load
5793 * additional languages or plugins yourself.
5794 *
5795 * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.
5796 *
5797 * You obviously have to change this value before the automatic highlighting started. To do this, you can add an
5798 * empty Prism object into the global scope before loading the Prism script like this:
5799 *
5800 * ```js
5801 * window.Prism = window.Prism || {};
5802 * Prism.manual = true;
5803 * // add a new <script> to load Prism's script
5804 * ```
5805 *
5806 * @default false
5807 * @type {boolean}
5808 * @memberof Prism
5809 * @public
5810 */
5811 manual: _self.Prism && _self.Prism.manual,
5812 disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
5813
5814 /**
5815 * A namespace for utility methods.
5816 *
5817 * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may
5818 * change or disappear at any time.
5819 *
5820 * @namespace
5821 * @memberof Prism
5822 */
5823 util: {
5824 encode: function encode(tokens) {
5825 if (tokens instanceof Token) {
5826 return new Token(tokens.type, encode(tokens.content), tokens.alias);
5827 } else if (Array.isArray(tokens)) {
5828 return tokens.map(encode);
5829 } else {
5830 return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
5831 }
5832 },
5833
5834 /**
5835 * Returns the name of the type of the given value.
5836 *
5837 * @param {any} o
5838 * @returns {string}
5839 * @example
5840 * type(null) === 'Null'
5841 * type(undefined) === 'Undefined'
5842 * type(123) === 'Number'
5843 * type('foo') === 'String'
5844 * type(true) === 'Boolean'
5845 * type([1, 2]) === 'Array'
5846 * type({}) === 'Object'
5847 * type(String) === 'Function'
5848 * type(/abc+/) === 'RegExp'
5849 */
5850 type: function (o) {
5851 return Object.prototype.toString.call(o).slice(8, -1);
5852 },
5853
5854 /**
5855 * Returns a unique number for the given object. Later calls will still return the same number.
5856 *
5857 * @param {Object} obj
5858 * @returns {number}
5859 */
5860 objId: function (obj) {
5861 if (!obj['__id']) {
5862 Object.defineProperty(obj, '__id', { value: ++uniqueId });
5863 }
5864 return obj['__id'];
5865 },
5866
5867 /**
5868 * Creates a deep clone of the given object.
5869 *
5870 * The main intended use of this function is to clone language definitions.
5871 *
5872 * @param {T} o
5873 * @param {Record<number, any>} [visited]
5874 * @returns {T}
5875 * @template T
5876 */
5877 clone: function deepClone(o, visited) {
5878 visited = visited || {};
5879
5880 var clone, id;
5881 switch (_.util.type(o)) {
5882 case 'Object':
5883 id = _.util.objId(o);
5884 if (visited[id]) {
5885 return visited[id];
5886 }
5887 clone = /** @type {Record<string, any>} */ ({});
5888 visited[id] = clone;
5889
5890 for (var key in o) {
5891 if (o.hasOwnProperty(key)) {
5892 clone[key] = deepClone(o[key], visited);
5893 }
5894 }
5895
5896 return /** @type {any} */ (clone);
5897
5898 case 'Array':
5899 id = _.util.objId(o);
5900 if (visited[id]) {
5901 return visited[id];
5902 }
5903 clone = [];
5904 visited[id] = clone;
5905
5906 (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) {
5907 clone[i] = deepClone(v, visited);
5908 });
5909
5910 return /** @type {any} */ (clone);
5911
5912 default:
5913 return o;
5914 }
5915 },
5916
5917 /**
5918 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
5919 *
5920 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
5921 *
5922 * @param {Element} element
5923 * @returns {string}
5924 */
5925 getLanguage: function (element) {
5926 while (element && !lang.test(element.className)) {
5927 element = element.parentElement;
5928 }
5929 if (element) {
5930 return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
5931 }
5932 return 'none';
5933 },
5934
5935 /**
5936 * Returns the script element that is currently executing.
5937 *
5938 * This does __not__ work for line script element.
5939 *
5940 * @returns {HTMLScriptElement | null}
5941 */
5942 currentScript: function () {
5943 if (typeof document === 'undefined') {
5944 return null;
5945 }
5946 if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) {
5947 return /** @type {any} */ (document.currentScript);
5948 }
5949
5950 // IE11 workaround
5951 // we'll get the src of the current script by parsing IE11's error stack trace
5952 // this will not work for inline scripts
5953
5954 try {
5955 throw new Error();
5956 } catch (err) {
5957 // Get file src url from stack. Specifically works with the format of stack traces in IE.
5958 // A stack will look like this:
5959 //
5960 // Error
5961 // at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
5962 // at Global code (http://localhost/components/prism-core.js:606:1)
5963
5964 var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
5965 if (src) {
5966 var scripts = document.getElementsByTagName('script');
5967 for (var i in scripts) {
5968 if (scripts[i].src == src) {
5969 return scripts[i];
5970 }
5971 }
5972 }
5973 return null;
5974 }
5975 },
5976
5977 /**
5978 * Returns whether a given class is active for `element`.
5979 *
5980 * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated
5981 * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the
5982 * given class is just the given class with a `no-` prefix.
5983 *
5984 * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is
5985 * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its
5986 * ancestors have the given class or the negated version of it, then the default activation will be returned.
5987 *
5988 * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated
5989 * version of it, the class is considered active.
5990 *
5991 * @param {Element} element
5992 * @param {string} className
5993 * @param {boolean} [defaultActivation=false]
5994 * @returns {boolean}
5995 */
5996 isActive: function (element, className, defaultActivation) {
5997 var no = 'no-' + className;
5998
5999 while (element) {
6000 var classList = element.classList;
6001 if (classList.contains(className)) {
6002 return true;
6003 }
6004 if (classList.contains(no)) {
6005 return false;
6006 }
6007 element = element.parentElement;
6008 }
6009 return !!defaultActivation;
6010 }
6011 },
6012
6013 /**
6014 * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.
6015 *
6016 * @namespace
6017 * @memberof Prism
6018 * @public
6019 */
6020 languages: {
6021 /**
6022 * Creates a deep copy of the language with the given id and appends the given tokens.
6023 *
6024 * If a token in `redef` also appears in the copied language, then the existing token in the copied language
6025 * will be overwritten at its original position.
6026 *
6027 * ## Best practices
6028 *
6029 * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)
6030 * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to
6031 * understand the language definition because, normally, the order of tokens matters in Prism grammars.
6032 *
6033 * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
6034 * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
6035 *
6036 * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.
6037 * @param {Grammar} redef The new tokens to append.
6038 * @returns {Grammar} The new language created.
6039 * @public
6040 * @example
6041 * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
6042 * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
6043 * // at its original position
6044 * 'comment': { ... },
6045 * // CSS doesn't have a 'color' token, so this token will be appended
6046 * 'color': /\b(?:red|green|blue)\b/
6047 * });
6048 */
6049 extend: function (id, redef) {
6050 var lang = _.util.clone(_.languages[id]);
6051
6052 for (var key in redef) {
6053 lang[key] = redef[key];
6054 }
6055
6056 return lang;
6057 },
6058
6059 /**
6060 * Inserts tokens _before_ another token in a language definition or any other grammar.
6061 *
6062 * ## Usage
6063 *
6064 * This helper method makes it easy to modify existing languages. For example, the CSS language definition
6065 * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded
6066 * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the
6067 * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do
6068 * this:
6069 *
6070 * ```js
6071 * Prism.languages.markup.style = {
6072 * // token
6073 * };
6074 * ```
6075 *
6076 * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens
6077 * before existing tokens. For the CSS example above, you would use it like this:
6078 *
6079 * ```js
6080 * Prism.languages.insertBefore('markup', 'cdata', {
6081 * 'style': {
6082 * // token
6083 * }
6084 * });
6085 * ```
6086 *
6087 * ## Special cases
6088 *
6089 * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar
6090 * will be ignored.
6091 *
6092 * This behavior can be used to insert tokens after `before`:
6093 *
6094 * ```js
6095 * Prism.languages.insertBefore('markup', 'comment', {
6096 * 'comment': Prism.languages.markup.comment,
6097 * // tokens after 'comment'
6098 * });
6099 * ```
6100 *
6101 * ## Limitations
6102 *
6103 * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object
6104 * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
6105 * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily
6106 * deleting properties which is necessary to insert at arbitrary positions.
6107 *
6108 * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.
6109 * Instead, it will create a new object and replace all references to the target object with the new one. This
6110 * can be done without temporarily deleting properties, so the iteration order is well-defined.
6111 *
6112 * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if
6113 * you hold the target object in a variable, then the value of the variable will not change.
6114 *
6115 * ```js
6116 * var oldMarkup = Prism.languages.markup;
6117 * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
6118 *
6119 * assert(oldMarkup !== Prism.languages.markup);
6120 * assert(newMarkup === Prism.languages.markup);
6121 * ```
6122 *
6123 * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the
6124 * object to be modified.
6125 * @param {string} before The key to insert before.
6126 * @param {Grammar} insert An object containing the key-value pairs to be inserted.
6127 * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the
6128 * object to be modified.
6129 *
6130 * Defaults to `Prism.languages`.
6131 * @returns {Grammar} The new grammar object.
6132 * @public
6133 */
6134 insertBefore: function (inside, before, insert, root) {
6135 root = root || /** @type {any} */ (_.languages);
6136 var grammar = root[inside];
6137 /** @type {Grammar} */
6138 var ret = {};
6139
6140 for (var token in grammar) {
6141 if (grammar.hasOwnProperty(token)) {
6142
6143 if (token == before) {
6144 for (var newToken in insert) {
6145 if (insert.hasOwnProperty(newToken)) {
6146 ret[newToken] = insert[newToken];
6147 }
6148 }
6149 }
6150
6151 // Do not insert token which also occur in insert. See #1525
6152 if (!insert.hasOwnProperty(token)) {
6153 ret[token] = grammar[token];
6154 }
6155 }
6156 }
6157
6158 var old = root[inside];
6159 root[inside] = ret;
6160
6161 // Update references in other language definitions
6162 _.languages.DFS(_.languages, function(key, value) {
6163 if (value === old && key != inside) {
6164 this[key] = ret;
6165 }
6166 });
6167
6168 return ret;
6169 },
6170
6171 // Traverse a language definition with Depth First Search
6172 DFS: function DFS(o, callback, type, visited) {
6173 visited = visited || {};
6174
6175 var objId = _.util.objId;
6176
6177 for (var i in o) {
6178 if (o.hasOwnProperty(i)) {
6179 callback.call(o, i, o[i], type || i);
6180
6181 var property = o[i],
6182 propertyType = _.util.type(property);
6183
6184 if (propertyType === 'Object' && !visited[objId(property)]) {
6185 visited[objId(property)] = true;
6186 DFS(property, callback, null, visited);
6187 }
6188 else if (propertyType === 'Array' && !visited[objId(property)]) {
6189 visited[objId(property)] = true;
6190 DFS(property, callback, i, visited);
6191 }
6192 }
6193 }
6194 }
6195 },
6196
6197 plugins: {},
6198
6199 /**
6200 * This is the most high-level function in Prism’s API.
6201 * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on
6202 * each one of them.
6203 *
6204 * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.
6205 *
6206 * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.
6207 * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.
6208 * @memberof Prism
6209 * @public
6210 */
6211 highlightAll: function(async, callback) {
6212 _.highlightAllUnder(document, async, callback);
6213 },
6214
6215 /**
6216 * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls
6217 * {@link Prism.highlightElement} on each one of them.
6218 *
6219 * The following hooks will be run:
6220 * 1. `before-highlightall`
6221 * 2. `before-all-elements-highlight`
6222 * 3. All hooks of {@link Prism.highlightElement} for each element.
6223 *
6224 * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.
6225 * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.
6226 * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.
6227 * @memberof Prism
6228 * @public
6229 */
6230 highlightAllUnder: function(container, async, callback) {
6231 var env = {
6232 callback: callback,
6233 container: container,
6234 selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
6235 };
6236
6237 _.hooks.run('before-highlightall', env);
6238
6239 env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
6240
6241 _.hooks.run('before-all-elements-highlight', env);
6242
6243 for (var i = 0, element; element = env.elements[i++];) {
6244 _.highlightElement(element, async === true, env.callback);
6245 }
6246 },
6247
6248 /**
6249 * Highlights the code inside a single element.
6250 *
6251 * The following hooks will be run:
6252 * 1. `before-sanity-check`
6253 * 2. `before-highlight`
6254 * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.
6255 * 4. `before-insert`
6256 * 5. `after-highlight`
6257 * 6. `complete`
6258 *
6259 * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for
6260 * the element's language.
6261 *
6262 * @param {Element} element The element containing the code.
6263 * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.
6264 * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers
6265 * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is
6266 * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).
6267 *
6268 * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for
6269 * asynchronous highlighting to work. You can build your own bundle on the
6270 * [Download page](https://prismjs.com/download.html).
6271 * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.
6272 * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.
6273 * @memberof Prism
6274 * @public
6275 */
6276 highlightElement: function(element, async, callback) {
6277 // Find language
6278 var language = _.util.getLanguage(element);
6279 var grammar = _.languages[language];
6280
6281 // Set language on the element, if not present
6282 element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
6283
6284 // Set language on the parent, for styling
6285 var parent = element.parentElement;
6286 if (parent && parent.nodeName.toLowerCase() === 'pre') {
6287 parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
6288 }
6289
6290 var code = element.textContent;
6291
6292 var env = {
6293 element: element,
6294 language: language,
6295 grammar: grammar,
6296 code: code
6297 };
6298
6299 function insertHighlightedCode(highlightedCode) {
6300 env.highlightedCode = highlightedCode;
6301
6302 _.hooks.run('before-insert', env);
6303
6304 env.element.innerHTML = env.highlightedCode;
6305
6306 _.hooks.run('after-highlight', env);
6307 _.hooks.run('complete', env);
6308 callback && callback.call(env.element);
6309 }
6310
6311 _.hooks.run('before-sanity-check', env);
6312
6313 if (!env.code) {
6314 _.hooks.run('complete', env);
6315 callback && callback.call(env.element);
6316 return;
6317 }
6318
6319 _.hooks.run('before-highlight', env);
6320
6321 if (!env.grammar) {
6322 insertHighlightedCode(_.util.encode(env.code));
6323 return;
6324 }
6325
6326 if (async && _self.Worker) {
6327 var worker = new Worker(_.filename);
6328
6329 worker.onmessage = function(evt) {
6330 insertHighlightedCode(evt.data);
6331 };
6332
6333 worker.postMessage(JSON.stringify({
6334 language: env.language,
6335 code: env.code,
6336 immediateClose: true
6337 }));
6338 }
6339 else {
6340 insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
6341 }
6342 },
6343
6344 /**
6345 * Low-level function, only use if you know what you’re doing. It accepts a string of text as input
6346 * and the language definitions to use, and returns a string with the HTML produced.
6347 *
6348 * The following hooks will be run:
6349 * 1. `before-tokenize`
6350 * 2. `after-tokenize`
6351 * 3. `wrap`: On each {@link Token}.
6352 *
6353 * @param {string} text A string with the code to be highlighted.
6354 * @param {Grammar} grammar An object containing the tokens to use.
6355 *
6356 * Usually a language definition like `Prism.languages.markup`.
6357 * @param {string} language The name of the language definition passed to `grammar`.
6358 * @returns {string} The highlighted HTML.
6359 * @memberof Prism
6360 * @public
6361 * @example
6362 * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
6363 */
6364 highlight: function (text, grammar, language) {
6365 var env = {
6366 code: text,
6367 grammar: grammar,
6368 language: language
6369 };
6370 _.hooks.run('before-tokenize', env);
6371 env.tokens = _.tokenize(env.code, env.grammar);
6372 _.hooks.run('after-tokenize', env);
6373 return Token.stringify(_.util.encode(env.tokens), env.language);
6374 },
6375
6376 /**
6377 * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input
6378 * and the language definitions to use, and returns an array with the tokenized code.
6379 *
6380 * When the language definition includes nested tokens, the function is called recursively on each of these tokens.
6381 *
6382 * This method could be useful in other contexts as well, as a very crude parser.
6383 *
6384 * @param {string} text A string with the code to be highlighted.
6385 * @param {Grammar} grammar An object containing the tokens to use.
6386 *
6387 * Usually a language definition like `Prism.languages.markup`.
6388 * @returns {TokenStream} An array of strings and tokens, a token stream.
6389 * @memberof Prism
6390 * @public
6391 * @example
6392 * let code = `var foo = 0;`;
6393 * let tokens = Prism.tokenize(code, Prism.languages.javascript);
6394 * tokens.forEach(token => {
6395 * if (token instanceof Prism.Token && token.type === 'number') {
6396 * console.log(`Found numeric literal: ${token.content}`);
6397 * }
6398 * });
6399 */
6400 tokenize: function(text, grammar) {
6401 var rest = grammar.rest;
6402 if (rest) {
6403 for (var token in rest) {
6404 grammar[token] = rest[token];
6405 }
6406
6407 delete grammar.rest;
6408 }
6409
6410 var tokenList = new LinkedList();
6411 addAfter(tokenList, tokenList.head, text);
6412
6413 matchGrammar(text, tokenList, grammar, tokenList.head, 0);
6414
6415 return toArray(tokenList);
6416 },
6417
6418 /**
6419 * @namespace
6420 * @memberof Prism
6421 * @public
6422 */
6423 hooks: {
6424 all: {},
6425
6426 /**
6427 * Adds the given callback to the list of callbacks for the given hook.
6428 *
6429 * The callback will be invoked when the hook it is registered for is run.
6430 * Hooks are usually directly run by a highlight function but you can also run hooks yourself.
6431 *
6432 * One callback function can be registered to multiple hooks and the same hook multiple times.
6433 *
6434 * @param {string} name The name of the hook.
6435 * @param {HookCallback} callback The callback function which is given environment variables.
6436 * @public
6437 */
6438 add: function (name, callback) {
6439 var hooks = _.hooks.all;
6440
6441 hooks[name] = hooks[name] || [];
6442
6443 hooks[name].push(callback);
6444 },
6445
6446 /**
6447 * Runs a hook invoking all registered callbacks with the given environment variables.
6448 *
6449 * Callbacks will be invoked synchronously and in the order in which they were registered.
6450 *
6451 * @param {string} name The name of the hook.
6452 * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
6453 * @public
6454 */
6455 run: function (name, env) {
6456 var callbacks = _.hooks.all[name];
6457
6458 if (!callbacks || !callbacks.length) {
6459 return;
6460 }
6461
6462 for (var i=0, callback; callback = callbacks[i++];) {
6463 callback(env);
6464 }
6465 }
6466 },
6467
6468 Token: Token
6469 };
6470 _self.Prism = _;
6471
6472
6473 // Typescript note:
6474 // The following can be used to import the Token type in JSDoc:
6475 //
6476 // @typedef {InstanceType<import("./prism-core")["Token"]>} Token
6477
6478 /**
6479 * Creates a new token.
6480 *
6481 * @param {string} type See {@link Token#type type}
6482 * @param {string | TokenStream} content See {@link Token#content content}
6483 * @param {string|string[]} [alias] The alias(es) of the token.
6484 * @param {string} [matchedStr=""] A copy of the full string this token was created from.
6485 * @class
6486 * @global
6487 * @public
6488 */
6489 function Token(type, content, alias, matchedStr) {
6490 /**
6491 * The type of the token.
6492 *
6493 * This is usually the key of a pattern in a {@link Grammar}.
6494 *
6495 * @type {string}
6496 * @see GrammarToken
6497 * @public
6498 */
6499 this.type = type;
6500 /**
6501 * The strings or tokens contained by this token.
6502 *
6503 * This will be a token stream if the pattern matched also defined an `inside` grammar.
6504 *
6505 * @type {string | TokenStream}
6506 * @public
6507 */
6508 this.content = content;
6509 /**
6510 * The alias(es) of the token.
6511 *
6512 * @type {string|string[]}
6513 * @see GrammarToken
6514 * @public
6515 */
6516 this.alias = alias;
6517 // Copy of the full string this token was created from
6518 this.length = (matchedStr || '').length | 0;
6519 }
6520
6521 /**
6522 * A token stream is an array of strings and {@link Token Token} objects.
6523 *
6524 * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process
6525 * them.
6526 *
6527 * 1. No adjacent strings.
6528 * 2. No empty strings.
6529 *
6530 * The only exception here is the token stream that only contains the empty string and nothing else.
6531 *
6532 * @typedef {Array<string | Token>} TokenStream
6533 * @global
6534 * @public
6535 */
6536
6537 /**
6538 * Converts the given token or token stream to an HTML representation.
6539 *
6540 * The following hooks will be run:
6541 * 1. `wrap`: On each {@link Token}.
6542 *
6543 * @param {string | Token | TokenStream} o The token or token stream to be converted.
6544 * @param {string} language The name of current language.
6545 * @returns {string} The HTML representation of the token or token stream.
6546 * @memberof Token
6547 * @static
6548 */
6549 Token.stringify = function stringify(o, language) {
6550 if (typeof o == 'string') {
6551 return o;
6552 }
6553 if (Array.isArray(o)) {
6554 var s = '';
6555 o.forEach(function (e) {
6556 s += stringify(e, language);
6557 });
6558 return s;
6559 }
6560
6561 var env = {
6562 type: o.type,
6563 content: stringify(o.content, language),
6564 tag: 'span',
6565 classes: ['token', o.type],
6566 attributes: {},
6567 language: language
6568 };
6569
6570 var aliases = o.alias;
6571 if (aliases) {
6572 if (Array.isArray(aliases)) {
6573 Array.prototype.push.apply(env.classes, aliases);
6574 } else {
6575 env.classes.push(aliases);
6576 }
6577 }
6578
6579 _.hooks.run('wrap', env);
6580
6581 var attributes = '';
6582 for (var name in env.attributes) {
6583 attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
6584 }
6585
6586 return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
6587 };
6588
6589 /**
6590 * @param {RegExp} pattern
6591 * @param {number} pos
6592 * @param {string} text
6593 * @param {boolean} lookbehind
6594 * @returns {RegExpExecArray | null}
6595 */
6596 function matchPattern(pattern, pos, text, lookbehind) {
6597 pattern.lastIndex = pos;
6598 var match = pattern.exec(text);
6599 if (match && lookbehind && match[1]) {
6600 // change the match to remove the text matched by the Prism lookbehind group
6601 var lookbehindLength = match[1].length;
6602 match.index += lookbehindLength;
6603 match[0] = match[0].slice(lookbehindLength);
6604 }
6605 return match;
6606 }
6607
6608 /**
6609 * @param {string} text
6610 * @param {LinkedList<string | Token>} tokenList
6611 * @param {any} grammar
6612 * @param {LinkedListNode<string | Token>} startNode
6613 * @param {number} startPos
6614 * @param {RematchOptions} [rematch]
6615 * @returns {void}
6616 * @private
6617 *
6618 * @typedef RematchOptions
6619 * @property {string} cause
6620 * @property {number} reach
6621 */
6622 function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) {
6623 for (var token in grammar) {
6624 if (!grammar.hasOwnProperty(token) || !grammar[token]) {
6625 continue;
6626 }
6627
6628 var patterns = grammar[token];
6629 patterns = Array.isArray(patterns) ? patterns : [patterns];
6630
6631 for (var j = 0; j < patterns.length; ++j) {
6632 if (rematch && rematch.cause == token + ',' + j) {
6633 return;
6634 }
6635
6636 var patternObj = patterns[j],
6637 inside = patternObj.inside,
6638 lookbehind = !!patternObj.lookbehind,
6639 greedy = !!patternObj.greedy,
6640 alias = patternObj.alias;
6641
6642 if (greedy && !patternObj.pattern.global) {
6643 // Without the global flag, lastIndex won't work
6644 var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];
6645 patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g');
6646 }
6647
6648 /** @type {RegExp} */
6649 var pattern = patternObj.pattern || patternObj;
6650
6651 for ( // iterate the token list and keep track of the current token/string position
6652 var currentNode = startNode.next, pos = startPos;
6653 currentNode !== tokenList.tail;
6654 pos += currentNode.value.length, currentNode = currentNode.next
6655 ) {
6656
6657 if (rematch && pos >= rematch.reach) {
6658 break;
6659 }
6660
6661 var str = currentNode.value;
6662
6663 if (tokenList.length > text.length) {
6664 // Something went terribly wrong, ABORT, ABORT!
6665 return;
6666 }
6667
6668 if (str instanceof Token) {
6669 continue;
6670 }
6671
6672 var removeCount = 1; // this is the to parameter of removeBetween
6673 var match;
6674
6675 if (greedy) {
6676 match = matchPattern(pattern, pos, text, lookbehind);
6677 if (!match) {
6678 break;
6679 }
6680
6681 var from = match.index;
6682 var to = match.index + match[0].length;
6683 var p = pos;
6684
6685 // find the node that contains the match
6686 p += currentNode.value.length;
6687 while (from >= p) {
6688 currentNode = currentNode.next;
6689 p += currentNode.value.length;
6690 }
6691 // adjust pos (and p)
6692 p -= currentNode.value.length;
6693 pos = p;
6694
6695 // the current node is a Token, then the match starts inside another Token, which is invalid
6696 if (currentNode.value instanceof Token) {
6697 continue;
6698 }
6699
6700 // find the last node which is affected by this match
6701 for (
6702 var k = currentNode;
6703 k !== tokenList.tail && (p < to || typeof k.value === 'string');
6704 k = k.next
6705 ) {
6706 removeCount++;
6707 p += k.value.length;
6708 }
6709 removeCount--;
6710
6711 // replace with the new match
6712 str = text.slice(pos, p);
6713 match.index -= pos;
6714 } else {
6715 match = matchPattern(pattern, 0, str, lookbehind);
6716 if (!match) {
6717 continue;
6718 }
6719 }
6720
6721 var from = match.index,
6722 matchStr = match[0],
6723 before = str.slice(0, from),
6724 after = str.slice(from + matchStr.length);
6725
6726 var reach = pos + str.length;
6727 if (rematch && reach > rematch.reach) {
6728 rematch.reach = reach;
6729 }
6730
6731 var removeFrom = currentNode.prev;
6732
6733 if (before) {
6734 removeFrom = addAfter(tokenList, removeFrom, before);
6735 pos += before.length;
6736 }
6737
6738 removeRange(tokenList, removeFrom, removeCount);
6739
6740 var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr);
6741 currentNode = addAfter(tokenList, removeFrom, wrapped);
6742
6743 if (after) {
6744 addAfter(tokenList, currentNode, after);
6745 }
6746
6747 if (removeCount > 1) {
6748 // at least one Token object was removed, so we have to do some rematching
6749 // this can only happen if the current pattern is greedy
6750 matchGrammar(text, tokenList, grammar, currentNode.prev, pos, {
6751 cause: token + ',' + j,
6752 reach: reach
6753 });
6754 }
6755 }
6756 }
6757 }
6758 }
6759
6760 /**
6761 * @typedef LinkedListNode
6762 * @property {T} value
6763 * @property {LinkedListNode<T> | null} prev The previous node.
6764 * @property {LinkedListNode<T> | null} next The next node.
6765 * @template T
6766 * @private
6767 */
6768
6769 /**
6770 * @template T
6771 * @private
6772 */
6773 function LinkedList() {
6774 /** @type {LinkedListNode<T>} */
6775 var head = { value: null, prev: null, next: null };
6776 /** @type {LinkedListNode<T>} */
6777 var tail = { value: null, prev: head, next: null };
6778 head.next = tail;
6779
6780 /** @type {LinkedListNode<T>} */
6781 this.head = head;
6782 /** @type {LinkedListNode<T>} */
6783 this.tail = tail;
6784 this.length = 0;
6785 }
6786
6787 /**
6788 * Adds a new node with the given value to the list.
6789 * @param {LinkedList<T>} list
6790 * @param {LinkedListNode<T>} node
6791 * @param {T} value
6792 * @returns {LinkedListNode<T>} The added node.
6793 * @template T
6794 */
6795 function addAfter(list, node, value) {
6796 // assumes that node != list.tail && values.length >= 0
6797 var next = node.next;
6798
6799 var newNode = { value: value, prev: node, next: next };
6800 node.next = newNode;
6801 next.prev = newNode;
6802 list.length++;
6803
6804 return newNode;
6805 }
6806 /**
6807 * Removes `count` nodes after the given node. The given node will not be removed.
6808 * @param {LinkedList<T>} list
6809 * @param {LinkedListNode<T>} node
6810 * @param {number} count
6811 * @template T
6812 */
6813 function removeRange(list, node, count) {
6814 var next = node.next;
6815 for (var i = 0; i < count && next !== list.tail; i++) {
6816 next = next.next;
6817 }
6818 node.next = next;
6819 next.prev = node;
6820 list.length -= i;
6821 }
6822 /**
6823 * @param {LinkedList<T>} list
6824 * @returns {T[]}
6825 * @template T
6826 */
6827 function toArray(list) {
6828 var array = [];
6829 var node = list.head.next;
6830 while (node !== list.tail) {
6831 array.push(node.value);
6832 node = node.next;
6833 }
6834 return array;
6835 }
6836
6837
6838 if (!_self.document) {
6839 if (!_self.addEventListener) {
6840 // in Node.js
6841 return _;
6842 }
6843
6844 if (!_.disableWorkerMessageHandler) {
6845 // In worker
6846 _self.addEventListener('message', function (evt) {
6847 var message = JSON.parse(evt.data),
6848 lang = message.language,
6849 code = message.code,
6850 immediateClose = message.immediateClose;
6851
6852 _self.postMessage(_.highlight(code, _.languages[lang], lang));
6853 if (immediateClose) {
6854 _self.close();
6855 }
6856 }, false);
6857 }
6858
6859 return _;
6860 }
6861
6862 // Get current script and highlight
6863 var script = _.util.currentScript();
6864
6865 if (script) {
6866 _.filename = script.src;
6867
6868 if (script.hasAttribute('data-manual')) {
6869 _.manual = true;
6870 }
6871 }
6872
6873 function highlightAutomaticallyCallback() {
6874 if (!_.manual) {
6875 _.highlightAll();
6876 }
6877 }
6878
6879 if (!_.manual) {
6880 // If the document state is "loading", then we'll use DOMContentLoaded.
6881 // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
6882 // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
6883 // might take longer one animation frame to execute which can create a race condition where only some plugins have
6884 // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
6885 // See https://github.com/PrismJS/prism/issues/2102
6886 var readyState = document.readyState;
6887 if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
6888 document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
6889 } else {
6890 if (window.requestAnimationFrame) {
6891 window.requestAnimationFrame(highlightAutomaticallyCallback);
6892 } else {
6893 window.setTimeout(highlightAutomaticallyCallback, 16);
6894 }
6895 }
6896 }
6897
6898 return _;
6899
6900 })(_self);
6901
6902 if ( module.exports) {
6903 module.exports = Prism;
6904 }
6905
6906 // hack for components to work correctly in node.js
6907 if (typeof commonjsGlobal !== 'undefined') {
6908 commonjsGlobal.Prism = Prism;
6909 }
6910
6911 // some additional documentation/types
6912
6913 /**
6914 * The expansion of a simple `RegExp` literal to support additional properties.
6915 *
6916 * @typedef GrammarToken
6917 * @property {RegExp} pattern The regular expression of the token.
6918 * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively)
6919 * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.
6920 * @property {boolean} [greedy=false] Whether the token is greedy.
6921 * @property {string|string[]} [alias] An optional alias or list of aliases.
6922 * @property {Grammar} [inside] The nested grammar of this token.
6923 *
6924 * The `inside` grammar will be used to tokenize the text value of each token of this kind.
6925 *
6926 * This can be used to make nested and even recursive language definitions.
6927 *
6928 * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into
6929 * each another.
6930 * @global
6931 * @public
6932 */
6933
6934 /**
6935 * @typedef Grammar
6936 * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>}
6937 * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar.
6938 * @global
6939 * @public
6940 */
6941
6942 /**
6943 * A function which will invoked after an element was successfully highlighted.
6944 *
6945 * @callback HighlightCallback
6946 * @param {Element} element The element successfully highlighted.
6947 * @returns {void}
6948 * @global
6949 * @public
6950 */
6951
6952 /**
6953 * @callback HookCallback
6954 * @param {Object<string, any>} env The environment variables of the hook.
6955 * @returns {void}
6956 * @global
6957 * @public
6958 */
6959
6960
6961 /* **********************************************
6962 Begin prism-markup.js
6963 ********************************************** */
6964
6965 Prism.languages.markup = {
6966 'comment': /<!--[\s\S]*?-->/,
6967 'prolog': /<\?[\s\S]+?\?>/,
6968 'doctype': {
6969 // https://www.w3.org/TR/xml/#NT-doctypedecl
6970 pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
6971 greedy: true,
6972 inside: {
6973 'internal-subset': {
6974 pattern: /(\[)[\s\S]+(?=\]>$)/,
6975 lookbehind: true,
6976 greedy: true,
6977 inside: null // see below
6978 },
6979 'string': {
6980 pattern: /"[^"]*"|'[^']*'/,
6981 greedy: true
6982 },
6983 'punctuation': /^<!|>$|[[\]]/,
6984 'doctype-tag': /^DOCTYPE/,
6985 'name': /[^\s<>'"]+/
6986 }
6987 },
6988 'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
6989 'tag': {
6990 pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
6991 greedy: true,
6992 inside: {
6993 'tag': {
6994 pattern: /^<\/?[^\s>\/]+/,
6995 inside: {
6996 'punctuation': /^<\/?/,
6997 'namespace': /^[^\s>\/:]+:/
6998 }
6999 },
7000 'attr-value': {
7001 pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
7002 inside: {
7003 'punctuation': [
7004 {
7005 pattern: /^=/,
7006 alias: 'attr-equals'
7007 },
7008 /"|'/
7009 ]
7010 }
7011 },
7012 'punctuation': /\/?>/,
7013 'attr-name': {
7014 pattern: /[^\s>\/]+/,
7015 inside: {
7016 'namespace': /^[^\s>\/:]+:/
7017 }
7018 }
7019
7020 }
7021 },
7022 'entity': [
7023 {
7024 pattern: /&[\da-z]{1,8};/i,
7025 alias: 'named-entity'
7026 },
7027 /&#x?[\da-f]{1,8};/i
7028 ]
7029 };
7030
7031 Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
7032 Prism.languages.markup['entity'];
7033 Prism.languages.markup['doctype'].inside['internal-subset'].inside = Prism.languages.markup;
7034
7035 // Plugin to make entity title show the real entity, idea by Roman Komarov
7036 Prism.hooks.add('wrap', function (env) {
7037
7038 if (env.type === 'entity') {
7039 env.attributes['title'] = env.content.replace(/&amp;/, '&');
7040 }
7041 });
7042
7043 Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
7044 /**
7045 * Adds an inlined language to markup.
7046 *
7047 * An example of an inlined language is CSS with `<style>` tags.
7048 *
7049 * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
7050 * case insensitive.
7051 * @param {string} lang The language key.
7052 * @example
7053 * addInlined('style', 'css');
7054 */
7055 value: function addInlined(tagName, lang) {
7056 var includedCdataInside = {};
7057 includedCdataInside['language-' + lang] = {
7058 pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
7059 lookbehind: true,
7060 inside: Prism.languages[lang]
7061 };
7062 includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;
7063
7064 var inside = {
7065 'included-cdata': {
7066 pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
7067 inside: includedCdataInside
7068 }
7069 };
7070 inside['language-' + lang] = {
7071 pattern: /[\s\S]+/,
7072 inside: Prism.languages[lang]
7073 };
7074
7075 var def = {};
7076 def[tagName] = {
7077 pattern: RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),
7078 lookbehind: true,
7079 greedy: true,
7080 inside: inside
7081 };
7082
7083 Prism.languages.insertBefore('markup', 'cdata', def);
7084 }
7085 });
7086
7087 Prism.languages.html = Prism.languages.markup;
7088 Prism.languages.mathml = Prism.languages.markup;
7089 Prism.languages.svg = Prism.languages.markup;
7090
7091 Prism.languages.xml = Prism.languages.extend('markup', {});
7092 Prism.languages.ssml = Prism.languages.xml;
7093 Prism.languages.atom = Prism.languages.xml;
7094 Prism.languages.rss = Prism.languages.xml;
7095
7096
7097 /* **********************************************
7098 Begin prism-css.js
7099 ********************************************** */
7100
7101 (function (Prism) {
7102
7103 var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;
7104
7105 Prism.languages.css = {
7106 'comment': /\/\*[\s\S]*?\*\//,
7107 'atrule': {
7108 pattern: /@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,
7109 inside: {
7110 'rule': /^@[\w-]+/,
7111 'selector-function-argument': {
7112 pattern: /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,
7113 lookbehind: true,
7114 alias: 'selector'
7115 },
7116 'keyword': {
7117 pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/,
7118 lookbehind: true
7119 }
7120 // See rest below
7121 }
7122 },
7123 'url': {
7124 // https://drafts.csswg.org/css-values-3/#urls
7125 pattern: RegExp('\\burl\\((?:' + string.source + '|' + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ')\\)', 'i'),
7126 greedy: true,
7127 inside: {
7128 'function': /^url/i,
7129 'punctuation': /^\(|\)$/,
7130 'string': {
7131 pattern: RegExp('^' + string.source + '$'),
7132 alias: 'url'
7133 }
7134 }
7135 },
7136 'selector': RegExp('[^{}\\s](?:[^{};"\'\\s]|\\s+(?![\\s{])|' + string.source + ')*(?=\\s*\\{)'),
7137 'string': {
7138 pattern: string,
7139 greedy: true
7140 },
7141 'property': /(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,
7142 'important': /!important\b/i,
7143 'function': /[-a-z0-9]+(?=\()/i,
7144 'punctuation': /[(){};:,]/
7145 };
7146
7147 Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
7148
7149 var markup = Prism.languages.markup;
7150 if (markup) {
7151 markup.tag.addInlined('style', 'css');
7152
7153 Prism.languages.insertBefore('inside', 'attr-value', {
7154 'style-attr': {
7155 pattern: /(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,
7156 lookbehind: true,
7157 inside: {
7158 'attr-value': {
7159 pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
7160 inside: {
7161 'style': {
7162 pattern: /(["'])[\s\S]+(?=["']$)/,
7163 lookbehind: true,
7164 alias: 'language-css',
7165 inside: Prism.languages.css
7166 },
7167 'punctuation': [
7168 {
7169 pattern: /^=/,
7170 alias: 'attr-equals'
7171 },
7172 /"|'/
7173 ]
7174 }
7175 },
7176 'attr-name': /^style/i
7177 }
7178 }
7179 }, markup.tag);
7180 }
7181
7182 }(Prism));
7183
7184
7185 /* **********************************************
7186 Begin prism-clike.js
7187 ********************************************** */
7188
7189 Prism.languages.clike = {
7190 'comment': [
7191 {
7192 pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
7193 lookbehind: true,
7194 greedy: true
7195 },
7196 {
7197 pattern: /(^|[^\\:])\/\/.*/,
7198 lookbehind: true,
7199 greedy: true
7200 }
7201 ],
7202 'string': {
7203 pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
7204 greedy: true
7205 },
7206 'class-name': {
7207 pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
7208 lookbehind: true,
7209 inside: {
7210 'punctuation': /[.\\]/
7211 }
7212 },
7213 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
7214 'boolean': /\b(?:true|false)\b/,
7215 'function': /\w+(?=\()/,
7216 'number': /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
7217 'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
7218 'punctuation': /[{}[\];(),.:]/
7219 };
7220
7221
7222 /* **********************************************
7223 Begin prism-javascript.js
7224 ********************************************** */
7225
7226 Prism.languages.javascript = Prism.languages.extend('clike', {
7227 'class-name': [
7228 Prism.languages.clike['class-name'],
7229 {
7230 pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,
7231 lookbehind: true
7232 }
7233 ],
7234 'keyword': [
7235 {
7236 pattern: /((?:^|})\s*)(?:catch|finally)\b/,
7237 lookbehind: true
7238 },
7239 {
7240 pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
7241 lookbehind: true
7242 } ],
7243 // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
7244 'function': /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
7245 'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,
7246 'operator': /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
7247 });
7248
7249 Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;
7250
7251 Prism.languages.insertBefore('javascript', 'keyword', {
7252 'regex': {
7253 pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
7254 lookbehind: true,
7255 greedy: true,
7256 inside: {
7257 'regex-source': {
7258 pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
7259 lookbehind: true,
7260 alias: 'language-regex',
7261 inside: Prism.languages.regex
7262 },
7263 'regex-flags': /[a-z]+$/,
7264 'regex-delimiter': /^\/|\/$/
7265 }
7266 },
7267 // This must be declared before keyword because we use "function" inside the look-forward
7268 'function-variable': {
7269 pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
7270 alias: 'function'
7271 },
7272 'parameter': [
7273 {
7274 pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
7275 lookbehind: true,
7276 inside: Prism.languages.javascript
7277 },
7278 {
7279 pattern: /(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
7280 inside: Prism.languages.javascript
7281 },
7282 {
7283 pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
7284 lookbehind: true,
7285 inside: Prism.languages.javascript
7286 },
7287 {
7288 pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
7289 lookbehind: true,
7290 inside: Prism.languages.javascript
7291 }
7292 ],
7293 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
7294 });
7295
7296 Prism.languages.insertBefore('javascript', 'string', {
7297 'template-string': {
7298 pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,
7299 greedy: true,
7300 inside: {
7301 'template-punctuation': {
7302 pattern: /^`|`$/,
7303 alias: 'string'
7304 },
7305 'interpolation': {
7306 pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,
7307 lookbehind: true,
7308 inside: {
7309 'interpolation-punctuation': {
7310 pattern: /^\${|}$/,
7311 alias: 'punctuation'
7312 },
7313 rest: Prism.languages.javascript
7314 }
7315 },
7316 'string': /[\s\S]+/
7317 }
7318 }
7319 });
7320
7321 if (Prism.languages.markup) {
7322 Prism.languages.markup.tag.addInlined('script', 'javascript');
7323 }
7324
7325 Prism.languages.js = Prism.languages.javascript;
7326
7327
7328 /* **********************************************
7329 Begin prism-file-highlight.js
7330 ********************************************** */
7331
7332 (function () {
7333 if (typeof self === 'undefined' || !self.Prism || !self.document) {
7334 return;
7335 }
7336
7337 // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
7338 if (!Element.prototype.matches) {
7339 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
7340 }
7341
7342 var Prism = window.Prism;
7343
7344 var LOADING_MESSAGE = 'Loading…';
7345 var FAILURE_MESSAGE = function (status, message) {
7346 return '✖ Error ' + status + ' while fetching file: ' + message;
7347 };
7348 var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty';
7349
7350 var EXTENSIONS = {
7351 'js': 'javascript',
7352 'py': 'python',
7353 'rb': 'ruby',
7354 'ps1': 'powershell',
7355 'psm1': 'powershell',
7356 'sh': 'bash',
7357 'bat': 'batch',
7358 'h': 'c',
7359 'tex': 'latex'
7360 };
7361
7362 var STATUS_ATTR = 'data-src-status';
7363 var STATUS_LOADING = 'loading';
7364 var STATUS_LOADED = 'loaded';
7365 var STATUS_FAILED = 'failed';
7366
7367 var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])'
7368 + ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])';
7369
7370 var lang = /\blang(?:uage)?-([\w-]+)\b/i;
7371
7372 /**
7373 * Sets the Prism `language-xxxx` or `lang-xxxx` class to the given language.
7374 *
7375 * @param {HTMLElement} element
7376 * @param {string} language
7377 * @returns {void}
7378 */
7379 function setLanguageClass(element, language) {
7380 var className = element.className;
7381 className = className.replace(lang, ' ') + ' language-' + language;
7382 element.className = className.replace(/\s+/g, ' ').trim();
7383 }
7384
7385
7386 Prism.hooks.add('before-highlightall', function (env) {
7387 env.selector += ', ' + SELECTOR;
7388 });
7389
7390 Prism.hooks.add('before-sanity-check', function (env) {
7391 var pre = /** @type {HTMLPreElement} */ (env.element);
7392 if (pre.matches(SELECTOR)) {
7393 env.code = ''; // fast-path the whole thing and go to complete
7394
7395 pre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading
7396
7397 // add code element with loading message
7398 var code = pre.appendChild(document.createElement('CODE'));
7399 code.textContent = LOADING_MESSAGE;
7400
7401 var src = pre.getAttribute('data-src');
7402
7403 var language = env.language;
7404 if (language === 'none') {
7405 // the language might be 'none' because there is no language set;
7406 // in this case, we want to use the extension as the language
7407 var extension = (/\.(\w+)$/.exec(src) || [, 'none'])[1];
7408 language = EXTENSIONS[extension] || extension;
7409 }
7410
7411 // set language classes
7412 setLanguageClass(code, language);
7413 setLanguageClass(pre, language);
7414
7415 // preload the language
7416 var autoloader = Prism.plugins.autoloader;
7417 if (autoloader) {
7418 autoloader.loadLanguages(language);
7419 }
7420
7421 // load file
7422 var xhr = new XMLHttpRequest();
7423 xhr.open('GET', src, true);
7424 xhr.onreadystatechange = function () {
7425 if (xhr.readyState == 4) {
7426 if (xhr.status < 400 && xhr.responseText) {
7427 // mark as loaded
7428 pre.setAttribute(STATUS_ATTR, STATUS_LOADED);
7429
7430 // highlight code
7431 code.textContent = xhr.responseText;
7432 Prism.highlightElement(code);
7433
7434 } else {
7435 // mark as failed
7436 pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
7437
7438 if (xhr.status >= 400) {
7439 code.textContent = FAILURE_MESSAGE(xhr.status, xhr.statusText);
7440 } else {
7441 code.textContent = FAILURE_EMPTY_MESSAGE;
7442 }
7443 }
7444 }
7445 };
7446 xhr.send(null);
7447 }
7448 });
7449
7450 Prism.plugins.fileHighlight = {
7451 /**
7452 * Executes the File Highlight plugin for all matching `pre` elements under the given container.
7453 *
7454 * Note: Elements which are already loaded or currently loading will not be touched by this method.
7455 *
7456 * @param {ParentNode} [container=document]
7457 */
7458 highlight: function highlight(container) {
7459 var elements = (container || document).querySelectorAll(SELECTOR);
7460
7461 for (var i = 0, element; element = elements[i++];) {
7462 Prism.highlightElement(element);
7463 }
7464 }
7465 };
7466
7467 var logged = false;
7468 /** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */
7469 Prism.fileHighlight = function () {
7470 if (!logged) {
7471 console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.');
7472 logged = true;
7473 }
7474 Prism.plugins.fileHighlight.highlight.apply(this, arguments);
7475 };
7476
7477 })();
7478 });
7479
7480 (function (Prism) {
7481
7482 /**
7483 * Returns the placeholder for the given language id and index.
7484 *
7485 * @param {string} language
7486 * @param {string|number} index
7487 * @returns {string}
7488 */
7489 function getPlaceholder(language, index) {
7490 return '___' + language.toUpperCase() + index + '___';
7491 }
7492
7493 Object.defineProperties(Prism.languages['markup-templating'] = {}, {
7494 buildPlaceholders: {
7495 /**
7496 * Tokenize all inline templating expressions matching `placeholderPattern`.
7497 *
7498 * If `replaceFilter` is provided, only matches of `placeholderPattern` for which `replaceFilter` returns
7499 * `true` will be replaced.
7500 *
7501 * @param {object} env The environment of the `before-tokenize` hook.
7502 * @param {string} language The language id.
7503 * @param {RegExp} placeholderPattern The matches of this pattern will be replaced by placeholders.
7504 * @param {(match: string) => boolean} [replaceFilter]
7505 */
7506 value: function (env, language, placeholderPattern, replaceFilter) {
7507 if (env.language !== language) {
7508 return;
7509 }
7510
7511 var tokenStack = env.tokenStack = [];
7512
7513 env.code = env.code.replace(placeholderPattern, function (match) {
7514 if (typeof replaceFilter === 'function' && !replaceFilter(match)) {
7515 return match;
7516 }
7517 var i = tokenStack.length;
7518 var placeholder;
7519
7520 // Check for existing strings
7521 while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1)
7522 { ++i; }
7523
7524 // Create a sparse array
7525 tokenStack[i] = match;
7526
7527 return placeholder;
7528 });
7529
7530 // Switch the grammar to markup
7531 env.grammar = Prism.languages.markup;
7532 }
7533 },
7534 tokenizePlaceholders: {
7535 /**
7536 * Replace placeholders with proper tokens after tokenizing.
7537 *
7538 * @param {object} env The environment of the `after-tokenize` hook.
7539 * @param {string} language The language id.
7540 */
7541 value: function (env, language) {
7542 if (env.language !== language || !env.tokenStack) {
7543 return;
7544 }
7545
7546 // Switch the grammar back
7547 env.grammar = Prism.languages[language];
7548
7549 var j = 0;
7550 var keys = Object.keys(env.tokenStack);
7551
7552 function walkTokens(tokens) {
7553 for (var i = 0; i < tokens.length; i++) {
7554 // all placeholders are replaced already
7555 if (j >= keys.length) {
7556 break;
7557 }
7558
7559 var token = tokens[i];
7560 if (typeof token === 'string' || (token.content && typeof token.content === 'string')) {
7561 var k = keys[j];
7562 var t = env.tokenStack[k];
7563 var s = typeof token === 'string' ? token : token.content;
7564 var placeholder = getPlaceholder(language, k);
7565
7566 var index = s.indexOf(placeholder);
7567 if (index > -1) {
7568 ++j;
7569
7570 var before = s.substring(0, index);
7571 var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar), 'language-' + language, t);
7572 var after = s.substring(index + placeholder.length);
7573
7574 var replacement = [];
7575 if (before) {
7576 replacement.push.apply(replacement, walkTokens([before]));
7577 }
7578 replacement.push(middle);
7579 if (after) {
7580 replacement.push.apply(replacement, walkTokens([after]));
7581 }
7582
7583 if (typeof token === 'string') {
7584 tokens.splice.apply(tokens, [i, 1].concat(replacement));
7585 } else {
7586 token.content = replacement;
7587 }
7588 }
7589 } else if (token.content /* && typeof token.content !== 'string' */) {
7590 walkTokens(token.content);
7591 }
7592 }
7593
7594 return tokens;
7595 }
7596
7597 walkTokens(env.tokens);
7598 }
7599 }
7600 });
7601
7602 }(Prism));
7603
7604 var highlightCodeCompiler = function (ref) {
7605 var renderer = ref.renderer;
7606
7607 return (renderer.code = function(code, lang) {
7608 if ( lang === void 0 ) lang = 'markup';
7609
7610 var langOrMarkup = prism.languages[lang] || prism.languages.markup;
7611 var text = prism.highlight(
7612 code.replace(/@DOCSIFY_QM@/g, '`'),
7613 langOrMarkup,
7614 lang
7615 );
7616
7617 return ("<pre v-pre data-lang=\"" + lang + "\"><code class=\"lang-" + lang + "\">" + text + "</code></pre>");
7618 });
7619 };
7620
7621 var paragraphCompiler = function (ref) {
7622 var renderer = ref.renderer;
7623
7624 return (renderer.paragraph = function (text) {
7625 var result;
7626 if (/^!&gt;/.test(text)) {
7627 result = helper('tip', text);
7628 } else if (/^\?&gt;/.test(text)) {
7629 result = helper('warn', text);
7630 } else {
7631 result = "<p>" + text + "</p>";
7632 }
7633
7634 return result;
7635 });
7636 };
7637
7638 var taskListCompiler = function (ref) {
7639 var renderer = ref.renderer;
7640
7641 return (renderer.list = function (body, ordered, start) {
7642 var isTaskList = /<li class="task-list-item">/.test(
7643 body.split('class="task-list"')[0]
7644 );
7645 var isStartReq = start && start > 1;
7646 var tag = ordered ? 'ol' : 'ul';
7647 var tagAttrs = [
7648 isTaskList ? 'class="task-list"' : '',
7649 isStartReq ? ("start=\"" + start + "\"") : '' ]
7650 .join(' ')
7651 .trim();
7652
7653 return ("<" + tag + " " + tagAttrs + ">" + body + "</" + tag + ">");
7654 });
7655 };
7656
7657 var taskListItemCompiler = function (ref) {
7658 var renderer = ref.renderer;
7659
7660 return (renderer.listitem = function (text) {
7661 var isTaskItem = /^(<input.*type="checkbox"[^>]*>)/.test(text);
7662 var html = isTaskItem
7663 ? ("<li class=\"task-list-item\"><label>" + text + "</label></li>")
7664 : ("<li>" + text + "</li>");
7665
7666 return html;
7667 });
7668 };
7669
7670 var linkCompiler = function (ref) {
7671 var renderer = ref.renderer;
7672 var router = ref.router;
7673 var linkTarget = ref.linkTarget;
7674 var linkRel = ref.linkRel;
7675 var compilerClass = ref.compilerClass;
7676
7677 return (renderer.link = function (href, title, text) {
7678 if ( title === void 0 ) title = '';
7679
7680 var attrs = [];
7681 var ref = getAndRemoveConfig(title);
7682 var str = ref.str;
7683 var config = ref.config;
7684 linkTarget = config.target || linkTarget;
7685 linkRel =
7686 linkTarget === '_blank'
7687 ? compilerClass.config.externalLinkRel || 'noopener'
7688 : '';
7689 title = str;
7690
7691 if (
7692 !isAbsolutePath(href) &&
7693 !compilerClass._matchNotCompileLink(href) &&
7694 !config.ignore
7695 ) {
7696 if (href === compilerClass.config.homepage) {
7697 href = 'README';
7698 }
7699
7700 href = router.toURL(href, null, router.getCurrentPath());
7701 } else {
7702 if (!isAbsolutePath(href) && href.slice(0, 2) === './') {
7703 href =
7704 document.URL.replace(/\/(?!.*\/).*/, '/').replace('#/./', '') + href;
7705 }
7706 attrs.push(href.indexOf('mailto:') === 0 ? '' : ("target=\"" + linkTarget + "\""));
7707 attrs.push(
7708 href.indexOf('mailto:') === 0
7709 ? ''
7710 : linkRel !== ''
7711 ? (" rel=\"" + linkRel + "\"")
7712 : ''
7713 );
7714 }
7715
7716 // special case to check crossorigin urls
7717 if (
7718 config.crossorgin &&
7719 linkTarget === '_self' &&
7720 compilerClass.config.routerMode === 'history'
7721 ) {
7722 if (compilerClass.config.crossOriginLinks.indexOf(href) === -1) {
7723 compilerClass.config.crossOriginLinks.push(href);
7724 }
7725 }
7726
7727 if (config.disabled) {
7728 attrs.push('disabled');
7729 href = 'javascript:void(0)';
7730 }
7731
7732 if (config.class) {
7733 attrs.push(("class=\"" + (config.class) + "\""));
7734 }
7735
7736 if (config.id) {
7737 attrs.push(("id=\"" + (config.id) + "\""));
7738 }
7739
7740 if (title) {
7741 attrs.push(("title=\"" + title + "\""));
7742 }
7743
7744 return ("<a href=\"" + href + "\" " + (attrs.join(' ')) + ">" + text + "</a>");
7745 });
7746 };
7747
7748 var cachedLinks = {};
7749
7750 var compileMedia = {
7751 markdown: function markdown(url) {
7752 return {
7753 url: url,
7754 };
7755 },
7756 mermaid: function mermaid(url) {
7757 return {
7758 url: url,
7759 };
7760 },
7761 iframe: function iframe(url, title) {
7762 return {
7763 html: ("<iframe src=\"" + url + "\" " + (title ||
7764 'width=100% height=400') + "></iframe>"),
7765 };
7766 },
7767 video: function video(url, title) {
7768 return {
7769 html: ("<video src=\"" + url + "\" " + (title || 'controls') + ">Not Support</video>"),
7770 };
7771 },
7772 audio: function audio(url, title) {
7773 return {
7774 html: ("<audio src=\"" + url + "\" " + (title || 'controls') + ">Not Support</audio>"),
7775 };
7776 },
7777 code: function code(url, title) {
7778 var lang = url.match(/\.(\w+)$/);
7779
7780 lang = title || (lang && lang[1]);
7781 if (lang === 'md') {
7782 lang = 'markdown';
7783 }
7784
7785 return {
7786 url: url,
7787 lang: lang,
7788 };
7789 },
7790 };
7791
7792 var Compiler = function Compiler(config, router) {
7793 var this$1 = this;
7794
7795 this.config = config;
7796 this.router = router;
7797 this.cacheTree = {};
7798 this.toc = [];
7799 this.cacheTOC = {};
7800 this.linkTarget = config.externalLinkTarget || '_blank';
7801 this.linkRel =
7802 this.linkTarget === '_blank' ? config.externalLinkRel || 'noopener' : '';
7803 this.contentBase = router.getBasePath();
7804
7805 var renderer = this._initRenderer();
7806 this.heading = renderer.heading;
7807 var compile;
7808 var mdConf = config.markdown || {};
7809
7810 if (isFn(mdConf)) {
7811 compile = mdConf(marked_1, renderer);
7812 } else {
7813 marked_1.setOptions(
7814 merge(mdConf, {
7815 renderer: merge(renderer, mdConf.renderer),
7816 })
7817 );
7818 compile = marked_1;
7819 }
7820
7821 this._marked = compile;
7822 this.compile = function (text) {
7823 var isCached = true;
7824 // eslint-disable-next-line no-unused-vars
7825 var result = cached(function (_) {
7826 isCached = false;
7827 var html = '';
7828
7829 if (!text) {
7830 return text;
7831 }
7832
7833 if (isPrimitive(text)) {
7834 html = compile(text);
7835 } else {
7836 html = compile.parser(text);
7837 }
7838
7839 html = config.noEmoji ? html : emojify(html);
7840 slugify.clear();
7841
7842 return html;
7843 })(text);
7844
7845 var curFileName = this$1.router.parse().file;
7846
7847 if (isCached) {
7848 this$1.toc = this$1.cacheTOC[curFileName];
7849 } else {
7850 this$1.cacheTOC[curFileName] = [].concat( this$1.toc );
7851 }
7852
7853 return result;
7854 };
7855 };
7856
7857 /**
7858 * Pulls content from file and renders inline on the page as a embedded item.
7859 *
7860 * This allows you to embed different file types on the returned
7861 * page.
7862 * The basic format is:
7863 * ```
7864 * [filename](_media/example.md ':include')
7865 * ```
7866 *
7867 * @param {string} href The href to the file to embed in the page.
7868 * @param {string} titleTitle of the link used to make the embed.
7869 *
7870 * @return {type} Return value description.
7871 */
7872 Compiler.prototype.compileEmbed = function compileEmbed (href, title) {
7873 var ref = getAndRemoveConfig(title);
7874 var str = ref.str;
7875 var config = ref.config;
7876 var embed;
7877 title = str;
7878
7879 if (config.include) {
7880 if (!isAbsolutePath(href)) {
7881 href = getPath(
7882 this.contentBase,
7883 getParentPath(this.router.getCurrentPath()),
7884 href
7885 );
7886 }
7887
7888 var media;
7889 if (config.type && (media = compileMedia[config.type])) {
7890 embed = media.call(this, href, title);
7891 embed.type = config.type;
7892 } else {
7893 var type = 'code';
7894 if (/\.(md|markdown)/.test(href)) {
7895 type = 'markdown';
7896 } else if (/\.mmd/.test(href)) {
7897 type = 'mermaid';
7898 } else if (/\.html?/.test(href)) {
7899 type = 'iframe';
7900 } else if (/\.(mp4|ogg)/.test(href)) {
7901 type = 'video';
7902 } else if (/\.mp3/.test(href)) {
7903 type = 'audio';
7904 }
7905
7906 embed = compileMedia[type].call(this, href, title);
7907 embed.type = type;
7908 }
7909
7910 embed.fragment = config.fragment;
7911
7912 return embed;
7913 }
7914 };
7915
7916 Compiler.prototype._matchNotCompileLink = function _matchNotCompileLink (link) {
7917 var links = this.config.noCompileLinks || [];
7918
7919 for (var i = 0; i < links.length; i++) {
7920 var n = links[i];
7921 var re = cachedLinks[n] || (cachedLinks[n] = new RegExp(("^" + n + "$")));
7922
7923 if (re.test(link)) {
7924 return link;
7925 }
7926 }
7927 };
7928
7929 Compiler.prototype._initRenderer = function _initRenderer () {
7930 var renderer = new marked_1.Renderer();
7931 var ref = this;
7932 var linkTarget = ref.linkTarget;
7933 var linkRel = ref.linkRel;
7934 var router = ref.router;
7935 var contentBase = ref.contentBase;
7936 var _self = this;
7937 var origin = {};
7938
7939 /**
7940 * Render anchor tag
7941 * @link https://github.com/markedjs/marked#overriding-renderer-methods
7942 * @param {String} text Text content
7943 * @param {Number} level Type of heading (h<level> tag)
7944 * @returns {String} Heading element
7945 */
7946 origin.heading = renderer.heading = function(text, level) {
7947 var ref = getAndRemoveConfig(text);
7948 var str = ref.str;
7949 var config = ref.config;
7950 var nextToc = { level: level, title: removeAtag(str) };
7951
7952 if (/<!-- {docsify-ignore} -->/g.test(str)) {
7953 str = str.replace('<!-- {docsify-ignore} -->', '');
7954 nextToc.title = removeAtag(str);
7955 nextToc.ignoreSubHeading = true;
7956 }
7957
7958 if (/{docsify-ignore}/g.test(str)) {
7959 str = str.replace('{docsify-ignore}', '');
7960 nextToc.title = removeAtag(str);
7961 nextToc.ignoreSubHeading = true;
7962 }
7963
7964 if (/<!-- {docsify-ignore-all} -->/g.test(str)) {
7965 str = str.replace('<!-- {docsify-ignore-all} -->', '');
7966 nextToc.title = removeAtag(str);
7967 nextToc.ignoreAllSubs = true;
7968 }
7969
7970 if (/{docsify-ignore-all}/g.test(str)) {
7971 str = str.replace('{docsify-ignore-all}', '');
7972 nextToc.title = removeAtag(str);
7973 nextToc.ignoreAllSubs = true;
7974 }
7975
7976 var slug = slugify(config.id || str);
7977 var url = router.toURL(router.getCurrentPath(), { id: slug });
7978 nextToc.slug = url;
7979 _self.toc.push(nextToc);
7980
7981 return ("<h" + level + " id=\"" + slug + "\"><a href=\"" + url + "\" data-id=\"" + slug + "\" class=\"anchor\"><span>" + str + "</span></a></h" + level + ">");
7982 };
7983
7984 origin.code = highlightCodeCompiler({ renderer: renderer });
7985 origin.link = linkCompiler({
7986 renderer: renderer,
7987 router: router,
7988 linkTarget: linkTarget,
7989 linkRel: linkRel,
7990 compilerClass: _self,
7991 });
7992 origin.paragraph = paragraphCompiler({ renderer: renderer });
7993 origin.image = imageCompiler({ renderer: renderer, contentBase: contentBase, router: router });
7994 origin.list = taskListCompiler({ renderer: renderer });
7995 origin.listitem = taskListItemCompiler({ renderer: renderer });
7996
7997 renderer.origin = origin;
7998
7999 return renderer;
8000 };
8001
8002 /**
8003 * Compile sidebar
8004 * @param {String} text Text content
8005 * @param {Number} level Type of heading (h<level> tag)
8006 * @returns {String} Sidebar element
8007 */
8008 Compiler.prototype.sidebar = function sidebar (text, level) {
8009 var ref = this;
8010 var toc = ref.toc;
8011 var currentPath = this.router.getCurrentPath();
8012 var html = '';
8013
8014 if (text) {
8015 html = this.compile(text);
8016 } else {
8017 for (var i = 0; i < toc.length; i++) {
8018 if (toc[i].ignoreSubHeading) {
8019 var deletedHeaderLevel = toc[i].level;
8020 toc.splice(i, 1);
8021 // Remove headers who are under current header
8022 for (
8023 var j = i;
8024 j < toc.length && deletedHeaderLevel < toc[j].level;
8025 j++
8026 ) {
8027 toc.splice(j, 1) && j-- && i++;
8028 }
8029
8030 i--;
8031 }
8032 }
8033
8034 var tree$1 = this.cacheTree[currentPath] || genTree(toc, level);
8035 html = tree(tree$1, '<ul>{inner}</ul>');
8036 this.cacheTree[currentPath] = tree$1;
8037 }
8038
8039 return html;
8040 };
8041
8042 /**
8043 * Compile sub sidebar
8044 * @param {Number} level Type of heading (h<level> tag)
8045 * @returns {String} Sub-sidebar element
8046 */
8047 Compiler.prototype.subSidebar = function subSidebar (level) {
8048 if (!level) {
8049 this.toc = [];
8050 return;
8051 }
8052
8053 var currentPath = this.router.getCurrentPath();
8054 var ref = this;
8055 var cacheTree = ref.cacheTree;
8056 var toc = ref.toc;
8057
8058 toc[0] && toc[0].ignoreAllSubs && toc.splice(0);
8059 toc[0] && toc[0].level === 1 && toc.shift();
8060
8061 for (var i = 0; i < toc.length; i++) {
8062 toc[i].ignoreSubHeading && toc.splice(i, 1) && i--;
8063 }
8064
8065 var tree$1 = cacheTree[currentPath] || genTree(toc, level);
8066
8067 cacheTree[currentPath] = tree$1;
8068 this.toc = [];
8069 return tree(tree$1);
8070 };
8071
8072 Compiler.prototype.header = function header (text, level) {
8073 return this.heading(text, level);
8074 };
8075
8076 Compiler.prototype.article = function article (text) {
8077 return this.compile(text);
8078 };
8079
8080 /**
8081 * Compile cover page
8082 * @param {Text} text Text content
8083 * @returns {String} Cover page
8084 */
8085 Compiler.prototype.cover = function cover (text) {
8086 var cacheToc = this.toc.slice();
8087 var html = this.compile(text);
8088
8089 this.toc = cacheToc.slice();
8090
8091 return html;
8092 };
8093
8094 var minIndent = function (string) {
8095 var match = string.match(/^[ \t]*(?=\S)/gm);
8096
8097 if (!match) {
8098 return 0;
8099 }
8100
8101 return match.reduce(function (r, a) { return Math.min(r, a.length); }, Infinity);
8102 };
8103
8104 var stripIndent = function (string) {
8105 var indent = minIndent(string);
8106
8107 if (indent === 0) {
8108 return string;
8109 }
8110
8111 var regex = new RegExp(("^[ \\t]{" + indent + "}"), 'gm');
8112
8113 return string.replace(regex, '');
8114 };
8115
8116 var cached$2 = {};
8117
8118 function walkFetchEmbed(ref, cb) {
8119 var embedTokens = ref.embedTokens;
8120 var compile = ref.compile;
8121 var fetch = ref.fetch;
8122
8123 var token;
8124 var step = 0;
8125 var count = 1;
8126
8127 if (!embedTokens.length) {
8128 return cb({});
8129 }
8130
8131 while ((token = embedTokens[step++])) {
8132 // eslint-disable-next-line no-shadow
8133 var next = (function(token) {
8134 return function (text) {
8135 var embedToken;
8136 if (text) {
8137 if (token.embed.type === 'markdown') {
8138 var path = token.embed.url.split('/');
8139 path.pop();
8140 path = path.join('/');
8141 // Resolves relative links to absolute
8142 text = text.replace(/\[([^[\]]+)\]\(([^)]+)\)/g, function (x) {
8143 var linkBeginIndex = x.indexOf('(');
8144 if (x.slice(linkBeginIndex, linkBeginIndex + 2) === '(.') {
8145 return (
8146 x.substring(0, linkBeginIndex) +
8147 "(" + (window.location.protocol) + "//" + (window.location.host) + path + "/" +
8148 x.substring(linkBeginIndex + 1, x.length - 1) +
8149 ')'
8150 );
8151 }
8152 return x;
8153 });
8154
8155 // This may contain YAML front matter and will need to be stripped.
8156 var frontMatterInstalled =
8157 ($docsify.frontMatter || {}).installed || false;
8158 if (frontMatterInstalled === true) {
8159 text = $docsify.frontMatter.parseMarkdown(text);
8160 }
8161
8162 embedToken = compile.lexer(text);
8163 } else if (token.embed.type === 'code') {
8164 if (token.embed.fragment) {
8165 var fragment = token.embed.fragment;
8166 var pattern = new RegExp(
8167 ("(?:###|\\/\\/\\/)\\s*\\[" + fragment + "\\]([\\s\\S]*)(?:###|\\/\\/\\/)\\s*\\[" + fragment + "\\]")
8168 );
8169 text = stripIndent((text.match(pattern) || [])[1] || '').trim();
8170 }
8171
8172 embedToken = compile.lexer(
8173 '```' +
8174 token.embed.lang +
8175 '\n' +
8176 text.replace(/`/g, '@DOCSIFY_QM@') +
8177 '\n```\n'
8178 );
8179 } else if (token.embed.type === 'mermaid') {
8180 embedToken = [
8181 { type: 'html', text: ("<div class=\"mermaid\">\n" + text + "\n</div>") } ];
8182 embedToken.links = {};
8183 } else {
8184 embedToken = [{ type: 'html', text: text }];
8185 embedToken.links = {};
8186 }
8187 }
8188
8189 cb({ token: token, embedToken: embedToken });
8190 if (++count >= step) {
8191 cb({});
8192 }
8193 };
8194 })(token);
8195
8196 if (token.embed.url) {
8197 {
8198 get(token.embed.url).then(next);
8199 }
8200 } else {
8201 next(token.embed.html);
8202 }
8203 }
8204 }
8205
8206 function prerenderEmbed(ref, done) {
8207 var compiler = ref.compiler;
8208 var raw = ref.raw; if ( raw === void 0 ) raw = '';
8209 var fetch = ref.fetch;
8210
8211 var hit = cached$2[raw];
8212 if (hit) {
8213 var copy = hit.slice();
8214 copy.links = hit.links;
8215 return done(copy);
8216 }
8217
8218 var compile = compiler._marked;
8219 var tokens = compile.lexer(raw);
8220 var embedTokens = [];
8221 var linkRE = compile.Lexer.rules.inline.link;
8222 var links = tokens.links;
8223
8224 tokens.forEach(function (token, index) {
8225 if (token.type === 'paragraph') {
8226 token.text = token.text.replace(
8227 new RegExp(linkRE.source, 'g'),
8228 function (src, filename, href, title) {
8229 var embed = compiler.compileEmbed(href, title);
8230
8231 if (embed) {
8232 embedTokens.push({
8233 index: index,
8234 embed: embed,
8235 });
8236 }
8237
8238 return src;
8239 }
8240 );
8241 }
8242 });
8243
8244 // keep track of which tokens have been embedded so far
8245 // so that we know where to insert the embedded tokens as they
8246 // are returned
8247 var moves = [];
8248 walkFetchEmbed({ compile: compile, embedTokens: embedTokens, fetch: fetch }, function (ref) {
8249 var embedToken = ref.embedToken;
8250 var token = ref.token;
8251
8252 if (token) {
8253 // iterate through the array of previously inserted tokens
8254 // to determine where the current embedded tokens should be inserted
8255 var index = token.index;
8256 moves.forEach(function (pos) {
8257 if (index > pos.start) {
8258 index += pos.length;
8259 }
8260 });
8261
8262 merge(links, embedToken.links);
8263
8264 tokens = tokens
8265 .slice(0, index)
8266 .concat(embedToken, tokens.slice(index + 1));
8267 moves.push({ start: index, length: embedToken.length - 1 });
8268 } else {
8269 cached$2[raw] = tokens.concat();
8270 tokens.links = cached$2[raw].links = links;
8271 done(tokens);
8272 }
8273 });
8274 }
8275
8276 /* eslint-disable no-unused-vars */
8277
8278 var vueGlobalData;
8279
8280 function executeScript() {
8281 var script = findAll('.markdown-section>script')
8282 .filter(function (s) { return !/template/.test(s.type); })[0];
8283 if (!script) {
8284 return false;
8285 }
8286
8287 var code = script.innerText.trim();
8288 if (!code) {
8289 return false;
8290 }
8291
8292 new Function(code)();
8293 }
8294
8295 function formatUpdated(html, updated, fn) {
8296 updated =
8297 typeof fn === 'function'
8298 ? fn(updated)
8299 : typeof fn === 'string'
8300 ? tinydate(fn)(new Date(updated))
8301 : updated;
8302
8303 return html.replace(/{docsify-updated}/g, updated);
8304 }
8305
8306 function renderMain(html) {
8307 var docsifyConfig = this.config;
8308 var markdownElm = find('.markdown-section');
8309 var vueVersion =
8310 'Vue' in window &&
8311 window.Vue.version &&
8312 Number(window.Vue.version.charAt(0));
8313
8314 var isMountedVue = function (elm) {
8315 var isVue2 = Boolean(elm.__vue__ && elm.__vue__._isVue);
8316 var isVue3 = Boolean(elm._vnode && elm._vnode.__v_skip);
8317
8318 return isVue2 || isVue3;
8319 };
8320
8321 if (!html) {
8322 html = '<h1>404 - Not found</h1>';
8323 }
8324
8325 if ('Vue' in window) {
8326 var mountedElms = findAll('.markdown-section > *')
8327 .filter(function (elm) { return isMountedVue(elm); });
8328
8329 // Destroy/unmount existing Vue instances
8330 for (var i = 0, list = mountedElms; i < list.length; i += 1) {
8331 var mountedElm = list[i];
8332
8333 if (vueVersion === 2) {
8334 mountedElm.__vue__.$destroy();
8335 } else if (vueVersion === 3) {
8336 mountedElm.__vue_app__.unmount();
8337 }
8338 }
8339 }
8340
8341 this._renderTo(markdownElm, html);
8342
8343 // Render sidebar with the TOC
8344 !docsifyConfig.loadSidebar && this._renderSidebar();
8345
8346 // Execute markdown <script>
8347 if (
8348 docsifyConfig.executeScript ||
8349 ('Vue' in window && docsifyConfig.executeScript !== false)
8350 ) {
8351 executeScript();
8352 }
8353
8354 // Handle Vue content not mounted by markdown <script>
8355 if ('Vue' in window) {
8356 var vueMountData = [];
8357 var vueComponentNames = Object.keys(docsifyConfig.vueComponents || {});
8358
8359 // Register global vueComponents
8360 if (vueVersion === 2 && vueComponentNames.length) {
8361 vueComponentNames.forEach(function (name) {
8362 var isNotRegistered = !window.Vue.options.components[name];
8363
8364 if (isNotRegistered) {
8365 window.Vue.component(name, docsifyConfig.vueComponents[name]);
8366 }
8367 });
8368 }
8369
8370 // Store global data() return value as shared data object
8371 if (
8372 !vueGlobalData &&
8373 docsifyConfig.vueGlobalOptions &&
8374 typeof docsifyConfig.vueGlobalOptions.data === 'function'
8375 ) {
8376 vueGlobalData = docsifyConfig.vueGlobalOptions.data();
8377 }
8378
8379 // vueMounts
8380 vueMountData.push.apply(
8381 vueMountData, Object.keys(docsifyConfig.vueMounts || {})
8382 .map(function (cssSelector) { return [
8383 find(markdownElm, cssSelector),
8384 docsifyConfig.vueMounts[cssSelector] ]; })
8385 .filter(function (ref) {
8386 var elm = ref[0];
8387 var vueConfig = ref[1];
8388
8389 return elm;
8390 })
8391 );
8392
8393 // Template syntax, vueComponents, vueGlobalOptions
8394 if (docsifyConfig.vueGlobalOptions || vueComponentNames.length) {
8395 var reHasBraces = /{{2}[^{}]*}{2}/;
8396 // Matches Vue full and shorthand syntax as attributes in HTML tags.
8397 //
8398 // Full syntax examples:
8399 // v-foo, v-foo[bar], v-foo-bar, v-foo:bar-baz.prop
8400 //
8401 // Shorthand syntax examples:
8402 // @foo, @foo.bar, @foo.bar.baz, @[foo], :foo, :[foo]
8403 //
8404 // Markup examples:
8405 // <div v-html>{{ html }}</div>
8406 // <div v-text="msg"></div>
8407 // <div v-bind:text-content.prop="text">
8408 // <button v-on:click="doThis"></button>
8409 // <button v-on:click.once="doThis"></button>
8410 // <button v-on:[event]="doThis"></button>
8411 // <button @click.stop.prevent="doThis">
8412 // <a :href="url">
8413 // <a :[key]="url">
8414 var reHasDirective = /<[^>/]+\s([@:]|v-)[\w-:.[\]]+[=>\s]/;
8415
8416 vueMountData.push.apply(
8417 vueMountData, findAll('.markdown-section > *')
8418 // Remove duplicates
8419 .filter(function (elm) { return !vueMountData.some(function (ref) {
8420 var e = ref[0];
8421 var c = ref[1];
8422
8423 return e === elm;
8424 }); })
8425 // Detect Vue content
8426 .filter(function (elm) {
8427 var isVueMount =
8428 // is a component
8429 elm.tagName.toLowerCase() in
8430 (docsifyConfig.vueComponents || {}) ||
8431 // has a component(s)
8432 elm.querySelector(vueComponentNames.join(',') || null) ||
8433 // has curly braces
8434 reHasBraces.test(elm.outerHTML) ||
8435 // has content directive
8436 reHasDirective.test(elm.outerHTML);
8437
8438 return isVueMount;
8439 })
8440 .map(function (elm) {
8441 // Clone global configuration
8442 var vueConfig = merge({}, docsifyConfig.vueGlobalOptions || {});
8443
8444 // Replace vueGlobalOptions data() return value with shared data object.
8445 // This provides a global store for all Vue instances that receive
8446 // vueGlobalOptions as their configuration.
8447 if (vueGlobalData) {
8448 vueConfig.data = function() {
8449 return vueGlobalData;
8450 };
8451 }
8452
8453 return [elm, vueConfig];
8454 })
8455 );
8456 }
8457
8458 // Mount
8459 for (var i$1 = 0, list$1 = vueMountData; i$1 < list$1.length; i$1 += 1) {
8460 var ref = list$1[i$1];
8461 var mountElm = ref[0];
8462 var vueConfig = ref[1];
8463
8464 var isVueAttr = 'data-isvue';
8465 var isSkipElm =
8466 // Is an invalid tag
8467 mountElm.matches('pre, script') ||
8468 // Is a mounted instance
8469 isMountedVue(mountElm) ||
8470 // Has mounted instance(s)
8471 mountElm.querySelector(("[" + isVueAttr + "]"));
8472
8473 if (!isSkipElm) {
8474 mountElm.setAttribute(isVueAttr, '');
8475
8476 if (vueVersion === 2) {
8477 vueConfig.el = undefined;
8478 new window.Vue(vueConfig).$mount(mountElm);
8479 } else if (vueVersion === 3) {
8480 var app = window.Vue.createApp(vueConfig);
8481
8482 // Register global vueComponents
8483 vueComponentNames.forEach(function (name) {
8484 var config = docsifyConfig.vueComponents[name];
8485
8486 app.component(name, config);
8487 });
8488
8489 app.mount(mountElm);
8490 }
8491 }
8492 }
8493 }
8494 }
8495
8496 function renderNameLink(vm) {
8497 var el = getNode('.app-name-link');
8498 var nameLink = vm.config.nameLink;
8499 var path = vm.route.path;
8500
8501 if (!el) {
8502 return;
8503 }
8504
8505 if (isPrimitive(vm.config.nameLink)) {
8506 el.setAttribute('href', nameLink);
8507 } else if (typeof nameLink === 'object') {
8508 var match = Object.keys(nameLink).filter(
8509 function (key) { return path.indexOf(key) > -1; }
8510 )[0];
8511
8512 el.setAttribute('href', nameLink[match]);
8513 }
8514 }
8515
8516 /** @typedef {import('../Docsify').Constructor} Constructor */
8517
8518 /**
8519 * @template {!Constructor} T
8520 * @param {T} Base - The class to extend
8521 */
8522 function Render(Base) {
8523 return /*@__PURE__*/(function (Base) {
8524 function Render () {
8525 Base.apply(this, arguments);
8526 }
8527
8528 if ( Base ) Render.__proto__ = Base;
8529 Render.prototype = Object.create( Base && Base.prototype );
8530 Render.prototype.constructor = Render;
8531
8532 Render.prototype._renderTo = function _renderTo (el, content, replace) {
8533 var node = getNode(el);
8534 if (node) {
8535 node[replace ? 'outerHTML' : 'innerHTML'] = content;
8536 }
8537 };
8538
8539 Render.prototype._renderSidebar = function _renderSidebar (text) {
8540 var ref = this.config;
8541 var maxLevel = ref.maxLevel;
8542 var subMaxLevel = ref.subMaxLevel;
8543 var loadSidebar = ref.loadSidebar;
8544 var hideSidebar = ref.hideSidebar;
8545
8546 if (hideSidebar) {
8547 // FIXME : better styling solution
8548 [
8549 document.querySelector('aside.sidebar'),
8550 document.querySelector('button.sidebar-toggle') ].forEach(function (node) { return node.parentNode.removeChild(node); });
8551 document.querySelector('section.content').style.right = 'unset';
8552 document.querySelector('section.content').style.left = 'unset';
8553 document.querySelector('section.content').style.position = 'relative';
8554 document.querySelector('section.content').style.width = '100%';
8555 return null;
8556 }
8557
8558 this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel));
8559 var activeEl = getAndActive(this.router, '.sidebar-nav', true, true);
8560 if (loadSidebar && activeEl) {
8561 activeEl.parentNode.innerHTML +=
8562 this.compiler.subSidebar(subMaxLevel) || '';
8563 } else {
8564 // Reset toc
8565 this.compiler.subSidebar();
8566 }
8567
8568 // Bind event
8569 this._bindEventOnRendered(activeEl);
8570 };
8571
8572 Render.prototype._bindEventOnRendered = function _bindEventOnRendered (activeEl) {
8573 var ref = this.config;
8574 var autoHeader = ref.autoHeader;
8575
8576 scrollActiveSidebar(this.router);
8577
8578 if (autoHeader && activeEl) {
8579 var main = getNode('#main');
8580 var firstNode = main.children[0];
8581 if (firstNode && firstNode.tagName !== 'H1') {
8582 var h1 = this.compiler.header(activeEl.innerText, 1);
8583 var wrapper = create('div', h1);
8584 before(main, wrapper.children[0]);
8585 }
8586 }
8587 };
8588
8589 Render.prototype._renderNav = function _renderNav (text) {
8590 text && this._renderTo('nav', this.compiler.compile(text));
8591 if (this.config.loadNavbar) {
8592 getAndActive(this.router, 'nav');
8593 }
8594 };
8595
8596 Render.prototype._renderMain = function _renderMain (text, opt, next) {
8597 var this$1 = this;
8598 if ( opt === void 0 ) opt = {};
8599
8600 if (!text) {
8601 return renderMain.call(this, text);
8602 }
8603
8604 this.callHook('beforeEach', text, function (result) {
8605 var html;
8606 var callback = function () {
8607 if (opt.updatedAt) {
8608 html = formatUpdated(
8609 html,
8610 opt.updatedAt,
8611 this$1.config.formatUpdated
8612 );
8613 }
8614
8615 this$1.callHook('afterEach', html, function (hookData) { return renderMain.call(this$1, hookData); }
8616 );
8617 };
8618
8619 if (this$1.isHTML) {
8620 html = this$1.result = text;
8621 callback();
8622 next();
8623 } else {
8624 prerenderEmbed(
8625 {
8626 compiler: this$1.compiler,
8627 raw: result,
8628 },
8629 function (tokens) {
8630 html = this$1.compiler.compile(tokens);
8631 html = this$1.isRemoteUrl
8632 ? purify.sanitize(html, { ADD_TAGS: ['script'] })
8633 : html;
8634 callback();
8635 next();
8636 }
8637 );
8638 }
8639 });
8640 };
8641
8642 Render.prototype._renderCover = function _renderCover (text, coverOnly) {
8643 var el = getNode('.cover');
8644
8645 toggleClass(
8646 getNode('main'),
8647 coverOnly ? 'add' : 'remove',
8648 'hidden'
8649 );
8650 if (!text) {
8651 toggleClass(el, 'remove', 'show');
8652 return;
8653 }
8654
8655 toggleClass(el, 'add', 'show');
8656
8657 var html = this.coverIsHTML ? text : this.compiler.cover(text);
8658
8659 var m = html
8660 .trim()
8661 .match('<p><img.*?data-origin="(.*?)"[^a]+alt="(.*?)">([^<]*?)</p>$');
8662
8663 if (m) {
8664 if (m[2] === 'color') {
8665 el.style.background = m[1] + (m[3] || '');
8666 } else {
8667 var path = m[1];
8668
8669 toggleClass(el, 'add', 'has-mask');
8670 if (!isAbsolutePath(m[1])) {
8671 path = getPath(this.router.getBasePath(), m[1]);
8672 }
8673
8674 el.style.backgroundImage = "url(" + path + ")";
8675 el.style.backgroundSize = 'cover';
8676 el.style.backgroundPosition = 'center center';
8677 }
8678
8679 html = html.replace(m[0], '');
8680 }
8681
8682 this._renderTo('.cover-main', html);
8683 sticky();
8684 };
8685
8686 Render.prototype._updateRender = function _updateRender () {
8687 // Render name link
8688 renderNameLink(this);
8689 };
8690
8691 Render.prototype.initRender = function initRender () {
8692 var config = this.config;
8693
8694 // Init markdown compiler
8695 this.compiler = new Compiler(config, this.router);
8696 {
8697 /* eslint-disable-next-line camelcase */
8698 window.__current_docsify_compiler__ = this.compiler;
8699 }
8700
8701 var id = config.el || '#app';
8702 var navEl = find('nav') || create('nav');
8703
8704 var el = find(id);
8705 var html = '';
8706 var navAppendToTarget = body;
8707
8708 if (el) {
8709 if (config.repo) {
8710 html += corner(config.repo, config.cornerExternalLinkTarge);
8711 }
8712
8713 if (config.coverpage) {
8714 html += cover();
8715 }
8716
8717 if (config.logo) {
8718 var isBase64 = /^data:image/.test(config.logo);
8719 var isExternal = /(?:http[s]?:)?\/\//.test(config.logo);
8720 var isRelative = /^\./.test(config.logo);
8721
8722 if (!isBase64 && !isExternal && !isRelative) {
8723 config.logo = getPath(this.router.getBasePath(), config.logo);
8724 }
8725 }
8726
8727 html += main(config);
8728 // Render main app
8729 this._renderTo(el, html, true);
8730 } else {
8731 this.rendered = true;
8732 }
8733
8734 if (config.mergeNavbar && isMobile) {
8735 navAppendToTarget = find('.sidebar');
8736 } else {
8737 navEl.classList.add('app-nav');
8738
8739 if (!config.repo) {
8740 navEl.classList.add('no-badge');
8741 }
8742 }
8743
8744 // Add nav
8745 if (config.loadNavbar) {
8746 before(navAppendToTarget, navEl);
8747 }
8748
8749 if (config.themeColor) {
8750 $.head.appendChild(
8751 create('div', theme(config.themeColor)).firstElementChild
8752 );
8753 // Polyfll
8754 cssVars(config.themeColor);
8755 }
8756
8757 this._updateRender();
8758 toggleClass(body, 'ready');
8759 };
8760
8761 return Render;
8762 }(Base));
8763 }
8764
8765 /* eslint-disable no-unused-vars */
8766
8767 function loadNested(path, qs, file, next, vm, first) {
8768 path = first ? path : path.replace(/\/$/, '');
8769 path = getParentPath(path);
8770
8771 if (!path) {
8772 return;
8773 }
8774
8775 get(
8776 vm.router.getFile(path + file) + qs,
8777 false,
8778 vm.config.requestHeaders
8779 ).then(next, function (_) { return loadNested(path, qs, file, next, vm); });
8780 }
8781
8782 /** @typedef {import('../Docsify').Constructor} Constructor */
8783
8784 /**
8785 * @template {!Constructor} T
8786 * @param {T} Base - The class to extend
8787 */
8788 function Fetch(Base) {
8789 var last;
8790
8791 var abort = function () { return last && last.abort && last.abort(); };
8792 var request = function (url, hasbar, requestHeaders) {
8793 abort();
8794 last = get(url, true, requestHeaders);
8795 return last;
8796 };
8797
8798 var get404Path = function (path, config) {
8799 var notFoundPage = config.notFoundPage;
8800 var ext = config.ext;
8801 var defaultPath = '_404' + (ext || '.md');
8802 var key;
8803 var path404;
8804
8805 switch (typeof notFoundPage) {
8806 case 'boolean':
8807 path404 = defaultPath;
8808 break;
8809 case 'string':
8810 path404 = notFoundPage;
8811 break;
8812
8813 case 'object':
8814 key = Object.keys(notFoundPage)
8815 .sort(function (a, b) { return b.length - a.length; })
8816 .filter(function (k) { return path.match(new RegExp('^' + k)); })[0];
8817
8818 path404 = (key && notFoundPage[key]) || defaultPath;
8819 break;
8820 }
8821
8822 return path404;
8823 };
8824
8825 return /*@__PURE__*/(function (Base) {
8826 function Fetch () {
8827 Base.apply(this, arguments);
8828 }
8829
8830 if ( Base ) Fetch.__proto__ = Base;
8831 Fetch.prototype = Object.create( Base && Base.prototype );
8832 Fetch.prototype.constructor = Fetch;
8833
8834 Fetch.prototype._loadSideAndNav = function _loadSideAndNav (path, qs, loadSidebar, cb) {
8835 var this$1 = this;
8836
8837 return function () {
8838 if (!loadSidebar) {
8839 return cb();
8840 }
8841
8842 var fn = function (result) {
8843 this$1._renderSidebar(result);
8844 cb();
8845 };
8846
8847 // Load sidebar
8848 loadNested(path, qs, loadSidebar, fn, this$1, true);
8849 };
8850 };
8851
8852 Fetch.prototype._fetch = function _fetch (cb) {
8853 var this$1 = this;
8854 if ( cb === void 0 ) cb = noop;
8855
8856 var ref = this.route;
8857 var query = ref.query;
8858 var ref$1 = this.route;
8859 var path = ref$1.path;
8860
8861 // Prevent loading remote content via URL hash
8862 // Ex: https://foo.com/#//bar.com/file.md
8863 if (isExternal(path)) {
8864 history.replaceState(null, '', '#');
8865 this.router.normalize();
8866 } else {
8867 var qs = stringifyQuery(query, ['id']);
8868 var ref$2 = this.config;
8869 var loadNavbar = ref$2.loadNavbar;
8870 var requestHeaders = ref$2.requestHeaders;
8871 var loadSidebar = ref$2.loadSidebar;
8872 // Abort last request
8873
8874 var file = this.router.getFile(path);
8875 var req = request(file + qs, true, requestHeaders);
8876
8877 this.isRemoteUrl = isExternal(file);
8878 // Current page is html
8879 this.isHTML = /\.html$/g.test(file);
8880
8881 // Load main content
8882 req.then(
8883 function (text, opt) { return this$1._renderMain(
8884 text,
8885 opt,
8886 this$1._loadSideAndNav(path, qs, loadSidebar, cb)
8887 ); },
8888 function (_) {
8889 this$1._fetchFallbackPage(path, qs, cb) ||
8890 this$1._fetch404(file, qs, cb);
8891 }
8892 );
8893
8894 // Load nav
8895 loadNavbar &&
8896 loadNested(
8897 path,
8898 qs,
8899 loadNavbar,
8900 function (text) { return this$1._renderNav(text); },
8901 this,
8902 true
8903 );
8904 }
8905 };
8906
8907 Fetch.prototype._fetchCover = function _fetchCover () {
8908 var this$1 = this;
8909
8910 var ref = this.config;
8911 var coverpage = ref.coverpage;
8912 var requestHeaders = ref.requestHeaders;
8913 var query = this.route.query;
8914 var root = getParentPath(this.route.path);
8915
8916 if (coverpage) {
8917 var path = null;
8918 var routePath = this.route.path;
8919 if (typeof coverpage === 'string') {
8920 if (routePath === '/') {
8921 path = coverpage;
8922 }
8923 } else if (Array.isArray(coverpage)) {
8924 path = coverpage.indexOf(routePath) > -1 && '_coverpage';
8925 } else {
8926 var cover = coverpage[routePath];
8927 path = cover === true ? '_coverpage' : cover;
8928 }
8929
8930 var coverOnly = Boolean(path) && this.config.onlyCover;
8931 if (path) {
8932 path = this.router.getFile(root + path);
8933 this.coverIsHTML = /\.html$/g.test(path);
8934 get(
8935 path + stringifyQuery(query, ['id']),
8936 false,
8937 requestHeaders
8938 ).then(function (text) { return this$1._renderCover(text, coverOnly); });
8939 } else {
8940 this._renderCover(null, coverOnly);
8941 }
8942
8943 return coverOnly;
8944 }
8945 };
8946
8947 Fetch.prototype.$fetch = function $fetch (cb, $resetEvents) {
8948 var this$1 = this;
8949 if ( cb === void 0 ) cb = noop;
8950 if ( $resetEvents === void 0 ) $resetEvents = this.$resetEvents.bind(this);
8951
8952 var done = function () {
8953 this$1.callHook('doneEach');
8954 cb();
8955 };
8956
8957 var onlyCover = this._fetchCover();
8958
8959 if (onlyCover) {
8960 done();
8961 } else {
8962 this._fetch(function () {
8963 $resetEvents();
8964 done();
8965 });
8966 }
8967 };
8968
8969 Fetch.prototype._fetchFallbackPage = function _fetchFallbackPage (path, qs, cb) {
8970 var this$1 = this;
8971 if ( cb === void 0 ) cb = noop;
8972
8973 var ref = this.config;
8974 var requestHeaders = ref.requestHeaders;
8975 var fallbackLanguages = ref.fallbackLanguages;
8976 var loadSidebar = ref.loadSidebar;
8977
8978 if (!fallbackLanguages) {
8979 return false;
8980 }
8981
8982 var local = path.split('/')[1];
8983
8984 if (fallbackLanguages.indexOf(local) === -1) {
8985 return false;
8986 }
8987
8988 var newPath = this.router.getFile(
8989 path.replace(new RegExp(("^/" + local)), '')
8990 );
8991 var req = request(newPath + qs, true, requestHeaders);
8992
8993 req.then(
8994 function (text, opt) { return this$1._renderMain(
8995 text,
8996 opt,
8997 this$1._loadSideAndNav(path, qs, loadSidebar, cb)
8998 ); },
8999 function () { return this$1._fetch404(path, qs, cb); }
9000 );
9001
9002 return true;
9003 };
9004
9005 /**
9006 * Load the 404 page
9007 * @param {String} path URL to be loaded
9008 * @param {*} qs TODO: define
9009 * @param {Function} cb Callback
9010 * @returns {Boolean} True if the requested page is not found
9011 * @private
9012 */
9013 Fetch.prototype._fetch404 = function _fetch404 (path, qs, cb) {
9014 var this$1 = this;
9015 if ( cb === void 0 ) cb = noop;
9016
9017 var ref = this.config;
9018 var loadSidebar = ref.loadSidebar;
9019 var requestHeaders = ref.requestHeaders;
9020 var notFoundPage = ref.notFoundPage;
9021
9022 var fnLoadSideAndNav = this._loadSideAndNav(path, qs, loadSidebar, cb);
9023 if (notFoundPage) {
9024 var path404 = get404Path(path, this.config);
9025
9026 request(this.router.getFile(path404), true, requestHeaders).then(
9027 function (text, opt) { return this$1._renderMain(text, opt, fnLoadSideAndNav); },
9028 function () { return this$1._renderMain(null, {}, fnLoadSideAndNav); }
9029 );
9030 return true;
9031 }
9032
9033 this._renderMain(null, {}, fnLoadSideAndNav);
9034 return false;
9035 };
9036
9037 Fetch.prototype.initFetch = function initFetch () {
9038 var this$1 = this;
9039
9040 var ref = this.config;
9041 var loadSidebar = ref.loadSidebar;
9042
9043 // Server-Side Rendering
9044 if (this.rendered) {
9045 var activeEl = getAndActive(this.router, '.sidebar-nav', true, true);
9046 if (loadSidebar && activeEl) {
9047 activeEl.parentNode.innerHTML += window.__SUB_SIDEBAR__;
9048 }
9049
9050 this._bindEventOnRendered(activeEl);
9051 this.$resetEvents();
9052 this.callHook('doneEach');
9053 this.callHook('ready');
9054 } else {
9055 this.$fetch(function (_) { return this$1.callHook('ready'); });
9056 }
9057 };
9058
9059 return Fetch;
9060 }(Base));
9061 }
9062
9063 /** @typedef {import('../Docsify').Constructor} Constructor */
9064
9065 /**
9066 * @template {!Constructor} T
9067 * @param {T} Base - The class to extend
9068 */
9069 function Events(Base) {
9070 return /*@__PURE__*/(function (Base) {
9071 function Events () {
9072 Base.apply(this, arguments);
9073 }
9074
9075 if ( Base ) Events.__proto__ = Base;
9076 Events.prototype = Object.create( Base && Base.prototype );
9077 Events.prototype.constructor = Events;
9078
9079 Events.prototype.$resetEvents = function $resetEvents (source) {
9080 var this$1 = this;
9081
9082 var ref = this.config;
9083 var auto2top = ref.auto2top;
9084
9085 (function () {
9086 // Rely on the browser's scroll auto-restoration when going back or forward
9087 if (source === 'history') {
9088 return;
9089 }
9090 // Scroll to ID if specified
9091 if (this$1.route.query.id) {
9092 scrollIntoView(this$1.route.path, this$1.route.query.id);
9093 }
9094 // Scroll to top if a link was clicked and auto2top is enabled
9095 if (source === 'navigate') {
9096 auto2top && scroll2Top(auto2top);
9097 }
9098 })();
9099
9100 if (this.config.loadNavbar) {
9101 getAndActive(this.router, 'nav');
9102 }
9103 };
9104
9105 Events.prototype.initEvent = function initEvent () {
9106 // Bind toggle button
9107 btn('button.sidebar-toggle', this.router);
9108 collapse('.sidebar', this.router);
9109 // Bind sticky effect
9110 if (this.config.coverpage) {
9111 !isMobile && on('scroll', sticky);
9112 } else {
9113 body.classList.add('sticky');
9114 }
9115 };
9116
9117 return Events;
9118 }(Base));
9119 }
9120
9121
9122
9123 var util = /*#__PURE__*/Object.freeze({
9124 __proto__: null,
9125 cached: cached,
9126 hyphenate: hyphenate,
9127 hasOwn: hasOwn,
9128 merge: merge,
9129 isPrimitive: isPrimitive,
9130 noop: noop,
9131 isFn: isFn,
9132 isExternal: isExternal,
9133 inBrowser: inBrowser,
9134 isMobile: isMobile,
9135 supportsPushState: supportsPushState,
9136 parseQuery: parseQuery,
9137 stringifyQuery: stringifyQuery,
9138 isAbsolutePath: isAbsolutePath,
9139 removeParams: removeParams,
9140 getParentPath: getParentPath,
9141 cleanPath: cleanPath,
9142 resolvePath: resolvePath,
9143 getPath: getPath,
9144 replaceSlug: replaceSlug,
9145 endsWith: endsWith
9146 });
9147
9148 // TODO This is deprecated, kept for backwards compatibility. Remove in next
9149 // major release. We'll tell people to get everything from the DOCSIFY global
9150 // when using the global build, but we'll highly recommend for them to import
9151 // from the ESM build (f.e. lib/docsify.esm.js and lib/docsify.min.esm.js).
9152 function initGlobalAPI() {
9153 window.Docsify = {
9154 util: util,
9155 dom: dom,
9156 get: get,
9157 slugify: slugify,
9158 version: '4.12.2',
9159 };
9160 window.DocsifyCompiler = Compiler;
9161 window.marked = marked_1;
9162 window.Prism = prism;
9163 }
9164
9165 /** @typedef {import('../Docsify').Constructor} Constructor */
9166
9167 /**
9168 * @template {!Constructor} T
9169 * @param {T} Base - The class to extend
9170 */
9171 function Lifecycle(Base) {
9172 return /*@__PURE__*/(function (Base) {
9173 function Lifecycle () {
9174 Base.apply(this, arguments);
9175 }
9176
9177 if ( Base ) Lifecycle.__proto__ = Base;
9178 Lifecycle.prototype = Object.create( Base && Base.prototype );
9179 Lifecycle.prototype.constructor = Lifecycle;
9180
9181 Lifecycle.prototype.initLifecycle = function initLifecycle () {
9182 var this$1 = this;
9183
9184 var hooks = [
9185 'init',
9186 'mounted',
9187 'beforeEach',
9188 'afterEach',
9189 'doneEach',
9190 'ready' ];
9191
9192 this._hooks = {};
9193 this._lifecycle = {};
9194
9195 hooks.forEach(function (hook) {
9196 var arr = (this$1._hooks[hook] = []);
9197 this$1._lifecycle[hook] = function (fn) { return arr.push(fn); };
9198 });
9199 };
9200
9201 Lifecycle.prototype.callHook = function callHook (hookName, data, next) {
9202 if ( next === void 0 ) next = noop;
9203
9204 var queue = this._hooks[hookName];
9205
9206 var step = function(index) {
9207 var hookFn = queue[index];
9208
9209 if (index >= queue.length) {
9210 next(data);
9211 } else if (typeof hookFn === 'function') {
9212 if (hookFn.length === 2) {
9213 hookFn(data, function (result) {
9214 data = result;
9215 step(index + 1);
9216 });
9217 } else {
9218 var result = hookFn(data);
9219 data = result === undefined ? data : result;
9220 step(index + 1);
9221 }
9222 } else {
9223 step(index + 1);
9224 }
9225 };
9226
9227 step(0);
9228 };
9229
9230 return Lifecycle;
9231 }(Base));
9232 }
9233
9234 /** @typedef {new (...args: any[]) => any} Constructor */
9235
9236 // eslint-disable-next-line new-cap
9237 var Docsify = /*@__PURE__*/(function (superclass) {
9238 function Docsify() {
9239 superclass.call(this);
9240
9241 this.config = config(this);
9242
9243 this.initLifecycle(); // Init hooks
9244 this.initPlugin(); // Install plugins
9245 this.callHook('init');
9246 this.initRouter(); // Add router
9247 this.initRender(); // Render base DOM
9248 this.initEvent(); // Bind events
9249 this.initFetch(); // Fetch data
9250 this.callHook('mounted');
9251 }
9252
9253 if ( superclass ) Docsify.__proto__ = superclass;
9254 Docsify.prototype = Object.create( superclass && superclass.prototype );
9255 Docsify.prototype.constructor = Docsify;
9256
9257 Docsify.prototype.initPlugin = function initPlugin () {
9258 var this$1 = this;
9259
9260 []
9261 .concat(this.config.plugins)
9262 .forEach(function (fn) { return isFn(fn) && fn(this$1._lifecycle, this$1); });
9263 };
9264
9265 return Docsify;
9266 }(Fetch(Events(Render(Router(Lifecycle(Object)))))));
9267
9268 /**
9269 * Global API
9270 */
9271 initGlobalAPI();
9272
9273 /**
9274 * Run Docsify
9275 */
9276 // eslint-disable-next-line no-unused-vars
9277 documentReady(function (_) { return new Docsify(); });
9278
9279}());