PluginProbe
Gutenberg / 16.2.0
Gutenberg v16.2.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / blocks / index.js

index.js in Gutenberg 16.2.0, at build/blocks/index.js

15,379 lines 519.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ 1919:
5 /***/ ((module) => {
6
7 "use strict";
8
9
10 var isMergeableObject = function isMergeableObject(value) {
11 return isNonNullObject(value)
12 && !isSpecial(value)
13 };
14
15 function isNonNullObject(value) {
16 return !!value && typeof value === 'object'
17 }
18
19 function isSpecial(value) {
20 var stringValue = Object.prototype.toString.call(value);
21
22 return stringValue === '[object RegExp]'
23 || stringValue === '[object Date]'
24 || isReactElement(value)
25 }
26
27 // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
28 var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
29 var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
30
31 function isReactElement(value) {
32 return value.$$typeof === REACT_ELEMENT_TYPE
33 }
34
35 function emptyTarget(val) {
36 return Array.isArray(val) ? [] : {}
37 }
38
39 function cloneUnlessOtherwiseSpecified(value, options) {
40 return (options.clone !== false && options.isMergeableObject(value))
41 ? deepmerge(emptyTarget(value), value, options)
42 : value
43 }
44
45 function defaultArrayMerge(target, source, options) {
46 return target.concat(source).map(function(element) {
47 return cloneUnlessOtherwiseSpecified(element, options)
48 })
49 }
50
51 function getMergeFunction(key, options) {
52 if (!options.customMerge) {
53 return deepmerge
54 }
55 var customMerge = options.customMerge(key);
56 return typeof customMerge === 'function' ? customMerge : deepmerge
57 }
58
59 function getEnumerableOwnPropertySymbols(target) {
60 return Object.getOwnPropertySymbols
61 ? Object.getOwnPropertySymbols(target).filter(function(symbol) {
62 return Object.propertyIsEnumerable.call(target, symbol)
63 })
64 : []
65 }
66
67 function getKeys(target) {
68 return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
69 }
70
71 function propertyIsOnObject(object, property) {
72 try {
73 return property in object
74 } catch(_) {
75 return false
76 }
77 }
78
79 // Protects from prototype poisoning and unexpected merging up the prototype chain.
80 function propertyIsUnsafe(target, key) {
81 return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
82 && !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
83 && Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
84 }
85
86 function mergeObject(target, source, options) {
87 var destination = {};
88 if (options.isMergeableObject(target)) {
89 getKeys(target).forEach(function(key) {
90 destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
91 });
92 }
93 getKeys(source).forEach(function(key) {
94 if (propertyIsUnsafe(target, key)) {
95 return
96 }
97
98 if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
99 destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
100 } else {
101 destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
102 }
103 });
104 return destination
105 }
106
107 function deepmerge(target, source, options) {
108 options = options || {};
109 options.arrayMerge = options.arrayMerge || defaultArrayMerge;
110 options.isMergeableObject = options.isMergeableObject || isMergeableObject;
111 // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
112 // implementations can use it. The caller may not replace it.
113 options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
114
115 var sourceIsArray = Array.isArray(source);
116 var targetIsArray = Array.isArray(target);
117 var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
118
119 if (!sourceAndTargetTypesMatch) {
120 return cloneUnlessOtherwiseSpecified(source, options)
121 } else if (sourceIsArray) {
122 return options.arrayMerge(target, source, options)
123 } else {
124 return mergeObject(target, source, options)
125 }
126 }
127
128 deepmerge.all = function deepmergeAll(array, options) {
129 if (!Array.isArray(array)) {
130 throw new Error('first argument should be an array')
131 }
132
133 return array.reduce(function(prev, next) {
134 return deepmerge(prev, next, options)
135 }, {})
136 };
137
138 var deepmerge_1 = deepmerge;
139
140 module.exports = deepmerge_1;
141
142
143 /***/ }),
144
145 /***/ 5619:
146 /***/ ((module) => {
147
148 "use strict";
149
150
151 // do not edit .js files directly - edit src/index.jst
152
153
154 var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
155
156
157 module.exports = function equal(a, b) {
158 if (a === b) return true;
159
160 if (a && b && typeof a == 'object' && typeof b == 'object') {
161 if (a.constructor !== b.constructor) return false;
162
163 var length, i, keys;
164 if (Array.isArray(a)) {
165 length = a.length;
166 if (length != b.length) return false;
167 for (i = length; i-- !== 0;)
168 if (!equal(a[i], b[i])) return false;
169 return true;
170 }
171
172
173 if ((a instanceof Map) && (b instanceof Map)) {
174 if (a.size !== b.size) return false;
175 for (i of a.entries())
176 if (!b.has(i[0])) return false;
177 for (i of a.entries())
178 if (!equal(i[1], b.get(i[0]))) return false;
179 return true;
180 }
181
182 if ((a instanceof Set) && (b instanceof Set)) {
183 if (a.size !== b.size) return false;
184 for (i of a.entries())
185 if (!b.has(i[0])) return false;
186 return true;
187 }
188
189 if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
190 length = a.length;
191 if (length != b.length) return false;
192 for (i = length; i-- !== 0;)
193 if (a[i] !== b[i]) return false;
194 return true;
195 }
196
197
198 if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
199 if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
200 if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
201
202 keys = Object.keys(a);
203 length = keys.length;
204 if (length !== Object.keys(b).length) return false;
205
206 for (i = length; i-- !== 0;)
207 if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
208
209 for (i = length; i-- !== 0;) {
210 var key = keys[i];
211
212 if (!equal(a[key], b[key])) return false;
213 }
214
215 return true;
216 }
217
218 // true if both NaN, false otherwise
219 return a!==a && b!==b;
220 };
221
222
223 /***/ }),
224
225 /***/ 4793:
226 /***/ ((module) => {
227
228 var characterMap = {
229 "À": "A",
230 "Á": "A",
231 "Â": "A",
232 "Ã": "A",
233 "Ä": "A",
234 "Å": "A",
235 "Ấ": "A",
236 "Ắ": "A",
237 "Ẳ": "A",
238 "Ẵ": "A",
239 "Ặ": "A",
240 "Æ": "AE",
241 "Ầ": "A",
242 "Ằ": "A",
243 "Ȃ": "A",
244 "Ç": "C",
245 "Ḉ": "C",
246 "È": "E",
247 "É": "E",
248 "Ê": "E",
249 "Ë": "E",
250 "Ế": "E",
251 "Ḗ": "E",
252 "Ề": "E",
253 "Ḕ": "E",
254 "Ḝ": "E",
255 "Ȇ": "E",
256 "Ì": "I",
257 "Í": "I",
258 "Î": "I",
259 "Ï": "I",
260 "Ḯ": "I",
261 "Ȋ": "I",
262 "Ð": "D",
263 "Ñ": "N",
264 "Ò": "O",
265 "Ó": "O",
266 "Ô": "O",
267 "Õ": "O",
268 "Ö": "O",
269 "Ø": "O",
270 "Ố": "O",
271 "Ṍ": "O",
272 "Ṓ": "O",
273 "Ȏ": "O",
274 "Ù": "U",
275 "Ú": "U",
276 "Û": "U",
277 "Ü": "U",
278 "Ý": "Y",
279 "à": "a",
280 "á": "a",
281 "â": "a",
282 "ã": "a",
283 "ä": "a",
284 "å": "a",
285 "ấ": "a",
286 "ắ": "a",
287 "ẳ": "a",
288 "ẵ": "a",
289 "ặ": "a",
290 "æ": "ae",
291 "ầ": "a",
292 "ằ": "a",
293 "ȃ": "a",
294 "ç": "c",
295 "ḉ": "c",
296 "è": "e",
297 "é": "e",
298 "ê": "e",
299 "ë": "e",
300 "ế": "e",
301 "ḗ": "e",
302 "ề": "e",
303 "ḕ": "e",
304 "ḝ": "e",
305 "ȇ": "e",
306 "ì": "i",
307 "í": "i",
308 "î": "i",
309 "ï": "i",
310 "ḯ": "i",
311 "ȋ": "i",
312 "ð": "d",
313 "ñ": "n",
314 "ò": "o",
315 "ó": "o",
316 "ô": "o",
317 "õ": "o",
318 "ö": "o",
319 "ø": "o",
320 "ố": "o",
321 "ṍ": "o",
322 "ṓ": "o",
323 "ȏ": "o",
324 "ù": "u",
325 "ú": "u",
326 "û": "u",
327 "ü": "u",
328 "ý": "y",
329 "ÿ": "y",
330 "Ā": "A",
331 "ā": "a",
332 "Ă": "A",
333 "ă": "a",
334 "Ą": "A",
335 "ą": "a",
336 "Ć": "C",
337 "ć": "c",
338 "Ĉ": "C",
339 "ĉ": "c",
340 "Ċ": "C",
341 "ċ": "c",
342 "Č": "C",
343 "č": "c",
344 "C̆": "C",
345 "c̆": "c",
346 "Ď": "D",
347 "ď": "d",
348 "Đ": "D",
349 "đ": "d",
350 "Ē": "E",
351 "ē": "e",
352 "Ĕ": "E",
353 "ĕ": "e",
354 "Ė": "E",
355 "ė": "e",
356 "Ę": "E",
357 "ę": "e",
358 "Ě": "E",
359 "ě": "e",
360 "Ĝ": "G",
361 "Ǵ": "G",
362 "ĝ": "g",
363 "ǵ": "g",
364 "Ğ": "G",
365 "ğ": "g",
366 "Ġ": "G",
367 "ġ": "g",
368 "Ģ": "G",
369 "ģ": "g",
370 "Ĥ": "H",
371 "ĥ": "h",
372 "Ħ": "H",
373 "ħ": "h",
374 "Ḫ": "H",
375 "ḫ": "h",
376 "Ĩ": "I",
377 "ĩ": "i",
378 "Ī": "I",
379 "ī": "i",
380 "Ĭ": "I",
381 "ĭ": "i",
382 "Į": "I",
383 "į": "i",
384 "İ": "I",
385 "ı": "i",
386 "IJ": "IJ",
387 "ij": "ij",
388 "Ĵ": "J",
389 "ĵ": "j",
390 "Ķ": "K",
391 "ķ": "k",
392 "Ḱ": "K",
393 "ḱ": "k",
394 "K̆": "K",
395 "k̆": "k",
396 "Ĺ": "L",
397 "ĺ": "l",
398 "Ļ": "L",
399 "ļ": "l",
400 "Ľ": "L",
401 "ľ": "l",
402 "Ŀ": "L",
403 "ŀ": "l",
404 "Ł": "l",
405 "ł": "l",
406 "Ḿ": "M",
407 "ḿ": "m",
408 "M̆": "M",
409 "m̆": "m",
410 "Ń": "N",
411 "ń": "n",
412 "Ņ": "N",
413 "ņ": "n",
414 "Ň": "N",
415 "ň": "n",
416 "ʼn": "n",
417 "N̆": "N",
418 "n̆": "n",
419 "Ō": "O",
420 "ō": "o",
421 "Ŏ": "O",
422 "ŏ": "o",
423 "Ő": "O",
424 "ő": "o",
425 "Œ": "OE",
426 "œ": "oe",
427 "P̆": "P",
428 "p̆": "p",
429 "Ŕ": "R",
430 "ŕ": "r",
431 "Ŗ": "R",
432 "ŗ": "r",
433 "Ř": "R",
434 "ř": "r",
435 "R̆": "R",
436 "r̆": "r",
437 "Ȓ": "R",
438 "ȓ": "r",
439 "Ś": "S",
440 "ś": "s",
441 "Ŝ": "S",
442 "ŝ": "s",
443 "Ş": "S",
444 "Ș": "S",
445 "ș": "s",
446 "ş": "s",
447 "Š": "S",
448 "š": "s",
449 "Ţ": "T",
450 "ţ": "t",
451 "ț": "t",
452 "Ț": "T",
453 "Ť": "T",
454 "ť": "t",
455 "Ŧ": "T",
456 "ŧ": "t",
457 "T̆": "T",
458 "t̆": "t",
459 "Ũ": "U",
460 "ũ": "u",
461 "Ū": "U",
462 "ū": "u",
463 "Ŭ": "U",
464 "ŭ": "u",
465 "Ů": "U",
466 "ů": "u",
467 "Ű": "U",
468 "ű": "u",
469 "Ų": "U",
470 "ų": "u",
471 "Ȗ": "U",
472 "ȗ": "u",
473 "V̆": "V",
474 "v̆": "v",
475 "Ŵ": "W",
476 "ŵ": "w",
477 "Ẃ": "W",
478 "ẃ": "w",
479 "X̆": "X",
480 "x̆": "x",
481 "Ŷ": "Y",
482 "ŷ": "y",
483 "Ÿ": "Y",
484 "Y̆": "Y",
485 "y̆": "y",
486 "Ź": "Z",
487 "ź": "z",
488 "Ż": "Z",
489 "ż": "z",
490 "Ž": "Z",
491 "ž": "z",
492 "ſ": "s",
493 "ƒ": "f",
494 "Ơ": "O",
495 "ơ": "o",
496 "Ư": "U",
497 "ư": "u",
498 "Ǎ": "A",
499 "ǎ": "a",
500 "Ǐ": "I",
501 "ǐ": "i",
502 "Ǒ": "O",
503 "ǒ": "o",
504 "Ǔ": "U",
505 "ǔ": "u",
506 "Ǖ": "U",
507 "ǖ": "u",
508 "Ǘ": "U",
509 "ǘ": "u",
510 "Ǚ": "U",
511 "ǚ": "u",
512 "Ǜ": "U",
513 "ǜ": "u",
514 "Ứ": "U",
515 "ứ": "u",
516 "Ṹ": "U",
517 "ṹ": "u",
518 "Ǻ": "A",
519 "ǻ": "a",
520 "Ǽ": "AE",
521 "ǽ": "ae",
522 "Ǿ": "O",
523 "ǿ": "o",
524 "Þ": "TH",
525 "þ": "th",
526 "Ṕ": "P",
527 "ṕ": "p",
528 "Ṥ": "S",
529 "ṥ": "s",
530 "X́": "X",
531 "x́": "x",
532 "Ѓ": "Г",
533 "ѓ": "г",
534 "Ќ": "К",
535 "ќ": "к",
536 "A̋": "A",
537 "a̋": "a",
538 "E̋": "E",
539 "e̋": "e",
540 "I̋": "I",
541 "i̋": "i",
542 "Ǹ": "N",
543 "ǹ": "n",
544 "Ồ": "O",
545 "ồ": "o",
546 "Ṑ": "O",
547 "ṑ": "o",
548 "Ừ": "U",
549 "ừ": "u",
550 "Ẁ": "W",
551 "ẁ": "w",
552 "Ỳ": "Y",
553 "ỳ": "y",
554 "Ȁ": "A",
555 "ȁ": "a",
556 "Ȅ": "E",
557 "ȅ": "e",
558 "Ȉ": "I",
559 "ȉ": "i",
560 "Ȍ": "O",
561 "ȍ": "o",
562 "Ȑ": "R",
563 "ȑ": "r",
564 "Ȕ": "U",
565 "ȕ": "u",
566 "B̌": "B",
567 "b̌": "b",
568 "Č̣": "C",
569 "č̣": "c",
570 "Ê̌": "E",
571 "ê̌": "e",
572 "F̌": "F",
573 "f̌": "f",
574 "Ǧ": "G",
575 "ǧ": "g",
576 "Ȟ": "H",
577 "ȟ": "h",
578 "J̌": "J",
579 "ǰ": "j",
580 "Ǩ": "K",
581 "ǩ": "k",
582 "M̌": "M",
583 "m̌": "m",
584 "P̌": "P",
585 "p̌": "p",
586 "Q̌": "Q",
587 "q̌": "q",
588 "Ř̩": "R",
589 "ř̩": "r",
590 "Ṧ": "S",
591 "ṧ": "s",
592 "V̌": "V",
593 "v̌": "v",
594 "W̌": "W",
595 "w̌": "w",
596 "X̌": "X",
597 "x̌": "x",
598 "Y̌": "Y",
599 "y̌": "y",
600 "A̧": "A",
601 "a̧": "a",
602 "B̧": "B",
603 "b̧": "b",
604 "Ḑ": "D",
605 "ḑ": "d",
606 "Ȩ": "E",
607 "ȩ": "e",
608 "Ɛ̧": "E",
609 "ɛ̧": "e",
610 "Ḩ": "H",
611 "ḩ": "h",
612 "I̧": "I",
613 "i̧": "i",
614 "Ɨ̧": "I",
615 "ɨ̧": "i",
616 "M̧": "M",
617 "m̧": "m",
618 "O̧": "O",
619 "o̧": "o",
620 "Q̧": "Q",
621 "q̧": "q",
622 "U̧": "U",
623 "u̧": "u",
624 "X̧": "X",
625 "x̧": "x",
626 "Z̧": "Z",
627 "z̧": "z",
628 };
629
630 var chars = Object.keys(characterMap).join('|');
631 var allAccents = new RegExp(chars, 'g');
632 var firstAccent = new RegExp(chars, '');
633
634 var removeAccents = function(string) {
635 return string.replace(allAccents, function(match) {
636 return characterMap[match];
637 });
638 };
639
640 var hasAccents = function(string) {
641 return !!string.match(firstAccent);
642 };
643
644 module.exports = removeAccents;
645 module.exports.has = hasAccents;
646 module.exports.remove = removeAccents;
647
648
649 /***/ }),
650
651 /***/ 7308:
652 /***/ (function(module, exports, __webpack_require__) {
653
654 var __WEBPACK_AMD_DEFINE_RESULT__;;/*! showdown v 1.9.1 - 02-11-2019 */
655 (function(){
656 /**
657 * Created by Tivie on 13-07-2015.
658 */
659
660 function getDefaultOpts (simple) {
661 'use strict';
662
663 var defaultOptions = {
664 omitExtraWLInCodeBlocks: {
665 defaultValue: false,
666 describe: 'Omit the default extra whiteline added to code blocks',
667 type: 'boolean'
668 },
669 noHeaderId: {
670 defaultValue: false,
671 describe: 'Turn on/off generated header id',
672 type: 'boolean'
673 },
674 prefixHeaderId: {
675 defaultValue: false,
676 describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
677 type: 'string'
678 },
679 rawPrefixHeaderId: {
680 defaultValue: false,
681 describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
682 type: 'boolean'
683 },
684 ghCompatibleHeaderId: {
685 defaultValue: false,
686 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
687 type: 'boolean'
688 },
689 rawHeaderId: {
690 defaultValue: false,
691 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
692 type: 'boolean'
693 },
694 headerLevelStart: {
695 defaultValue: false,
696 describe: 'The header blocks level start',
697 type: 'integer'
698 },
699 parseImgDimensions: {
700 defaultValue: false,
701 describe: 'Turn on/off image dimension parsing',
702 type: 'boolean'
703 },
704 simplifiedAutoLink: {
705 defaultValue: false,
706 describe: 'Turn on/off GFM autolink style',
707 type: 'boolean'
708 },
709 excludeTrailingPunctuationFromURLs: {
710 defaultValue: false,
711 describe: 'Excludes trailing punctuation from links generated with autoLinking',
712 type: 'boolean'
713 },
714 literalMidWordUnderscores: {
715 defaultValue: false,
716 describe: 'Parse midword underscores as literal underscores',
717 type: 'boolean'
718 },
719 literalMidWordAsterisks: {
720 defaultValue: false,
721 describe: 'Parse midword asterisks as literal asterisks',
722 type: 'boolean'
723 },
724 strikethrough: {
725 defaultValue: false,
726 describe: 'Turn on/off strikethrough support',
727 type: 'boolean'
728 },
729 tables: {
730 defaultValue: false,
731 describe: 'Turn on/off tables support',
732 type: 'boolean'
733 },
734 tablesHeaderId: {
735 defaultValue: false,
736 describe: 'Add an id to table headers',
737 type: 'boolean'
738 },
739 ghCodeBlocks: {
740 defaultValue: true,
741 describe: 'Turn on/off GFM fenced code blocks support',
742 type: 'boolean'
743 },
744 tasklists: {
745 defaultValue: false,
746 describe: 'Turn on/off GFM tasklist support',
747 type: 'boolean'
748 },
749 smoothLivePreview: {
750 defaultValue: false,
751 describe: 'Prevents weird effects in live previews due to incomplete input',
752 type: 'boolean'
753 },
754 smartIndentationFix: {
755 defaultValue: false,
756 description: 'Tries to smartly fix indentation in es6 strings',
757 type: 'boolean'
758 },
759 disableForced4SpacesIndentedSublists: {
760 defaultValue: false,
761 description: 'Disables the requirement of indenting nested sublists by 4 spaces',
762 type: 'boolean'
763 },
764 simpleLineBreaks: {
765 defaultValue: false,
766 description: 'Parses simple line breaks as <br> (GFM Style)',
767 type: 'boolean'
768 },
769 requireSpaceBeforeHeadingText: {
770 defaultValue: false,
771 description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
772 type: 'boolean'
773 },
774 ghMentions: {
775 defaultValue: false,
776 description: 'Enables github @mentions',
777 type: 'boolean'
778 },
779 ghMentionsLink: {
780 defaultValue: 'https://github.com/{u}',
781 description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
782 type: 'string'
783 },
784 encodeEmails: {
785 defaultValue: true,
786 description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
787 type: 'boolean'
788 },
789 openLinksInNewWindow: {
790 defaultValue: false,
791 description: 'Open all links in new windows',
792 type: 'boolean'
793 },
794 backslashEscapesHTMLTags: {
795 defaultValue: false,
796 description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
797 type: 'boolean'
798 },
799 emoji: {
800 defaultValue: false,
801 description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
802 type: 'boolean'
803 },
804 underline: {
805 defaultValue: false,
806 description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
807 type: 'boolean'
808 },
809 completeHTMLDocument: {
810 defaultValue: false,
811 description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
812 type: 'boolean'
813 },
814 metadata: {
815 defaultValue: false,
816 description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
817 type: 'boolean'
818 },
819 splitAdjacentBlockquotes: {
820 defaultValue: false,
821 description: 'Split adjacent blockquote blocks',
822 type: 'boolean'
823 }
824 };
825 if (simple === false) {
826 return JSON.parse(JSON.stringify(defaultOptions));
827 }
828 var ret = {};
829 for (var opt in defaultOptions) {
830 if (defaultOptions.hasOwnProperty(opt)) {
831 ret[opt] = defaultOptions[opt].defaultValue;
832 }
833 }
834 return ret;
835 }
836
837 function allOptionsOn () {
838 'use strict';
839 var options = getDefaultOpts(true),
840 ret = {};
841 for (var opt in options) {
842 if (options.hasOwnProperty(opt)) {
843 ret[opt] = true;
844 }
845 }
846 return ret;
847 }
848
849 /**
850 * Created by Tivie on 06-01-2015.
851 */
852
853 // Private properties
854 var showdown = {},
855 parsers = {},
856 extensions = {},
857 globalOptions = getDefaultOpts(true),
858 setFlavor = 'vanilla',
859 flavor = {
860 github: {
861 omitExtraWLInCodeBlocks: true,
862 simplifiedAutoLink: true,
863 excludeTrailingPunctuationFromURLs: true,
864 literalMidWordUnderscores: true,
865 strikethrough: true,
866 tables: true,
867 tablesHeaderId: true,
868 ghCodeBlocks: true,
869 tasklists: true,
870 disableForced4SpacesIndentedSublists: true,
871 simpleLineBreaks: true,
872 requireSpaceBeforeHeadingText: true,
873 ghCompatibleHeaderId: true,
874 ghMentions: true,
875 backslashEscapesHTMLTags: true,
876 emoji: true,
877 splitAdjacentBlockquotes: true
878 },
879 original: {
880 noHeaderId: true,
881 ghCodeBlocks: false
882 },
883 ghost: {
884 omitExtraWLInCodeBlocks: true,
885 parseImgDimensions: true,
886 simplifiedAutoLink: true,
887 excludeTrailingPunctuationFromURLs: true,
888 literalMidWordUnderscores: true,
889 strikethrough: true,
890 tables: true,
891 tablesHeaderId: true,
892 ghCodeBlocks: true,
893 tasklists: true,
894 smoothLivePreview: true,
895 simpleLineBreaks: true,
896 requireSpaceBeforeHeadingText: true,
897 ghMentions: false,
898 encodeEmails: true
899 },
900 vanilla: getDefaultOpts(true),
901 allOn: allOptionsOn()
902 };
903
904 /**
905 * helper namespace
906 * @type {{}}
907 */
908 showdown.helper = {};
909
910 /**
911 * TODO LEGACY SUPPORT CODE
912 * @type {{}}
913 */
914 showdown.extensions = {};
915
916 /**
917 * Set a global option
918 * @static
919 * @param {string} key
920 * @param {*} value
921 * @returns {showdown}
922 */
923 showdown.setOption = function (key, value) {
924 'use strict';
925 globalOptions[key] = value;
926 return this;
927 };
928
929 /**
930 * Get a global option
931 * @static
932 * @param {string} key
933 * @returns {*}
934 */
935 showdown.getOption = function (key) {
936 'use strict';
937 return globalOptions[key];
938 };
939
940 /**
941 * Get the global options
942 * @static
943 * @returns {{}}
944 */
945 showdown.getOptions = function () {
946 'use strict';
947 return globalOptions;
948 };
949
950 /**
951 * Reset global options to the default values
952 * @static
953 */
954 showdown.resetOptions = function () {
955 'use strict';
956 globalOptions = getDefaultOpts(true);
957 };
958
959 /**
960 * Set the flavor showdown should use as default
961 * @param {string} name
962 */
963 showdown.setFlavor = function (name) {
964 'use strict';
965 if (!flavor.hasOwnProperty(name)) {
966 throw Error(name + ' flavor was not found');
967 }
968 showdown.resetOptions();
969 var preset = flavor[name];
970 setFlavor = name;
971 for (var option in preset) {
972 if (preset.hasOwnProperty(option)) {
973 globalOptions[option] = preset[option];
974 }
975 }
976 };
977
978 /**
979 * Get the currently set flavor
980 * @returns {string}
981 */
982 showdown.getFlavor = function () {
983 'use strict';
984 return setFlavor;
985 };
986
987 /**
988 * Get the options of a specified flavor. Returns undefined if the flavor was not found
989 * @param {string} name Name of the flavor
990 * @returns {{}|undefined}
991 */
992 showdown.getFlavorOptions = function (name) {
993 'use strict';
994 if (flavor.hasOwnProperty(name)) {
995 return flavor[name];
996 }
997 };
998
999 /**
1000 * Get the default options
1001 * @static
1002 * @param {boolean} [simple=true]
1003 * @returns {{}}
1004 */
1005 showdown.getDefaultOptions = function (simple) {
1006 'use strict';
1007 return getDefaultOpts(simple);
1008 };
1009
1010 /**
1011 * Get or set a subParser
1012 *
1013 * subParser(name) - Get a registered subParser
1014 * subParser(name, func) - Register a subParser
1015 * @static
1016 * @param {string} name
1017 * @param {function} [func]
1018 * @returns {*}
1019 */
1020 showdown.subParser = function (name, func) {
1021 'use strict';
1022 if (showdown.helper.isString(name)) {
1023 if (typeof func !== 'undefined') {
1024 parsers[name] = func;
1025 } else {
1026 if (parsers.hasOwnProperty(name)) {
1027 return parsers[name];
1028 } else {
1029 throw Error('SubParser named ' + name + ' not registered!');
1030 }
1031 }
1032 }
1033 };
1034
1035 /**
1036 * Gets or registers an extension
1037 * @static
1038 * @param {string} name
1039 * @param {object|function=} ext
1040 * @returns {*}
1041 */
1042 showdown.extension = function (name, ext) {
1043 'use strict';
1044
1045 if (!showdown.helper.isString(name)) {
1046 throw Error('Extension \'name\' must be a string');
1047 }
1048
1049 name = showdown.helper.stdExtName(name);
1050
1051 // Getter
1052 if (showdown.helper.isUndefined(ext)) {
1053 if (!extensions.hasOwnProperty(name)) {
1054 throw Error('Extension named ' + name + ' is not registered!');
1055 }
1056 return extensions[name];
1057
1058 // Setter
1059 } else {
1060 // Expand extension if it's wrapped in a function
1061 if (typeof ext === 'function') {
1062 ext = ext();
1063 }
1064
1065 // Ensure extension is an array
1066 if (!showdown.helper.isArray(ext)) {
1067 ext = [ext];
1068 }
1069
1070 var validExtension = validate(ext, name);
1071
1072 if (validExtension.valid) {
1073 extensions[name] = ext;
1074 } else {
1075 throw Error(validExtension.error);
1076 }
1077 }
1078 };
1079
1080 /**
1081 * Gets all extensions registered
1082 * @returns {{}}
1083 */
1084 showdown.getAllExtensions = function () {
1085 'use strict';
1086 return extensions;
1087 };
1088
1089 /**
1090 * Remove an extension
1091 * @param {string} name
1092 */
1093 showdown.removeExtension = function (name) {
1094 'use strict';
1095 delete extensions[name];
1096 };
1097
1098 /**
1099 * Removes all extensions
1100 */
1101 showdown.resetExtensions = function () {
1102 'use strict';
1103 extensions = {};
1104 };
1105
1106 /**
1107 * Validate extension
1108 * @param {array} extension
1109 * @param {string} name
1110 * @returns {{valid: boolean, error: string}}
1111 */
1112 function validate (extension, name) {
1113 'use strict';
1114
1115 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
1116 ret = {
1117 valid: true,
1118 error: ''
1119 };
1120
1121 if (!showdown.helper.isArray(extension)) {
1122 extension = [extension];
1123 }
1124
1125 for (var i = 0; i < extension.length; ++i) {
1126 var baseMsg = errMsg + ' sub-extension ' + i + ': ',
1127 ext = extension[i];
1128 if (typeof ext !== 'object') {
1129 ret.valid = false;
1130 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
1131 return ret;
1132 }
1133
1134 if (!showdown.helper.isString(ext.type)) {
1135 ret.valid = false;
1136 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
1137 return ret;
1138 }
1139
1140 var type = ext.type = ext.type.toLowerCase();
1141
1142 // normalize extension type
1143 if (type === 'language') {
1144 type = ext.type = 'lang';
1145 }
1146
1147 if (type === 'html') {
1148 type = ext.type = 'output';
1149 }
1150
1151 if (type !== 'lang' && type !== 'output' && type !== 'listener') {
1152 ret.valid = false;
1153 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
1154 return ret;
1155 }
1156
1157 if (type === 'listener') {
1158 if (showdown.helper.isUndefined(ext.listeners)) {
1159 ret.valid = false;
1160 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
1161 return ret;
1162 }
1163 } else {
1164 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
1165 ret.valid = false;
1166 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
1167 return ret;
1168 }
1169 }
1170
1171 if (ext.listeners) {
1172 if (typeof ext.listeners !== 'object') {
1173 ret.valid = false;
1174 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
1175 return ret;
1176 }
1177 for (var ln in ext.listeners) {
1178 if (ext.listeners.hasOwnProperty(ln)) {
1179 if (typeof ext.listeners[ln] !== 'function') {
1180 ret.valid = false;
1181 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
1182 ' must be a function but ' + typeof ext.listeners[ln] + ' given';
1183 return ret;
1184 }
1185 }
1186 }
1187 }
1188
1189 if (ext.filter) {
1190 if (typeof ext.filter !== 'function') {
1191 ret.valid = false;
1192 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
1193 return ret;
1194 }
1195 } else if (ext.regex) {
1196 if (showdown.helper.isString(ext.regex)) {
1197 ext.regex = new RegExp(ext.regex, 'g');
1198 }
1199 if (!(ext.regex instanceof RegExp)) {
1200 ret.valid = false;
1201 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
1202 return ret;
1203 }
1204 if (showdown.helper.isUndefined(ext.replace)) {
1205 ret.valid = false;
1206 ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
1207 return ret;
1208 }
1209 }
1210 }
1211 return ret;
1212 }
1213
1214 /**
1215 * Validate extension
1216 * @param {object} ext
1217 * @returns {boolean}
1218 */
1219 showdown.validateExtension = function (ext) {
1220 'use strict';
1221
1222 var validateExtension = validate(ext, null);
1223 if (!validateExtension.valid) {
1224 console.warn(validateExtension.error);
1225 return false;
1226 }
1227 return true;
1228 };
1229
1230 /**
1231 * showdownjs helper functions
1232 */
1233
1234 if (!showdown.hasOwnProperty('helper')) {
1235 showdown.helper = {};
1236 }
1237
1238 /**
1239 * Check if var is string
1240 * @static
1241 * @param {string} a
1242 * @returns {boolean}
1243 */
1244 showdown.helper.isString = function (a) {
1245 'use strict';
1246 return (typeof a === 'string' || a instanceof String);
1247 };
1248
1249 /**
1250 * Check if var is a function
1251 * @static
1252 * @param {*} a
1253 * @returns {boolean}
1254 */
1255 showdown.helper.isFunction = function (a) {
1256 'use strict';
1257 var getType = {};
1258 return a && getType.toString.call(a) === '[object Function]';
1259 };
1260
1261 /**
1262 * isArray helper function
1263 * @static
1264 * @param {*} a
1265 * @returns {boolean}
1266 */
1267 showdown.helper.isArray = function (a) {
1268 'use strict';
1269 return Array.isArray(a);
1270 };
1271
1272 /**
1273 * Check if value is undefined
1274 * @static
1275 * @param {*} value The value to check.
1276 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
1277 */
1278 showdown.helper.isUndefined = function (value) {
1279 'use strict';
1280 return typeof value === 'undefined';
1281 };
1282
1283 /**
1284 * ForEach helper function
1285 * Iterates over Arrays and Objects (own properties only)
1286 * @static
1287 * @param {*} obj
1288 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
1289 */
1290 showdown.helper.forEach = function (obj, callback) {
1291 'use strict';
1292 // check if obj is defined
1293 if (showdown.helper.isUndefined(obj)) {
1294 throw new Error('obj param is required');
1295 }
1296
1297 if (showdown.helper.isUndefined(callback)) {
1298 throw new Error('callback param is required');
1299 }
1300
1301 if (!showdown.helper.isFunction(callback)) {
1302 throw new Error('callback param must be a function/closure');
1303 }
1304
1305 if (typeof obj.forEach === 'function') {
1306 obj.forEach(callback);
1307 } else if (showdown.helper.isArray(obj)) {
1308 for (var i = 0; i < obj.length; i++) {
1309 callback(obj[i], i, obj);
1310 }
1311 } else if (typeof (obj) === 'object') {
1312 for (var prop in obj) {
1313 if (obj.hasOwnProperty(prop)) {
1314 callback(obj[prop], prop, obj);
1315 }
1316 }
1317 } else {
1318 throw new Error('obj does not seem to be an array or an iterable object');
1319 }
1320 };
1321
1322 /**
1323 * Standardidize extension name
1324 * @static
1325 * @param {string} s extension name
1326 * @returns {string}
1327 */
1328 showdown.helper.stdExtName = function (s) {
1329 'use strict';
1330 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
1331 };
1332
1333 function escapeCharactersCallback (wholeMatch, m1) {
1334 'use strict';
1335 var charCodeToEscape = m1.charCodeAt(0);
1336 return '¨E' + charCodeToEscape + 'E';
1337 }
1338
1339 /**
1340 * Callback used to escape characters when passing through String.replace
1341 * @static
1342 * @param {string} wholeMatch
1343 * @param {string} m1
1344 * @returns {string}
1345 */
1346 showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
1347
1348 /**
1349 * Escape characters in a string
1350 * @static
1351 * @param {string} text
1352 * @param {string} charsToEscape
1353 * @param {boolean} afterBackslash
1354 * @returns {XML|string|void|*}
1355 */
1356 showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
1357 'use strict';
1358 // First we have to escape the escape characters so that
1359 // we can build a character class out of them
1360 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
1361
1362 if (afterBackslash) {
1363 regexString = '\\\\' + regexString;
1364 }
1365
1366 var regex = new RegExp(regexString, 'g');
1367 text = text.replace(regex, escapeCharactersCallback);
1368
1369 return text;
1370 };
1371
1372 /**
1373 * Unescape HTML entities
1374 * @param txt
1375 * @returns {string}
1376 */
1377 showdown.helper.unescapeHTMLEntities = function (txt) {
1378 'use strict';
1379
1380 return txt
1381 .replace(/&quot;/g, '"')
1382 .replace(/&lt;/g, '<')
1383 .replace(/&gt;/g, '>')
1384 .replace(/&amp;/g, '&');
1385 };
1386
1387 var rgxFindMatchPos = function (str, left, right, flags) {
1388 'use strict';
1389 var f = flags || '',
1390 g = f.indexOf('g') > -1,
1391 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
1392 l = new RegExp(left, f.replace(/g/g, '')),
1393 pos = [],
1394 t, s, m, start, end;
1395
1396 do {
1397 t = 0;
1398 while ((m = x.exec(str))) {
1399 if (l.test(m[0])) {
1400 if (!(t++)) {
1401 s = x.lastIndex;
1402 start = s - m[0].length;
1403 }
1404 } else if (t) {
1405 if (!--t) {
1406 end = m.index + m[0].length;
1407 var obj = {
1408 left: {start: start, end: s},
1409 match: {start: s, end: m.index},
1410 right: {start: m.index, end: end},
1411 wholeMatch: {start: start, end: end}
1412 };
1413 pos.push(obj);
1414 if (!g) {
1415 return pos;
1416 }
1417 }
1418 }
1419 }
1420 } while (t && (x.lastIndex = s));
1421
1422 return pos;
1423 };
1424
1425 /**
1426 * matchRecursiveRegExp
1427 *
1428 * (c) 2007 Steven Levithan <stevenlevithan.com>
1429 * MIT License
1430 *
1431 * Accepts a string to search, a left and right format delimiter
1432 * as regex patterns, and optional regex flags. Returns an array
1433 * of matches, allowing nested instances of left/right delimiters.
1434 * Use the "g" flag to return all matches, otherwise only the
1435 * first is returned. Be careful to ensure that the left and
1436 * right format delimiters produce mutually exclusive matches.
1437 * Backreferences are not supported within the right delimiter
1438 * due to how it is internally combined with the left delimiter.
1439 * When matching strings whose format delimiters are unbalanced
1440 * to the left or right, the output is intentionally as a
1441 * conventional regex library with recursion support would
1442 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
1443 * "<" and ">" as the delimiters (both strings contain a single,
1444 * balanced instance of "<x>").
1445 *
1446 * examples:
1447 * matchRecursiveRegExp("test", "\\(", "\\)")
1448 * returns: []
1449 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
1450 * returns: ["t<<e>><s>", ""]
1451 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
1452 * returns: ["test"]
1453 */
1454 showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
1455 'use strict';
1456
1457 var matchPos = rgxFindMatchPos (str, left, right, flags),
1458 results = [];
1459
1460 for (var i = 0; i < matchPos.length; ++i) {
1461 results.push([
1462 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1463 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1464 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1465 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1466 ]);
1467 }
1468 return results;
1469 };
1470
1471 /**
1472 *
1473 * @param {string} str
1474 * @param {string|function} replacement
1475 * @param {string} left
1476 * @param {string} right
1477 * @param {string} flags
1478 * @returns {string}
1479 */
1480 showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
1481 'use strict';
1482
1483 if (!showdown.helper.isFunction(replacement)) {
1484 var repStr = replacement;
1485 replacement = function () {
1486 return repStr;
1487 };
1488 }
1489
1490 var matchPos = rgxFindMatchPos(str, left, right, flags),
1491 finalStr = str,
1492 lng = matchPos.length;
1493
1494 if (lng > 0) {
1495 var bits = [];
1496 if (matchPos[0].wholeMatch.start !== 0) {
1497 bits.push(str.slice(0, matchPos[0].wholeMatch.start));
1498 }
1499 for (var i = 0; i < lng; ++i) {
1500 bits.push(
1501 replacement(
1502 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1503 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1504 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1505 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1506 )
1507 );
1508 if (i < lng - 1) {
1509 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
1510 }
1511 }
1512 if (matchPos[lng - 1].wholeMatch.end < str.length) {
1513 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
1514 }
1515 finalStr = bits.join('');
1516 }
1517 return finalStr;
1518 };
1519
1520 /**
1521 * Returns the index within the passed String object of the first occurrence of the specified regex,
1522 * starting the search at fromIndex. Returns -1 if the value is not found.
1523 *
1524 * @param {string} str string to search
1525 * @param {RegExp} regex Regular expression to search
1526 * @param {int} [fromIndex = 0] Index to start the search
1527 * @returns {Number}
1528 * @throws InvalidArgumentError
1529 */
1530 showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
1531 'use strict';
1532 if (!showdown.helper.isString(str)) {
1533 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1534 }
1535 if (regex instanceof RegExp === false) {
1536 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
1537 }
1538 var indexOf = str.substring(fromIndex || 0).search(regex);
1539 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
1540 };
1541
1542 /**
1543 * Splits the passed string object at the defined index, and returns an array composed of the two substrings
1544 * @param {string} str string to split
1545 * @param {int} index index to split string at
1546 * @returns {[string,string]}
1547 * @throws InvalidArgumentError
1548 */
1549 showdown.helper.splitAtIndex = function (str, index) {
1550 'use strict';
1551 if (!showdown.helper.isString(str)) {
1552 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1553 }
1554 return [str.substring(0, index), str.substring(index)];
1555 };
1556
1557 /**
1558 * Obfuscate an e-mail address through the use of Character Entities,
1559 * transforming ASCII characters into their equivalent decimal or hex entities.
1560 *
1561 * Since it has a random component, subsequent calls to this function produce different results
1562 *
1563 * @param {string} mail
1564 * @returns {string}
1565 */
1566 showdown.helper.encodeEmailAddress = function (mail) {
1567 'use strict';
1568 var encode = [
1569 function (ch) {
1570 return '&#' + ch.charCodeAt(0) + ';';
1571 },
1572 function (ch) {
1573 return '&#x' + ch.charCodeAt(0).toString(16) + ';';
1574 },
1575 function (ch) {
1576 return ch;
1577 }
1578 ];
1579
1580 mail = mail.replace(/./g, function (ch) {
1581 if (ch === '@') {
1582 // this *must* be encoded. I insist.
1583 ch = encode[Math.floor(Math.random() * 2)](ch);
1584 } else {
1585 var r = Math.random();
1586 // roughly 10% raw, 45% hex, 45% dec
1587 ch = (
1588 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1589 );
1590 }
1591 return ch;
1592 });
1593
1594 return mail;
1595 };
1596
1597 /**
1598 *
1599 * @param str
1600 * @param targetLength
1601 * @param padString
1602 * @returns {string}
1603 */
1604 showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
1605 'use strict';
1606 /*jshint bitwise: false*/
1607 // eslint-disable-next-line space-infix-ops
1608 targetLength = targetLength>>0; //floor if number or convert non-number to 0;
1609 /*jshint bitwise: true*/
1610 padString = String(padString || ' ');
1611 if (str.length > targetLength) {
1612 return String(str);
1613 } else {
1614 targetLength = targetLength - str.length;
1615 if (targetLength > padString.length) {
1616 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
1617 }
1618 return String(str) + padString.slice(0,targetLength);
1619 }
1620 };
1621
1622 /**
1623 * POLYFILLS
1624 */
1625 // use this instead of builtin is undefined for IE8 compatibility
1626 if (typeof console === 'undefined') {
1627 console = {
1628 warn: function (msg) {
1629 'use strict';
1630 alert(msg);
1631 },
1632 log: function (msg) {
1633 'use strict';
1634 alert(msg);
1635 },
1636 error: function (msg) {
1637 'use strict';
1638 throw msg;
1639 }
1640 };
1641 }
1642
1643 /**
1644 * Common regexes.
1645 * We declare some common regexes to improve performance
1646 */
1647 showdown.helper.regexes = {
1648 asteriskDashAndColon: /([*_:~])/g
1649 };
1650
1651 /**
1652 * EMOJIS LIST
1653 */
1654 showdown.helper.emojis = {
1655 '+1':'\ud83d\udc4d',
1656 '-1':'\ud83d\udc4e',
1657 '100':'\ud83d\udcaf',
1658 '1234':'\ud83d\udd22',
1659 '1st_place_medal':'\ud83e\udd47',
1660 '2nd_place_medal':'\ud83e\udd48',
1661 '3rd_place_medal':'\ud83e\udd49',
1662 '8ball':'\ud83c\udfb1',
1663 'a':'\ud83c\udd70\ufe0f',
1664 'ab':'\ud83c\udd8e',
1665 'abc':'\ud83d\udd24',
1666 'abcd':'\ud83d\udd21',
1667 'accept':'\ud83c\ude51',
1668 'aerial_tramway':'\ud83d\udea1',
1669 'airplane':'\u2708\ufe0f',
1670 'alarm_clock':'\u23f0',
1671 'alembic':'\u2697\ufe0f',
1672 'alien':'\ud83d\udc7d',
1673 'ambulance':'\ud83d\ude91',
1674 'amphora':'\ud83c\udffa',
1675 'anchor':'\u2693\ufe0f',
1676 'angel':'\ud83d\udc7c',
1677 'anger':'\ud83d\udca2',
1678 'angry':'\ud83d\ude20',
1679 'anguished':'\ud83d\ude27',
1680 'ant':'\ud83d\udc1c',
1681 'apple':'\ud83c\udf4e',
1682 'aquarius':'\u2652\ufe0f',
1683 'aries':'\u2648\ufe0f',
1684 'arrow_backward':'\u25c0\ufe0f',
1685 'arrow_double_down':'\u23ec',
1686 'arrow_double_up':'\u23eb',
1687 'arrow_down':'\u2b07\ufe0f',
1688 'arrow_down_small':'\ud83d\udd3d',
1689 'arrow_forward':'\u25b6\ufe0f',
1690 'arrow_heading_down':'\u2935\ufe0f',
1691 'arrow_heading_up':'\u2934\ufe0f',
1692 'arrow_left':'\u2b05\ufe0f',
1693 'arrow_lower_left':'\u2199\ufe0f',
1694 'arrow_lower_right':'\u2198\ufe0f',
1695 'arrow_right':'\u27a1\ufe0f',
1696 'arrow_right_hook':'\u21aa\ufe0f',
1697 'arrow_up':'\u2b06\ufe0f',
1698 'arrow_up_down':'\u2195\ufe0f',
1699 'arrow_up_small':'\ud83d\udd3c',
1700 'arrow_upper_left':'\u2196\ufe0f',
1701 'arrow_upper_right':'\u2197\ufe0f',
1702 'arrows_clockwise':'\ud83d\udd03',
1703 'arrows_counterclockwise':'\ud83d\udd04',
1704 'art':'\ud83c\udfa8',
1705 'articulated_lorry':'\ud83d\ude9b',
1706 'artificial_satellite':'\ud83d\udef0',
1707 'astonished':'\ud83d\ude32',
1708 'athletic_shoe':'\ud83d\udc5f',
1709 'atm':'\ud83c\udfe7',
1710 'atom_symbol':'\u269b\ufe0f',
1711 'avocado':'\ud83e\udd51',
1712 'b':'\ud83c\udd71\ufe0f',
1713 'baby':'\ud83d\udc76',
1714 'baby_bottle':'\ud83c\udf7c',
1715 'baby_chick':'\ud83d\udc24',
1716 'baby_symbol':'\ud83d\udebc',
1717 'back':'\ud83d\udd19',
1718 'bacon':'\ud83e\udd53',
1719 'badminton':'\ud83c\udff8',
1720 'baggage_claim':'\ud83d\udec4',
1721 'baguette_bread':'\ud83e\udd56',
1722 'balance_scale':'\u2696\ufe0f',
1723 'balloon':'\ud83c\udf88',
1724 'ballot_box':'\ud83d\uddf3',
1725 'ballot_box_with_check':'\u2611\ufe0f',
1726 'bamboo':'\ud83c\udf8d',
1727 'banana':'\ud83c\udf4c',
1728 'bangbang':'\u203c\ufe0f',
1729 'bank':'\ud83c\udfe6',
1730 'bar_chart':'\ud83d\udcca',
1731 'barber':'\ud83d\udc88',
1732 'baseball':'\u26be\ufe0f',
1733 'basketball':'\ud83c\udfc0',
1734 'basketball_man':'\u26f9\ufe0f',
1735 'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1736 'bat':'\ud83e\udd87',
1737 'bath':'\ud83d\udec0',
1738 'bathtub':'\ud83d\udec1',
1739 'battery':'\ud83d\udd0b',
1740 'beach_umbrella':'\ud83c\udfd6',
1741 'bear':'\ud83d\udc3b',
1742 'bed':'\ud83d\udecf',
1743 'bee':'\ud83d\udc1d',
1744 'beer':'\ud83c\udf7a',
1745 'beers':'\ud83c\udf7b',
1746 'beetle':'\ud83d\udc1e',
1747 'beginner':'\ud83d\udd30',
1748 'bell':'\ud83d\udd14',
1749 'bellhop_bell':'\ud83d\udece',
1750 'bento':'\ud83c\udf71',
1751 'biking_man':'\ud83d\udeb4',
1752 'bike':'\ud83d\udeb2',
1753 'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1754 'bikini':'\ud83d\udc59',
1755 'biohazard':'\u2623\ufe0f',
1756 'bird':'\ud83d\udc26',
1757 'birthday':'\ud83c\udf82',
1758 'black_circle':'\u26ab\ufe0f',
1759 'black_flag':'\ud83c\udff4',
1760 'black_heart':'\ud83d\udda4',
1761 'black_joker':'\ud83c\udccf',
1762 'black_large_square':'\u2b1b\ufe0f',
1763 'black_medium_small_square':'\u25fe\ufe0f',
1764 'black_medium_square':'\u25fc\ufe0f',
1765 'black_nib':'\u2712\ufe0f',
1766 'black_small_square':'\u25aa\ufe0f',
1767 'black_square_button':'\ud83d\udd32',
1768 'blonde_man':'\ud83d\udc71',
1769 'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1770 'blossom':'\ud83c\udf3c',
1771 'blowfish':'\ud83d\udc21',
1772 'blue_book':'\ud83d\udcd8',
1773 'blue_car':'\ud83d\ude99',
1774 'blue_heart':'\ud83d\udc99',
1775 'blush':'\ud83d\ude0a',
1776 'boar':'\ud83d\udc17',
1777 'boat':'\u26f5\ufe0f',
1778 'bomb':'\ud83d\udca3',
1779 'book':'\ud83d\udcd6',
1780 'bookmark':'\ud83d\udd16',
1781 'bookmark_tabs':'\ud83d\udcd1',
1782 'books':'\ud83d\udcda',
1783 'boom':'\ud83d\udca5',
1784 'boot':'\ud83d\udc62',
1785 'bouquet':'\ud83d\udc90',
1786 'bowing_man':'\ud83d\ude47',
1787 'bow_and_arrow':'\ud83c\udff9',
1788 'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1789 'bowling':'\ud83c\udfb3',
1790 'boxing_glove':'\ud83e\udd4a',
1791 'boy':'\ud83d\udc66',
1792 'bread':'\ud83c\udf5e',
1793 'bride_with_veil':'\ud83d\udc70',
1794 'bridge_at_night':'\ud83c\udf09',
1795 'briefcase':'\ud83d\udcbc',
1796 'broken_heart':'\ud83d\udc94',
1797 'bug':'\ud83d\udc1b',
1798 'building_construction':'\ud83c\udfd7',
1799 'bulb':'\ud83d\udca1',
1800 'bullettrain_front':'\ud83d\ude85',
1801 'bullettrain_side':'\ud83d\ude84',
1802 'burrito':'\ud83c\udf2f',
1803 'bus':'\ud83d\ude8c',
1804 'business_suit_levitating':'\ud83d\udd74',
1805 'busstop':'\ud83d\ude8f',
1806 'bust_in_silhouette':'\ud83d\udc64',
1807 'busts_in_silhouette':'\ud83d\udc65',
1808 'butterfly':'\ud83e\udd8b',
1809 'cactus':'\ud83c\udf35',
1810 'cake':'\ud83c\udf70',
1811 'calendar':'\ud83d\udcc6',
1812 'call_me_hand':'\ud83e\udd19',
1813 'calling':'\ud83d\udcf2',
1814 'camel':'\ud83d\udc2b',
1815 'camera':'\ud83d\udcf7',
1816 'camera_flash':'\ud83d\udcf8',
1817 'camping':'\ud83c\udfd5',
1818 'cancer':'\u264b\ufe0f',
1819 'candle':'\ud83d\udd6f',
1820 'candy':'\ud83c\udf6c',
1821 'canoe':'\ud83d\udef6',
1822 'capital_abcd':'\ud83d\udd20',
1823 'capricorn':'\u2651\ufe0f',
1824 'car':'\ud83d\ude97',
1825 'card_file_box':'\ud83d\uddc3',
1826 'card_index':'\ud83d\udcc7',
1827 'card_index_dividers':'\ud83d\uddc2',
1828 'carousel_horse':'\ud83c\udfa0',
1829 'carrot':'\ud83e\udd55',
1830 'cat':'\ud83d\udc31',
1831 'cat2':'\ud83d\udc08',
1832 'cd':'\ud83d\udcbf',
1833 'chains':'\u26d3',
1834 'champagne':'\ud83c\udf7e',
1835 'chart':'\ud83d\udcb9',
1836 'chart_with_downwards_trend':'\ud83d\udcc9',
1837 'chart_with_upwards_trend':'\ud83d\udcc8',
1838 'checkered_flag':'\ud83c\udfc1',
1839 'cheese':'\ud83e\uddc0',
1840 'cherries':'\ud83c\udf52',
1841 'cherry_blossom':'\ud83c\udf38',
1842 'chestnut':'\ud83c\udf30',
1843 'chicken':'\ud83d\udc14',
1844 'children_crossing':'\ud83d\udeb8',
1845 'chipmunk':'\ud83d\udc3f',
1846 'chocolate_bar':'\ud83c\udf6b',
1847 'christmas_tree':'\ud83c\udf84',
1848 'church':'\u26ea\ufe0f',
1849 'cinema':'\ud83c\udfa6',
1850 'circus_tent':'\ud83c\udfaa',
1851 'city_sunrise':'\ud83c\udf07',
1852 'city_sunset':'\ud83c\udf06',
1853 'cityscape':'\ud83c\udfd9',
1854 'cl':'\ud83c\udd91',
1855 'clamp':'\ud83d\udddc',
1856 'clap':'\ud83d\udc4f',
1857 'clapper':'\ud83c\udfac',
1858 'classical_building':'\ud83c\udfdb',
1859 'clinking_glasses':'\ud83e\udd42',
1860 'clipboard':'\ud83d\udccb',
1861 'clock1':'\ud83d\udd50',
1862 'clock10':'\ud83d\udd59',
1863 'clock1030':'\ud83d\udd65',
1864 'clock11':'\ud83d\udd5a',
1865 'clock1130':'\ud83d\udd66',
1866 'clock12':'\ud83d\udd5b',
1867 'clock1230':'\ud83d\udd67',
1868 'clock130':'\ud83d\udd5c',
1869 'clock2':'\ud83d\udd51',
1870 'clock230':'\ud83d\udd5d',
1871 'clock3':'\ud83d\udd52',
1872 'clock330':'\ud83d\udd5e',
1873 'clock4':'\ud83d\udd53',
1874 'clock430':'\ud83d\udd5f',
1875 'clock5':'\ud83d\udd54',
1876 'clock530':'\ud83d\udd60',
1877 'clock6':'\ud83d\udd55',
1878 'clock630':'\ud83d\udd61',
1879 'clock7':'\ud83d\udd56',
1880 'clock730':'\ud83d\udd62',
1881 'clock8':'\ud83d\udd57',
1882 'clock830':'\ud83d\udd63',
1883 'clock9':'\ud83d\udd58',
1884 'clock930':'\ud83d\udd64',
1885 'closed_book':'\ud83d\udcd5',
1886 'closed_lock_with_key':'\ud83d\udd10',
1887 'closed_umbrella':'\ud83c\udf02',
1888 'cloud':'\u2601\ufe0f',
1889 'cloud_with_lightning':'\ud83c\udf29',
1890 'cloud_with_lightning_and_rain':'\u26c8',
1891 'cloud_with_rain':'\ud83c\udf27',
1892 'cloud_with_snow':'\ud83c\udf28',
1893 'clown_face':'\ud83e\udd21',
1894 'clubs':'\u2663\ufe0f',
1895 'cocktail':'\ud83c\udf78',
1896 'coffee':'\u2615\ufe0f',
1897 'coffin':'\u26b0\ufe0f',
1898 'cold_sweat':'\ud83d\ude30',
1899 'comet':'\u2604\ufe0f',
1900 'computer':'\ud83d\udcbb',
1901 'computer_mouse':'\ud83d\uddb1',
1902 'confetti_ball':'\ud83c\udf8a',
1903 'confounded':'\ud83d\ude16',
1904 'confused':'\ud83d\ude15',
1905 'congratulations':'\u3297\ufe0f',
1906 'construction':'\ud83d\udea7',
1907 'construction_worker_man':'\ud83d\udc77',
1908 'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1909 'control_knobs':'\ud83c\udf9b',
1910 'convenience_store':'\ud83c\udfea',
1911 'cookie':'\ud83c\udf6a',
1912 'cool':'\ud83c\udd92',
1913 'policeman':'\ud83d\udc6e',
1914 'copyright':'\u00a9\ufe0f',
1915 'corn':'\ud83c\udf3d',
1916 'couch_and_lamp':'\ud83d\udecb',
1917 'couple':'\ud83d\udc6b',
1918 'couple_with_heart_woman_man':'\ud83d\udc91',
1919 'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1920 'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1921 'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1922 'couplekiss_man_woman':'\ud83d\udc8f',
1923 'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1924 'cow':'\ud83d\udc2e',
1925 'cow2':'\ud83d\udc04',
1926 'cowboy_hat_face':'\ud83e\udd20',
1927 'crab':'\ud83e\udd80',
1928 'crayon':'\ud83d\udd8d',
1929 'credit_card':'\ud83d\udcb3',
1930 'crescent_moon':'\ud83c\udf19',
1931 'cricket':'\ud83c\udfcf',
1932 'crocodile':'\ud83d\udc0a',
1933 'croissant':'\ud83e\udd50',
1934 'crossed_fingers':'\ud83e\udd1e',
1935 'crossed_flags':'\ud83c\udf8c',
1936 'crossed_swords':'\u2694\ufe0f',
1937 'crown':'\ud83d\udc51',
1938 'cry':'\ud83d\ude22',
1939 'crying_cat_face':'\ud83d\ude3f',
1940 'crystal_ball':'\ud83d\udd2e',
1941 'cucumber':'\ud83e\udd52',
1942 'cupid':'\ud83d\udc98',
1943 'curly_loop':'\u27b0',
1944 'currency_exchange':'\ud83d\udcb1',
1945 'curry':'\ud83c\udf5b',
1946 'custard':'\ud83c\udf6e',
1947 'customs':'\ud83d\udec3',
1948 'cyclone':'\ud83c\udf00',
1949 'dagger':'\ud83d\udde1',
1950 'dancer':'\ud83d\udc83',
1951 'dancing_women':'\ud83d\udc6f',
1952 'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1953 'dango':'\ud83c\udf61',
1954 'dark_sunglasses':'\ud83d\udd76',
1955 'dart':'\ud83c\udfaf',
1956 'dash':'\ud83d\udca8',
1957 'date':'\ud83d\udcc5',
1958 'deciduous_tree':'\ud83c\udf33',
1959 'deer':'\ud83e\udd8c',
1960 'department_store':'\ud83c\udfec',
1961 'derelict_house':'\ud83c\udfda',
1962 'desert':'\ud83c\udfdc',
1963 'desert_island':'\ud83c\udfdd',
1964 'desktop_computer':'\ud83d\udda5',
1965 'male_detective':'\ud83d\udd75\ufe0f',
1966 'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1967 'diamonds':'\u2666\ufe0f',
1968 'disappointed':'\ud83d\ude1e',
1969 'disappointed_relieved':'\ud83d\ude25',
1970 'dizzy':'\ud83d\udcab',
1971 'dizzy_face':'\ud83d\ude35',
1972 'do_not_litter':'\ud83d\udeaf',
1973 'dog':'\ud83d\udc36',
1974 'dog2':'\ud83d\udc15',
1975 'dollar':'\ud83d\udcb5',
1976 'dolls':'\ud83c\udf8e',
1977 'dolphin':'\ud83d\udc2c',
1978 'door':'\ud83d\udeaa',
1979 'doughnut':'\ud83c\udf69',
1980 'dove':'\ud83d\udd4a',
1981 'dragon':'\ud83d\udc09',
1982 'dragon_face':'\ud83d\udc32',
1983 'dress':'\ud83d\udc57',
1984 'dromedary_camel':'\ud83d\udc2a',
1985 'drooling_face':'\ud83e\udd24',
1986 'droplet':'\ud83d\udca7',
1987 'drum':'\ud83e\udd41',
1988 'duck':'\ud83e\udd86',
1989 'dvd':'\ud83d\udcc0',
1990 'e-mail':'\ud83d\udce7',
1991 'eagle':'\ud83e\udd85',
1992 'ear':'\ud83d\udc42',
1993 'ear_of_rice':'\ud83c\udf3e',
1994 'earth_africa':'\ud83c\udf0d',
1995 'earth_americas':'\ud83c\udf0e',
1996 'earth_asia':'\ud83c\udf0f',
1997 'egg':'\ud83e\udd5a',
1998 'eggplant':'\ud83c\udf46',
1999 'eight_pointed_black_star':'\u2734\ufe0f',
2000 'eight_spoked_asterisk':'\u2733\ufe0f',
2001 'electric_plug':'\ud83d\udd0c',
2002 'elephant':'\ud83d\udc18',
2003 'email':'\u2709\ufe0f',
2004 'end':'\ud83d\udd1a',
2005 'envelope_with_arrow':'\ud83d\udce9',
2006 'euro':'\ud83d\udcb6',
2007 'european_castle':'\ud83c\udff0',
2008 'european_post_office':'\ud83c\udfe4',
2009 'evergreen_tree':'\ud83c\udf32',
2010 'exclamation':'\u2757\ufe0f',
2011 'expressionless':'\ud83d\ude11',
2012 'eye':'\ud83d\udc41',
2013 'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
2014 'eyeglasses':'\ud83d\udc53',
2015 'eyes':'\ud83d\udc40',
2016 'face_with_head_bandage':'\ud83e\udd15',
2017 'face_with_thermometer':'\ud83e\udd12',
2018 'fist_oncoming':'\ud83d\udc4a',
2019 'factory':'\ud83c\udfed',
2020 'fallen_leaf':'\ud83c\udf42',
2021 'family_man_woman_boy':'\ud83d\udc6a',
2022 'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
2023 'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
2024 'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
2025 'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
2026 'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
2027 'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
2028 'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
2029 'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
2030 'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
2031 'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
2032 'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
2033 'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
2034 'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
2035 'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
2036 'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
2037 'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
2038 'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
2039 'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
2040 'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
2041 'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
2042 'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
2043 'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
2044 'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
2045 'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
2046 'fast_forward':'\u23e9',
2047 'fax':'\ud83d\udce0',
2048 'fearful':'\ud83d\ude28',
2049 'feet':'\ud83d\udc3e',
2050 'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
2051 'ferris_wheel':'\ud83c\udfa1',
2052 'ferry':'\u26f4',
2053 'field_hockey':'\ud83c\udfd1',
2054 'file_cabinet':'\ud83d\uddc4',
2055 'file_folder':'\ud83d\udcc1',
2056 'film_projector':'\ud83d\udcfd',
2057 'film_strip':'\ud83c\udf9e',
2058 'fire':'\ud83d\udd25',
2059 'fire_engine':'\ud83d\ude92',
2060 'fireworks':'\ud83c\udf86',
2061 'first_quarter_moon':'\ud83c\udf13',
2062 'first_quarter_moon_with_face':'\ud83c\udf1b',
2063 'fish':'\ud83d\udc1f',
2064 'fish_cake':'\ud83c\udf65',
2065 'fishing_pole_and_fish':'\ud83c\udfa3',
2066 'fist_raised':'\u270a',
2067 'fist_left':'\ud83e\udd1b',
2068 'fist_right':'\ud83e\udd1c',
2069 'flags':'\ud83c\udf8f',
2070 'flashlight':'\ud83d\udd26',
2071 'fleur_de_lis':'\u269c\ufe0f',
2072 'flight_arrival':'\ud83d\udeec',
2073 'flight_departure':'\ud83d\udeeb',
2074 'floppy_disk':'\ud83d\udcbe',
2075 'flower_playing_cards':'\ud83c\udfb4',
2076 'flushed':'\ud83d\ude33',
2077 'fog':'\ud83c\udf2b',
2078 'foggy':'\ud83c\udf01',
2079 'football':'\ud83c\udfc8',
2080 'footprints':'\ud83d\udc63',
2081 'fork_and_knife':'\ud83c\udf74',
2082 'fountain':'\u26f2\ufe0f',
2083 'fountain_pen':'\ud83d\udd8b',
2084 'four_leaf_clover':'\ud83c\udf40',
2085 'fox_face':'\ud83e\udd8a',
2086 'framed_picture':'\ud83d\uddbc',
2087 'free':'\ud83c\udd93',
2088 'fried_egg':'\ud83c\udf73',
2089 'fried_shrimp':'\ud83c\udf64',
2090 'fries':'\ud83c\udf5f',
2091 'frog':'\ud83d\udc38',
2092 'frowning':'\ud83d\ude26',
2093 'frowning_face':'\u2639\ufe0f',
2094 'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
2095 'frowning_woman':'\ud83d\ude4d',
2096 'middle_finger':'\ud83d\udd95',
2097 'fuelpump':'\u26fd\ufe0f',
2098 'full_moon':'\ud83c\udf15',
2099 'full_moon_with_face':'\ud83c\udf1d',
2100 'funeral_urn':'\u26b1\ufe0f',
2101 'game_die':'\ud83c\udfb2',
2102 'gear':'\u2699\ufe0f',
2103 'gem':'\ud83d\udc8e',
2104 'gemini':'\u264a\ufe0f',
2105 'ghost':'\ud83d\udc7b',
2106 'gift':'\ud83c\udf81',
2107 'gift_heart':'\ud83d\udc9d',
2108 'girl':'\ud83d\udc67',
2109 'globe_with_meridians':'\ud83c\udf10',
2110 'goal_net':'\ud83e\udd45',
2111 'goat':'\ud83d\udc10',
2112 'golf':'\u26f3\ufe0f',
2113 'golfing_man':'\ud83c\udfcc\ufe0f',
2114 'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
2115 'gorilla':'\ud83e\udd8d',
2116 'grapes':'\ud83c\udf47',
2117 'green_apple':'\ud83c\udf4f',
2118 'green_book':'\ud83d\udcd7',
2119 'green_heart':'\ud83d\udc9a',
2120 'green_salad':'\ud83e\udd57',
2121 'grey_exclamation':'\u2755',
2122 'grey_question':'\u2754',
2123 'grimacing':'\ud83d\ude2c',
2124 'grin':'\ud83d\ude01',
2125 'grinning':'\ud83d\ude00',
2126 'guardsman':'\ud83d\udc82',
2127 'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
2128 'guitar':'\ud83c\udfb8',
2129 'gun':'\ud83d\udd2b',
2130 'haircut_woman':'\ud83d\udc87',
2131 'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
2132 'hamburger':'\ud83c\udf54',
2133 'hammer':'\ud83d\udd28',
2134 'hammer_and_pick':'\u2692',
2135 'hammer_and_wrench':'\ud83d\udee0',
2136 'hamster':'\ud83d\udc39',
2137 'hand':'\u270b',
2138 'handbag':'\ud83d\udc5c',
2139 'handshake':'\ud83e\udd1d',
2140 'hankey':'\ud83d\udca9',
2141 'hatched_chick':'\ud83d\udc25',
2142 'hatching_chick':'\ud83d\udc23',
2143 'headphones':'\ud83c\udfa7',
2144 'hear_no_evil':'\ud83d\ude49',
2145 'heart':'\u2764\ufe0f',
2146 'heart_decoration':'\ud83d\udc9f',
2147 'heart_eyes':'\ud83d\ude0d',
2148 'heart_eyes_cat':'\ud83d\ude3b',
2149 'heartbeat':'\ud83d\udc93',
2150 'heartpulse':'\ud83d\udc97',
2151 'hearts':'\u2665\ufe0f',
2152 'heavy_check_mark':'\u2714\ufe0f',
2153 'heavy_division_sign':'\u2797',
2154 'heavy_dollar_sign':'\ud83d\udcb2',
2155 'heavy_heart_exclamation':'\u2763\ufe0f',
2156 'heavy_minus_sign':'\u2796',
2157 'heavy_multiplication_x':'\u2716\ufe0f',
2158 'heavy_plus_sign':'\u2795',
2159 'helicopter':'\ud83d\ude81',
2160 'herb':'\ud83c\udf3f',
2161 'hibiscus':'\ud83c\udf3a',
2162 'high_brightness':'\ud83d\udd06',
2163 'high_heel':'\ud83d\udc60',
2164 'hocho':'\ud83d\udd2a',
2165 'hole':'\ud83d\udd73',
2166 'honey_pot':'\ud83c\udf6f',
2167 'horse':'\ud83d\udc34',
2168 'horse_racing':'\ud83c\udfc7',
2169 'hospital':'\ud83c\udfe5',
2170 'hot_pepper':'\ud83c\udf36',
2171 'hotdog':'\ud83c\udf2d',
2172 'hotel':'\ud83c\udfe8',
2173 'hotsprings':'\u2668\ufe0f',
2174 'hourglass':'\u231b\ufe0f',
2175 'hourglass_flowing_sand':'\u23f3',
2176 'house':'\ud83c\udfe0',
2177 'house_with_garden':'\ud83c\udfe1',
2178 'houses':'\ud83c\udfd8',
2179 'hugs':'\ud83e\udd17',
2180 'hushed':'\ud83d\ude2f',
2181 'ice_cream':'\ud83c\udf68',
2182 'ice_hockey':'\ud83c\udfd2',
2183 'ice_skate':'\u26f8',
2184 'icecream':'\ud83c\udf66',
2185 'id':'\ud83c\udd94',
2186 'ideograph_advantage':'\ud83c\ude50',
2187 'imp':'\ud83d\udc7f',
2188 'inbox_tray':'\ud83d\udce5',
2189 'incoming_envelope':'\ud83d\udce8',
2190 'tipping_hand_woman':'\ud83d\udc81',
2191 'information_source':'\u2139\ufe0f',
2192 'innocent':'\ud83d\ude07',
2193 'interrobang':'\u2049\ufe0f',
2194 'iphone':'\ud83d\udcf1',
2195 'izakaya_lantern':'\ud83c\udfee',
2196 'jack_o_lantern':'\ud83c\udf83',
2197 'japan':'\ud83d\uddfe',
2198 'japanese_castle':'\ud83c\udfef',
2199 'japanese_goblin':'\ud83d\udc7a',
2200 'japanese_ogre':'\ud83d\udc79',
2201 'jeans':'\ud83d\udc56',
2202 'joy':'\ud83d\ude02',
2203 'joy_cat':'\ud83d\ude39',
2204 'joystick':'\ud83d\udd79',
2205 'kaaba':'\ud83d\udd4b',
2206 'key':'\ud83d\udd11',
2207 'keyboard':'\u2328\ufe0f',
2208 'keycap_ten':'\ud83d\udd1f',
2209 'kick_scooter':'\ud83d\udef4',
2210 'kimono':'\ud83d\udc58',
2211 'kiss':'\ud83d\udc8b',
2212 'kissing':'\ud83d\ude17',
2213 'kissing_cat':'\ud83d\ude3d',
2214 'kissing_closed_eyes':'\ud83d\ude1a',
2215 'kissing_heart':'\ud83d\ude18',
2216 'kissing_smiling_eyes':'\ud83d\ude19',
2217 'kiwi_fruit':'\ud83e\udd5d',
2218 'koala':'\ud83d\udc28',
2219 'koko':'\ud83c\ude01',
2220 'label':'\ud83c\udff7',
2221 'large_blue_circle':'\ud83d\udd35',
2222 'large_blue_diamond':'\ud83d\udd37',
2223 'large_orange_diamond':'\ud83d\udd36',
2224 'last_quarter_moon':'\ud83c\udf17',
2225 'last_quarter_moon_with_face':'\ud83c\udf1c',
2226 'latin_cross':'\u271d\ufe0f',
2227 'laughing':'\ud83d\ude06',
2228 'leaves':'\ud83c\udf43',
2229 'ledger':'\ud83d\udcd2',
2230 'left_luggage':'\ud83d\udec5',
2231 'left_right_arrow':'\u2194\ufe0f',
2232 'leftwards_arrow_with_hook':'\u21a9\ufe0f',
2233 'lemon':'\ud83c\udf4b',
2234 'leo':'\u264c\ufe0f',
2235 'leopard':'\ud83d\udc06',
2236 'level_slider':'\ud83c\udf9a',
2237 'libra':'\u264e\ufe0f',
2238 'light_rail':'\ud83d\ude88',
2239 'link':'\ud83d\udd17',
2240 'lion':'\ud83e\udd81',
2241 'lips':'\ud83d\udc44',
2242 'lipstick':'\ud83d\udc84',
2243 'lizard':'\ud83e\udd8e',
2244 'lock':'\ud83d\udd12',
2245 'lock_with_ink_pen':'\ud83d\udd0f',
2246 'lollipop':'\ud83c\udf6d',
2247 'loop':'\u27bf',
2248 'loud_sound':'\ud83d\udd0a',
2249 'loudspeaker':'\ud83d\udce2',
2250 'love_hotel':'\ud83c\udfe9',
2251 'love_letter':'\ud83d\udc8c',
2252 'low_brightness':'\ud83d\udd05',
2253 'lying_face':'\ud83e\udd25',
2254 'm':'\u24c2\ufe0f',
2255 'mag':'\ud83d\udd0d',
2256 'mag_right':'\ud83d\udd0e',
2257 'mahjong':'\ud83c\udc04\ufe0f',
2258 'mailbox':'\ud83d\udceb',
2259 'mailbox_closed':'\ud83d\udcea',
2260 'mailbox_with_mail':'\ud83d\udcec',
2261 'mailbox_with_no_mail':'\ud83d\udced',
2262 'man':'\ud83d\udc68',
2263 'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
2264 'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
2265 'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
2266 'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
2267 'man_dancing':'\ud83d\udd7a',
2268 'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
2269 'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
2270 'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
2271 'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
2272 'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
2273 'man_in_tuxedo':'\ud83e\udd35',
2274 'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
2275 'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
2276 'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
2277 'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
2278 'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
2279 'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
2280 'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
2281 'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
2282 'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
2283 'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
2284 'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
2285 'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
2286 'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
2287 'man_with_gua_pi_mao':'\ud83d\udc72',
2288 'man_with_turban':'\ud83d\udc73',
2289 'tangerine':'\ud83c\udf4a',
2290 'mans_shoe':'\ud83d\udc5e',
2291 'mantelpiece_clock':'\ud83d\udd70',
2292 'maple_leaf':'\ud83c\udf41',
2293 'martial_arts_uniform':'\ud83e\udd4b',
2294 'mask':'\ud83d\ude37',
2295 'massage_woman':'\ud83d\udc86',
2296 'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
2297 'meat_on_bone':'\ud83c\udf56',
2298 'medal_military':'\ud83c\udf96',
2299 'medal_sports':'\ud83c\udfc5',
2300 'mega':'\ud83d\udce3',
2301 'melon':'\ud83c\udf48',
2302 'memo':'\ud83d\udcdd',
2303 'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
2304 'menorah':'\ud83d\udd4e',
2305 'mens':'\ud83d\udeb9',
2306 'metal':'\ud83e\udd18',
2307 'metro':'\ud83d\ude87',
2308 'microphone':'\ud83c\udfa4',
2309 'microscope':'\ud83d\udd2c',
2310 'milk_glass':'\ud83e\udd5b',
2311 'milky_way':'\ud83c\udf0c',
2312 'minibus':'\ud83d\ude90',
2313 'minidisc':'\ud83d\udcbd',
2314 'mobile_phone_off':'\ud83d\udcf4',
2315 'money_mouth_face':'\ud83e\udd11',
2316 'money_with_wings':'\ud83d\udcb8',
2317 'moneybag':'\ud83d\udcb0',
2318 'monkey':'\ud83d\udc12',
2319 'monkey_face':'\ud83d\udc35',
2320 'monorail':'\ud83d\ude9d',
2321 'moon':'\ud83c\udf14',
2322 'mortar_board':'\ud83c\udf93',
2323 'mosque':'\ud83d\udd4c',
2324 'motor_boat':'\ud83d\udee5',
2325 'motor_scooter':'\ud83d\udef5',
2326 'motorcycle':'\ud83c\udfcd',
2327 'motorway':'\ud83d\udee3',
2328 'mount_fuji':'\ud83d\uddfb',
2329 'mountain':'\u26f0',
2330 'mountain_biking_man':'\ud83d\udeb5',
2331 'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
2332 'mountain_cableway':'\ud83d\udea0',
2333 'mountain_railway':'\ud83d\ude9e',
2334 'mountain_snow':'\ud83c\udfd4',
2335 'mouse':'\ud83d\udc2d',
2336 'mouse2':'\ud83d\udc01',
2337 'movie_camera':'\ud83c\udfa5',
2338 'moyai':'\ud83d\uddff',
2339 'mrs_claus':'\ud83e\udd36',
2340 'muscle':'\ud83d\udcaa',
2341 'mushroom':'\ud83c\udf44',
2342 'musical_keyboard':'\ud83c\udfb9',
2343 'musical_note':'\ud83c\udfb5',
2344 'musical_score':'\ud83c\udfbc',
2345 'mute':'\ud83d\udd07',
2346 'nail_care':'\ud83d\udc85',
2347 'name_badge':'\ud83d\udcdb',
2348 'national_park':'\ud83c\udfde',
2349 'nauseated_face':'\ud83e\udd22',
2350 'necktie':'\ud83d\udc54',
2351 'negative_squared_cross_mark':'\u274e',
2352 'nerd_face':'\ud83e\udd13',
2353 'neutral_face':'\ud83d\ude10',
2354 'new':'\ud83c\udd95',
2355 'new_moon':'\ud83c\udf11',
2356 'new_moon_with_face':'\ud83c\udf1a',
2357 'newspaper':'\ud83d\udcf0',
2358 'newspaper_roll':'\ud83d\uddde',
2359 'next_track_button':'\u23ed',
2360 'ng':'\ud83c\udd96',
2361 'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
2362 'no_good_woman':'\ud83d\ude45',
2363 'night_with_stars':'\ud83c\udf03',
2364 'no_bell':'\ud83d\udd15',
2365 'no_bicycles':'\ud83d\udeb3',
2366 'no_entry':'\u26d4\ufe0f',
2367 'no_entry_sign':'\ud83d\udeab',
2368 'no_mobile_phones':'\ud83d\udcf5',
2369 'no_mouth':'\ud83d\ude36',
2370 'no_pedestrians':'\ud83d\udeb7',
2371 'no_smoking':'\ud83d\udead',
2372 'non-potable_water':'\ud83d\udeb1',
2373 'nose':'\ud83d\udc43',
2374 'notebook':'\ud83d\udcd3',
2375 'notebook_with_decorative_cover':'\ud83d\udcd4',
2376 'notes':'\ud83c\udfb6',
2377 'nut_and_bolt':'\ud83d\udd29',
2378 'o':'\u2b55\ufe0f',
2379 'o2':'\ud83c\udd7e\ufe0f',
2380 'ocean':'\ud83c\udf0a',
2381 'octopus':'\ud83d\udc19',
2382 'oden':'\ud83c\udf62',
2383 'office':'\ud83c\udfe2',
2384 'oil_drum':'\ud83d\udee2',
2385 'ok':'\ud83c\udd97',
2386 'ok_hand':'\ud83d\udc4c',
2387 'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
2388 'ok_woman':'\ud83d\ude46',
2389 'old_key':'\ud83d\udddd',
2390 'older_man':'\ud83d\udc74',
2391 'older_woman':'\ud83d\udc75',
2392 'om':'\ud83d\udd49',
2393 'on':'\ud83d\udd1b',
2394 'oncoming_automobile':'\ud83d\ude98',
2395 'oncoming_bus':'\ud83d\ude8d',
2396 'oncoming_police_car':'\ud83d\ude94',
2397 'oncoming_taxi':'\ud83d\ude96',
2398 'open_file_folder':'\ud83d\udcc2',
2399 'open_hands':'\ud83d\udc50',
2400 'open_mouth':'\ud83d\ude2e',
2401 'open_umbrella':'\u2602\ufe0f',
2402 'ophiuchus':'\u26ce',
2403 'orange_book':'\ud83d\udcd9',
2404 'orthodox_cross':'\u2626\ufe0f',
2405 'outbox_tray':'\ud83d\udce4',
2406 'owl':'\ud83e\udd89',
2407 'ox':'\ud83d\udc02',
2408 'package':'\ud83d\udce6',
2409 'page_facing_up':'\ud83d\udcc4',
2410 'page_with_curl':'\ud83d\udcc3',
2411 'pager':'\ud83d\udcdf',
2412 'paintbrush':'\ud83d\udd8c',
2413 'palm_tree':'\ud83c\udf34',
2414 'pancakes':'\ud83e\udd5e',
2415 'panda_face':'\ud83d\udc3c',
2416 'paperclip':'\ud83d\udcce',
2417 'paperclips':'\ud83d\udd87',
2418 'parasol_on_ground':'\u26f1',
2419 'parking':'\ud83c\udd7f\ufe0f',
2420 'part_alternation_mark':'\u303d\ufe0f',
2421 'partly_sunny':'\u26c5\ufe0f',
2422 'passenger_ship':'\ud83d\udef3',
2423 'passport_control':'\ud83d\udec2',
2424 'pause_button':'\u23f8',
2425 'peace_symbol':'\u262e\ufe0f',
2426 'peach':'\ud83c\udf51',
2427 'peanuts':'\ud83e\udd5c',
2428 'pear':'\ud83c\udf50',
2429 'pen':'\ud83d\udd8a',
2430 'pencil2':'\u270f\ufe0f',
2431 'penguin':'\ud83d\udc27',
2432 'pensive':'\ud83d\ude14',
2433 'performing_arts':'\ud83c\udfad',
2434 'persevere':'\ud83d\ude23',
2435 'person_fencing':'\ud83e\udd3a',
2436 'pouting_woman':'\ud83d\ude4e',
2437 'phone':'\u260e\ufe0f',
2438 'pick':'\u26cf',
2439 'pig':'\ud83d\udc37',
2440 'pig2':'\ud83d\udc16',
2441 'pig_nose':'\ud83d\udc3d',
2442 'pill':'\ud83d\udc8a',
2443 'pineapple':'\ud83c\udf4d',
2444 'ping_pong':'\ud83c\udfd3',
2445 'pisces':'\u2653\ufe0f',
2446 'pizza':'\ud83c\udf55',
2447 'place_of_worship':'\ud83d\uded0',
2448 'plate_with_cutlery':'\ud83c\udf7d',
2449 'play_or_pause_button':'\u23ef',
2450 'point_down':'\ud83d\udc47',
2451 'point_left':'\ud83d\udc48',
2452 'point_right':'\ud83d\udc49',
2453 'point_up':'\u261d\ufe0f',
2454 'point_up_2':'\ud83d\udc46',
2455 'police_car':'\ud83d\ude93',
2456 'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
2457 'poodle':'\ud83d\udc29',
2458 'popcorn':'\ud83c\udf7f',
2459 'post_office':'\ud83c\udfe3',
2460 'postal_horn':'\ud83d\udcef',
2461 'postbox':'\ud83d\udcee',
2462 'potable_water':'\ud83d\udeb0',
2463 'potato':'\ud83e\udd54',
2464 'pouch':'\ud83d\udc5d',
2465 'poultry_leg':'\ud83c\udf57',
2466 'pound':'\ud83d\udcb7',
2467 'rage':'\ud83d\ude21',
2468 'pouting_cat':'\ud83d\ude3e',
2469 'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
2470 'pray':'\ud83d\ude4f',
2471 'prayer_beads':'\ud83d\udcff',
2472 'pregnant_woman':'\ud83e\udd30',
2473 'previous_track_button':'\u23ee',
2474 'prince':'\ud83e\udd34',
2475 'princess':'\ud83d\udc78',
2476 'printer':'\ud83d\udda8',
2477 'purple_heart':'\ud83d\udc9c',
2478 'purse':'\ud83d\udc5b',
2479 'pushpin':'\ud83d\udccc',
2480 'put_litter_in_its_place':'\ud83d\udeae',
2481 'question':'\u2753',
2482 'rabbit':'\ud83d\udc30',
2483 'rabbit2':'\ud83d\udc07',
2484 'racehorse':'\ud83d\udc0e',
2485 'racing_car':'\ud83c\udfce',
2486 'radio':'\ud83d\udcfb',
2487 'radio_button':'\ud83d\udd18',
2488 'radioactive':'\u2622\ufe0f',
2489 'railway_car':'\ud83d\ude83',
2490 'railway_track':'\ud83d\udee4',
2491 'rainbow':'\ud83c\udf08',
2492 'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
2493 'raised_back_of_hand':'\ud83e\udd1a',
2494 'raised_hand_with_fingers_splayed':'\ud83d\udd90',
2495 'raised_hands':'\ud83d\ude4c',
2496 'raising_hand_woman':'\ud83d\ude4b',
2497 'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
2498 'ram':'\ud83d\udc0f',
2499 'ramen':'\ud83c\udf5c',
2500 'rat':'\ud83d\udc00',
2501 'record_button':'\u23fa',
2502 'recycle':'\u267b\ufe0f',
2503 'red_circle':'\ud83d\udd34',
2504 'registered':'\u00ae\ufe0f',
2505 'relaxed':'\u263a\ufe0f',
2506 'relieved':'\ud83d\ude0c',
2507 'reminder_ribbon':'\ud83c\udf97',
2508 'repeat':'\ud83d\udd01',
2509 'repeat_one':'\ud83d\udd02',
2510 'rescue_worker_helmet':'\u26d1',
2511 'restroom':'\ud83d\udebb',
2512 'revolving_hearts':'\ud83d\udc9e',
2513 'rewind':'\u23ea',
2514 'rhinoceros':'\ud83e\udd8f',
2515 'ribbon':'\ud83c\udf80',
2516 'rice':'\ud83c\udf5a',
2517 'rice_ball':'\ud83c\udf59',
2518 'rice_cracker':'\ud83c\udf58',
2519 'rice_scene':'\ud83c\udf91',
2520 'right_anger_bubble':'\ud83d\uddef',
2521 'ring':'\ud83d\udc8d',
2522 'robot':'\ud83e\udd16',
2523 'rocket':'\ud83d\ude80',
2524 'rofl':'\ud83e\udd23',
2525 'roll_eyes':'\ud83d\ude44',
2526 'roller_coaster':'\ud83c\udfa2',
2527 'rooster':'\ud83d\udc13',
2528 'rose':'\ud83c\udf39',
2529 'rosette':'\ud83c\udff5',
2530 'rotating_light':'\ud83d\udea8',
2531 'round_pushpin':'\ud83d\udccd',
2532 'rowing_man':'\ud83d\udea3',
2533 'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
2534 'rugby_football':'\ud83c\udfc9',
2535 'running_man':'\ud83c\udfc3',
2536 'running_shirt_with_sash':'\ud83c\udfbd',
2537 'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
2538 'sa':'\ud83c\ude02\ufe0f',
2539 'sagittarius':'\u2650\ufe0f',
2540 'sake':'\ud83c\udf76',
2541 'sandal':'\ud83d\udc61',
2542 'santa':'\ud83c\udf85',
2543 'satellite':'\ud83d\udce1',
2544 'saxophone':'\ud83c\udfb7',
2545 'school':'\ud83c\udfeb',
2546 'school_satchel':'\ud83c\udf92',
2547 'scissors':'\u2702\ufe0f',
2548 'scorpion':'\ud83e\udd82',
2549 'scorpius':'\u264f\ufe0f',
2550 'scream':'\ud83d\ude31',
2551 'scream_cat':'\ud83d\ude40',
2552 'scroll':'\ud83d\udcdc',
2553 'seat':'\ud83d\udcba',
2554 'secret':'\u3299\ufe0f',
2555 'see_no_evil':'\ud83d\ude48',
2556 'seedling':'\ud83c\udf31',
2557 'selfie':'\ud83e\udd33',
2558 'shallow_pan_of_food':'\ud83e\udd58',
2559 'shamrock':'\u2618\ufe0f',
2560 'shark':'\ud83e\udd88',
2561 'shaved_ice':'\ud83c\udf67',
2562 'sheep':'\ud83d\udc11',
2563 'shell':'\ud83d\udc1a',
2564 'shield':'\ud83d\udee1',
2565 'shinto_shrine':'\u26e9',
2566 'ship':'\ud83d\udea2',
2567 'shirt':'\ud83d\udc55',
2568 'shopping':'\ud83d\udecd',
2569 'shopping_cart':'\ud83d\uded2',
2570 'shower':'\ud83d\udebf',
2571 'shrimp':'\ud83e\udd90',
2572 'signal_strength':'\ud83d\udcf6',
2573 'six_pointed_star':'\ud83d\udd2f',
2574 'ski':'\ud83c\udfbf',
2575 'skier':'\u26f7',
2576 'skull':'\ud83d\udc80',
2577 'skull_and_crossbones':'\u2620\ufe0f',
2578 'sleeping':'\ud83d\ude34',
2579 'sleeping_bed':'\ud83d\udecc',
2580 'sleepy':'\ud83d\ude2a',
2581 'slightly_frowning_face':'\ud83d\ude41',
2582 'slightly_smiling_face':'\ud83d\ude42',
2583 'slot_machine':'\ud83c\udfb0',
2584 'small_airplane':'\ud83d\udee9',
2585 'small_blue_diamond':'\ud83d\udd39',
2586 'small_orange_diamond':'\ud83d\udd38',
2587 'small_red_triangle':'\ud83d\udd3a',
2588 'small_red_triangle_down':'\ud83d\udd3b',
2589 'smile':'\ud83d\ude04',
2590 'smile_cat':'\ud83d\ude38',
2591 'smiley':'\ud83d\ude03',
2592 'smiley_cat':'\ud83d\ude3a',
2593 'smiling_imp':'\ud83d\ude08',
2594 'smirk':'\ud83d\ude0f',
2595 'smirk_cat':'\ud83d\ude3c',
2596 'smoking':'\ud83d\udeac',
2597 'snail':'\ud83d\udc0c',
2598 'snake':'\ud83d\udc0d',
2599 'sneezing_face':'\ud83e\udd27',
2600 'snowboarder':'\ud83c\udfc2',
2601 'snowflake':'\u2744\ufe0f',
2602 'snowman':'\u26c4\ufe0f',
2603 'snowman_with_snow':'\u2603\ufe0f',
2604 'sob':'\ud83d\ude2d',
2605 'soccer':'\u26bd\ufe0f',
2606 'soon':'\ud83d\udd1c',
2607 'sos':'\ud83c\udd98',
2608 'sound':'\ud83d\udd09',
2609 'space_invader':'\ud83d\udc7e',
2610 'spades':'\u2660\ufe0f',
2611 'spaghetti':'\ud83c\udf5d',
2612 'sparkle':'\u2747\ufe0f',
2613 'sparkler':'\ud83c\udf87',
2614 'sparkles':'\u2728',
2615 'sparkling_heart':'\ud83d\udc96',
2616 'speak_no_evil':'\ud83d\ude4a',
2617 'speaker':'\ud83d\udd08',
2618 'speaking_head':'\ud83d\udde3',
2619 'speech_balloon':'\ud83d\udcac',
2620 'speedboat':'\ud83d\udea4',
2621 'spider':'\ud83d\udd77',
2622 'spider_web':'\ud83d\udd78',
2623 'spiral_calendar':'\ud83d\uddd3',
2624 'spiral_notepad':'\ud83d\uddd2',
2625 'spoon':'\ud83e\udd44',
2626 'squid':'\ud83e\udd91',
2627 'stadium':'\ud83c\udfdf',
2628 'star':'\u2b50\ufe0f',
2629 'star2':'\ud83c\udf1f',
2630 'star_and_crescent':'\u262a\ufe0f',
2631 'star_of_david':'\u2721\ufe0f',
2632 'stars':'\ud83c\udf20',
2633 'station':'\ud83d\ude89',
2634 'statue_of_liberty':'\ud83d\uddfd',
2635 'steam_locomotive':'\ud83d\ude82',
2636 'stew':'\ud83c\udf72',
2637 'stop_button':'\u23f9',
2638 'stop_sign':'\ud83d\uded1',
2639 'stopwatch':'\u23f1',
2640 'straight_ruler':'\ud83d\udccf',
2641 'strawberry':'\ud83c\udf53',
2642 'stuck_out_tongue':'\ud83d\ude1b',
2643 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2644 'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2645 'studio_microphone':'\ud83c\udf99',
2646 'stuffed_flatbread':'\ud83e\udd59',
2647 'sun_behind_large_cloud':'\ud83c\udf25',
2648 'sun_behind_rain_cloud':'\ud83c\udf26',
2649 'sun_behind_small_cloud':'\ud83c\udf24',
2650 'sun_with_face':'\ud83c\udf1e',
2651 'sunflower':'\ud83c\udf3b',
2652 'sunglasses':'\ud83d\ude0e',
2653 'sunny':'\u2600\ufe0f',
2654 'sunrise':'\ud83c\udf05',
2655 'sunrise_over_mountains':'\ud83c\udf04',
2656 'surfing_man':'\ud83c\udfc4',
2657 'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2658 'sushi':'\ud83c\udf63',
2659 'suspension_railway':'\ud83d\ude9f',
2660 'sweat':'\ud83d\ude13',
2661 'sweat_drops':'\ud83d\udca6',
2662 'sweat_smile':'\ud83d\ude05',
2663 'sweet_potato':'\ud83c\udf60',
2664 'swimming_man':'\ud83c\udfca',
2665 'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2666 'symbols':'\ud83d\udd23',
2667 'synagogue':'\ud83d\udd4d',
2668 'syringe':'\ud83d\udc89',
2669 'taco':'\ud83c\udf2e',
2670 'tada':'\ud83c\udf89',
2671 'tanabata_tree':'\ud83c\udf8b',
2672 'taurus':'\u2649\ufe0f',
2673 'taxi':'\ud83d\ude95',
2674 'tea':'\ud83c\udf75',
2675 'telephone_receiver':'\ud83d\udcde',
2676 'telescope':'\ud83d\udd2d',
2677 'tennis':'\ud83c\udfbe',
2678 'tent':'\u26fa\ufe0f',
2679 'thermometer':'\ud83c\udf21',
2680 'thinking':'\ud83e\udd14',
2681 'thought_balloon':'\ud83d\udcad',
2682 'ticket':'\ud83c\udfab',
2683 'tickets':'\ud83c\udf9f',
2684 'tiger':'\ud83d\udc2f',
2685 'tiger2':'\ud83d\udc05',
2686 'timer_clock':'\u23f2',
2687 'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2688 'tired_face':'\ud83d\ude2b',
2689 'tm':'\u2122\ufe0f',
2690 'toilet':'\ud83d\udebd',
2691 'tokyo_tower':'\ud83d\uddfc',
2692 'tomato':'\ud83c\udf45',
2693 'tongue':'\ud83d\udc45',
2694 'top':'\ud83d\udd1d',
2695 'tophat':'\ud83c\udfa9',
2696 'tornado':'\ud83c\udf2a',
2697 'trackball':'\ud83d\uddb2',
2698 'tractor':'\ud83d\ude9c',
2699 'traffic_light':'\ud83d\udea5',
2700 'train':'\ud83d\ude8b',
2701 'train2':'\ud83d\ude86',
2702 'tram':'\ud83d\ude8a',
2703 'triangular_flag_on_post':'\ud83d\udea9',
2704 'triangular_ruler':'\ud83d\udcd0',
2705 'trident':'\ud83d\udd31',
2706 'triumph':'\ud83d\ude24',
2707 'trolleybus':'\ud83d\ude8e',
2708 'trophy':'\ud83c\udfc6',
2709 'tropical_drink':'\ud83c\udf79',
2710 'tropical_fish':'\ud83d\udc20',
2711 'truck':'\ud83d\ude9a',
2712 'trumpet':'\ud83c\udfba',
2713 'tulip':'\ud83c\udf37',
2714 'tumbler_glass':'\ud83e\udd43',
2715 'turkey':'\ud83e\udd83',
2716 'turtle':'\ud83d\udc22',
2717 'tv':'\ud83d\udcfa',
2718 'twisted_rightwards_arrows':'\ud83d\udd00',
2719 'two_hearts':'\ud83d\udc95',
2720 'two_men_holding_hands':'\ud83d\udc6c',
2721 'two_women_holding_hands':'\ud83d\udc6d',
2722 'u5272':'\ud83c\ude39',
2723 'u5408':'\ud83c\ude34',
2724 'u55b6':'\ud83c\ude3a',
2725 'u6307':'\ud83c\ude2f\ufe0f',
2726 'u6708':'\ud83c\ude37\ufe0f',
2727 'u6709':'\ud83c\ude36',
2728 'u6e80':'\ud83c\ude35',
2729 'u7121':'\ud83c\ude1a\ufe0f',
2730 'u7533':'\ud83c\ude38',
2731 'u7981':'\ud83c\ude32',
2732 'u7a7a':'\ud83c\ude33',
2733 'umbrella':'\u2614\ufe0f',
2734 'unamused':'\ud83d\ude12',
2735 'underage':'\ud83d\udd1e',
2736 'unicorn':'\ud83e\udd84',
2737 'unlock':'\ud83d\udd13',
2738 'up':'\ud83c\udd99',
2739 'upside_down_face':'\ud83d\ude43',
2740 'v':'\u270c\ufe0f',
2741 'vertical_traffic_light':'\ud83d\udea6',
2742 'vhs':'\ud83d\udcfc',
2743 'vibration_mode':'\ud83d\udcf3',
2744 'video_camera':'\ud83d\udcf9',
2745 'video_game':'\ud83c\udfae',
2746 'violin':'\ud83c\udfbb',
2747 'virgo':'\u264d\ufe0f',
2748 'volcano':'\ud83c\udf0b',
2749 'volleyball':'\ud83c\udfd0',
2750 'vs':'\ud83c\udd9a',
2751 'vulcan_salute':'\ud83d\udd96',
2752 'walking_man':'\ud83d\udeb6',
2753 'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2754 'waning_crescent_moon':'\ud83c\udf18',
2755 'waning_gibbous_moon':'\ud83c\udf16',
2756 'warning':'\u26a0\ufe0f',
2757 'wastebasket':'\ud83d\uddd1',
2758 'watch':'\u231a\ufe0f',
2759 'water_buffalo':'\ud83d\udc03',
2760 'watermelon':'\ud83c\udf49',
2761 'wave':'\ud83d\udc4b',
2762 'wavy_dash':'\u3030\ufe0f',
2763 'waxing_crescent_moon':'\ud83c\udf12',
2764 'wc':'\ud83d\udebe',
2765 'weary':'\ud83d\ude29',
2766 'wedding':'\ud83d\udc92',
2767 'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2768 'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2769 'whale':'\ud83d\udc33',
2770 'whale2':'\ud83d\udc0b',
2771 'wheel_of_dharma':'\u2638\ufe0f',
2772 'wheelchair':'\u267f\ufe0f',
2773 'white_check_mark':'\u2705',
2774 'white_circle':'\u26aa\ufe0f',
2775 'white_flag':'\ud83c\udff3\ufe0f',
2776 'white_flower':'\ud83d\udcae',
2777 'white_large_square':'\u2b1c\ufe0f',
2778 'white_medium_small_square':'\u25fd\ufe0f',
2779 'white_medium_square':'\u25fb\ufe0f',
2780 'white_small_square':'\u25ab\ufe0f',
2781 'white_square_button':'\ud83d\udd33',
2782 'wilted_flower':'\ud83e\udd40',
2783 'wind_chime':'\ud83c\udf90',
2784 'wind_face':'\ud83c\udf2c',
2785 'wine_glass':'\ud83c\udf77',
2786 'wink':'\ud83d\ude09',
2787 'wolf':'\ud83d\udc3a',
2788 'woman':'\ud83d\udc69',
2789 'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2790 'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2791 'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2792 'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2793 'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2794 'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2795 'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2796 'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2797 'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2798 'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2799 'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2800 'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2801 'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2802 'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2803 'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2804 'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2805 'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2806 'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2807 'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2808 'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2809 'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2810 'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2811 'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2812 'womans_clothes':'\ud83d\udc5a',
2813 'womans_hat':'\ud83d\udc52',
2814 'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2815 'womens':'\ud83d\udeba',
2816 'world_map':'\ud83d\uddfa',
2817 'worried':'\ud83d\ude1f',
2818 'wrench':'\ud83d\udd27',
2819 'writing_hand':'\u270d\ufe0f',
2820 'x':'\u274c',
2821 'yellow_heart':'\ud83d\udc9b',
2822 'yen':'\ud83d\udcb4',
2823 'yin_yang':'\u262f\ufe0f',
2824 'yum':'\ud83d\ude0b',
2825 'zap':'\u26a1\ufe0f',
2826 'zipper_mouth_face':'\ud83e\udd10',
2827 'zzz':'\ud83d\udca4',
2828
2829 /* special emojis :P */
2830 'octocat': '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
2831 'showdown': '<span style="font-family: \'Anonymous Pro\', monospace; text-decoration: underline; text-decoration-style: dashed; text-decoration-color: #3e8b8a;text-underline-position: under;">S</span>'
2832 };
2833
2834 /**
2835 * Created by Estevao on 31-05-2015.
2836 */
2837
2838 /**
2839 * Showdown Converter class
2840 * @class
2841 * @param {object} [converterOptions]
2842 * @returns {Converter}
2843 */
2844 showdown.Converter = function (converterOptions) {
2845 'use strict';
2846
2847 var
2848 /**
2849 * Options used by this converter
2850 * @private
2851 * @type {{}}
2852 */
2853 options = {},
2854
2855 /**
2856 * Language extensions used by this converter
2857 * @private
2858 * @type {Array}
2859 */
2860 langExtensions = [],
2861
2862 /**
2863 * Output modifiers extensions used by this converter
2864 * @private
2865 * @type {Array}
2866 */
2867 outputModifiers = [],
2868
2869 /**
2870 * Event listeners
2871 * @private
2872 * @type {{}}
2873 */
2874 listeners = {},
2875
2876 /**
2877 * The flavor set in this converter
2878 */
2879 setConvFlavor = setFlavor,
2880
2881 /**
2882 * Metadata of the document
2883 * @type {{parsed: {}, raw: string, format: string}}
2884 */
2885 metadata = {
2886 parsed: {},
2887 raw: '',
2888 format: ''
2889 };
2890
2891 _constructor();
2892
2893 /**
2894 * Converter constructor
2895 * @private
2896 */
2897 function _constructor () {
2898 converterOptions = converterOptions || {};
2899
2900 for (var gOpt in globalOptions) {
2901 if (globalOptions.hasOwnProperty(gOpt)) {
2902 options[gOpt] = globalOptions[gOpt];
2903 }
2904 }
2905
2906 // Merge options
2907 if (typeof converterOptions === 'object') {
2908 for (var opt in converterOptions) {
2909 if (converterOptions.hasOwnProperty(opt)) {
2910 options[opt] = converterOptions[opt];
2911 }
2912 }
2913 } else {
2914 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
2915 ' was passed instead.');
2916 }
2917
2918 if (options.extensions) {
2919 showdown.helper.forEach(options.extensions, _parseExtension);
2920 }
2921 }
2922
2923 /**
2924 * Parse extension
2925 * @param {*} ext
2926 * @param {string} [name='']
2927 * @private
2928 */
2929 function _parseExtension (ext, name) {
2930
2931 name = name || null;
2932 // If it's a string, the extension was previously loaded
2933 if (showdown.helper.isString(ext)) {
2934 ext = showdown.helper.stdExtName(ext);
2935 name = ext;
2936
2937 // LEGACY_SUPPORT CODE
2938 if (showdown.extensions[ext]) {
2939 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
2940 'Please inform the developer that the extension should be updated!');
2941 legacyExtensionLoading(showdown.extensions[ext], ext);
2942 return;
2943 // END LEGACY SUPPORT CODE
2944
2945 } else if (!showdown.helper.isUndefined(extensions[ext])) {
2946 ext = extensions[ext];
2947
2948 } else {
2949 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
2950 }
2951 }
2952
2953 if (typeof ext === 'function') {
2954 ext = ext();
2955 }
2956
2957 if (!showdown.helper.isArray(ext)) {
2958 ext = [ext];
2959 }
2960
2961 var validExt = validate(ext, name);
2962 if (!validExt.valid) {
2963 throw Error(validExt.error);
2964 }
2965
2966 for (var i = 0; i < ext.length; ++i) {
2967 switch (ext[i].type) {
2968
2969 case 'lang':
2970 langExtensions.push(ext[i]);
2971 break;
2972
2973 case 'output':
2974 outputModifiers.push(ext[i]);
2975 break;
2976 }
2977 if (ext[i].hasOwnProperty('listeners')) {
2978 for (var ln in ext[i].listeners) {
2979 if (ext[i].listeners.hasOwnProperty(ln)) {
2980 listen(ln, ext[i].listeners[ln]);
2981 }
2982 }
2983 }
2984 }
2985
2986 }
2987
2988 /**
2989 * LEGACY_SUPPORT
2990 * @param {*} ext
2991 * @param {string} name
2992 */
2993 function legacyExtensionLoading (ext, name) {
2994 if (typeof ext === 'function') {
2995 ext = ext(new showdown.Converter());
2996 }
2997 if (!showdown.helper.isArray(ext)) {
2998 ext = [ext];
2999 }
3000 var valid = validate(ext, name);
3001
3002 if (!valid.valid) {
3003 throw Error(valid.error);
3004 }
3005
3006 for (var i = 0; i < ext.length; ++i) {
3007 switch (ext[i].type) {
3008 case 'lang':
3009 langExtensions.push(ext[i]);
3010 break;
3011 case 'output':
3012 outputModifiers.push(ext[i]);
3013 break;
3014 default:// should never reach here
3015 throw Error('Extension loader error: Type unrecognized!!!');
3016 }
3017 }
3018 }
3019
3020 /**
3021 * Listen to an event
3022 * @param {string} name
3023 * @param {function} callback
3024 */
3025 function listen (name, callback) {
3026 if (!showdown.helper.isString(name)) {
3027 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
3028 }
3029
3030 if (typeof callback !== 'function') {
3031 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
3032 }
3033
3034 if (!listeners.hasOwnProperty(name)) {
3035 listeners[name] = [];
3036 }
3037 listeners[name].push(callback);
3038 }
3039
3040 function rTrimInputText (text) {
3041 var rsp = text.match(/^\s*/)[0].length,
3042 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
3043 return text.replace(rgx, '');
3044 }
3045
3046 /**
3047 * Dispatch an event
3048 * @private
3049 * @param {string} evtName Event name
3050 * @param {string} text Text
3051 * @param {{}} options Converter Options
3052 * @param {{}} globals
3053 * @returns {string}
3054 */
3055 this._dispatch = function dispatch (evtName, text, options, globals) {
3056 if (listeners.hasOwnProperty(evtName)) {
3057 for (var ei = 0; ei < listeners[evtName].length; ++ei) {
3058 var nText = listeners[evtName][ei](evtName, text, this, options, globals);
3059 if (nText && typeof nText !== 'undefined') {
3060 text = nText;
3061 }
3062 }
3063 }
3064 return text;
3065 };
3066
3067 /**
3068 * Listen to an event
3069 * @param {string} name
3070 * @param {function} callback
3071 * @returns {showdown.Converter}
3072 */
3073 this.listen = function (name, callback) {
3074 listen(name, callback);
3075 return this;
3076 };
3077
3078 /**
3079 * Converts a markdown string into HTML
3080 * @param {string} text
3081 * @returns {*}
3082 */
3083 this.makeHtml = function (text) {
3084 //check if text is not falsy
3085 if (!text) {
3086 return text;
3087 }
3088
3089 var globals = {
3090 gHtmlBlocks: [],
3091 gHtmlMdBlocks: [],
3092 gHtmlSpans: [],
3093 gUrls: {},
3094 gTitles: {},
3095 gDimensions: {},
3096 gListLevel: 0,
3097 hashLinkCounts: {},
3098 langExtensions: langExtensions,
3099 outputModifiers: outputModifiers,
3100 converter: this,
3101 ghCodeBlocks: [],
3102 metadata: {
3103 parsed: {},
3104 raw: '',
3105 format: ''
3106 }
3107 };
3108
3109 // This lets us use ¨ trema as an escape char to avoid md5 hashes
3110 // The choice of character is arbitrary; anything that isn't
3111 // magic in Markdown will work.
3112 text = text.replace(/¨/g, '¨T');
3113
3114 // Replace $ with ¨D
3115 // RegExp interprets $ as a special character
3116 // when it's in a replacement string
3117 text = text.replace(/\$/g, '¨D');
3118
3119 // Standardize line endings
3120 text = text.replace(/\r\n/g, '\n'); // DOS to Unix
3121 text = text.replace(/\r/g, '\n'); // Mac to Unix
3122
3123 // Stardardize line spaces
3124 text = text.replace(/\u00A0/g, '&nbsp;');
3125
3126 if (options.smartIndentationFix) {
3127 text = rTrimInputText(text);
3128 }
3129
3130 // Make sure text begins and ends with a couple of newlines:
3131 text = '\n\n' + text + '\n\n';
3132
3133 // detab
3134 text = showdown.subParser('detab')(text, options, globals);
3135
3136 /**
3137 * Strip any lines consisting only of spaces and tabs.
3138 * This makes subsequent regexs easier to write, because we can
3139 * match consecutive blank lines with /\n+/ instead of something
3140 * contorted like /[ \t]*\n+/
3141 */
3142 text = text.replace(/^[ \t]+$/mg, '');
3143
3144 //run languageExtensions
3145 showdown.helper.forEach(langExtensions, function (ext) {
3146 text = showdown.subParser('runExtension')(ext, text, options, globals);
3147 });
3148
3149 // run the sub parsers
3150 text = showdown.subParser('metadata')(text, options, globals);
3151 text = showdown.subParser('hashPreCodeTags')(text, options, globals);
3152 text = showdown.subParser('githubCodeBlocks')(text, options, globals);
3153 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3154 text = showdown.subParser('hashCodeTags')(text, options, globals);
3155 text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
3156 text = showdown.subParser('blockGamut')(text, options, globals);
3157 text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
3158 text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
3159
3160 // attacklab: Restore dollar signs
3161 text = text.replace(/¨D/g, '$$');
3162
3163 // attacklab: Restore tremas
3164 text = text.replace(/¨T/g, '¨');
3165
3166 // render a complete html document instead of a partial if the option is enabled
3167 text = showdown.subParser('completeHTMLDocument')(text, options, globals);
3168
3169 // Run output modifiers
3170 showdown.helper.forEach(outputModifiers, function (ext) {
3171 text = showdown.subParser('runExtension')(ext, text, options, globals);
3172 });
3173
3174 // update metadata
3175 metadata = globals.metadata;
3176 return text;
3177 };
3178
3179 /**
3180 * Converts an HTML string into a markdown string
3181 * @param src
3182 * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
3183 * @returns {string}
3184 */
3185 this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
3186
3187 // replace \r\n with \n
3188 src = src.replace(/\r\n/g, '\n');
3189 src = src.replace(/\r/g, '\n'); // old macs
3190
3191 // due to an edge case, we need to find this: > <
3192 // to prevent removing of non silent white spaces
3193 // ex: <em>this is</em> <strong>sparta</strong>
3194 src = src.replace(/>[ \t]+</, '>¨NBSP;<');
3195
3196 if (!HTMLParser) {
3197 if (window && window.document) {
3198 HTMLParser = window.document;
3199 } else {
3200 throw new Error('HTMLParser is undefined. If in a webworker or nodejs environment, you need to provide a WHATWG DOM and HTML such as JSDOM');
3201 }
3202 }
3203
3204 var doc = HTMLParser.createElement('div');
3205 doc.innerHTML = src;
3206
3207 var globals = {
3208 preList: substitutePreCodeTags(doc)
3209 };
3210
3211 // remove all newlines and collapse spaces
3212 clean(doc);
3213
3214 // some stuff, like accidental reference links must now be escaped
3215 // TODO
3216 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
3217
3218 var nodes = doc.childNodes,
3219 mdDoc = '';
3220
3221 for (var i = 0; i < nodes.length; i++) {
3222 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
3223 }
3224
3225 function clean (node) {
3226 for (var n = 0; n < node.childNodes.length; ++n) {
3227 var child = node.childNodes[n];
3228 if (child.nodeType === 3) {
3229 if (!/\S/.test(child.nodeValue)) {
3230 node.removeChild(child);
3231 --n;
3232 } else {
3233 child.nodeValue = child.nodeValue.split('\n').join(' ');
3234 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
3235 }
3236 } else if (child.nodeType === 1) {
3237 clean(child);
3238 }
3239 }
3240 }
3241
3242 // find all pre tags and replace contents with placeholder
3243 // we need this so that we can remove all indentation from html
3244 // to ease up parsing
3245 function substitutePreCodeTags (doc) {
3246
3247 var pres = doc.querySelectorAll('pre'),
3248 presPH = [];
3249
3250 for (var i = 0; i < pres.length; ++i) {
3251
3252 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
3253 var content = pres[i].firstChild.innerHTML.trim(),
3254 language = pres[i].firstChild.getAttribute('data-language') || '';
3255
3256 // if data-language attribute is not defined, then we look for class language-*
3257 if (language === '') {
3258 var classes = pres[i].firstChild.className.split(' ');
3259 for (var c = 0; c < classes.length; ++c) {
3260 var matches = classes[c].match(/^language-(.+)$/);
3261 if (matches !== null) {
3262 language = matches[1];
3263 break;
3264 }
3265 }
3266 }
3267
3268 // unescape html entities in content
3269 content = showdown.helper.unescapeHTMLEntities(content);
3270
3271 presPH.push(content);
3272 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
3273 } else {
3274 presPH.push(pres[i].innerHTML);
3275 pres[i].innerHTML = '';
3276 pres[i].setAttribute('prenum', i.toString());
3277 }
3278 }
3279 return presPH;
3280 }
3281
3282 return mdDoc;
3283 };
3284
3285 /**
3286 * Set an option of this Converter instance
3287 * @param {string} key
3288 * @param {*} value
3289 */
3290 this.setOption = function (key, value) {
3291 options[key] = value;
3292 };
3293
3294 /**
3295 * Get the option of this Converter instance
3296 * @param {string} key
3297 * @returns {*}
3298 */
3299 this.getOption = function (key) {
3300 return options[key];
3301 };
3302
3303 /**
3304 * Get the options of this Converter instance
3305 * @returns {{}}
3306 */
3307 this.getOptions = function () {
3308 return options;
3309 };
3310
3311 /**
3312 * Add extension to THIS converter
3313 * @param {{}} extension
3314 * @param {string} [name=null]
3315 */
3316 this.addExtension = function (extension, name) {
3317 name = name || null;
3318 _parseExtension(extension, name);
3319 };
3320
3321 /**
3322 * Use a global registered extension with THIS converter
3323 * @param {string} extensionName Name of the previously registered extension
3324 */
3325 this.useExtension = function (extensionName) {
3326 _parseExtension(extensionName);
3327 };
3328
3329 /**
3330 * Set the flavor THIS converter should use
3331 * @param {string} name
3332 */
3333 this.setFlavor = function (name) {
3334 if (!flavor.hasOwnProperty(name)) {
3335 throw Error(name + ' flavor was not found');
3336 }
3337 var preset = flavor[name];
3338 setConvFlavor = name;
3339 for (var option in preset) {
3340 if (preset.hasOwnProperty(option)) {
3341 options[option] = preset[option];
3342 }
3343 }
3344 };
3345
3346 /**
3347 * Get the currently set flavor of this converter
3348 * @returns {string}
3349 */
3350 this.getFlavor = function () {
3351 return setConvFlavor;
3352 };
3353
3354 /**
3355 * Remove an extension from THIS converter.
3356 * Note: This is a costly operation. It's better to initialize a new converter
3357 * and specify the extensions you wish to use
3358 * @param {Array} extension
3359 */
3360 this.removeExtension = function (extension) {
3361 if (!showdown.helper.isArray(extension)) {
3362 extension = [extension];
3363 }
3364 for (var a = 0; a < extension.length; ++a) {
3365 var ext = extension[a];
3366 for (var i = 0; i < langExtensions.length; ++i) {
3367 if (langExtensions[i] === ext) {
3368 langExtensions[i].splice(i, 1);
3369 }
3370 }
3371 for (var ii = 0; ii < outputModifiers.length; ++i) {
3372 if (outputModifiers[ii] === ext) {
3373 outputModifiers[ii].splice(i, 1);
3374 }
3375 }
3376 }
3377 };
3378
3379 /**
3380 * Get all extension of THIS converter
3381 * @returns {{language: Array, output: Array}}
3382 */
3383 this.getAllExtensions = function () {
3384 return {
3385 language: langExtensions,
3386 output: outputModifiers
3387 };
3388 };
3389
3390 /**
3391 * Get the metadata of the previously parsed document
3392 * @param raw
3393 * @returns {string|{}}
3394 */
3395 this.getMetadata = function (raw) {
3396 if (raw) {
3397 return metadata.raw;
3398 } else {
3399 return metadata.parsed;
3400 }
3401 };
3402
3403 /**
3404 * Get the metadata format of the previously parsed document
3405 * @returns {string}
3406 */
3407 this.getMetadataFormat = function () {
3408 return metadata.format;
3409 };
3410
3411 /**
3412 * Private: set a single key, value metadata pair
3413 * @param {string} key
3414 * @param {string} value
3415 */
3416 this._setMetadataPair = function (key, value) {
3417 metadata.parsed[key] = value;
3418 };
3419
3420 /**
3421 * Private: set metadata format
3422 * @param {string} format
3423 */
3424 this._setMetadataFormat = function (format) {
3425 metadata.format = format;
3426 };
3427
3428 /**
3429 * Private: set metadata raw text
3430 * @param {string} raw
3431 */
3432 this._setMetadataRaw = function (raw) {
3433 metadata.raw = raw;
3434 };
3435 };
3436
3437 /**
3438 * Turn Markdown link shortcuts into XHTML <a> tags.
3439 */
3440 showdown.subParser('anchors', function (text, options, globals) {
3441 'use strict';
3442
3443 text = globals.converter._dispatch('anchors.before', text, options, globals);
3444
3445 var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
3446 if (showdown.helper.isUndefined(title)) {
3447 title = '';
3448 }
3449 linkId = linkId.toLowerCase();
3450
3451 // Special case for explicit empty url
3452 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3453 url = '';
3454 } else if (!url) {
3455 if (!linkId) {
3456 // lower-case and turn embedded newlines into spaces
3457 linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
3458 }
3459 url = '#' + linkId;
3460
3461 if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
3462 url = globals.gUrls[linkId];
3463 if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
3464 title = globals.gTitles[linkId];
3465 }
3466 } else {
3467 return wholeMatch;
3468 }
3469 }
3470
3471 //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
3472 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3473
3474 var result = '<a href="' + url + '"';
3475
3476 if (title !== '' && title !== null) {
3477 title = title.replace(/"/g, '&quot;');
3478 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3479 title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3480 result += ' title="' + title + '"';
3481 }
3482
3483 // optionLinksInNewWindow only applies
3484 // to external links. Hash links (#) open in same page
3485 if (options.openLinksInNewWindow && !/^#/.test(url)) {
3486 // escaped _
3487 result += ' rel="noopener noreferrer" target="¨E95Eblank"';
3488 }
3489
3490 result += '>' + linkText + '</a>';
3491
3492 return result;
3493 };
3494
3495 // First, handle reference-style links: [link text] [id]
3496 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
3497
3498 // Next, inline-style links: [link text](url "optional title")
3499 // cases with crazy urls like ./image/cat1).png
3500 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3501 writeAnchorTag);
3502
3503 // normal cases
3504 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3505 writeAnchorTag);
3506
3507 // handle reference-style shortcuts: [link text]
3508 // These must come last in case you've also got [link test][1]
3509 // or [link test](/foo)
3510 text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
3511
3512 // Lastly handle GithubMentions if option is enabled
3513 if (options.ghMentions) {
3514 text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
3515 if (escape === '\\') {
3516 return st + mentions;
3517 }
3518
3519 //check if options.ghMentionsLink is a string
3520 if (!showdown.helper.isString(options.ghMentionsLink)) {
3521 throw new Error('ghMentionsLink option must be a string');
3522 }
3523 var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
3524 target = '';
3525 if (options.openLinksInNewWindow) {
3526 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3527 }
3528 return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
3529 });
3530 }
3531
3532 text = globals.converter._dispatch('anchors.after', text, options, globals);
3533 return text;
3534 });
3535
3536 // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
3537
3538 var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
3539 simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
3540 delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
3541 simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
3542 delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
3543
3544 replaceLink = function (options) {
3545 'use strict';
3546 return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
3547 link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3548 var lnkTxt = link,
3549 append = '',
3550 target = '',
3551 lmc = leadingMagicChars || '',
3552 tmc = trailingMagicChars || '';
3553 if (/^www\./i.test(link)) {
3554 link = link.replace(/^www\./i, 'http://www.');
3555 }
3556 if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
3557 append = trailingPunctuation;
3558 }
3559 if (options.openLinksInNewWindow) {
3560 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3561 }
3562 return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
3563 };
3564 },
3565
3566 replaceMail = function (options, globals) {
3567 'use strict';
3568 return function (wholeMatch, b, mail) {
3569 var href = 'mailto:';
3570 b = b || '';
3571 mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
3572 if (options.encodeEmails) {
3573 href = showdown.helper.encodeEmailAddress(href + mail);
3574 mail = showdown.helper.encodeEmailAddress(mail);
3575 } else {
3576 href = href + mail;
3577 }
3578 return b + '<a href="' + href + '">' + mail + '</a>';
3579 };
3580 };
3581
3582 showdown.subParser('autoLinks', function (text, options, globals) {
3583 'use strict';
3584
3585 text = globals.converter._dispatch('autoLinks.before', text, options, globals);
3586
3587 text = text.replace(delimUrlRegex, replaceLink(options));
3588 text = text.replace(delimMailRegex, replaceMail(options, globals));
3589
3590 text = globals.converter._dispatch('autoLinks.after', text, options, globals);
3591
3592 return text;
3593 });
3594
3595 showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
3596 'use strict';
3597
3598 if (!options.simplifiedAutoLink) {
3599 return text;
3600 }
3601
3602 text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
3603
3604 if (options.excludeTrailingPunctuationFromURLs) {
3605 text = text.replace(simpleURLRegex2, replaceLink(options));
3606 } else {
3607 text = text.replace(simpleURLRegex, replaceLink(options));
3608 }
3609 text = text.replace(simpleMailRegex, replaceMail(options, globals));
3610
3611 text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
3612
3613 return text;
3614 });
3615
3616 /**
3617 * These are all the transformations that form block-level
3618 * tags like paragraphs, headers, and list items.
3619 */
3620 showdown.subParser('blockGamut', function (text, options, globals) {
3621 'use strict';
3622
3623 text = globals.converter._dispatch('blockGamut.before', text, options, globals);
3624
3625 // we parse blockquotes first so that we can have headings and hrs
3626 // inside blockquotes
3627 text = showdown.subParser('blockQuotes')(text, options, globals);
3628 text = showdown.subParser('headers')(text, options, globals);
3629
3630 // Do Horizontal Rules:
3631 text = showdown.subParser('horizontalRule')(text, options, globals);
3632
3633 text = showdown.subParser('lists')(text, options, globals);
3634 text = showdown.subParser('codeBlocks')(text, options, globals);
3635 text = showdown.subParser('tables')(text, options, globals);
3636
3637 // We already ran _HashHTMLBlocks() before, in Markdown(), but that
3638 // was to escape raw HTML in the original Markdown source. This time,
3639 // we're escaping the markup we've just created, so that we don't wrap
3640 // <p> tags around block-level tags.
3641 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3642 text = showdown.subParser('paragraphs')(text, options, globals);
3643
3644 text = globals.converter._dispatch('blockGamut.after', text, options, globals);
3645
3646 return text;
3647 });
3648
3649 showdown.subParser('blockQuotes', function (text, options, globals) {
3650 'use strict';
3651
3652 text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
3653
3654 // add a couple extra lines after the text and endtext mark
3655 text = text + '\n\n';
3656
3657 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
3658
3659 if (options.splitAdjacentBlockquotes) {
3660 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
3661 }
3662
3663 text = text.replace(rgx, function (bq) {
3664 // attacklab: hack around Konqueror 3.5.4 bug:
3665 // "----------bug".replace(/^-/g,"") == "bug"
3666 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
3667
3668 // attacklab: clean up hack
3669 bq = bq.replace(/¨0/g, '');
3670
3671 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
3672 bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
3673 bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
3674
3675 bq = bq.replace(/(^|\n)/g, '$1 ');
3676 // These leading spaces screw with <pre> content, so we need to fix that:
3677 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
3678 var pre = m1;
3679 // attacklab: hack around Konqueror 3.5.4 bug:
3680 pre = pre.replace(/^ /mg, '¨0');
3681 pre = pre.replace(/¨0/g, '');
3682 return pre;
3683 });
3684
3685 return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
3686 });
3687
3688 text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
3689 return text;
3690 });
3691
3692 /**
3693 * Process Markdown `<pre><code>` blocks.
3694 */
3695 showdown.subParser('codeBlocks', function (text, options, globals) {
3696 'use strict';
3697
3698 text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
3699
3700 // sentinel workarounds for lack of \A and \Z, safari\khtml bug
3701 text += '¨0';
3702
3703 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
3704 text = text.replace(pattern, function (wholeMatch, m1, m2) {
3705 var codeblock = m1,
3706 nextChar = m2,
3707 end = '\n';
3708
3709 codeblock = showdown.subParser('outdent')(codeblock, options, globals);
3710 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3711 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3712 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3713 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
3714
3715 if (options.omitExtraWLInCodeBlocks) {
3716 end = '';
3717 }
3718
3719 codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
3720
3721 return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
3722 });
3723
3724 // strip sentinel
3725 text = text.replace(/¨0/, '');
3726
3727 text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
3728 return text;
3729 });
3730
3731 /**
3732 *
3733 * * Backtick quotes are used for <code></code> spans.
3734 *
3735 * * You can use multiple backticks as the delimiters if you want to
3736 * include literal backticks in the code span. So, this input:
3737 *
3738 * Just type ``foo `bar` baz`` at the prompt.
3739 *
3740 * Will translate to:
3741 *
3742 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
3743 *
3744 * There's no arbitrary limit to the number of backticks you
3745 * can use as delimters. If you need three consecutive backticks
3746 * in your code, use four for delimiters, etc.
3747 *
3748 * * You can use spaces to get literal backticks at the edges:
3749 *
3750 * ... type `` `bar` `` ...
3751 *
3752 * Turns to:
3753 *
3754 * ... type <code>`bar`</code> ...
3755 */
3756 showdown.subParser('codeSpans', function (text, options, globals) {
3757 'use strict';
3758
3759 text = globals.converter._dispatch('codeSpans.before', text, options, globals);
3760
3761 if (typeof text === 'undefined') {
3762 text = '';
3763 }
3764 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
3765 function (wholeMatch, m1, m2, m3) {
3766 var c = m3;
3767 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
3768 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
3769 c = showdown.subParser('encodeCode')(c, options, globals);
3770 c = m1 + '<code>' + c + '</code>';
3771 c = showdown.subParser('hashHTMLSpans')(c, options, globals);
3772 return c;
3773 }
3774 );
3775
3776 text = globals.converter._dispatch('codeSpans.after', text, options, globals);
3777 return text;
3778 });
3779
3780 /**
3781 * Create a full HTML document from the processed markdown
3782 */
3783 showdown.subParser('completeHTMLDocument', function (text, options, globals) {
3784 'use strict';
3785
3786 if (!options.completeHTMLDocument) {
3787 return text;
3788 }
3789
3790 text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
3791
3792 var doctype = 'html',
3793 doctypeParsed = '<!DOCTYPE HTML>\n',
3794 title = '',
3795 charset = '<meta charset="utf-8">\n',
3796 lang = '',
3797 metadata = '';
3798
3799 if (typeof globals.metadata.parsed.doctype !== 'undefined') {
3800 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n';
3801 doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
3802 if (doctype === 'html' || doctype === 'html5') {
3803 charset = '<meta charset="utf-8">';
3804 }
3805 }
3806
3807 for (var meta in globals.metadata.parsed) {
3808 if (globals.metadata.parsed.hasOwnProperty(meta)) {
3809 switch (meta.toLowerCase()) {
3810 case 'doctype':
3811 break;
3812
3813 case 'title':
3814 title = '<title>' + globals.metadata.parsed.title + '</title>\n';
3815 break;
3816
3817 case 'charset':
3818 if (doctype === 'html' || doctype === 'html5') {
3819 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
3820 } else {
3821 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
3822 }
3823 break;
3824
3825 case 'language':
3826 case 'lang':
3827 lang = ' lang="' + globals.metadata.parsed[meta] + '"';
3828 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3829 break;
3830
3831 default:
3832 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3833 }
3834 }
3835 }
3836
3837 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
3838
3839 text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
3840 return text;
3841 });
3842
3843 /**
3844 * Convert all tabs to spaces
3845 */
3846 showdown.subParser('detab', function (text, options, globals) {
3847 'use strict';
3848 text = globals.converter._dispatch('detab.before', text, options, globals);
3849
3850 // expand first n-1 tabs
3851 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
3852
3853 // replace the nth with two sentinels
3854 text = text.replace(/\t/g, '¨A¨B');
3855
3856 // use the sentinel to anchor our regex so it doesn't explode
3857 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
3858 var leadingText = m1,
3859 numSpaces = 4 - leadingText.length % 4; // g_tab_width
3860
3861 // there *must* be a better way to do this:
3862 for (var i = 0; i < numSpaces; i++) {
3863 leadingText += ' ';
3864 }
3865
3866 return leadingText;
3867 });
3868
3869 // clean up sentinels
3870 text = text.replace(/¨A/g, ' '); // g_tab_width
3871 text = text.replace(/¨B/g, '');
3872
3873 text = globals.converter._dispatch('detab.after', text, options, globals);
3874 return text;
3875 });
3876
3877 showdown.subParser('ellipsis', function (text, options, globals) {
3878 'use strict';
3879
3880 text = globals.converter._dispatch('ellipsis.before', text, options, globals);
3881
3882 text = text.replace(/\.\.\./g, '…');
3883
3884 text = globals.converter._dispatch('ellipsis.after', text, options, globals);
3885
3886 return text;
3887 });
3888
3889 /**
3890 * Turn emoji codes into emojis
3891 *
3892 * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
3893 */
3894 showdown.subParser('emoji', function (text, options, globals) {
3895 'use strict';
3896
3897 if (!options.emoji) {
3898 return text;
3899 }
3900
3901 text = globals.converter._dispatch('emoji.before', text, options, globals);
3902
3903 var emojiRgx = /:([\S]+?):/g;
3904
3905 text = text.replace(emojiRgx, function (wm, emojiCode) {
3906 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
3907 return showdown.helper.emojis[emojiCode];
3908 }
3909 return wm;
3910 });
3911
3912 text = globals.converter._dispatch('emoji.after', text, options, globals);
3913
3914 return text;
3915 });
3916
3917 /**
3918 * Smart processing for ampersands and angle brackets that need to be encoded.
3919 */
3920 showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
3921 'use strict';
3922 text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
3923
3924 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
3925 // http://bumppo.net/projects/amputator/
3926 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
3927
3928 // Encode naked <'s
3929 text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3930
3931 // Encode <
3932 text = text.replace(/</g, '&lt;');
3933
3934 // Encode >
3935 text = text.replace(/>/g, '&gt;');
3936
3937 text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
3938 return text;
3939 });
3940
3941 /**
3942 * Returns the string, with after processing the following backslash escape sequences.
3943 *
3944 * attacklab: The polite way to do this is with the new escapeCharacters() function:
3945 *
3946 * text = escapeCharacters(text,"\\",true);
3947 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
3948 *
3949 * ...but we're sidestepping its use of the (slow) RegExp constructor
3950 * as an optimization for Firefox. This function gets called a LOT.
3951 */
3952 showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
3953 'use strict';
3954 text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
3955
3956 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
3957 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
3958
3959 text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
3960 return text;
3961 });
3962
3963 /**
3964 * Encode/escape certain characters inside Markdown code runs.
3965 * The point is that in code, these characters are literals,
3966 * and lose their special Markdown meanings.
3967 */
3968 showdown.subParser('encodeCode', function (text, options, globals) {
3969 'use strict';
3970
3971 text = globals.converter._dispatch('encodeCode.before', text, options, globals);
3972
3973 // Encode all ampersands; HTML entities are not
3974 // entities within a Markdown code span.
3975 text = text
3976 .replace(/&/g, '&amp;')
3977 // Do the angle bracket song and dance:
3978 .replace(/</g, '&lt;')
3979 .replace(/>/g, '&gt;')
3980 // Now, escape characters that are magic in Markdown:
3981 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
3982
3983 text = globals.converter._dispatch('encodeCode.after', text, options, globals);
3984 return text;
3985 });
3986
3987 /**
3988 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
3989 * don't conflict with their use in Markdown for code, italics and strong.
3990 */
3991 showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
3992 'use strict';
3993 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
3994
3995 // Build a regex to find HTML tags.
3996 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
3997 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
3998
3999 text = text.replace(tags, function (wholeMatch) {
4000 return wholeMatch
4001 .replace(/(.)<\/?code>(?=.)/g, '$1`')
4002 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
4003 });
4004
4005 text = text.replace(comments, function (wholeMatch) {
4006 return wholeMatch
4007 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
4008 });
4009
4010 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
4011 return text;
4012 });
4013
4014 /**
4015 * Handle github codeblocks prior to running HashHTML so that
4016 * HTML contained within the codeblock gets escaped properly
4017 * Example:
4018 * ```ruby
4019 * def hello_world(x)
4020 * puts "Hello, #{x}"
4021 * end
4022 * ```
4023 */
4024 showdown.subParser('githubCodeBlocks', function (text, options, globals) {
4025 'use strict';
4026
4027 // early exit if option is not enabled
4028 if (!options.ghCodeBlocks) {
4029 return text;
4030 }
4031
4032 text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
4033
4034 text += '¨0';
4035
4036 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
4037 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
4038
4039 // First parse the github code block
4040 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
4041 codeblock = showdown.subParser('detab')(codeblock, options, globals);
4042 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
4043 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
4044
4045 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
4046
4047 codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
4048
4049 // Since GHCodeblocks can be false positives, we need to
4050 // store the primitive text and the parsed text in a global var,
4051 // and then return a token
4052 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
4053 });
4054
4055 // attacklab: strip sentinel
4056 text = text.replace(/¨0/, '');
4057
4058 return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
4059 });
4060
4061 showdown.subParser('hashBlock', function (text, options, globals) {
4062 'use strict';
4063 text = globals.converter._dispatch('hashBlock.before', text, options, globals);
4064 text = text.replace(/(^\n+|\n+$)/g, '');
4065 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
4066 text = globals.converter._dispatch('hashBlock.after', text, options, globals);
4067 return text;
4068 });
4069
4070 /**
4071 * Hash and escape <code> elements that should not be parsed as markdown
4072 */
4073 showdown.subParser('hashCodeTags', function (text, options, globals) {
4074 'use strict';
4075 text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
4076
4077 var repFunc = function (wholeMatch, match, left, right) {
4078 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4079 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
4080 };
4081
4082 // Hash naked <code>
4083 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
4084
4085 text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
4086 return text;
4087 });
4088
4089 showdown.subParser('hashElement', function (text, options, globals) {
4090 'use strict';
4091
4092 return function (wholeMatch, m1) {
4093 var blockText = m1;
4094
4095 // Undo double lines
4096 blockText = blockText.replace(/\n\n/g, '\n');
4097 blockText = blockText.replace(/^\n/, '');
4098
4099 // strip trailing blank lines
4100 blockText = blockText.replace(/\n+$/g, '');
4101
4102 // Replace the element text with a marker ("¨KxK" where x is its key)
4103 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
4104
4105 return blockText;
4106 };
4107 });
4108
4109 showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
4110 'use strict';
4111 text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
4112
4113 var blockTags = [
4114 'pre',
4115 'div',
4116 'h1',
4117 'h2',
4118 'h3',
4119 'h4',
4120 'h5',
4121 'h6',
4122 'blockquote',
4123 'table',
4124 'dl',
4125 'ol',
4126 'ul',
4127 'script',
4128 'noscript',
4129 'form',
4130 'fieldset',
4131 'iframe',
4132 'math',
4133 'style',
4134 'section',
4135 'header',
4136 'footer',
4137 'nav',
4138 'article',
4139 'aside',
4140 'address',
4141 'audio',
4142 'canvas',
4143 'figure',
4144 'hgroup',
4145 'output',
4146 'video',
4147 'p'
4148 ],
4149 repFunc = function (wholeMatch, match, left, right) {
4150 var txt = wholeMatch;
4151 // check if this html element is marked as markdown
4152 // if so, it's contents should be parsed as markdown
4153 if (left.search(/\bmarkdown\b/) !== -1) {
4154 txt = left + globals.converter.makeHtml(match) + right;
4155 }
4156 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4157 };
4158
4159 if (options.backslashEscapesHTMLTags) {
4160 // encode backslash escaped HTML tags
4161 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
4162 return '&lt;' + inside + '&gt;';
4163 });
4164 }
4165
4166 // hash HTML Blocks
4167 for (var i = 0; i < blockTags.length; ++i) {
4168
4169 var opTagPos,
4170 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
4171 patLeft = '<' + blockTags[i] + '\\b[^>]*>',
4172 patRight = '</' + blockTags[i] + '>';
4173 // 1. Look for the first position of the first opening HTML tag in the text
4174 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
4175
4176 // if the HTML tag is \ escaped, we need to escape it and break
4177
4178
4179 //2. Split the text in that position
4180 var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
4181 //3. Match recursively
4182 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
4183
4184 // prevent an infinite loop
4185 if (newSubText1 === subTexts[1]) {
4186 break;
4187 }
4188 text = subTexts[0].concat(newSubText1);
4189 }
4190 }
4191 // HR SPECIAL CASE
4192 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
4193 showdown.subParser('hashElement')(text, options, globals));
4194
4195 // Special case for standalone HTML comments
4196 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
4197 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4198 }, '^ {0,3}<!--', '-->', 'gm');
4199
4200 // PHP and ASP-style processor instructions (<?...?> and <%...%>)
4201 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
4202 showdown.subParser('hashElement')(text, options, globals));
4203
4204 text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
4205 return text;
4206 });
4207
4208 /**
4209 * Hash span elements that should not be parsed as markdown
4210 */
4211 showdown.subParser('hashHTMLSpans', function (text, options, globals) {
4212 'use strict';
4213 text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
4214
4215 function hashHTMLSpan (html) {
4216 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
4217 }
4218
4219 // Hash Self Closing tags
4220 text = text.replace(/<[^>]+?\/>/gi, function (wm) {
4221 return hashHTMLSpan(wm);
4222 });
4223
4224 // Hash tags without properties
4225 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
4226 return hashHTMLSpan(wm);
4227 });
4228
4229 // Hash tags with properties
4230 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
4231 return hashHTMLSpan(wm);
4232 });
4233
4234 // Hash self closing tags without />
4235 text = text.replace(/<[^>]+?>/gi, function (wm) {
4236 return hashHTMLSpan(wm);
4237 });
4238
4239 /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
4240
4241 text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
4242 return text;
4243 });
4244
4245 /**
4246 * Unhash HTML spans
4247 */
4248 showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
4249 'use strict';
4250 text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
4251
4252 for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
4253 var repText = globals.gHtmlSpans[i],
4254 // limiter to prevent infinite loop (assume 10 as limit for recurse)
4255 limit = 0;
4256
4257 while (/¨C(\d+)C/.test(repText)) {
4258 var num = RegExp.$1;
4259 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
4260 if (limit === 10) {
4261 console.error('maximum nesting of 10 spans reached!!!');
4262 break;
4263 }
4264 ++limit;
4265 }
4266 text = text.replace('¨C' + i + 'C', repText);
4267 }
4268
4269 text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
4270 return text;
4271 });
4272
4273 /**
4274 * Hash and escape <pre><code> elements that should not be parsed as markdown
4275 */
4276 showdown.subParser('hashPreCodeTags', function (text, options, globals) {
4277 'use strict';
4278 text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
4279
4280 var repFunc = function (wholeMatch, match, left, right) {
4281 // encode html entities
4282 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4283 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
4284 };
4285
4286 // Hash <pre><code>
4287 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
4288
4289 text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
4290 return text;
4291 });
4292
4293 showdown.subParser('headers', function (text, options, globals) {
4294 'use strict';
4295
4296 text = globals.converter._dispatch('headers.before', text, options, globals);
4297
4298 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
4299
4300 // Set text-style headers:
4301 // Header 1
4302 // ========
4303 //
4304 // Header 2
4305 // --------
4306 //
4307 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
4308 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
4309
4310 text = text.replace(setextRegexH1, function (wholeMatch, m1) {
4311
4312 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4313 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4314 hLevel = headerLevelStart,
4315 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4316 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4317 });
4318
4319 text = text.replace(setextRegexH2, function (matchFound, m1) {
4320 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4321 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4322 hLevel = headerLevelStart + 1,
4323 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4324 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4325 });
4326
4327 // atx-style headers:
4328 // # Header 1
4329 // ## Header 2
4330 // ## Header 2 with closing hashes ##
4331 // ...
4332 // ###### Header 6
4333 //
4334 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
4335
4336 text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
4337 var hText = m2;
4338 if (options.customizedHeaderId) {
4339 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
4340 }
4341
4342 var span = showdown.subParser('spanGamut')(hText, options, globals),
4343 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
4344 hLevel = headerLevelStart - 1 + m1.length,
4345 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
4346
4347 return showdown.subParser('hashBlock')(header, options, globals);
4348 });
4349
4350 function headerId (m) {
4351 var title,
4352 prefix;
4353
4354 // It is separate from other options to allow combining prefix and customized
4355 if (options.customizedHeaderId) {
4356 var match = m.match(/\{([^{]+?)}\s*$/);
4357 if (match && match[1]) {
4358 m = match[1];
4359 }
4360 }
4361
4362 title = m;
4363
4364 // Prefix id to prevent causing inadvertent pre-existing style matches.
4365 if (showdown.helper.isString(options.prefixHeaderId)) {
4366 prefix = options.prefixHeaderId;
4367 } else if (options.prefixHeaderId === true) {
4368 prefix = 'section-';
4369 } else {
4370 prefix = '';
4371 }
4372
4373 if (!options.rawPrefixHeaderId) {
4374 title = prefix + title;
4375 }
4376
4377 if (options.ghCompatibleHeaderId) {
4378 title = title
4379 .replace(/ /g, '-')
4380 // replace previously escaped chars (&, ¨ and $)
4381 .replace(/&amp;/g, '')
4382 .replace(/¨T/g, '')
4383 .replace(/¨D/g, '')
4384 // replace rest of the chars (&~$ are repeated as they might have been escaped)
4385 // borrowed from github's redcarpet (some they should produce similar results)
4386 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
4387 .toLowerCase();
4388 } else if (options.rawHeaderId) {
4389 title = title
4390 .replace(/ /g, '-')
4391 // replace previously escaped chars (&, ¨ and $)
4392 .replace(/&amp;/g, '&')
4393 .replace(/¨T/g, '¨')
4394 .replace(/¨D/g, '$')
4395 // replace " and '
4396 .replace(/["']/g, '-')
4397 .toLowerCase();
4398 } else {
4399 title = title
4400 .replace(/[^\w]/g, '')
4401 .toLowerCase();
4402 }
4403
4404 if (options.rawPrefixHeaderId) {
4405 title = prefix + title;
4406 }
4407
4408 if (globals.hashLinkCounts[title]) {
4409 title = title + '-' + (globals.hashLinkCounts[title]++);
4410 } else {
4411 globals.hashLinkCounts[title] = 1;
4412 }
4413 return title;
4414 }
4415
4416 text = globals.converter._dispatch('headers.after', text, options, globals);
4417 return text;
4418 });
4419
4420 /**
4421 * Turn Markdown link shortcuts into XHTML <a> tags.
4422 */
4423 showdown.subParser('horizontalRule', function (text, options, globals) {
4424 'use strict';
4425 text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
4426
4427 var key = showdown.subParser('hashBlock')('<hr />', options, globals);
4428 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
4429 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
4430 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
4431
4432 text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
4433 return text;
4434 });
4435
4436 /**
4437 * Turn Markdown image shortcuts into <img> tags.
4438 */
4439 showdown.subParser('images', function (text, options, globals) {
4440 'use strict';
4441
4442 text = globals.converter._dispatch('images.before', text, options, globals);
4443
4444 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
4445 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
4446 base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
4447 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
4448 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
4449
4450 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
4451 url = url.replace(/\s/g, '');
4452 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
4453 }
4454
4455 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
4456
4457 var gUrls = globals.gUrls,
4458 gTitles = globals.gTitles,
4459 gDims = globals.gDimensions;
4460
4461 linkId = linkId.toLowerCase();
4462
4463 if (!title) {
4464 title = '';
4465 }
4466 // Special case for explicit empty url
4467 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
4468 url = '';
4469
4470 } else if (url === '' || url === null) {
4471 if (linkId === '' || linkId === null) {
4472 // lower-case and turn embedded newlines into spaces
4473 linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
4474 }
4475 url = '#' + linkId;
4476
4477 if (!showdown.helper.isUndefined(gUrls[linkId])) {
4478 url = gUrls[linkId];
4479 if (!showdown.helper.isUndefined(gTitles[linkId])) {
4480 title = gTitles[linkId];
4481 }
4482 if (!showdown.helper.isUndefined(gDims[linkId])) {
4483 width = gDims[linkId].width;
4484 height = gDims[linkId].height;
4485 }
4486 } else {
4487 return wholeMatch;
4488 }
4489 }
4490
4491 altText = altText
4492 .replace(/"/g, '&quot;')
4493 //altText = showdown.helper.escapeCharacters(altText, '*_', false);
4494 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4495 //url = showdown.helper.escapeCharacters(url, '*_', false);
4496 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4497 var result = '<img src="' + url + '" alt="' + altText + '"';
4498
4499 if (title && showdown.helper.isString(title)) {
4500 title = title
4501 .replace(/"/g, '&quot;')
4502 //title = showdown.helper.escapeCharacters(title, '*_', false);
4503 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4504 result += ' title="' + title + '"';
4505 }
4506
4507 if (width && height) {
4508 width = (width === '*') ? 'auto' : width;
4509 height = (height === '*') ? 'auto' : height;
4510
4511 result += ' width="' + width + '"';
4512 result += ' height="' + height + '"';
4513 }
4514
4515 result += ' />';
4516
4517 return result;
4518 }
4519
4520 // First, handle reference-style labeled images: ![alt text][id]
4521 text = text.replace(referenceRegExp, writeImageTag);
4522
4523 // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
4524
4525 // base64 encoded images
4526 text = text.replace(base64RegExp, writeImageTagBase64);
4527
4528 // cases with crazy urls like ./image/cat1).png
4529 text = text.replace(crazyRegExp, writeImageTag);
4530
4531 // normal cases
4532 text = text.replace(inlineRegExp, writeImageTag);
4533
4534 // handle reference-style shortcuts: ![img text]
4535 text = text.replace(refShortcutRegExp, writeImageTag);
4536
4537 text = globals.converter._dispatch('images.after', text, options, globals);
4538 return text;
4539 });
4540
4541 showdown.subParser('italicsAndBold', function (text, options, globals) {
4542 'use strict';
4543
4544 text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
4545
4546 // it's faster to have 3 separate regexes for each case than have just one
4547 // because of backtracing, in some cases, it could lead to an exponential effect
4548 // called "catastrophic backtrace". Ominous!
4549
4550 function parseInside (txt, left, right) {
4551 /*
4552 if (options.simplifiedAutoLink) {
4553 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4554 }
4555 */
4556 return left + txt + right;
4557 }
4558
4559 // Parse underscores
4560 if (options.literalMidWordUnderscores) {
4561 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4562 return parseInside (txt, '<strong><em>', '</em></strong>');
4563 });
4564 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4565 return parseInside (txt, '<strong>', '</strong>');
4566 });
4567 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
4568 return parseInside (txt, '<em>', '</em>');
4569 });
4570 } else {
4571 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4572 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4573 });
4574 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4575 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4576 });
4577 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
4578 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
4579 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4580 });
4581 }
4582
4583 // Now parse asterisks
4584 if (options.literalMidWordAsterisks) {
4585 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
4586 return parseInside (txt, lead + '<strong><em>', '</em></strong>');
4587 });
4588 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
4589 return parseInside (txt, lead + '<strong>', '</strong>');
4590 });
4591 text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
4592 return parseInside (txt, lead + '<em>', '</em>');
4593 });
4594 } else {
4595 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
4596 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4597 });
4598 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
4599 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4600 });
4601 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
4602 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
4603 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4604 });
4605 }
4606
4607
4608 text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
4609 return text;
4610 });
4611
4612 /**
4613 * Form HTML ordered (numbered) and unordered (bulleted) lists.
4614 */
4615 showdown.subParser('lists', function (text, options, globals) {
4616 'use strict';
4617
4618 /**
4619 * Process the contents of a single ordered or unordered list, splitting it
4620 * into individual list items.
4621 * @param {string} listStr
4622 * @param {boolean} trimTrailing
4623 * @returns {string}
4624 */
4625 function processListItems (listStr, trimTrailing) {
4626 // The $g_list_level global keeps track of when we're inside a list.
4627 // Each time we enter a list, we increment it; when we leave a list,
4628 // we decrement. If it's zero, we're not in a list anymore.
4629 //
4630 // We do this because when we're not inside a list, we want to treat
4631 // something like this:
4632 //
4633 // I recommend upgrading to version
4634 // 8. Oops, now this line is treated
4635 // as a sub-list.
4636 //
4637 // As a single paragraph, despite the fact that the second line starts
4638 // with a digit-period-space sequence.
4639 //
4640 // Whereas when we're inside a list (or sub-list), that line will be
4641 // treated as the start of a sub-list. What a kludge, huh? This is
4642 // an aspect of Markdown's syntax that's hard to parse perfectly
4643 // without resorting to mind-reading. Perhaps the solution is to
4644 // change the syntax rules such that sub-lists must start with a
4645 // starting cardinal number; e.g. "1." or "a.".
4646 globals.gListLevel++;
4647
4648 // trim trailing blank lines:
4649 listStr = listStr.replace(/\n{2,}$/, '\n');
4650
4651 // attacklab: add sentinel to emulate \z
4652 listStr += '¨0';
4653
4654 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
4655 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
4656
4657 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
4658 // which is a syntax breaking change
4659 // activating this option reverts to old behavior
4660 if (options.disableForced4SpacesIndentedSublists) {
4661 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
4662 }
4663
4664 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
4665 checked = (checked && checked.trim() !== '');
4666
4667 var item = showdown.subParser('outdent')(m4, options, globals),
4668 bulletStyle = '';
4669
4670 // Support for github tasklists
4671 if (taskbtn && options.tasklists) {
4672 bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
4673 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
4674 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
4675 if (checked) {
4676 otp += ' checked';
4677 }
4678 otp += '>';
4679 return otp;
4680 });
4681 }
4682
4683 // ISSUE #312
4684 // This input: - - - a
4685 // causes trouble to the parser, since it interprets it as:
4686 // <ul><li><li><li>a</li></li></li></ul>
4687 // instead of:
4688 // <ul><li>- - a</li></ul>
4689 // So, to prevent it, we will put a marker (¨A)in the beginning of the line
4690 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
4691 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
4692 return '¨A' + wm2;
4693 });
4694
4695 // m1 - Leading line or
4696 // Has a double return (multi paragraph) or
4697 // Has sublist
4698 if (m1 || (item.search(/\n{2,}/) > -1)) {
4699 item = showdown.subParser('githubCodeBlocks')(item, options, globals);
4700 item = showdown.subParser('blockGamut')(item, options, globals);
4701 } else {
4702 // Recursion for sub-lists:
4703 item = showdown.subParser('lists')(item, options, globals);
4704 item = item.replace(/\n$/, ''); // chomp(item)
4705 item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
4706
4707 // Colapse double linebreaks
4708 item = item.replace(/\n\n+/g, '\n\n');
4709 if (isParagraphed) {
4710 item = showdown.subParser('paragraphs')(item, options, globals);
4711 } else {
4712 item = showdown.subParser('spanGamut')(item, options, globals);
4713 }
4714 }
4715
4716 // now we need to remove the marker (¨A)
4717 item = item.replace('¨A', '');
4718 // we can finally wrap the line in list item tags
4719 item = '<li' + bulletStyle + '>' + item + '</li>\n';
4720
4721 return item;
4722 });
4723
4724 // attacklab: strip sentinel
4725 listStr = listStr.replace(/¨0/g, '');
4726
4727 globals.gListLevel--;
4728
4729 if (trimTrailing) {
4730 listStr = listStr.replace(/\s+$/, '');
4731 }
4732
4733 return listStr;
4734 }
4735
4736 function styleStartNumber (list, listType) {
4737 // check if ol and starts by a number different than 1
4738 if (listType === 'ol') {
4739 var res = list.match(/^ *(\d+)\./);
4740 if (res && res[1] !== '1') {
4741 return ' start="' + res[1] + '"';
4742 }
4743 }
4744 return '';
4745 }
4746
4747 /**
4748 * Check and parse consecutive lists (better fix for issue #142)
4749 * @param {string} list
4750 * @param {string} listType
4751 * @param {boolean} trimTrailing
4752 * @returns {string}
4753 */
4754 function parseConsecutiveLists (list, listType, trimTrailing) {
4755 // check if we caught 2 or more consecutive lists by mistake
4756 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
4757 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
4758 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
4759 counterRxg = (listType === 'ul') ? olRgx : ulRgx,
4760 result = '';
4761
4762 if (list.search(counterRxg) !== -1) {
4763 (function parseCL (txt) {
4764 var pos = txt.search(counterRxg),
4765 style = styleStartNumber(list, listType);
4766 if (pos !== -1) {
4767 // slice
4768 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
4769
4770 // invert counterType and listType
4771 listType = (listType === 'ul') ? 'ol' : 'ul';
4772 counterRxg = (listType === 'ul') ? olRgx : ulRgx;
4773
4774 //recurse
4775 parseCL(txt.slice(pos));
4776 } else {
4777 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
4778 }
4779 })(list);
4780 } else {
4781 var style = styleStartNumber(list, listType);
4782 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
4783 }
4784
4785 return result;
4786 }
4787
4788 /** Start of list parsing **/
4789 text = globals.converter._dispatch('lists.before', text, options, globals);
4790 // add sentinel to hack around khtml/safari bug:
4791 // http://bugs.webkit.org/show_bug.cgi?id=11231
4792 text += '¨0';
4793
4794 if (globals.gListLevel) {
4795 text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4796 function (wholeMatch, list, m2) {
4797 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4798 return parseConsecutiveLists(list, listType, true);
4799 }
4800 );
4801 } else {
4802 text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4803 function (wholeMatch, m1, list, m3) {
4804 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4805 return parseConsecutiveLists(list, listType, false);
4806 }
4807 );
4808 }
4809
4810 // strip sentinel
4811 text = text.replace(/¨0/, '');
4812 text = globals.converter._dispatch('lists.after', text, options, globals);
4813 return text;
4814 });
4815
4816 /**
4817 * Parse metadata at the top of the document
4818 */
4819 showdown.subParser('metadata', function (text, options, globals) {
4820 'use strict';
4821
4822 if (!options.metadata) {
4823 return text;
4824 }
4825
4826 text = globals.converter._dispatch('metadata.before', text, options, globals);
4827
4828 function parseMetadataContents (content) {
4829 // raw is raw so it's not changed in any way
4830 globals.metadata.raw = content;
4831
4832 // escape chars forbidden in html attributes
4833 // double quotes
4834 content = content
4835 // ampersand first
4836 .replace(/&/g, '&amp;')
4837 // double quotes
4838 .replace(/"/g, '&quot;');
4839
4840 content = content.replace(/\n {4}/g, ' ');
4841 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
4842 globals.metadata.parsed[key] = value;
4843 return '';
4844 });
4845 }
4846
4847 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
4848 parseMetadataContents(content);
4849 return '¨M';
4850 });
4851
4852 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
4853 if (format) {
4854 globals.metadata.format = format;
4855 }
4856 parseMetadataContents(content);
4857 return '¨M';
4858 });
4859
4860 text = text.replace(/¨M/g, '');
4861
4862 text = globals.converter._dispatch('metadata.after', text, options, globals);
4863 return text;
4864 });
4865
4866 /**
4867 * Remove one level of line-leading tabs or spaces
4868 */
4869 showdown.subParser('outdent', function (text, options, globals) {
4870 'use strict';
4871 text = globals.converter._dispatch('outdent.before', text, options, globals);
4872
4873 // attacklab: hack around Konqueror 3.5.4 bug:
4874 // "----------bug".replace(/^-/g,"") == "bug"
4875 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
4876
4877 // attacklab: clean up hack
4878 text = text.replace(/¨0/g, '');
4879
4880 text = globals.converter._dispatch('outdent.after', text, options, globals);
4881 return text;
4882 });
4883
4884 /**
4885 *
4886 */
4887 showdown.subParser('paragraphs', function (text, options, globals) {
4888 'use strict';
4889
4890 text = globals.converter._dispatch('paragraphs.before', text, options, globals);
4891 // Strip leading and trailing lines:
4892 text = text.replace(/^\n+/g, '');
4893 text = text.replace(/\n+$/g, '');
4894
4895 var grafs = text.split(/\n{2,}/g),
4896 grafsOut = [],
4897 end = grafs.length; // Wrap <p> tags
4898
4899 for (var i = 0; i < end; i++) {
4900 var str = grafs[i];
4901 // if this is an HTML marker, copy it
4902 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
4903 grafsOut.push(str);
4904
4905 // test for presence of characters to prevent empty lines being parsed
4906 // as paragraphs (resulting in undesired extra empty paragraphs)
4907 } else if (str.search(/\S/) >= 0) {
4908 str = showdown.subParser('spanGamut')(str, options, globals);
4909 str = str.replace(/^([ \t]*)/g, '<p>');
4910 str += '</p>';
4911 grafsOut.push(str);
4912 }
4913 }
4914
4915 /** Unhashify HTML blocks */
4916 end = grafsOut.length;
4917 for (i = 0; i < end; i++) {
4918 var blockText = '',
4919 grafsOutIt = grafsOut[i],
4920 codeFlag = false;
4921 // if this is a marker for an html block...
4922 // use RegExp.test instead of string.search because of QML bug
4923 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
4924 var delim = RegExp.$1,
4925 num = RegExp.$2;
4926
4927 if (delim === 'K') {
4928 blockText = globals.gHtmlBlocks[num];
4929 } else {
4930 // we need to check if ghBlock is a false positive
4931 if (codeFlag) {
4932 // use encoded version of all text
4933 blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4934 } else {
4935 blockText = globals.ghCodeBlocks[num].codeblock;
4936 }
4937 }
4938 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4939
4940 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4941 // Check if grafsOutIt is a pre->code
4942 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4943 codeFlag = true;
4944 }
4945 }
4946 grafsOut[i] = grafsOutIt;
4947 }
4948 text = grafsOut.join('\n');
4949 // Strip leading and trailing lines:
4950 text = text.replace(/^\n+/g, '');
4951 text = text.replace(/\n+$/g, '');
4952 return globals.converter._dispatch('paragraphs.after', text, options, globals);
4953 });
4954
4955 /**
4956 * Run extension
4957 */
4958 showdown.subParser('runExtension', function (ext, text, options, globals) {
4959 'use strict';
4960
4961 if (ext.filter) {
4962 text = ext.filter(text, globals.converter, options);
4963
4964 } else if (ext.regex) {
4965 // TODO remove this when old extension loading mechanism is deprecated
4966 var re = ext.regex;
4967 if (!(re instanceof RegExp)) {
4968 re = new RegExp(re, 'g');
4969 }
4970 text = text.replace(re, ext.replace);
4971 }
4972
4973 return text;
4974 });
4975
4976 /**
4977 * These are all the transformations that occur *within* block-level
4978 * tags like paragraphs, headers, and list items.
4979 */
4980 showdown.subParser('spanGamut', function (text, options, globals) {
4981 'use strict';
4982
4983 text = globals.converter._dispatch('spanGamut.before', text, options, globals);
4984 text = showdown.subParser('codeSpans')(text, options, globals);
4985 text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4986 text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
4987
4988 // Process anchor and image tags. Images must come first,
4989 // because ![foo][f] looks like an anchor.
4990 text = showdown.subParser('images')(text, options, globals);
4991 text = showdown.subParser('anchors')(text, options, globals);
4992
4993 // Make links out of things like `<http://example.com/>`
4994 // Must come after anchors, because you can use < and >
4995 // delimiters in inline links like [this](<url>).
4996 text = showdown.subParser('autoLinks')(text, options, globals);
4997 text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
4998 text = showdown.subParser('emoji')(text, options, globals);
4999 text = showdown.subParser('underline')(text, options, globals);
5000 text = showdown.subParser('italicsAndBold')(text, options, globals);
5001 text = showdown.subParser('strikethrough')(text, options, globals);
5002 text = showdown.subParser('ellipsis')(text, options, globals);
5003
5004 // we need to hash HTML tags inside spans
5005 text = showdown.subParser('hashHTMLSpans')(text, options, globals);
5006
5007 // now we encode amps and angles
5008 text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
5009
5010 // Do hard breaks
5011 if (options.simpleLineBreaks) {
5012 // GFM style hard breaks
5013 // only add line breaks if the text does not contain a block (special case for lists)
5014 if (!/\n\n¨K/.test(text)) {
5015 text = text.replace(/\n+/g, '<br />\n');
5016 }
5017 } else {
5018 // Vanilla hard breaks
5019 text = text.replace(/ +\n/g, '<br />\n');
5020 }
5021
5022 text = globals.converter._dispatch('spanGamut.after', text, options, globals);
5023 return text;
5024 });
5025
5026 showdown.subParser('strikethrough', function (text, options, globals) {
5027 'use strict';
5028
5029 function parseInside (txt) {
5030 if (options.simplifiedAutoLink) {
5031 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
5032 }
5033 return '<del>' + txt + '</del>';
5034 }
5035
5036 if (options.strikethrough) {
5037 text = globals.converter._dispatch('strikethrough.before', text, options, globals);
5038 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
5039 text = globals.converter._dispatch('strikethrough.after', text, options, globals);
5040 }
5041
5042 return text;
5043 });
5044
5045 /**
5046 * Strips link definitions from text, stores the URLs and titles in
5047 * hash references.
5048 * Link defs are in the form: ^[id]: url "optional title"
5049 */
5050 showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
5051 'use strict';
5052
5053 var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
5054 base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
5055
5056 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
5057 text += '¨0';
5058
5059 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
5060 linkId = linkId.toLowerCase();
5061 if (url.match(/^data:.+?\/.+?;base64,/)) {
5062 // remove newlines
5063 globals.gUrls[linkId] = url.replace(/\s/g, '');
5064 } else {
5065 globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
5066 }
5067
5068 if (blankLines) {
5069 // Oops, found blank lines, so it's not a title.
5070 // Put back the parenthetical statement we stole.
5071 return blankLines + title;
5072
5073 } else {
5074 if (title) {
5075 globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
5076 }
5077 if (options.parseImgDimensions && width && height) {
5078 globals.gDimensions[linkId] = {
5079 width: width,
5080 height: height
5081 };
5082 }
5083 }
5084 // Completely remove the definition from the text
5085 return '';
5086 };
5087
5088 // first we try to find base64 link references
5089 text = text.replace(base64Regex, replaceFunc);
5090
5091 text = text.replace(regex, replaceFunc);
5092
5093 // attacklab: strip sentinel
5094 text = text.replace(/¨0/, '');
5095
5096 return text;
5097 });
5098
5099 showdown.subParser('tables', function (text, options, globals) {
5100 'use strict';
5101
5102 if (!options.tables) {
5103 return text;
5104 }
5105
5106 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
5107 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
5108 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
5109
5110 function parseStyles (sLine) {
5111 if (/^:[ \t]*--*$/.test(sLine)) {
5112 return ' style="text-align:left;"';
5113 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
5114 return ' style="text-align:right;"';
5115 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
5116 return ' style="text-align:center;"';
5117 } else {
5118 return '';
5119 }
5120 }
5121
5122 function parseHeaders (header, style) {
5123 var id = '';
5124 header = header.trim();
5125 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
5126 if (options.tablesHeaderId || options.tableHeaderId) {
5127 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
5128 }
5129 header = showdown.subParser('spanGamut')(header, options, globals);
5130
5131 return '<th' + id + style + '>' + header + '</th>\n';
5132 }
5133
5134 function parseCells (cell, style) {
5135 var subText = showdown.subParser('spanGamut')(cell, options, globals);
5136 return '<td' + style + '>' + subText + '</td>\n';
5137 }
5138
5139 function buildTable (headers, cells) {
5140 var tb = '<table>\n<thead>\n<tr>\n',
5141 tblLgn = headers.length;
5142
5143 for (var i = 0; i < tblLgn; ++i) {
5144 tb += headers[i];
5145 }
5146 tb += '</tr>\n</thead>\n<tbody>\n';
5147
5148 for (i = 0; i < cells.length; ++i) {
5149 tb += '<tr>\n';
5150 for (var ii = 0; ii < tblLgn; ++ii) {
5151 tb += cells[i][ii];
5152 }
5153 tb += '</tr>\n';
5154 }
5155 tb += '</tbody>\n</table>\n';
5156 return tb;
5157 }
5158
5159 function parseTable (rawTable) {
5160 var i, tableLines = rawTable.split('\n');
5161
5162 for (i = 0; i < tableLines.length; ++i) {
5163 // strip wrong first and last column if wrapped tables are used
5164 if (/^ {0,3}\|/.test(tableLines[i])) {
5165 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
5166 }
5167 if (/\|[ \t]*$/.test(tableLines[i])) {
5168 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
5169 }
5170 // parse code spans first, but we only support one line code spans
5171 tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
5172 }
5173
5174 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
5175 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
5176 rawCells = [],
5177 headers = [],
5178 styles = [],
5179 cells = [];
5180
5181 tableLines.shift();
5182 tableLines.shift();
5183
5184 for (i = 0; i < tableLines.length; ++i) {
5185 if (tableLines[i].trim() === '') {
5186 continue;
5187 }
5188 rawCells.push(
5189 tableLines[i]
5190 .split('|')
5191 .map(function (s) {
5192 return s.trim();
5193 })
5194 );
5195 }
5196
5197 if (rawHeaders.length < rawStyles.length) {
5198 return rawTable;
5199 }
5200
5201 for (i = 0; i < rawStyles.length; ++i) {
5202 styles.push(parseStyles(rawStyles[i]));
5203 }
5204
5205 for (i = 0; i < rawHeaders.length; ++i) {
5206 if (showdown.helper.isUndefined(styles[i])) {
5207 styles[i] = '';
5208 }
5209 headers.push(parseHeaders(rawHeaders[i], styles[i]));
5210 }
5211
5212 for (i = 0; i < rawCells.length; ++i) {
5213 var row = [];
5214 for (var ii = 0; ii < headers.length; ++ii) {
5215 if (showdown.helper.isUndefined(rawCells[i][ii])) {
5216
5217 }
5218 row.push(parseCells(rawCells[i][ii], styles[ii]));
5219 }
5220 cells.push(row);
5221 }
5222
5223 return buildTable(headers, cells);
5224 }
5225
5226 text = globals.converter._dispatch('tables.before', text, options, globals);
5227
5228 // find escaped pipe characters
5229 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
5230
5231 // parse multi column tables
5232 text = text.replace(tableRgx, parseTable);
5233
5234 // parse one column tables
5235 text = text.replace(singeColTblRgx, parseTable);
5236
5237 text = globals.converter._dispatch('tables.after', text, options, globals);
5238
5239 return text;
5240 });
5241
5242 showdown.subParser('underline', function (text, options, globals) {
5243 'use strict';
5244
5245 if (!options.underline) {
5246 return text;
5247 }
5248
5249 text = globals.converter._dispatch('underline.before', text, options, globals);
5250
5251 if (options.literalMidWordUnderscores) {
5252 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
5253 return '<u>' + txt + '</u>';
5254 });
5255 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
5256 return '<u>' + txt + '</u>';
5257 });
5258 } else {
5259 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
5260 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5261 });
5262 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
5263 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5264 });
5265 }
5266
5267 // escape remaining underscores to prevent them being parsed by italic and bold
5268 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
5269
5270 text = globals.converter._dispatch('underline.after', text, options, globals);
5271
5272 return text;
5273 });
5274
5275 /**
5276 * Swap back in all the special characters we've hidden.
5277 */
5278 showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
5279 'use strict';
5280 text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
5281
5282 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
5283 var charCodeToReplace = parseInt(m1);
5284 return String.fromCharCode(charCodeToReplace);
5285 });
5286
5287 text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
5288 return text;
5289 });
5290
5291 showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
5292 'use strict';
5293
5294 var txt = '';
5295 if (node.hasChildNodes()) {
5296 var children = node.childNodes,
5297 childrenLength = children.length;
5298
5299 for (var i = 0; i < childrenLength; ++i) {
5300 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
5301
5302 if (innerTxt === '') {
5303 continue;
5304 }
5305 txt += innerTxt;
5306 }
5307 }
5308 // cleanup
5309 txt = txt.trim();
5310 txt = '> ' + txt.split('\n').join('\n> ');
5311 return txt;
5312 });
5313
5314 showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
5315 'use strict';
5316
5317 var lang = node.getAttribute('language'),
5318 num = node.getAttribute('precodenum');
5319 return '```' + lang + '\n' + globals.preList[num] + '\n```';
5320 });
5321
5322 showdown.subParser('makeMarkdown.codeSpan', function (node) {
5323 'use strict';
5324
5325 return '`' + node.innerHTML + '`';
5326 });
5327
5328 showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
5329 'use strict';
5330
5331 var txt = '';
5332 if (node.hasChildNodes()) {
5333 txt += '*';
5334 var children = node.childNodes,
5335 childrenLength = children.length;
5336 for (var i = 0; i < childrenLength; ++i) {
5337 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5338 }
5339 txt += '*';
5340 }
5341 return txt;
5342 });
5343
5344 showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
5345 'use strict';
5346
5347 var headerMark = new Array(headerLevel + 1).join('#'),
5348 txt = '';
5349
5350 if (node.hasChildNodes()) {
5351 txt = headerMark + ' ';
5352 var children = node.childNodes,
5353 childrenLength = children.length;
5354
5355 for (var i = 0; i < childrenLength; ++i) {
5356 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5357 }
5358 }
5359 return txt;
5360 });
5361
5362 showdown.subParser('makeMarkdown.hr', function () {
5363 'use strict';
5364
5365 return '---';
5366 });
5367
5368 showdown.subParser('makeMarkdown.image', function (node) {
5369 'use strict';
5370
5371 var txt = '';
5372 if (node.hasAttribute('src')) {
5373 txt += '![' + node.getAttribute('alt') + '](';
5374 txt += '<' + node.getAttribute('src') + '>';
5375 if (node.hasAttribute('width') && node.hasAttribute('height')) {
5376 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
5377 }
5378
5379 if (node.hasAttribute('title')) {
5380 txt += ' "' + node.getAttribute('title') + '"';
5381 }
5382 txt += ')';
5383 }
5384 return txt;
5385 });
5386
5387 showdown.subParser('makeMarkdown.links', function (node, globals) {
5388 'use strict';
5389
5390 var txt = '';
5391 if (node.hasChildNodes() && node.hasAttribute('href')) {
5392 var children = node.childNodes,
5393 childrenLength = children.length;
5394 txt = '[';
5395 for (var i = 0; i < childrenLength; ++i) {
5396 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5397 }
5398 txt += '](';
5399 txt += '<' + node.getAttribute('href') + '>';
5400 if (node.hasAttribute('title')) {
5401 txt += ' "' + node.getAttribute('title') + '"';
5402 }
5403 txt += ')';
5404 }
5405 return txt;
5406 });
5407
5408 showdown.subParser('makeMarkdown.list', function (node, globals, type) {
5409 'use strict';
5410
5411 var txt = '';
5412 if (!node.hasChildNodes()) {
5413 return '';
5414 }
5415 var listItems = node.childNodes,
5416 listItemsLenght = listItems.length,
5417 listNum = node.getAttribute('start') || 1;
5418
5419 for (var i = 0; i < listItemsLenght; ++i) {
5420 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
5421 continue;
5422 }
5423
5424 // define the bullet to use in list
5425 var bullet = '';
5426 if (type === 'ol') {
5427 bullet = listNum.toString() + '. ';
5428 } else {
5429 bullet = '- ';
5430 }
5431
5432 // parse list item
5433 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
5434 ++listNum;
5435 }
5436
5437 // add comment at the end to prevent consecutive lists to be parsed as one
5438 txt += '\n<!-- -->\n';
5439 return txt.trim();
5440 });
5441
5442 showdown.subParser('makeMarkdown.listItem', function (node, globals) {
5443 'use strict';
5444
5445 var listItemTxt = '';
5446
5447 var children = node.childNodes,
5448 childrenLenght = children.length;
5449
5450 for (var i = 0; i < childrenLenght; ++i) {
5451 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5452 }
5453 // if it's only one liner, we need to add a newline at the end
5454 if (!/\n$/.test(listItemTxt)) {
5455 listItemTxt += '\n';
5456 } else {
5457 // it's multiparagraph, so we need to indent
5458 listItemTxt = listItemTxt
5459 .split('\n')
5460 .join('\n ')
5461 .replace(/^ {4}$/gm, '')
5462 .replace(/\n\n+/g, '\n\n');
5463 }
5464
5465 return listItemTxt;
5466 });
5467
5468
5469
5470 showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
5471 'use strict';
5472
5473 spansOnly = spansOnly || false;
5474
5475 var txt = '';
5476
5477 // edge case of text without wrapper paragraph
5478 if (node.nodeType === 3) {
5479 return showdown.subParser('makeMarkdown.txt')(node, globals);
5480 }
5481
5482 // HTML comment
5483 if (node.nodeType === 8) {
5484 return '<!--' + node.data + '-->\n\n';
5485 }
5486
5487 // process only node elements
5488 if (node.nodeType !== 1) {
5489 return '';
5490 }
5491
5492 var tagName = node.tagName.toLowerCase();
5493
5494 switch (tagName) {
5495
5496 //
5497 // BLOCKS
5498 //
5499 case 'h1':
5500 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
5501 break;
5502 case 'h2':
5503 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
5504 break;
5505 case 'h3':
5506 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
5507 break;
5508 case 'h4':
5509 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
5510 break;
5511 case 'h5':
5512 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
5513 break;
5514 case 'h6':
5515 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
5516 break;
5517
5518 case 'p':
5519 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
5520 break;
5521
5522 case 'blockquote':
5523 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
5524 break;
5525
5526 case 'hr':
5527 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
5528 break;
5529
5530 case 'ol':
5531 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
5532 break;
5533
5534 case 'ul':
5535 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
5536 break;
5537
5538 case 'precode':
5539 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
5540 break;
5541
5542 case 'pre':
5543 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
5544 break;
5545
5546 case 'table':
5547 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
5548 break;
5549
5550 //
5551 // SPANS
5552 //
5553 case 'code':
5554 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
5555 break;
5556
5557 case 'em':
5558 case 'i':
5559 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
5560 break;
5561
5562 case 'strong':
5563 case 'b':
5564 txt = showdown.subParser('makeMarkdown.strong')(node, globals);
5565 break;
5566
5567 case 'del':
5568 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
5569 break;
5570
5571 case 'a':
5572 txt = showdown.subParser('makeMarkdown.links')(node, globals);
5573 break;
5574
5575 case 'img':
5576 txt = showdown.subParser('makeMarkdown.image')(node, globals);
5577 break;
5578
5579 default:
5580 txt = node.outerHTML + '\n\n';
5581 }
5582
5583 // common normalization
5584 // TODO eventually
5585
5586 return txt;
5587 });
5588
5589 showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
5590 'use strict';
5591
5592 var txt = '';
5593 if (node.hasChildNodes()) {
5594 var children = node.childNodes,
5595 childrenLength = children.length;
5596 for (var i = 0; i < childrenLength; ++i) {
5597 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5598 }
5599 }
5600
5601 // some text normalization
5602 txt = txt.trim();
5603
5604 return txt;
5605 });
5606
5607 showdown.subParser('makeMarkdown.pre', function (node, globals) {
5608 'use strict';
5609
5610 var num = node.getAttribute('prenum');
5611 return '<pre>' + globals.preList[num] + '</pre>';
5612 });
5613
5614 showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
5615 'use strict';
5616
5617 var txt = '';
5618 if (node.hasChildNodes()) {
5619 txt += '~~';
5620 var children = node.childNodes,
5621 childrenLength = children.length;
5622 for (var i = 0; i < childrenLength; ++i) {
5623 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5624 }
5625 txt += '~~';
5626 }
5627 return txt;
5628 });
5629
5630 showdown.subParser('makeMarkdown.strong', function (node, globals) {
5631 'use strict';
5632
5633 var txt = '';
5634 if (node.hasChildNodes()) {
5635 txt += '**';
5636 var children = node.childNodes,
5637 childrenLength = children.length;
5638 for (var i = 0; i < childrenLength; ++i) {
5639 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5640 }
5641 txt += '**';
5642 }
5643 return txt;
5644 });
5645
5646 showdown.subParser('makeMarkdown.table', function (node, globals) {
5647 'use strict';
5648
5649 var txt = '',
5650 tableArray = [[], []],
5651 headings = node.querySelectorAll('thead>tr>th'),
5652 rows = node.querySelectorAll('tbody>tr'),
5653 i, ii;
5654 for (i = 0; i < headings.length; ++i) {
5655 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
5656 allign = '---';
5657
5658 if (headings[i].hasAttribute('style')) {
5659 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
5660 switch (style) {
5661 case 'text-align:left;':
5662 allign = ':---';
5663 break;
5664 case 'text-align:right;':
5665 allign = '---:';
5666 break;
5667 case 'text-align:center;':
5668 allign = ':---:';
5669 break;
5670 }
5671 }
5672 tableArray[0][i] = headContent.trim();
5673 tableArray[1][i] = allign;
5674 }
5675
5676 for (i = 0; i < rows.length; ++i) {
5677 var r = tableArray.push([]) - 1,
5678 cols = rows[i].getElementsByTagName('td');
5679
5680 for (ii = 0; ii < headings.length; ++ii) {
5681 var cellContent = ' ';
5682 if (typeof cols[ii] !== 'undefined') {
5683 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
5684 }
5685 tableArray[r].push(cellContent);
5686 }
5687 }
5688
5689 var cellSpacesCount = 3;
5690 for (i = 0; i < tableArray.length; ++i) {
5691 for (ii = 0; ii < tableArray[i].length; ++ii) {
5692 var strLen = tableArray[i][ii].length;
5693 if (strLen > cellSpacesCount) {
5694 cellSpacesCount = strLen;
5695 }
5696 }
5697 }
5698
5699 for (i = 0; i < tableArray.length; ++i) {
5700 for (ii = 0; ii < tableArray[i].length; ++ii) {
5701 if (i === 1) {
5702 if (tableArray[i][ii].slice(-1) === ':') {
5703 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
5704 } else {
5705 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
5706 }
5707 } else {
5708 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
5709 }
5710 }
5711 txt += '| ' + tableArray[i].join(' | ') + ' |\n';
5712 }
5713
5714 return txt.trim();
5715 });
5716
5717 showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
5718 'use strict';
5719
5720 var txt = '';
5721 if (!node.hasChildNodes()) {
5722 return '';
5723 }
5724 var children = node.childNodes,
5725 childrenLength = children.length;
5726
5727 for (var i = 0; i < childrenLength; ++i) {
5728 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
5729 }
5730 return txt.trim();
5731 });
5732
5733 showdown.subParser('makeMarkdown.txt', function (node) {
5734 'use strict';
5735
5736 var txt = node.nodeValue;
5737
5738 // multiple spaces are collapsed
5739 txt = txt.replace(/ +/g, ' ');
5740
5741 // replace the custom ¨NBSP; with a space
5742 txt = txt.replace(/¨NBSP;/g, ' ');
5743
5744 // ", <, > and & should replace escaped html entities
5745 txt = showdown.helper.unescapeHTMLEntities(txt);
5746
5747 // escape markdown magic characters
5748 // emphasis, strong and strikethrough - can appear everywhere
5749 // we also escape pipe (|) because of tables
5750 // and escape ` because of code blocks and spans
5751 txt = txt.replace(/([*_~|`])/g, '\\$1');
5752
5753 // escape > because of blockquotes
5754 txt = txt.replace(/^(\s*)>/g, '\\$1>');
5755
5756 // hash character, only troublesome at the beginning of a line because of headers
5757 txt = txt.replace(/^#/gm, '\\#');
5758
5759 // horizontal rules
5760 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
5761
5762 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
5763 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
5764
5765 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
5766 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
5767
5768 // images and links, ] followed by ( is problematic, so we escape it
5769 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
5770
5771 // reference URIs must also be escaped
5772 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
5773
5774 return txt;
5775 });
5776
5777 var root = this;
5778
5779 // AMD Loader
5780 if (true) {
5781 !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {
5782 'use strict';
5783 return showdown;
5784 }).call(exports, __webpack_require__, exports, module),
5785 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5786
5787 // CommonJS/nodeJS Loader
5788 } else {}
5789 }).call(this);
5790
5791
5792
5793
5794 /***/ })
5795
5796 /******/ });
5797 /************************************************************************/
5798 /******/ // The module cache
5799 /******/ var __webpack_module_cache__ = {};
5800 /******/
5801 /******/ // The require function
5802 /******/ function __webpack_require__(moduleId) {
5803 /******/ // Check if module is in cache
5804 /******/ var cachedModule = __webpack_module_cache__[moduleId];
5805 /******/ if (cachedModule !== undefined) {
5806 /******/ return cachedModule.exports;
5807 /******/ }
5808 /******/ // Create a new module (and put it into the cache)
5809 /******/ var module = __webpack_module_cache__[moduleId] = {
5810 /******/ // no module.id needed
5811 /******/ // no module.loaded needed
5812 /******/ exports: {}
5813 /******/ };
5814 /******/
5815 /******/ // Execute the module function
5816 /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5817 /******/
5818 /******/ // Return the exports of the module
5819 /******/ return module.exports;
5820 /******/ }
5821 /******/
5822 /************************************************************************/
5823 /******/ /* webpack/runtime/compat get default export */
5824 /******/ (() => {
5825 /******/ // getDefaultExport function for compatibility with non-harmony modules
5826 /******/ __webpack_require__.n = (module) => {
5827 /******/ var getter = module && module.__esModule ?
5828 /******/ () => (module['default']) :
5829 /******/ () => (module);
5830 /******/ __webpack_require__.d(getter, { a: getter });
5831 /******/ return getter;
5832 /******/ };
5833 /******/ })();
5834 /******/
5835 /******/ /* webpack/runtime/define property getters */
5836 /******/ (() => {
5837 /******/ // define getter functions for harmony exports
5838 /******/ __webpack_require__.d = (exports, definition) => {
5839 /******/ for(var key in definition) {
5840 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
5841 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
5842 /******/ }
5843 /******/ }
5844 /******/ };
5845 /******/ })();
5846 /******/
5847 /******/ /* webpack/runtime/hasOwnProperty shorthand */
5848 /******/ (() => {
5849 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
5850 /******/ })();
5851 /******/
5852 /******/ /* webpack/runtime/make namespace object */
5853 /******/ (() => {
5854 /******/ // define __esModule on exports
5855 /******/ __webpack_require__.r = (exports) => {
5856 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
5857 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5858 /******/ }
5859 /******/ Object.defineProperty(exports, '__esModule', { value: true });
5860 /******/ };
5861 /******/ })();
5862 /******/
5863 /************************************************************************/
5864 var __webpack_exports__ = {};
5865 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
5866 (() => {
5867 "use strict";
5868 // ESM COMPAT FLAG
5869 __webpack_require__.r(__webpack_exports__);
5870
5871 // EXPORTS
5872 __webpack_require__.d(__webpack_exports__, {
5873 "__EXPERIMENTAL_ELEMENTS": () => (/* reexport */ __EXPERIMENTAL_ELEMENTS),
5874 "__EXPERIMENTAL_PATHS_WITH_MERGE": () => (/* reexport */ __EXPERIMENTAL_PATHS_WITH_MERGE),
5875 "__EXPERIMENTAL_STYLE_PROPERTY": () => (/* reexport */ __EXPERIMENTAL_STYLE_PROPERTY),
5876 "__experimentalCloneSanitizedBlock": () => (/* reexport */ __experimentalCloneSanitizedBlock),
5877 "__experimentalGetAccessibleBlockLabel": () => (/* reexport */ getAccessibleBlockLabel),
5878 "__experimentalGetBlockAttributesNamesByRole": () => (/* reexport */ __experimentalGetBlockAttributesNamesByRole),
5879 "__experimentalGetBlockLabel": () => (/* reexport */ getBlockLabel),
5880 "__experimentalSanitizeBlockAttributes": () => (/* reexport */ __experimentalSanitizeBlockAttributes),
5881 "__unstableGetBlockProps": () => (/* reexport */ getBlockProps),
5882 "__unstableGetInnerBlocksProps": () => (/* reexport */ getInnerBlocksProps),
5883 "__unstableSerializeAndClean": () => (/* reexport */ __unstableSerializeAndClean),
5884 "children": () => (/* reexport */ children),
5885 "cloneBlock": () => (/* reexport */ cloneBlock),
5886 "createBlock": () => (/* reexport */ createBlock),
5887 "createBlocksFromInnerBlocksTemplate": () => (/* reexport */ createBlocksFromInnerBlocksTemplate),
5888 "doBlocksMatchTemplate": () => (/* reexport */ doBlocksMatchTemplate),
5889 "findTransform": () => (/* reexport */ findTransform),
5890 "getBlockAttributes": () => (/* reexport */ getBlockAttributes),
5891 "getBlockContent": () => (/* reexport */ getBlockInnerHTML),
5892 "getBlockDefaultClassName": () => (/* reexport */ getBlockDefaultClassName),
5893 "getBlockFromExample": () => (/* reexport */ getBlockFromExample),
5894 "getBlockMenuDefaultClassName": () => (/* reexport */ getBlockMenuDefaultClassName),
5895 "getBlockSupport": () => (/* reexport */ getBlockSupport),
5896 "getBlockTransforms": () => (/* reexport */ getBlockTransforms),
5897 "getBlockType": () => (/* reexport */ getBlockType),
5898 "getBlockTypes": () => (/* reexport */ getBlockTypes),
5899 "getBlockVariations": () => (/* reexport */ getBlockVariations),
5900 "getCategories": () => (/* reexport */ categories_getCategories),
5901 "getChildBlockNames": () => (/* reexport */ getChildBlockNames),
5902 "getDefaultBlockName": () => (/* reexport */ getDefaultBlockName),
5903 "getFreeformContentHandlerName": () => (/* reexport */ getFreeformContentHandlerName),
5904 "getGroupingBlockName": () => (/* reexport */ getGroupingBlockName),
5905 "getPhrasingContentSchema": () => (/* reexport */ deprecatedGetPhrasingContentSchema),
5906 "getPossibleBlockTransformations": () => (/* reexport */ getPossibleBlockTransformations),
5907 "getSaveContent": () => (/* reexport */ getSaveContent),
5908 "getSaveElement": () => (/* reexport */ getSaveElement),
5909 "getUnregisteredTypeHandlerName": () => (/* reexport */ getUnregisteredTypeHandlerName),
5910 "hasBlockSupport": () => (/* reexport */ hasBlockSupport),
5911 "hasChildBlocks": () => (/* reexport */ hasChildBlocks),
5912 "hasChildBlocksWithInserterSupport": () => (/* reexport */ hasChildBlocksWithInserterSupport),
5913 "isReusableBlock": () => (/* reexport */ isReusableBlock),
5914 "isTemplatePart": () => (/* reexport */ isTemplatePart),
5915 "isUnmodifiedBlock": () => (/* reexport */ isUnmodifiedBlock),
5916 "isUnmodifiedDefaultBlock": () => (/* reexport */ isUnmodifiedDefaultBlock),
5917 "isValidBlockContent": () => (/* reexport */ isValidBlockContent),
5918 "isValidIcon": () => (/* reexport */ isValidIcon),
5919 "node": () => (/* reexport */ node),
5920 "normalizeIconObject": () => (/* reexport */ normalizeIconObject),
5921 "parse": () => (/* reexport */ parser_parse),
5922 "parseWithAttributeSchema": () => (/* reexport */ parseWithAttributeSchema),
5923 "pasteHandler": () => (/* reexport */ pasteHandler),
5924 "rawHandler": () => (/* reexport */ rawHandler),
5925 "registerBlockCollection": () => (/* reexport */ registerBlockCollection),
5926 "registerBlockStyle": () => (/* reexport */ registerBlockStyle),
5927 "registerBlockType": () => (/* reexport */ registerBlockType),
5928 "registerBlockVariation": () => (/* reexport */ registerBlockVariation),
5929 "serialize": () => (/* reexport */ serialize),
5930 "serializeRawBlock": () => (/* reexport */ serializeRawBlock),
5931 "setCategories": () => (/* reexport */ categories_setCategories),
5932 "setDefaultBlockName": () => (/* reexport */ setDefaultBlockName),
5933 "setFreeformContentHandlerName": () => (/* reexport */ setFreeformContentHandlerName),
5934 "setGroupingBlockName": () => (/* reexport */ setGroupingBlockName),
5935 "setUnregisteredTypeHandlerName": () => (/* reexport */ setUnregisteredTypeHandlerName),
5936 "store": () => (/* reexport */ store),
5937 "switchToBlockType": () => (/* reexport */ switchToBlockType),
5938 "synchronizeBlocksWithTemplate": () => (/* reexport */ synchronizeBlocksWithTemplate),
5939 "unregisterBlockStyle": () => (/* reexport */ unregisterBlockStyle),
5940 "unregisterBlockType": () => (/* reexport */ unregisterBlockType),
5941 "unregisterBlockVariation": () => (/* reexport */ unregisterBlockVariation),
5942 "unstable__bootstrapServerSideBlockDefinitions": () => (/* reexport */ unstable__bootstrapServerSideBlockDefinitions),
5943 "updateCategory": () => (/* reexport */ categories_updateCategory),
5944 "validateBlock": () => (/* reexport */ validateBlock),
5945 "withBlockContentContext": () => (/* reexport */ withBlockContentContext)
5946 });
5947
5948 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/selectors.js
5949 var selectors_namespaceObject = {};
5950 __webpack_require__.r(selectors_namespaceObject);
5951 __webpack_require__.d(selectors_namespaceObject, {
5952 "__experimentalGetUnprocessedBlockTypes": () => (__experimentalGetUnprocessedBlockTypes),
5953 "__experimentalHasContentRoleAttribute": () => (__experimentalHasContentRoleAttribute),
5954 "getActiveBlockVariation": () => (getActiveBlockVariation),
5955 "getBlockStyles": () => (getBlockStyles),
5956 "getBlockSupport": () => (selectors_getBlockSupport),
5957 "getBlockType": () => (selectors_getBlockType),
5958 "getBlockTypes": () => (selectors_getBlockTypes),
5959 "getBlockVariations": () => (selectors_getBlockVariations),
5960 "getCategories": () => (getCategories),
5961 "getChildBlockNames": () => (selectors_getChildBlockNames),
5962 "getCollections": () => (getCollections),
5963 "getDefaultBlockName": () => (selectors_getDefaultBlockName),
5964 "getDefaultBlockVariation": () => (getDefaultBlockVariation),
5965 "getFreeformFallbackBlockName": () => (getFreeformFallbackBlockName),
5966 "getGroupingBlockName": () => (selectors_getGroupingBlockName),
5967 "getUnregisteredFallbackBlockName": () => (getUnregisteredFallbackBlockName),
5968 "hasBlockSupport": () => (selectors_hasBlockSupport),
5969 "hasChildBlocks": () => (selectors_hasChildBlocks),
5970 "hasChildBlocksWithInserterSupport": () => (selectors_hasChildBlocksWithInserterSupport),
5971 "isMatchingSearchTerm": () => (isMatchingSearchTerm)
5972 });
5973
5974 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/private-selectors.js
5975 var private_selectors_namespaceObject = {};
5976 __webpack_require__.r(private_selectors_namespaceObject);
5977 __webpack_require__.d(private_selectors_namespaceObject, {
5978 "getSupportedStyles": () => (getSupportedStyles)
5979 });
5980
5981 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/actions.js
5982 var actions_namespaceObject = {};
5983 __webpack_require__.r(actions_namespaceObject);
5984 __webpack_require__.d(actions_namespaceObject, {
5985 "__experimentalReapplyBlockTypeFilters": () => (__experimentalReapplyBlockTypeFilters),
5986 "__experimentalRegisterBlockType": () => (__experimentalRegisterBlockType),
5987 "addBlockCollection": () => (addBlockCollection),
5988 "addBlockStyles": () => (addBlockStyles),
5989 "addBlockTypes": () => (addBlockTypes),
5990 "addBlockVariations": () => (addBlockVariations),
5991 "removeBlockCollection": () => (removeBlockCollection),
5992 "removeBlockStyles": () => (removeBlockStyles),
5993 "removeBlockTypes": () => (removeBlockTypes),
5994 "removeBlockVariations": () => (removeBlockVariations),
5995 "setCategories": () => (setCategories),
5996 "setDefaultBlockName": () => (actions_setDefaultBlockName),
5997 "setFreeformFallbackBlockName": () => (setFreeformFallbackBlockName),
5998 "setGroupingBlockName": () => (actions_setGroupingBlockName),
5999 "setUnregisteredFallbackBlockName": () => (setUnregisteredFallbackBlockName),
6000 "updateCategory": () => (updateCategory)
6001 });
6002
6003 ;// CONCATENATED MODULE: external ["wp","data"]
6004 const external_wp_data_namespaceObject = window["wp"]["data"];
6005 ;// CONCATENATED MODULE: external ["wp","i18n"]
6006 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
6007 ;// CONCATENATED MODULE: ./node_modules/colord/index.mjs
6008 var r={grad:.9,turn:360,rad:360/(2*Math.PI)},t=function(r){return"string"==typeof r?r.length>0:"number"==typeof r},n=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=Math.pow(10,t)),Math.round(n*r)/n+0},e=function(r,t,n){return void 0===t&&(t=0),void 0===n&&(n=1),r>n?n:r>t?r:t},u=function(r){return(r=isFinite(r)?r%360:0)>0?r:r+360},a=function(r){return{r:e(r.r,0,255),g:e(r.g,0,255),b:e(r.b,0,255),a:e(r.a)}},o=function(r){return{r:n(r.r),g:n(r.g),b:n(r.b),a:n(r.a,3)}},i=/^#([0-9a-f]{3,8})$/i,s=function(r){var t=r.toString(16);return t.length<2?"0"+t:t},h=function(r){var t=r.r,n=r.g,e=r.b,u=r.a,a=Math.max(t,n,e),o=a-Math.min(t,n,e),i=o?a===t?(n-e)/o:a===n?2+(e-t)/o:4+(t-n)/o:0;return{h:60*(i<0?i+6:i),s:a?o/a*100:0,v:a/255*100,a:u}},b=function(r){var t=r.h,n=r.s,e=r.v,u=r.a;t=t/360*6,n/=100,e/=100;var a=Math.floor(t),o=e*(1-n),i=e*(1-(t-a)*n),s=e*(1-(1-t+a)*n),h=a%6;return{r:255*[e,i,o,o,s,e][h],g:255*[s,e,e,i,o,o][h],b:255*[o,o,s,e,e,i][h],a:u}},g=function(r){return{h:u(r.h),s:e(r.s,0,100),l:e(r.l,0,100),a:e(r.a)}},d=function(r){return{h:n(r.h),s:n(r.s),l:n(r.l),a:n(r.a,3)}},f=function(r){return b((n=(t=r).s,{h:t.h,s:(n*=((e=t.l)<50?e:100-e)/100)>0?2*n/(e+n)*100:0,v:e+n,a:t.a}));var t,n,e},c=function(r){return{h:(t=h(r)).h,s:(u=(200-(n=t.s))*(e=t.v)/100)>0&&u<200?n*e/100/(u<=100?u:200-u)*100:0,l:u/2,a:t.a};var t,n,e,u},l=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,p=/^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,v=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,m=/^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i,y={string:[[function(r){var t=i.exec(r);return t?(r=t[1]).length<=4?{r:parseInt(r[0]+r[0],16),g:parseInt(r[1]+r[1],16),b:parseInt(r[2]+r[2],16),a:4===r.length?n(parseInt(r[3]+r[3],16)/255,2):1}:6===r.length||8===r.length?{r:parseInt(r.substr(0,2),16),g:parseInt(r.substr(2,2),16),b:parseInt(r.substr(4,2),16),a:8===r.length?n(parseInt(r.substr(6,2),16)/255,2):1}:null:null},"hex"],[function(r){var t=v.exec(r)||m.exec(r);return t?t[2]!==t[4]||t[4]!==t[6]?null:a({r:Number(t[1])/(t[2]?100/255:1),g:Number(t[3])/(t[4]?100/255:1),b:Number(t[5])/(t[6]?100/255:1),a:void 0===t[7]?1:Number(t[7])/(t[8]?100:1)}):null},"rgb"],[function(t){var n=l.exec(t)||p.exec(t);if(!n)return null;var e,u,a=g({h:(e=n[1],u=n[2],void 0===u&&(u="deg"),Number(e)*(r[u]||1)),s:Number(n[3]),l:Number(n[4]),a:void 0===n[5]?1:Number(n[5])/(n[6]?100:1)});return f(a)},"hsl"]],object:[[function(r){var n=r.r,e=r.g,u=r.b,o=r.a,i=void 0===o?1:o;return t(n)&&t(e)&&t(u)?a({r:Number(n),g:Number(e),b:Number(u),a:Number(i)}):null},"rgb"],[function(r){var n=r.h,e=r.s,u=r.l,a=r.a,o=void 0===a?1:a;if(!t(n)||!t(e)||!t(u))return null;var i=g({h:Number(n),s:Number(e),l:Number(u),a:Number(o)});return f(i)},"hsl"],[function(r){var n=r.h,a=r.s,o=r.v,i=r.a,s=void 0===i?1:i;if(!t(n)||!t(a)||!t(o))return null;var h=function(r){return{h:u(r.h),s:e(r.s,0,100),v:e(r.v,0,100),a:e(r.a)}}({h:Number(n),s:Number(a),v:Number(o),a:Number(s)});return b(h)},"hsv"]]},N=function(r,t){for(var n=0;n<t.length;n++){var e=t[n][0](r);if(e)return[e,t[n][1]]}return[null,void 0]},x=function(r){return"string"==typeof r?N(r.trim(),y.string):"object"==typeof r&&null!==r?N(r,y.object):[null,void 0]},I=function(r){return x(r)[1]},M=function(r,t){var n=c(r);return{h:n.h,s:e(n.s+100*t,0,100),l:n.l,a:n.a}},H=function(r){return(299*r.r+587*r.g+114*r.b)/1e3/255},$=function(r,t){var n=c(r);return{h:n.h,s:n.s,l:e(n.l+100*t,0,100),a:n.a}},j=function(){function r(r){this.parsed=x(r)[0],this.rgba=this.parsed||{r:0,g:0,b:0,a:1}}return r.prototype.isValid=function(){return null!==this.parsed},r.prototype.brightness=function(){return n(H(this.rgba),2)},r.prototype.isDark=function(){return H(this.rgba)<.5},r.prototype.isLight=function(){return H(this.rgba)>=.5},r.prototype.toHex=function(){return r=o(this.rgba),t=r.r,e=r.g,u=r.b,i=(a=r.a)<1?s(n(255*a)):"","#"+s(t)+s(e)+s(u)+i;var r,t,e,u,a,i},r.prototype.toRgb=function(){return o(this.rgba)},r.prototype.toRgbString=function(){return r=o(this.rgba),t=r.r,n=r.g,e=r.b,(u=r.a)<1?"rgba("+t+", "+n+", "+e+", "+u+")":"rgb("+t+", "+n+", "+e+")";var r,t,n,e,u},r.prototype.toHsl=function(){return d(c(this.rgba))},r.prototype.toHslString=function(){return r=d(c(this.rgba)),t=r.h,n=r.s,e=r.l,(u=r.a)<1?"hsla("+t+", "+n+"%, "+e+"%, "+u+")":"hsl("+t+", "+n+"%, "+e+"%)";var r,t,n,e,u},r.prototype.toHsv=function(){return r=h(this.rgba),{h:n(r.h),s:n(r.s),v:n(r.v),a:n(r.a,3)};var r},r.prototype.invert=function(){return w({r:255-(r=this.rgba).r,g:255-r.g,b:255-r.b,a:r.a});var r},r.prototype.saturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,r))},r.prototype.desaturate=function(r){return void 0===r&&(r=.1),w(M(this.rgba,-r))},r.prototype.grayscale=function(){return w(M(this.rgba,-1))},r.prototype.lighten=function(r){return void 0===r&&(r=.1),w($(this.rgba,r))},r.prototype.darken=function(r){return void 0===r&&(r=.1),w($(this.rgba,-r))},r.prototype.rotate=function(r){return void 0===r&&(r=15),this.hue(this.hue()+r)},r.prototype.alpha=function(r){return"number"==typeof r?w({r:(t=this.rgba).r,g:t.g,b:t.b,a:r}):n(this.rgba.a,3);var t},r.prototype.hue=function(r){var t=c(this.rgba);return"number"==typeof r?w({h:r,s:t.s,l:t.l,a:t.a}):n(t.h)},r.prototype.isEqual=function(r){return this.toHex()===w(r).toHex()},r}(),w=function(r){return r instanceof j?r:new j(r)},S=[],k=function(r){r.forEach(function(r){S.indexOf(r)<0&&(r(j,y),S.push(r))})},E=function(){return new j({r:255*Math.random(),g:255*Math.random(),b:255*Math.random()})};
6009
6010 ;// CONCATENATED MODULE: ./node_modules/colord/plugins/names.mjs
6011 /* harmony default export */ function names(e,f){var a={white:"#ffffff",bisque:"#ffe4c4",blue:"#0000ff",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",antiquewhite:"#faebd7",aqua:"#00ffff",azure:"#f0ffff",whitesmoke:"#f5f5f5",papayawhip:"#ffefd5",plum:"#dda0dd",blanchedalmond:"#ffebcd",black:"#000000",gold:"#ffd700",goldenrod:"#daa520",gainsboro:"#dcdcdc",cornsilk:"#fff8dc",cornflowerblue:"#6495ed",burlywood:"#deb887",aquamarine:"#7fffd4",beige:"#f5f5dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkkhaki:"#bdb76b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",peachpuff:"#ffdab9",darkmagenta:"#8b008b",darkred:"#8b0000",darkorchid:"#9932cc",darkorange:"#ff8c00",darkslateblue:"#483d8b",gray:"#808080",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",deeppink:"#ff1493",deepskyblue:"#00bfff",wheat:"#f5deb3",firebrick:"#b22222",floralwhite:"#fffaf0",ghostwhite:"#f8f8ff",darkviolet:"#9400d3",magenta:"#ff00ff",green:"#008000",dodgerblue:"#1e90ff",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",blueviolet:"#8a2be2",forestgreen:"#228b22",lawngreen:"#7cfc00",indianred:"#cd5c5c",indigo:"#4b0082",fuchsia:"#ff00ff",brown:"#a52a2a",maroon:"#800000",mediumblue:"#0000cd",lightcoral:"#f08080",darkturquoise:"#00ced1",lightcyan:"#e0ffff",ivory:"#fffff0",lightyellow:"#ffffe0",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",linen:"#faf0e6",mediumaquamarine:"#66cdaa",lemonchiffon:"#fffacd",lime:"#00ff00",khaki:"#f0e68c",mediumseagreen:"#3cb371",limegreen:"#32cd32",mediumspringgreen:"#00fa9a",lightskyblue:"#87cefa",lightblue:"#add8e6",midnightblue:"#191970",lightpink:"#ffb6c1",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",mintcream:"#f5fffa",lightslategray:"#778899",lightslategrey:"#778899",navajowhite:"#ffdead",navy:"#000080",mediumvioletred:"#c71585",powderblue:"#b0e0e6",palegoldenrod:"#eee8aa",oldlace:"#fdf5e6",paleturquoise:"#afeeee",mediumturquoise:"#48d1cc",mediumorchid:"#ba55d3",rebeccapurple:"#663399",lightsteelblue:"#b0c4de",mediumslateblue:"#7b68ee",thistle:"#d8bfd8",tan:"#d2b48c",orchid:"#da70d6",mediumpurple:"#9370db",purple:"#800080",pink:"#ffc0cb",skyblue:"#87ceeb",springgreen:"#00ff7f",palegreen:"#98fb98",red:"#ff0000",yellow:"#ffff00",slateblue:"#6a5acd",lavenderblush:"#fff0f5",peru:"#cd853f",palevioletred:"#db7093",violet:"#ee82ee",teal:"#008080",slategray:"#708090",slategrey:"#708090",aliceblue:"#f0f8ff",darkseagreen:"#8fbc8f",darkolivegreen:"#556b2f",greenyellow:"#adff2f",seagreen:"#2e8b57",seashell:"#fff5ee",tomato:"#ff6347",silver:"#c0c0c0",sienna:"#a0522d",lavender:"#e6e6fa",lightgreen:"#90ee90",orange:"#ffa500",orangered:"#ff4500",steelblue:"#4682b4",royalblue:"#4169e1",turquoise:"#40e0d0",yellowgreen:"#9acd32",salmon:"#fa8072",saddlebrown:"#8b4513",sandybrown:"#f4a460",rosybrown:"#bc8f8f",darksalmon:"#e9967a",lightgoldenrodyellow:"#fafad2",snow:"#fffafa",lightgrey:"#d3d3d3",lightgray:"#d3d3d3",dimgray:"#696969",dimgrey:"#696969",olivedrab:"#6b8e23",olive:"#808000"},r={};for(var d in a)r[a[d]]=d;var l={};e.prototype.toName=function(f){if(!(this.rgba.a||this.rgba.r||this.rgba.g||this.rgba.b))return"transparent";var d,i,n=r[this.toHex()];if(n)return n;if(null==f?void 0:f.closest){var o=this.toRgb(),t=1/0,b="black";if(!l.length)for(var c in a)l[c]=new e(a[c]).toRgb();for(var g in a){var u=(d=o,i=l[g],Math.pow(d.r-i.r,2)+Math.pow(d.g-i.g,2)+Math.pow(d.b-i.b,2));u<t&&(t=u,b=g)}return b}};f.string.push([function(f){var r=f.toLowerCase(),d="transparent"===r?"#0000":a[r];return d?new e(d).toRgb():null},"name"])}
6012
6013 ;// CONCATENATED MODULE: ./node_modules/colord/plugins/a11y.mjs
6014 var a11y_o=function(o){var t=o/255;return t<.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)},a11y_t=function(t){return.2126*a11y_o(t.r)+.7152*a11y_o(t.g)+.0722*a11y_o(t.b)};/* harmony default export */ function a11y(o){o.prototype.luminance=function(){return o=a11y_t(this.rgba),void 0===(r=2)&&(r=0),void 0===n&&(n=Math.pow(10,r)),Math.round(n*o)/n+0;var o,r,n},o.prototype.contrast=function(r){void 0===r&&(r="#FFF");var n,a,i,e,v,u,d,c=r instanceof o?r:new o(r);return e=this.rgba,v=c.toRgb(),u=a11y_t(e),d=a11y_t(v),n=u>d?(u+.05)/(d+.05):(d+.05)/(u+.05),void 0===(a=2)&&(a=0),void 0===i&&(i=Math.pow(10,a)),Math.floor(i*n)/i+0},o.prototype.isReadable=function(o,t){return void 0===o&&(o="#FFF"),void 0===t&&(t={}),this.contrast(o)>=(e=void 0===(i=(r=t).size)?"normal":i,"AAA"===(a=void 0===(n=r.level)?"AA":n)&&"normal"===e?7:"AA"===a&&"large"===e?3:4.5);var r,n,a,i,e}}
6015
6016 ;// CONCATENATED MODULE: external ["wp","element"]
6017 const external_wp_element_namespaceObject = window["wp"]["element"];
6018 ;// CONCATENATED MODULE: external ["wp","dom"]
6019 const external_wp_dom_namespaceObject = window["wp"]["dom"];
6020 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/constants.js
6021 const BLOCK_ICON_DEFAULT = 'block-default';
6022 /**
6023 * Array of valid keys in a block type settings deprecation object.
6024 *
6025 * @type {string[]}
6026 */
6027
6028 const DEPRECATED_ENTRY_KEYS = ['attributes', 'supports', 'save', 'migrate', 'isEligible', 'apiVersion'];
6029 const __EXPERIMENTAL_STYLE_PROPERTY = {
6030 // Kept for back-compatibility purposes.
6031 '--wp--style--color--link': {
6032 value: ['color', 'link'],
6033 support: ['color', 'link']
6034 },
6035 background: {
6036 value: ['color', 'gradient'],
6037 support: ['color', 'gradients'],
6038 useEngine: true
6039 },
6040 backgroundColor: {
6041 value: ['color', 'background'],
6042 support: ['color', 'background'],
6043 requiresOptOut: true,
6044 useEngine: true
6045 },
6046 borderColor: {
6047 value: ['border', 'color'],
6048 support: ['__experimentalBorder', 'color'],
6049 useEngine: true
6050 },
6051 borderRadius: {
6052 value: ['border', 'radius'],
6053 support: ['__experimentalBorder', 'radius'],
6054 properties: {
6055 borderTopLeftRadius: 'topLeft',
6056 borderTopRightRadius: 'topRight',
6057 borderBottomLeftRadius: 'bottomLeft',
6058 borderBottomRightRadius: 'bottomRight'
6059 },
6060 useEngine: true
6061 },
6062 borderStyle: {
6063 value: ['border', 'style'],
6064 support: ['__experimentalBorder', 'style'],
6065 useEngine: true
6066 },
6067 borderWidth: {
6068 value: ['border', 'width'],
6069 support: ['__experimentalBorder', 'width'],
6070 useEngine: true
6071 },
6072 borderTopColor: {
6073 value: ['border', 'top', 'color'],
6074 support: ['__experimentalBorder', 'color'],
6075 useEngine: true
6076 },
6077 borderTopStyle: {
6078 value: ['border', 'top', 'style'],
6079 support: ['__experimentalBorder', 'style'],
6080 useEngine: true
6081 },
6082 borderTopWidth: {
6083 value: ['border', 'top', 'width'],
6084 support: ['__experimentalBorder', 'width'],
6085 useEngine: true
6086 },
6087 borderRightColor: {
6088 value: ['border', 'right', 'color'],
6089 support: ['__experimentalBorder', 'color'],
6090 useEngine: true
6091 },
6092 borderRightStyle: {
6093 value: ['border', 'right', 'style'],
6094 support: ['__experimentalBorder', 'style'],
6095 useEngine: true
6096 },
6097 borderRightWidth: {
6098 value: ['border', 'right', 'width'],
6099 support: ['__experimentalBorder', 'width'],
6100 useEngine: true
6101 },
6102 borderBottomColor: {
6103 value: ['border', 'bottom', 'color'],
6104 support: ['__experimentalBorder', 'color'],
6105 useEngine: true
6106 },
6107 borderBottomStyle: {
6108 value: ['border', 'bottom', 'style'],
6109 support: ['__experimentalBorder', 'style'],
6110 useEngine: true
6111 },
6112 borderBottomWidth: {
6113 value: ['border', 'bottom', 'width'],
6114 support: ['__experimentalBorder', 'width'],
6115 useEngine: true
6116 },
6117 borderLeftColor: {
6118 value: ['border', 'left', 'color'],
6119 support: ['__experimentalBorder', 'color'],
6120 useEngine: true
6121 },
6122 borderLeftStyle: {
6123 value: ['border', 'left', 'style'],
6124 support: ['__experimentalBorder', 'style'],
6125 useEngine: true
6126 },
6127 borderLeftWidth: {
6128 value: ['border', 'left', 'width'],
6129 support: ['__experimentalBorder', 'width'],
6130 useEngine: true
6131 },
6132 color: {
6133 value: ['color', 'text'],
6134 support: ['color', 'text'],
6135 requiresOptOut: true,
6136 useEngine: true
6137 },
6138 columnCount: {
6139 value: ['typography', 'textColumns'],
6140 support: ['typography', 'textColumns'],
6141 useEngine: true
6142 },
6143 filter: {
6144 value: ['filter', 'duotone'],
6145 support: ['filter', 'duotone']
6146 },
6147 linkColor: {
6148 value: ['elements', 'link', 'color', 'text'],
6149 support: ['color', 'link']
6150 },
6151 captionColor: {
6152 value: ['elements', 'caption', 'color', 'text'],
6153 support: ['color', 'caption']
6154 },
6155 buttonColor: {
6156 value: ['elements', 'button', 'color', 'text'],
6157 support: ['color', 'button']
6158 },
6159 buttonBackgroundColor: {
6160 value: ['elements', 'button', 'color', 'background'],
6161 support: ['color', 'button']
6162 },
6163 headingColor: {
6164 value: ['elements', 'heading', 'color', 'text'],
6165 support: ['color', 'heading']
6166 },
6167 headingBackgroundColor: {
6168 value: ['elements', 'heading', 'color', 'background'],
6169 support: ['color', 'heading']
6170 },
6171 fontFamily: {
6172 value: ['typography', 'fontFamily'],
6173 support: ['typography', '__experimentalFontFamily'],
6174 useEngine: true
6175 },
6176 fontSize: {
6177 value: ['typography', 'fontSize'],
6178 support: ['typography', 'fontSize'],
6179 useEngine: true
6180 },
6181 fontStyle: {
6182 value: ['typography', 'fontStyle'],
6183 support: ['typography', '__experimentalFontStyle'],
6184 useEngine: true
6185 },
6186 fontWeight: {
6187 value: ['typography', 'fontWeight'],
6188 support: ['typography', '__experimentalFontWeight'],
6189 useEngine: true
6190 },
6191 lineHeight: {
6192 value: ['typography', 'lineHeight'],
6193 support: ['typography', 'lineHeight'],
6194 useEngine: true
6195 },
6196 margin: {
6197 value: ['spacing', 'margin'],
6198 support: ['spacing', 'margin'],
6199 properties: {
6200 marginTop: 'top',
6201 marginRight: 'right',
6202 marginBottom: 'bottom',
6203 marginLeft: 'left'
6204 },
6205 useEngine: true
6206 },
6207 minHeight: {
6208 value: ['dimensions', 'minHeight'],
6209 support: ['dimensions', 'minHeight'],
6210 useEngine: true
6211 },
6212 padding: {
6213 value: ['spacing', 'padding'],
6214 support: ['spacing', 'padding'],
6215 properties: {
6216 paddingTop: 'top',
6217 paddingRight: 'right',
6218 paddingBottom: 'bottom',
6219 paddingLeft: 'left'
6220 },
6221 useEngine: true
6222 },
6223 textDecoration: {
6224 value: ['typography', 'textDecoration'],
6225 support: ['typography', '__experimentalTextDecoration'],
6226 useEngine: true
6227 },
6228 textTransform: {
6229 value: ['typography', 'textTransform'],
6230 support: ['typography', '__experimentalTextTransform'],
6231 useEngine: true
6232 },
6233 letterSpacing: {
6234 value: ['typography', 'letterSpacing'],
6235 support: ['typography', '__experimentalLetterSpacing'],
6236 useEngine: true
6237 },
6238 writingMode: {
6239 value: ['typography', 'writingMode'],
6240 support: ['typography', '__experimentalWritingMode'],
6241 useEngine: true
6242 },
6243 '--wp--style--root--padding': {
6244 value: ['spacing', 'padding'],
6245 support: ['spacing', 'padding'],
6246 properties: {
6247 '--wp--style--root--padding-top': 'top',
6248 '--wp--style--root--padding-right': 'right',
6249 '--wp--style--root--padding-bottom': 'bottom',
6250 '--wp--style--root--padding-left': 'left'
6251 },
6252 rootOnly: true
6253 }
6254 };
6255 const __EXPERIMENTAL_ELEMENTS = {
6256 link: 'a',
6257 heading: 'h1, h2, h3, h4, h5, h6',
6258 h1: 'h1',
6259 h2: 'h2',
6260 h3: 'h3',
6261 h4: 'h4',
6262 h5: 'h5',
6263 h6: 'h6',
6264 button: '.wp-element-button, .wp-block-button__link',
6265 caption: '.wp-element-caption, .wp-block-audio figcaption, .wp-block-embed figcaption, .wp-block-gallery figcaption, .wp-block-image figcaption, .wp-block-table figcaption, .wp-block-video figcaption',
6266 cite: 'cite'
6267 };
6268 const __EXPERIMENTAL_PATHS_WITH_MERGE = {
6269 'color.duotone': true,
6270 'color.gradients': true,
6271 'color.palette': true,
6272 'typography.fontFamilies': true,
6273 'typography.fontSizes': true,
6274 'spacing.spacingSizes': true
6275 };
6276
6277 ;// CONCATENATED MODULE: ./node_modules/tslib/tslib.es6.js
6278 /*! *****************************************************************************
6279 Copyright (c) Microsoft Corporation.
6280
6281 Permission to use, copy, modify, and/or distribute this software for any
6282 purpose with or without fee is hereby granted.
6283
6284 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
6285 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
6286 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
6287 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
6288 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
6289 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
6290 PERFORMANCE OF THIS SOFTWARE.
6291 ***************************************************************************** */
6292 /* global Reflect, Promise */
6293
6294 var extendStatics = function(d, b) {
6295 extendStatics = Object.setPrototypeOf ||
6296 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6297 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6298 return extendStatics(d, b);
6299 };
6300
6301 function __extends(d, b) {
6302 if (typeof b !== "function" && b !== null)
6303 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
6304 extendStatics(d, b);
6305 function __() { this.constructor = d; }
6306 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6307 }
6308
6309 var __assign = function() {
6310 __assign = Object.assign || function __assign(t) {
6311 for (var s, i = 1, n = arguments.length; i < n; i++) {
6312 s = arguments[i];
6313 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
6314 }
6315 return t;
6316 }
6317 return __assign.apply(this, arguments);
6318 }
6319
6320 function __rest(s, e) {
6321 var t = {};
6322 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6323 t[p] = s[p];
6324 if (s != null && typeof Object.getOwnPropertySymbols === "function")
6325 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
6326 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
6327 t[p[i]] = s[p[i]];
6328 }
6329 return t;
6330 }
6331
6332 function __decorate(decorators, target, key, desc) {
6333 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6334 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6335 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6336 return c > 3 && r && Object.defineProperty(target, key, r), r;
6337 }
6338
6339 function __param(paramIndex, decorator) {
6340 return function (target, key) { decorator(target, key, paramIndex); }
6341 }
6342
6343 function __metadata(metadataKey, metadataValue) {
6344 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
6345 }
6346
6347 function __awaiter(thisArg, _arguments, P, generator) {
6348 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6349 return new (P || (P = Promise))(function (resolve, reject) {
6350 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6351 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6352 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
6353 step((generator = generator.apply(thisArg, _arguments || [])).next());
6354 });
6355 }
6356
6357 function __generator(thisArg, body) {
6358 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
6359 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
6360 function verb(n) { return function (v) { return step([n, v]); }; }
6361 function step(op) {
6362 if (f) throw new TypeError("Generator is already executing.");
6363 while (_) try {
6364 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
6365 if (y = 0, t) op = [op[0] & 2, t.value];
6366 switch (op[0]) {
6367 case 0: case 1: t = op; break;
6368 case 4: _.label++; return { value: op[1], done: false };
6369 case 5: _.label++; y = op[1]; op = [0]; continue;
6370 case 7: op = _.ops.pop(); _.trys.pop(); continue;
6371 default:
6372 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
6373 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
6374 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
6375 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
6376 if (t[2]) _.ops.pop();
6377 _.trys.pop(); continue;
6378 }
6379 op = body.call(thisArg, _);
6380 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
6381 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
6382 }
6383 }
6384
6385 var __createBinding = Object.create ? (function(o, m, k, k2) {
6386 if (k2 === undefined) k2 = k;
6387 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
6388 }) : (function(o, m, k, k2) {
6389 if (k2 === undefined) k2 = k;
6390 o[k2] = m[k];
6391 });
6392
6393 function __exportStar(m, o) {
6394 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
6395 }
6396
6397 function __values(o) {
6398 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
6399 if (m) return m.call(o);
6400 if (o && typeof o.length === "number") return {
6401 next: function () {
6402 if (o && i >= o.length) o = void 0;
6403 return { value: o && o[i++], done: !o };
6404 }
6405 };
6406 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
6407 }
6408
6409 function __read(o, n) {
6410 var m = typeof Symbol === "function" && o[Symbol.iterator];
6411 if (!m) return o;
6412 var i = m.call(o), r, ar = [], e;
6413 try {
6414 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
6415 }
6416 catch (error) { e = { error: error }; }
6417 finally {
6418 try {
6419 if (r && !r.done && (m = i["return"])) m.call(i);
6420 }
6421 finally { if (e) throw e.error; }
6422 }
6423 return ar;
6424 }
6425
6426 /** @deprecated */
6427 function __spread() {
6428 for (var ar = [], i = 0; i < arguments.length; i++)
6429 ar = ar.concat(__read(arguments[i]));
6430 return ar;
6431 }
6432
6433 /** @deprecated */
6434 function __spreadArrays() {
6435 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
6436 for (var r = Array(s), k = 0, i = 0; i < il; i++)
6437 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
6438 r[k] = a[j];
6439 return r;
6440 }
6441
6442 function __spreadArray(to, from, pack) {
6443 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
6444 if (ar || !(i in from)) {
6445 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6446 ar[i] = from[i];
6447 }
6448 }
6449 return to.concat(ar || from);
6450 }
6451
6452 function __await(v) {
6453 return this instanceof __await ? (this.v = v, this) : new __await(v);
6454 }
6455
6456 function __asyncGenerator(thisArg, _arguments, generator) {
6457 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6458 var g = generator.apply(thisArg, _arguments || []), i, q = [];
6459 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
6460 function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
6461 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
6462 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
6463 function fulfill(value) { resume("next", value); }
6464 function reject(value) { resume("throw", value); }
6465 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
6466 }
6467
6468 function __asyncDelegator(o) {
6469 var i, p;
6470 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
6471 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
6472 }
6473
6474 function __asyncValues(o) {
6475 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6476 var m = o[Symbol.asyncIterator], i;
6477 return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
6478 function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
6479 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
6480 }
6481
6482 function __makeTemplateObject(cooked, raw) {
6483 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
6484 return cooked;
6485 };
6486
6487 var __setModuleDefault = Object.create ? (function(o, v) {
6488 Object.defineProperty(o, "default", { enumerable: true, value: v });
6489 }) : function(o, v) {
6490 o["default"] = v;
6491 };
6492
6493 function __importStar(mod) {
6494 if (mod && mod.__esModule) return mod;
6495 var result = {};
6496 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
6497 __setModuleDefault(result, mod);
6498 return result;
6499 }
6500
6501 function __importDefault(mod) {
6502 return (mod && mod.__esModule) ? mod : { default: mod };
6503 }
6504
6505 function __classPrivateFieldGet(receiver, state, kind, f) {
6506 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
6507 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
6508 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6509 }
6510
6511 function __classPrivateFieldSet(receiver, state, value, kind, f) {
6512 if (kind === "m") throw new TypeError("Private method is not writable");
6513 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
6514 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6515 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6516 }
6517
6518 ;// CONCATENATED MODULE: ./node_modules/lower-case/dist.es2015/index.js
6519 /**
6520 * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
6521 */
6522 var SUPPORTED_LOCALE = {
6523 tr: {
6524 regexp: /\u0130|\u0049|\u0049\u0307/g,
6525 map: {
6526 İ: "\u0069",
6527 I: "\u0131",
6528 İ: "\u0069",
6529 },
6530 },
6531 az: {
6532 regexp: /\u0130/g,
6533 map: {
6534 İ: "\u0069",
6535 I: "\u0131",
6536 İ: "\u0069",
6537 },
6538 },
6539 lt: {
6540 regexp: /\u0049|\u004A|\u012E|\u00CC|\u00CD|\u0128/g,
6541 map: {
6542 I: "\u0069\u0307",
6543 J: "\u006A\u0307",
6544 Į: "\u012F\u0307",
6545 Ì: "\u0069\u0307\u0300",
6546 Í: "\u0069\u0307\u0301",
6547 Ĩ: "\u0069\u0307\u0303",
6548 },
6549 },
6550 };
6551 /**
6552 * Localized lower case.
6553 */
6554 function localeLowerCase(str, locale) {
6555 var lang = SUPPORTED_LOCALE[locale.toLowerCase()];
6556 if (lang)
6557 return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));
6558 return lowerCase(str);
6559 }
6560 /**
6561 * Lower case as a function.
6562 */
6563 function lowerCase(str) {
6564 return str.toLowerCase();
6565 }
6566
6567 ;// CONCATENATED MODULE: ./node_modules/no-case/dist.es2015/index.js
6568
6569 // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
6570 var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
6571 // Remove all non-word characters.
6572 var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
6573 /**
6574 * Normalize the string into something other libraries can manipulate easier.
6575 */
6576 function noCase(input, options) {
6577 if (options === void 0) { options = {}; }
6578 var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
6579 var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
6580 var start = 0;
6581 var end = result.length;
6582 // Trim the delimiter from around the output string.
6583 while (result.charAt(start) === "\0")
6584 start++;
6585 while (result.charAt(end - 1) === "\0")
6586 end--;
6587 // Transform each token independently.
6588 return result.slice(start, end).split("\0").map(transform).join(delimiter);
6589 }
6590 /**
6591 * Replace `re` in the input string with the replacement value.
6592 */
6593 function replace(input, re, value) {
6594 if (re instanceof RegExp)
6595 return input.replace(re, value);
6596 return re.reduce(function (input, re) { return input.replace(re, value); }, input);
6597 }
6598
6599 ;// CONCATENATED MODULE: ./node_modules/pascal-case/dist.es2015/index.js
6600
6601
6602 function pascalCaseTransform(input, index) {
6603 var firstChar = input.charAt(0);
6604 var lowerChars = input.substr(1).toLowerCase();
6605 if (index > 0 && firstChar >= "0" && firstChar <= "9") {
6606 return "_" + firstChar + lowerChars;
6607 }
6608 return "" + firstChar.toUpperCase() + lowerChars;
6609 }
6610 function dist_es2015_pascalCaseTransformMerge(input) {
6611 return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
6612 }
6613 function pascalCase(input, options) {
6614 if (options === void 0) { options = {}; }
6615 return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
6616 }
6617
6618 ;// CONCATENATED MODULE: ./node_modules/camel-case/dist.es2015/index.js
6619
6620
6621 function camelCaseTransform(input, index) {
6622 if (index === 0)
6623 return input.toLowerCase();
6624 return pascalCaseTransform(input, index);
6625 }
6626 function camelCaseTransformMerge(input, index) {
6627 if (index === 0)
6628 return input.toLowerCase();
6629 return pascalCaseTransformMerge(input);
6630 }
6631 function camelCase(input, options) {
6632 if (options === void 0) { options = {}; }
6633 return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
6634 }
6635
6636 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/registration.js
6637 /* eslint no-console: [ 'error', { allow: [ 'error', 'warn' ] } ] */
6638
6639 /**
6640 * External dependencies
6641 */
6642
6643 /**
6644 * WordPress dependencies
6645 */
6646
6647
6648
6649 /**
6650 * Internal dependencies
6651 */
6652
6653 const i18nBlockSchema = {
6654 title: "block title",
6655 description: "block description",
6656 keywords: ["block keyword"],
6657 styles: [{
6658 label: "block style label"
6659 }],
6660 variations: [{
6661 title: "block variation title",
6662 description: "block variation description",
6663 keywords: ["block variation keyword"]
6664 }]
6665 };
6666
6667
6668 /**
6669 * An icon type definition. One of a Dashicon slug, an element,
6670 * or a component.
6671 *
6672 * @typedef {(string|WPElement|WPComponent)} WPIcon
6673 *
6674 * @see https://developer.wordpress.org/resource/dashicons/
6675 */
6676
6677 /**
6678 * Render behavior of a block type icon; one of a Dashicon slug, an element,
6679 * or a component.
6680 *
6681 * @typedef {WPIcon} WPBlockTypeIconRender
6682 */
6683
6684 /**
6685 * An object describing a normalized block type icon.
6686 *
6687 * @typedef {Object} WPBlockTypeIconDescriptor
6688 *
6689 * @property {WPBlockTypeIconRender} src Render behavior of the icon,
6690 * one of a Dashicon slug, an
6691 * element, or a component.
6692 * @property {string} background Optimal background hex string
6693 * color when displaying icon.
6694 * @property {string} foreground Optimal foreground hex string
6695 * color when displaying icon.
6696 * @property {string} shadowColor Optimal shadow hex string
6697 * color when displaying icon.
6698 */
6699
6700 /**
6701 * Value to use to render the icon for a block type in an editor interface,
6702 * either a Dashicon slug, an element, a component, or an object describing
6703 * the icon.
6704 *
6705 * @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
6706 */
6707
6708 /**
6709 * Named block variation scopes.
6710 *
6711 * @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
6712 */
6713
6714 /**
6715 * An object describing a variation defined for the block type.
6716 *
6717 * @typedef {Object} WPBlockVariation
6718 *
6719 * @property {string} name The unique and machine-readable name.
6720 * @property {string} title A human-readable variation title.
6721 * @property {string} [description] A detailed variation description.
6722 * @property {string} [category] Block type category classification,
6723 * used in search interfaces to arrange
6724 * block types by category.
6725 * @property {WPIcon} [icon] An icon helping to visualize the variation.
6726 * @property {boolean} [isDefault] Indicates whether the current variation is
6727 * the default one. Defaults to `false`.
6728 * @property {Object} [attributes] Values which override block attributes.
6729 * @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
6730 * @property {Object} [example] Example provides structured data for
6731 * the block preview. You can set to
6732 * `undefined` to disable the preview shown
6733 * for the block type.
6734 * @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
6735 * is applicable. When not provided, it
6736 * assumes all available scopes.
6737 * @property {string[]} [keywords] An array of terms (which can be translated)
6738 * that help users discover the variation
6739 * while searching.
6740 * @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
6741 * Function that accepts a block's attributes and the
6742 * variation's attributes and determines if a variation is active.
6743 * This function doesn't try to find a match dynamically based
6744 * on all block's attributes, as in many cases some attributes are irrelevant.
6745 * An example would be for `embed` block where we only care
6746 * about `providerNameSlug` attribute's value.
6747 * We can also use a `string[]` to tell which attributes
6748 * should be compared as a shorthand. Each attributes will
6749 * be matched and the variation will be active if all of them are matching.
6750 */
6751
6752 /**
6753 * Defined behavior of a block type.
6754 *
6755 * @typedef {Object} WPBlockType
6756 *
6757 * @property {string} name Block type's namespaced name.
6758 * @property {string} title Human-readable block type label.
6759 * @property {string} [description] A detailed block type description.
6760 * @property {string} [category] Block type category classification,
6761 * used in search interfaces to arrange
6762 * block types by category.
6763 * @property {WPBlockTypeIcon} [icon] Block type icon.
6764 * @property {string[]} [keywords] Additional keywords to produce block
6765 * type as result in search interfaces.
6766 * @property {Object} [attributes] Block type attributes.
6767 * @property {WPComponent} [save] Optional component describing
6768 * serialized markup structure of a
6769 * block type.
6770 * @property {WPComponent} edit Component rendering an element to
6771 * manipulate the attributes of a block
6772 * in the context of an editor.
6773 * @property {WPBlockVariation[]} [variations] The list of block variations.
6774 * @property {Object} [example] Example provides structured data for
6775 * the block preview. When not defined
6776 * then no preview is shown.
6777 */
6778
6779 const serverSideBlockDefinitions = {};
6780
6781 function isObject(object) {
6782 return object !== null && typeof object === 'object';
6783 }
6784 /**
6785 * Sets the server side block definition of blocks.
6786 *
6787 * @param {Object} definitions Server-side block definitions
6788 */
6789 // eslint-disable-next-line camelcase
6790
6791
6792 function unstable__bootstrapServerSideBlockDefinitions(definitions) {
6793 for (const blockName of Object.keys(definitions)) {
6794 // Don't overwrite if already set. It covers the case when metadata
6795 // was initialized from the server.
6796 if (serverSideBlockDefinitions[blockName]) {
6797 // We still need to polyfill `apiVersion` for WordPress version
6798 // lower than 5.7. If it isn't present in the definition shared
6799 // from the server, we try to fallback to the definition passed.
6800 // @see https://github.com/WordPress/gutenberg/pull/29279
6801 if (serverSideBlockDefinitions[blockName].apiVersion === undefined && definitions[blockName].apiVersion) {
6802 serverSideBlockDefinitions[blockName].apiVersion = definitions[blockName].apiVersion;
6803 } // The `ancestor` prop is not included in the definitions shared
6804 // from the server yet, so it needs to be polyfilled as well.
6805 // @see https://github.com/WordPress/gutenberg/pull/39894
6806
6807
6808 if (serverSideBlockDefinitions[blockName].ancestor === undefined && definitions[blockName].ancestor) {
6809 serverSideBlockDefinitions[blockName].ancestor = definitions[blockName].ancestor;
6810 } // The `selectors` prop is not yet included in the server provided
6811 // definitions. Polyfill it as well. This can be removed when the
6812 // minimum supported WordPress is >= 6.3.
6813
6814
6815 if (serverSideBlockDefinitions[blockName].selectors === undefined && definitions[blockName].selectors) {
6816 serverSideBlockDefinitions[blockName].selectors = definitions[blockName].selectors;
6817 }
6818
6819 continue;
6820 }
6821
6822 serverSideBlockDefinitions[blockName] = Object.fromEntries(Object.entries(definitions[blockName]).filter(([, value]) => value !== null && value !== undefined).map(([key, value]) => [camelCase(key), value]));
6823 }
6824 }
6825 /**
6826 * Gets block settings from metadata loaded from `block.json` file.
6827 *
6828 * @param {Object} metadata Block metadata loaded from `block.json`.
6829 * @param {string} metadata.textdomain Textdomain to use with translations.
6830 *
6831 * @return {Object} Block settings.
6832 */
6833
6834 function getBlockSettingsFromMetadata({
6835 textdomain,
6836 ...metadata
6837 }) {
6838 const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'selectors', 'supports', 'styles', 'example', 'variations'];
6839 const settings = Object.fromEntries(Object.entries(metadata).filter(([key]) => allowedFields.includes(key)));
6840
6841 if (textdomain) {
6842 Object.keys(i18nBlockSchema).forEach(key => {
6843 if (!settings[key]) {
6844 return;
6845 }
6846
6847 settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
6848 });
6849 }
6850
6851 return settings;
6852 }
6853 /**
6854 * Registers a new block provided a unique name and an object defining its
6855 * behavior. Once registered, the block is made available as an option to any
6856 * editor interface where blocks are implemented.
6857 *
6858 * For more in-depth information on registering a custom block see the
6859 * [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).
6860 *
6861 * @param {string|Object} blockNameOrMetadata Block type name or its metadata.
6862 * @param {Object} settings Block settings.
6863 *
6864 * @example
6865 * ```js
6866 * import { __ } from '@wordpress/i18n';
6867 * import { registerBlockType } from '@wordpress/blocks'
6868 *
6869 * registerBlockType( 'namespace/block-name', {
6870 * title: __( 'My First Block' ),
6871 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
6872 * save: () => <div>Hello from the saved content!</div>,
6873 * } );
6874 * ```
6875 *
6876 * @return {WPBlockType | undefined} The block, if it has been successfully registered;
6877 * otherwise `undefined`.
6878 */
6879
6880
6881 function registerBlockType(blockNameOrMetadata, settings) {
6882 const name = isObject(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
6883
6884 if (typeof name !== 'string') {
6885 console.error('Block names must be strings.');
6886 return;
6887 }
6888
6889 if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
6890 console.error('Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block');
6891 return;
6892 }
6893
6894 if ((0,external_wp_data_namespaceObject.select)(store).getBlockType(name)) {
6895 console.error('Block "' + name + '" is already registered.');
6896 return;
6897 }
6898
6899 if (isObject(blockNameOrMetadata)) {
6900 unstable__bootstrapServerSideBlockDefinitions({
6901 [name]: getBlockSettingsFromMetadata(blockNameOrMetadata)
6902 });
6903 }
6904
6905 const blockType = {
6906 name,
6907 icon: BLOCK_ICON_DEFAULT,
6908 keywords: [],
6909 attributes: {},
6910 providesContext: {},
6911 usesContext: [],
6912 selectors: {},
6913 supports: {},
6914 styles: [],
6915 variations: [],
6916 save: () => null,
6917 ...serverSideBlockDefinitions?.[name],
6918 ...settings
6919 };
6920
6921 (0,external_wp_data_namespaceObject.dispatch)(store).__experimentalRegisterBlockType(blockType);
6922
6923 return (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
6924 }
6925 /**
6926 * Translates block settings provided with metadata using the i18n schema.
6927 *
6928 * @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
6929 * @param {string|string[]|Object[]} settingValue Value for the block setting.
6930 * @param {string} textdomain Textdomain to use with translations.
6931 *
6932 * @return {string|string[]|Object[]} Translated setting.
6933 */
6934
6935 function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
6936 if (typeof i18nSchema === 'string' && typeof settingValue === 'string') {
6937 // eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
6938 return (0,external_wp_i18n_namespaceObject._x)(settingValue, i18nSchema, textdomain);
6939 }
6940
6941 if (Array.isArray(i18nSchema) && i18nSchema.length && Array.isArray(settingValue)) {
6942 return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
6943 }
6944
6945 if (isObject(i18nSchema) && Object.entries(i18nSchema).length && isObject(settingValue)) {
6946 return Object.keys(settingValue).reduce((accumulator, key) => {
6947 if (!i18nSchema[key]) {
6948 accumulator[key] = settingValue[key];
6949 return accumulator;
6950 }
6951
6952 accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
6953 return accumulator;
6954 }, {});
6955 }
6956
6957 return settingValue;
6958 }
6959 /**
6960 * Registers a new block collection to group blocks in the same namespace in the inserter.
6961 *
6962 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
6963 * @param {Object} settings The block collection settings.
6964 * @param {string} settings.title The title to display in the block inserter.
6965 * @param {Object} [settings.icon] The icon to display in the block inserter.
6966 *
6967 * @example
6968 * ```js
6969 * import { __ } from '@wordpress/i18n';
6970 * import { registerBlockCollection, registerBlockType } from '@wordpress/blocks';
6971 *
6972 * // Register the collection.
6973 * registerBlockCollection( 'my-collection', {
6974 * title: __( 'Custom Collection' ),
6975 * } );
6976 *
6977 * // Register a block in the same namespace to add it to the collection.
6978 * registerBlockType( 'my-collection/block-name', {
6979 * title: __( 'My First Block' ),
6980 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
6981 * save: () => <div>'Hello from the saved content!</div>,
6982 * } );
6983 * ```
6984 */
6985
6986
6987 function registerBlockCollection(namespace, {
6988 title,
6989 icon
6990 }) {
6991 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockCollection(namespace, title, icon);
6992 }
6993 /**
6994 * Unregisters a block collection
6995 *
6996 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
6997 *
6998 * @example
6999 * ```js
7000 * import { unregisterBlockCollection } from '@wordpress/blocks';
7001 *
7002 * unregisterBlockCollection( 'my-collection' );
7003 * ```
7004 */
7005
7006 function unregisterBlockCollection(namespace) {
7007 dispatch(blocksStore).removeBlockCollection(namespace);
7008 }
7009 /**
7010 * Unregisters a block.
7011 *
7012 * @param {string} name Block name.
7013 *
7014 * @example
7015 * ```js
7016 * import { __ } from '@wordpress/i18n';
7017 * import { unregisterBlockType } from '@wordpress/blocks';
7018 *
7019 * const ExampleComponent = () => {
7020 * return (
7021 * <Button
7022 * onClick={ () =>
7023 * unregisterBlockType( 'my-collection/block-name' )
7024 * }
7025 * >
7026 * { __( 'Unregister my custom block.' ) }
7027 * </Button>
7028 * );
7029 * };
7030 * ```
7031 *
7032 * @return {WPBlockType | undefined} The previous block value, if it has been successfully
7033 * unregistered; otherwise `undefined`.
7034 */
7035
7036 function unregisterBlockType(name) {
7037 const oldBlock = (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
7038
7039 if (!oldBlock) {
7040 console.error('Block "' + name + '" is not registered.');
7041 return;
7042 }
7043
7044 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockTypes(name);
7045 return oldBlock;
7046 }
7047 /**
7048 * Assigns name of block for handling non-block content.
7049 *
7050 * @param {string} blockName Block name.
7051 */
7052
7053 function setFreeformContentHandlerName(blockName) {
7054 (0,external_wp_data_namespaceObject.dispatch)(store).setFreeformFallbackBlockName(blockName);
7055 }
7056 /**
7057 * Retrieves name of block handling non-block content, or undefined if no
7058 * handler has been defined.
7059 *
7060 * @return {?string} Block name.
7061 */
7062
7063 function getFreeformContentHandlerName() {
7064 return (0,external_wp_data_namespaceObject.select)(store).getFreeformFallbackBlockName();
7065 }
7066 /**
7067 * Retrieves name of block used for handling grouping interactions.
7068 *
7069 * @return {?string} Block name.
7070 */
7071
7072 function getGroupingBlockName() {
7073 return (0,external_wp_data_namespaceObject.select)(store).getGroupingBlockName();
7074 }
7075 /**
7076 * Assigns name of block handling unregistered block types.
7077 *
7078 * @param {string} blockName Block name.
7079 */
7080
7081 function setUnregisteredTypeHandlerName(blockName) {
7082 (0,external_wp_data_namespaceObject.dispatch)(store).setUnregisteredFallbackBlockName(blockName);
7083 }
7084 /**
7085 * Retrieves name of block handling unregistered block types, or undefined if no
7086 * handler has been defined.
7087 *
7088 * @return {?string} Block name.
7089 */
7090
7091 function getUnregisteredTypeHandlerName() {
7092 return (0,external_wp_data_namespaceObject.select)(store).getUnregisteredFallbackBlockName();
7093 }
7094 /**
7095 * Assigns the default block name.
7096 *
7097 * @param {string} name Block name.
7098 *
7099 * @example
7100 * ```js
7101 * import { setDefaultBlockName } from '@wordpress/blocks';
7102 *
7103 * const ExampleComponent = () => {
7104 *
7105 * return (
7106 * <Button onClick={ () => setDefaultBlockName( 'core/heading' ) }>
7107 * { __( 'Set the default block to Heading' ) }
7108 * </Button>
7109 * );
7110 * };
7111 * ```
7112 */
7113
7114 function setDefaultBlockName(name) {
7115 (0,external_wp_data_namespaceObject.dispatch)(store).setDefaultBlockName(name);
7116 }
7117 /**
7118 * Assigns name of block for handling block grouping interactions.
7119 *
7120 * This function lets you select a different block to group other blocks in instead of the
7121 * default `core/group` block. This function must be used in a component or when the DOM is fully
7122 * loaded. See https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dom-ready/
7123 *
7124 * @param {string} name Block name.
7125 *
7126 * @example
7127 * ```js
7128 * import { setGroupingBlockName } from '@wordpress/blocks';
7129 *
7130 * const ExampleComponent = () => {
7131 *
7132 * return (
7133 * <Button onClick={ () => setGroupingBlockName( 'core/columns' ) }>
7134 * { __( 'Wrap in columns' ) }
7135 * </Button>
7136 * );
7137 * };
7138 * ```
7139 */
7140
7141 function setGroupingBlockName(name) {
7142 (0,external_wp_data_namespaceObject.dispatch)(store).setGroupingBlockName(name);
7143 }
7144 /**
7145 * Retrieves the default block name.
7146 *
7147 * @return {?string} Block name.
7148 */
7149
7150 function getDefaultBlockName() {
7151 return (0,external_wp_data_namespaceObject.select)(store).getDefaultBlockName();
7152 }
7153 /**
7154 * Returns a registered block type.
7155 *
7156 * @param {string} name Block name.
7157 *
7158 * @return {?Object} Block type.
7159 */
7160
7161 function getBlockType(name) {
7162 return (0,external_wp_data_namespaceObject.select)(store)?.getBlockType(name);
7163 }
7164 /**
7165 * Returns all registered blocks.
7166 *
7167 * @return {Array} Block settings.
7168 */
7169
7170 function getBlockTypes() {
7171 return (0,external_wp_data_namespaceObject.select)(store).getBlockTypes();
7172 }
7173 /**
7174 * Returns the block support value for a feature, if defined.
7175 *
7176 * @param {(string|Object)} nameOrType Block name or type object
7177 * @param {string} feature Feature to retrieve
7178 * @param {*} defaultSupports Default value to return if not
7179 * explicitly defined
7180 *
7181 * @return {?*} Block support value
7182 */
7183
7184 function getBlockSupport(nameOrType, feature, defaultSupports) {
7185 return (0,external_wp_data_namespaceObject.select)(store).getBlockSupport(nameOrType, feature, defaultSupports);
7186 }
7187 /**
7188 * Returns true if the block defines support for a feature, or false otherwise.
7189 *
7190 * @param {(string|Object)} nameOrType Block name or type object.
7191 * @param {string} feature Feature to test.
7192 * @param {boolean} defaultSupports Whether feature is supported by
7193 * default if not explicitly defined.
7194 *
7195 * @return {boolean} Whether block supports feature.
7196 */
7197
7198 function hasBlockSupport(nameOrType, feature, defaultSupports) {
7199 return (0,external_wp_data_namespaceObject.select)(store).hasBlockSupport(nameOrType, feature, defaultSupports);
7200 }
7201 /**
7202 * Determines whether or not the given block is a reusable block. This is a
7203 * special block type that is used to point to a global block stored via the
7204 * API.
7205 *
7206 * @param {Object} blockOrType Block or Block Type to test.
7207 *
7208 * @return {boolean} Whether the given block is a reusable block.
7209 */
7210
7211 function isReusableBlock(blockOrType) {
7212 return blockOrType?.name === 'core/block';
7213 }
7214 /**
7215 * Determines whether or not the given block is a template part. This is a
7216 * special block type that allows composing a page template out of reusable
7217 * design elements.
7218 *
7219 * @param {Object} blockOrType Block or Block Type to test.
7220 *
7221 * @return {boolean} Whether the given block is a template part.
7222 */
7223
7224 function isTemplatePart(blockOrType) {
7225 return blockOrType?.name === 'core/template-part';
7226 }
7227 /**
7228 * Returns an array with the child blocks of a given block.
7229 *
7230 * @param {string} blockName Name of block (example: “latest-posts”).
7231 *
7232 * @return {Array} Array of child block names.
7233 */
7234
7235 const getChildBlockNames = blockName => {
7236 return (0,external_wp_data_namespaceObject.select)(store).getChildBlockNames(blockName);
7237 };
7238 /**
7239 * Returns a boolean indicating if a block has child blocks or not.
7240 *
7241 * @param {string} blockName Name of block (example: “latest-posts”).
7242 *
7243 * @return {boolean} True if a block contains child blocks and false otherwise.
7244 */
7245
7246 const hasChildBlocks = blockName => {
7247 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocks(blockName);
7248 };
7249 /**
7250 * Returns a boolean indicating if a block has at least one child block with inserter support.
7251 *
7252 * @param {string} blockName Block type name.
7253 *
7254 * @return {boolean} True if a block contains at least one child blocks with inserter support
7255 * and false otherwise.
7256 */
7257
7258 const hasChildBlocksWithInserterSupport = blockName => {
7259 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocksWithInserterSupport(blockName);
7260 };
7261 /**
7262 * Registers a new block style for the given block.
7263 *
7264 * For more information on connecting the styles with CSS
7265 * [the official documentation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/#styles).
7266 *
7267 * @param {string} blockName Name of block (example: “core/latest-posts”).
7268 * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
7269 *
7270 * @example
7271 * ```js
7272 * import { __ } from '@wordpress/i18n';
7273 * import { registerBlockStyle } from '@wordpress/blocks';
7274 * import { Button } from '@wordpress/components';
7275 *
7276 *
7277 * const ExampleComponent = () => {
7278 * return (
7279 * <Button
7280 * onClick={ () => {
7281 * registerBlockStyle( 'core/quote', {
7282 * name: 'fancy-quote',
7283 * label: __( 'Fancy Quote' ),
7284 * } );
7285 * } }
7286 * >
7287 * { __( 'Add a new block style for core/quote' ) }
7288 * </Button>
7289 * );
7290 * };
7291 * ```
7292 */
7293
7294 const registerBlockStyle = (blockName, styleVariation) => {
7295 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockStyles(blockName, styleVariation);
7296 };
7297 /**
7298 * Unregisters a block style for the given block.
7299 *
7300 * @param {string} blockName Name of block (example: “core/latest-posts”).
7301 * @param {string} styleVariationName Name of class applied to the block.
7302 *
7303 * @example
7304 * ```js
7305 * import { __ } from '@wordpress/i18n';
7306 * import { unregisterBlockStyle } from '@wordpress/blocks';
7307 * import { Button } from '@wordpress/components';
7308 *
7309 * const ExampleComponent = () => {
7310 * return (
7311 * <Button
7312 * onClick={ () => {
7313 * unregisterBlockStyle( 'core/quote', 'plain' );
7314 * } }
7315 * >
7316 * { __( 'Remove the "Plain" block style for core/quote' ) }
7317 * </Button>
7318 * );
7319 * };
7320 * ```
7321 */
7322
7323 const unregisterBlockStyle = (blockName, styleVariationName) => {
7324 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockStyles(blockName, styleVariationName);
7325 };
7326 /**
7327 * Returns an array with the variations of a given block type.
7328 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
7329 *
7330 * @ignore
7331 *
7332 * @param {string} blockName Name of block (example: “core/columns”).
7333 * @param {WPBlockVariationScope} [scope] Block variation scope name.
7334 *
7335 * @return {(WPBlockVariation[]|void)} Block variations.
7336 */
7337
7338 const getBlockVariations = (blockName, scope) => {
7339 return (0,external_wp_data_namespaceObject.select)(store).getBlockVariations(blockName, scope);
7340 };
7341 /**
7342 * Registers a new block variation for the given block type.
7343 *
7344 * For more information on block variations see
7345 * [the official documentation ](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/).
7346 *
7347 * @param {string} blockName Name of the block (example: “core/columns”).
7348 * @param {WPBlockVariation} variation Object describing a block variation.
7349 *
7350 * @example
7351 * ```js
7352 * import { __ } from '@wordpress/i18n';
7353 * import { registerBlockVariation } from '@wordpress/blocks';
7354 * import { Button } from '@wordpress/components';
7355 *
7356 * const ExampleComponent = () => {
7357 * return (
7358 * <Button
7359 * onClick={ () => {
7360 * registerBlockVariation( 'core/embed', {
7361 * name: 'custom',
7362 * title: __( 'My Custom Embed' ),
7363 * attributes: { providerNameSlug: 'custom' },
7364 * } );
7365 * } }
7366 * >
7367 * __( 'Add a custom variation for core/embed' ) }
7368 * </Button>
7369 * );
7370 * };
7371 * ```
7372 */
7373
7374 const registerBlockVariation = (blockName, variation) => {
7375 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockVariations(blockName, variation);
7376 };
7377 /**
7378 * Unregisters a block variation defined for the given block type.
7379 *
7380 * @param {string} blockName Name of the block (example: “core/columns”).
7381 * @param {string} variationName Name of the variation defined for the block.
7382 *
7383 * @example
7384 * ```js
7385 * import { __ } from '@wordpress/i18n';
7386 * import { unregisterBlockVariation } from '@wordpress/blocks';
7387 * import { Button } from '@wordpress/components';
7388 *
7389 * const ExampleComponent = () => {
7390 * return (
7391 * <Button
7392 * onClick={ () => {
7393 * unregisterBlockVariation( 'core/embed', 'youtube' );
7394 * } }
7395 * >
7396 * { __( 'Remove the YouTube variation from core/embed' ) }
7397 * </Button>
7398 * );
7399 * };
7400 * ```
7401 */
7402
7403 const unregisterBlockVariation = (blockName, variationName) => {
7404 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockVariations(blockName, variationName);
7405 };
7406
7407 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/rng.js
7408 // Unique ID creation requires a high quality random # generator. In the browser we therefore
7409 // require the crypto API and do not support built-in fallback to lower quality random number
7410 // generators (like Math.random()).
7411 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
7412 // find the complete implementation of crypto (msCrypto) on IE11.
7413 var getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
7414 var rnds8 = new Uint8Array(16);
7415 function rng() {
7416 if (!getRandomValues) {
7417 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
7418 }
7419
7420 return getRandomValues(rnds8);
7421 }
7422 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/regex.js
7423 /* harmony default export */ const regex = (/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i);
7424 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/validate.js
7425
7426
7427 function validate(uuid) {
7428 return typeof uuid === 'string' && regex.test(uuid);
7429 }
7430
7431 /* harmony default export */ const esm_browser_validate = (validate);
7432 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/stringify.js
7433
7434 /**
7435 * Convert array of 16 byte values to UUID string format of the form:
7436 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
7437 */
7438
7439 var byteToHex = [];
7440
7441 for (var stringify_i = 0; stringify_i < 256; ++stringify_i) {
7442 byteToHex.push((stringify_i + 0x100).toString(16).substr(1));
7443 }
7444
7445 function stringify(arr) {
7446 var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
7447 // Note: Be careful editing this code! It's been tuned for performance
7448 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
7449 var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
7450 // of the following:
7451 // - One or more input array values don't map to a hex octet (leading to
7452 // "undefined" in the uuid)
7453 // - Invalid input values for the RFC `version` or `variant` fields
7454
7455 if (!esm_browser_validate(uuid)) {
7456 throw TypeError('Stringified UUID is invalid');
7457 }
7458
7459 return uuid;
7460 }
7461
7462 /* harmony default export */ const esm_browser_stringify = (stringify);
7463 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/v4.js
7464
7465
7466
7467 function v4(options, buf, offset) {
7468 options = options || {};
7469 var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
7470
7471 rnds[6] = rnds[6] & 0x0f | 0x40;
7472 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
7473
7474 if (buf) {
7475 offset = offset || 0;
7476
7477 for (var i = 0; i < 16; ++i) {
7478 buf[offset + i] = rnds[i];
7479 }
7480
7481 return buf;
7482 }
7483
7484 return esm_browser_stringify(rnds);
7485 }
7486
7487 /* harmony default export */ const esm_browser_v4 = (v4);
7488 ;// CONCATENATED MODULE: external ["wp","hooks"]
7489 const external_wp_hooks_namespaceObject = window["wp"]["hooks"];
7490 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/factory.js
7491 /**
7492 * External dependencies
7493 */
7494
7495 /**
7496 * WordPress dependencies
7497 */
7498
7499
7500 /**
7501 * Internal dependencies
7502 */
7503
7504
7505
7506 /**
7507 * Returns a block object given its type and attributes.
7508 *
7509 * @param {string} name Block name.
7510 * @param {Object} attributes Block attributes.
7511 * @param {?Array} innerBlocks Nested blocks.
7512 *
7513 * @return {Object} Block object.
7514 */
7515
7516 function createBlock(name, attributes = {}, innerBlocks = []) {
7517 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, attributes);
7518
7519 const clientId = esm_browser_v4(); // Blocks are stored with a unique ID, the assigned type name, the block
7520 // attributes, and their inner blocks.
7521
7522 return {
7523 clientId,
7524 name,
7525 isValid: true,
7526 attributes: sanitizedAttributes,
7527 innerBlocks
7528 };
7529 }
7530 /**
7531 * Given an array of InnerBlocks templates or Block Objects,
7532 * returns an array of created Blocks from them.
7533 * It handles the case of having InnerBlocks as Blocks by
7534 * converting them to the proper format to continue recursively.
7535 *
7536 * @param {Array} innerBlocksOrTemplate Nested blocks or InnerBlocks templates.
7537 *
7538 * @return {Object[]} Array of Block objects.
7539 */
7540
7541 function createBlocksFromInnerBlocksTemplate(innerBlocksOrTemplate = []) {
7542 return innerBlocksOrTemplate.map(innerBlock => {
7543 const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [innerBlock.name, innerBlock.attributes, innerBlock.innerBlocks];
7544 const [name, attributes, innerBlocks = []] = innerBlockTemplate;
7545 return createBlock(name, attributes, createBlocksFromInnerBlocksTemplate(innerBlocks));
7546 });
7547 }
7548 /**
7549 * Given a block object, returns a copy of the block object while sanitizing its attributes,
7550 * optionally merging new attributes and/or replacing its inner blocks.
7551 *
7552 * @param {Object} block Block instance.
7553 * @param {Object} mergeAttributes Block attributes.
7554 * @param {?Array} newInnerBlocks Nested blocks.
7555 *
7556 * @return {Object} A cloned block.
7557 */
7558
7559 function __experimentalCloneSanitizedBlock(block, mergeAttributes = {}, newInnerBlocks) {
7560 const clientId = esm_browser_v4();
7561
7562 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(block.name, { ...block.attributes,
7563 ...mergeAttributes
7564 });
7565
7566 return { ...block,
7567 clientId,
7568 attributes: sanitizedAttributes,
7569 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => __experimentalCloneSanitizedBlock(innerBlock))
7570 };
7571 }
7572 /**
7573 * Given a block object, returns a copy of the block object,
7574 * optionally merging new attributes and/or replacing its inner blocks.
7575 *
7576 * @param {Object} block Block instance.
7577 * @param {Object} mergeAttributes Block attributes.
7578 * @param {?Array} newInnerBlocks Nested blocks.
7579 *
7580 * @return {Object} A cloned block.
7581 */
7582
7583 function cloneBlock(block, mergeAttributes = {}, newInnerBlocks) {
7584 const clientId = esm_browser_v4();
7585 return { ...block,
7586 clientId,
7587 attributes: { ...block.attributes,
7588 ...mergeAttributes
7589 },
7590 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => cloneBlock(innerBlock))
7591 };
7592 }
7593 /**
7594 * Returns a boolean indicating whether a transform is possible based on
7595 * various bits of context.
7596 *
7597 * @param {Object} transform The transform object to validate.
7598 * @param {string} direction Is this a 'from' or 'to' transform.
7599 * @param {Array} blocks The blocks to transform from.
7600 *
7601 * @return {boolean} Is the transform possible?
7602 */
7603
7604 const isPossibleTransformForSource = (transform, direction, blocks) => {
7605 if (!blocks.length) {
7606 return false;
7607 } // If multiple blocks are selected, only multi block transforms
7608 // or wildcard transforms are allowed.
7609
7610
7611 const isMultiBlock = blocks.length > 1;
7612 const firstBlockName = blocks[0].name;
7613 const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
7614
7615 if (!isValidForMultiBlocks) {
7616 return false;
7617 } // Check non-wildcard transforms to ensure that transform is valid
7618 // for a block selection of multiple blocks of different types.
7619
7620
7621 if (!isWildcardBlockTransform(transform) && !blocks.every(block => block.name === firstBlockName)) {
7622 return false;
7623 } // Only consider 'block' type transforms as valid.
7624
7625
7626 const isBlockType = transform.type === 'block';
7627
7628 if (!isBlockType) {
7629 return false;
7630 } // Check if the transform's block name matches the source block (or is a wildcard)
7631 // only if this is a transform 'from'.
7632
7633
7634 const sourceBlock = blocks[0];
7635 const hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
7636
7637 if (!hasMatchingName) {
7638 return false;
7639 } // Don't allow single Grouping blocks to be transformed into
7640 // a Grouping block.
7641
7642
7643 if (!isMultiBlock && direction === 'from' && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
7644 return false;
7645 } // If the transform has a `isMatch` function specified, check that it returns true.
7646
7647
7648 if (!maybeCheckTransformIsMatch(transform, blocks)) {
7649 return false;
7650 }
7651
7652 return true;
7653 };
7654 /**
7655 * Returns block types that the 'blocks' can be transformed into, based on
7656 * 'from' transforms on other blocks.
7657 *
7658 * @param {Array} blocks The blocks to transform from.
7659 *
7660 * @return {Array} Block types that the blocks can be transformed into.
7661 */
7662
7663
7664 const getBlockTypesForPossibleFromTransforms = blocks => {
7665 if (!blocks.length) {
7666 return [];
7667 }
7668
7669 const allBlockTypes = getBlockTypes(); // filter all blocks to find those with a 'from' transform.
7670
7671 const blockTypesWithPossibleFromTransforms = allBlockTypes.filter(blockType => {
7672 const fromTransforms = getBlockTransforms('from', blockType.name);
7673 return !!findTransform(fromTransforms, transform => {
7674 return isPossibleTransformForSource(transform, 'from', blocks);
7675 });
7676 });
7677 return blockTypesWithPossibleFromTransforms;
7678 };
7679 /**
7680 * Returns block types that the 'blocks' can be transformed into, based on
7681 * the source block's own 'to' transforms.
7682 *
7683 * @param {Array} blocks The blocks to transform from.
7684 *
7685 * @return {Array} Block types that the source can be transformed into.
7686 */
7687
7688
7689 const getBlockTypesForPossibleToTransforms = blocks => {
7690 if (!blocks.length) {
7691 return [];
7692 }
7693
7694 const sourceBlock = blocks[0];
7695 const blockType = getBlockType(sourceBlock.name);
7696 const transformsTo = blockType ? getBlockTransforms('to', blockType.name) : []; // filter all 'to' transforms to find those that are possible.
7697
7698 const possibleTransforms = transformsTo.filter(transform => {
7699 return transform && isPossibleTransformForSource(transform, 'to', blocks);
7700 }); // Build a list of block names using the possible 'to' transforms.
7701
7702 const blockNames = possibleTransforms.map(transformation => transformation.blocks).flat(); // Map block names to block types.
7703
7704 return blockNames.map(getBlockType);
7705 };
7706 /**
7707 * Determines whether transform is a "block" type
7708 * and if so whether it is a "wildcard" transform
7709 * ie: targets "any" block type
7710 *
7711 * @param {Object} t the Block transform object
7712 *
7713 * @return {boolean} whether transform is a wildcard transform
7714 */
7715
7716
7717 const isWildcardBlockTransform = t => t && t.type === 'block' && Array.isArray(t.blocks) && t.blocks.includes('*');
7718 /**
7719 * Determines whether the given Block is the core Block which
7720 * acts as a container Block for other Blocks as part of the
7721 * Grouping mechanics
7722 *
7723 * @param {string} name the name of the Block to test against
7724 *
7725 * @return {boolean} whether or not the Block is the container Block type
7726 */
7727
7728 const isContainerGroupBlock = name => name === getGroupingBlockName();
7729 /**
7730 * Returns an array of block types that the set of blocks received as argument
7731 * can be transformed into.
7732 *
7733 * @param {Array} blocks Blocks array.
7734 *
7735 * @return {Array} Block types that the blocks argument can be transformed to.
7736 */
7737
7738 function getPossibleBlockTransformations(blocks) {
7739 if (!blocks.length) {
7740 return [];
7741 }
7742
7743 const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
7744 const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
7745 return [...new Set([...blockTypesForFromTransforms, ...blockTypesForToTransforms])];
7746 }
7747 /**
7748 * Given an array of transforms, returns the highest-priority transform where
7749 * the predicate function returns a truthy value. A higher-priority transform
7750 * is one with a lower priority value (i.e. first in priority order). Returns
7751 * null if the transforms set is empty or the predicate function returns a
7752 * falsey value for all entries.
7753 *
7754 * @param {Object[]} transforms Transforms to search.
7755 * @param {Function} predicate Function returning true on matching transform.
7756 *
7757 * @return {?Object} Highest-priority transform candidate.
7758 */
7759
7760 function findTransform(transforms, predicate) {
7761 // The hooks library already has built-in mechanisms for managing priority
7762 // queue, so leverage via locally-defined instance.
7763 const hooks = (0,external_wp_hooks_namespaceObject.createHooks)();
7764
7765 for (let i = 0; i < transforms.length; i++) {
7766 const candidate = transforms[i];
7767
7768 if (predicate(candidate)) {
7769 hooks.addFilter('transform', 'transform/' + i.toString(), result => result ? result : candidate, candidate.priority);
7770 }
7771 } // Filter name is arbitrarily chosen but consistent with above aggregation.
7772
7773
7774 return hooks.applyFilters('transform', null);
7775 }
7776 /**
7777 * Returns normal block transforms for a given transform direction, optionally
7778 * for a specific block by name, or an empty array if there are no transforms.
7779 * If no block name is provided, returns transforms for all blocks. A normal
7780 * transform object includes `blockName` as a property.
7781 *
7782 * @param {string} direction Transform direction ("to", "from").
7783 * @param {string|Object} blockTypeOrName Block type or name.
7784 *
7785 * @return {Array} Block transforms for direction.
7786 */
7787
7788 function getBlockTransforms(direction, blockTypeOrName) {
7789 // When retrieving transforms for all block types, recurse into self.
7790 if (blockTypeOrName === undefined) {
7791 return getBlockTypes().map(({
7792 name
7793 }) => getBlockTransforms(direction, name)).flat();
7794 } // Validate that block type exists and has array of direction.
7795
7796
7797 const blockType = normalizeBlockType(blockTypeOrName);
7798 const {
7799 name: blockName,
7800 transforms
7801 } = blockType || {};
7802
7803 if (!transforms || !Array.isArray(transforms[direction])) {
7804 return [];
7805 }
7806
7807 const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
7808 const filteredTransforms = usingMobileTransformations ? transforms[direction].filter(t => {
7809 if (t.type === 'raw') {
7810 return true;
7811 }
7812
7813 if (!t.blocks || !t.blocks.length) {
7814 return false;
7815 }
7816
7817 if (isWildcardBlockTransform(t)) {
7818 return true;
7819 }
7820
7821 return t.blocks.every(transformBlockName => transforms.supportedMobileTransforms.includes(transformBlockName));
7822 }) : transforms[direction]; // Map transforms to normal form.
7823
7824 return filteredTransforms.map(transform => ({ ...transform,
7825 blockName,
7826 usingMobileTransformations
7827 }));
7828 }
7829 /**
7830 * Checks that a given transforms isMatch method passes for given source blocks.
7831 *
7832 * @param {Object} transform A transform object.
7833 * @param {Array} blocks Blocks array.
7834 *
7835 * @return {boolean} True if given blocks are a match for the transform.
7836 */
7837
7838 function maybeCheckTransformIsMatch(transform, blocks) {
7839 if (typeof transform.isMatch !== 'function') {
7840 return true;
7841 }
7842
7843 const sourceBlock = blocks[0];
7844 const attributes = transform.isMultiBlock ? blocks.map(block => block.attributes) : sourceBlock.attributes;
7845 const block = transform.isMultiBlock ? blocks : sourceBlock;
7846 return transform.isMatch(attributes, block);
7847 }
7848 /**
7849 * Switch one or more blocks into one or more blocks of the new block type.
7850 *
7851 * @param {Array|Object} blocks Blocks array or block object.
7852 * @param {string} name Block name.
7853 *
7854 * @return {?Array} Array of blocks or null.
7855 */
7856
7857
7858 function switchToBlockType(blocks, name) {
7859 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
7860 const isMultiBlock = blocksArray.length > 1;
7861 const firstBlock = blocksArray[0];
7862 const sourceName = firstBlock.name; // Find the right transformation by giving priority to the "to"
7863 // transformation.
7864
7865 const transformationsFrom = getBlockTransforms('from', name);
7866 const transformationsTo = getBlockTransforms('to', sourceName);
7867 const transformation = findTransform(transformationsTo, t => t.type === 'block' && (isWildcardBlockTransform(t) || t.blocks.indexOf(name) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)) || findTransform(transformationsFrom, t => t.type === 'block' && (isWildcardBlockTransform(t) || t.blocks.indexOf(sourceName) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)); // Stop if there is no valid transformation.
7868
7869 if (!transformation) {
7870 return null;
7871 }
7872
7873 let transformationResults;
7874
7875 if (transformation.isMultiBlock) {
7876 if ('__experimentalConvert' in transformation) {
7877 transformationResults = transformation.__experimentalConvert(blocksArray);
7878 } else {
7879 transformationResults = transformation.transform(blocksArray.map(currentBlock => currentBlock.attributes), blocksArray.map(currentBlock => currentBlock.innerBlocks));
7880 }
7881 } else if ('__experimentalConvert' in transformation) {
7882 transformationResults = transformation.__experimentalConvert(firstBlock);
7883 } else {
7884 transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
7885 } // Ensure that the transformation function returned an object or an array
7886 // of objects.
7887
7888
7889 if (transformationResults === null || typeof transformationResults !== 'object') {
7890 return null;
7891 } // If the transformation function returned a single object, we want to work
7892 // with an array instead.
7893
7894
7895 transformationResults = Array.isArray(transformationResults) ? transformationResults : [transformationResults]; // Ensure that every block object returned by the transformation has a
7896 // valid block type.
7897
7898 if (transformationResults.some(result => !getBlockType(result.name))) {
7899 return null;
7900 }
7901
7902 const hasSwitchedBlock = transformationResults.some(result => result.name === name); // Ensure that at least one block object returned by the transformation has
7903 // the expected "destination" block type.
7904
7905 if (!hasSwitchedBlock) {
7906 return null;
7907 }
7908
7909 const ret = transformationResults.map((result, index, results) => {
7910 /**
7911 * Filters an individual transform result from block transformation.
7912 * All of the original blocks are passed, since transformations are
7913 * many-to-many, not one-to-one.
7914 *
7915 * @param {Object} transformedBlock The transformed block.
7916 * @param {Object[]} blocks Original blocks transformed.
7917 * @param {Object[]} index Index of the transformed block on the array of results.
7918 * @param {Object[]} results An array all the blocks that resulted from the transformation.
7919 */
7920 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.switchToBlockType.transformedBlock', result, blocks, index, results);
7921 });
7922 return ret;
7923 }
7924 /**
7925 * Create a block object from the example API.
7926 *
7927 * @param {string} name
7928 * @param {Object} example
7929 *
7930 * @return {Object} block.
7931 */
7932
7933 const getBlockFromExample = (name, example) => {
7934 var _example$innerBlocks;
7935
7936 return createBlock(name, example.attributes, ((_example$innerBlocks = example.innerBlocks) !== null && _example$innerBlocks !== void 0 ? _example$innerBlocks : []).map(innerBlock => getBlockFromExample(innerBlock.name, innerBlock)));
7937 };
7938
7939 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/utils.js
7940 /**
7941 * External dependencies
7942 */
7943
7944
7945
7946 /**
7947 * WordPress dependencies
7948 */
7949
7950
7951
7952
7953 /**
7954 * Internal dependencies
7955 */
7956
7957
7958
7959
7960 k([names, a11y]);
7961 /**
7962 * Array of icon colors containing a color to be used if the icon color
7963 * was not explicitly set but the icon background color was.
7964 *
7965 * @type {Object}
7966 */
7967
7968 const ICON_COLORS = ['#191e23', '#f8f9f9'];
7969 /**
7970 * Determines whether the block's attributes are equal to the default attributes
7971 * which means the block is unmodified.
7972 *
7973 * @param {WPBlock} block Block Object
7974 *
7975 * @return {boolean} Whether the block is an unmodified block.
7976 */
7977
7978 function isUnmodifiedBlock(block) {
7979 var _blockType$attributes;
7980
7981 // Cache a created default block if no cache exists or the default block
7982 // name changed.
7983 if (!isUnmodifiedBlock[block.name]) {
7984 isUnmodifiedBlock[block.name] = createBlock(block.name);
7985 }
7986
7987 const newBlock = isUnmodifiedBlock[block.name];
7988 const blockType = getBlockType(block.name);
7989 return Object.keys((_blockType$attributes = blockType?.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}).every(key => newBlock.attributes[key] === block.attributes[key]);
7990 }
7991 /**
7992 * Determines whether the block is a default block and its attributes are equal
7993 * to the default attributes which means the block is unmodified.
7994 *
7995 * @param {WPBlock} block Block Object
7996 *
7997 * @return {boolean} Whether the block is an unmodified default block.
7998 */
7999
8000 function isUnmodifiedDefaultBlock(block) {
8001 return block.name === getDefaultBlockName() && isUnmodifiedBlock(block);
8002 }
8003 /**
8004 * Function that checks if the parameter is a valid icon.
8005 *
8006 * @param {*} icon Parameter to be checked.
8007 *
8008 * @return {boolean} True if the parameter is a valid icon and false otherwise.
8009 */
8010
8011 function isValidIcon(icon) {
8012 return !!icon && (typeof icon === 'string' || (0,external_wp_element_namespaceObject.isValidElement)(icon) || typeof icon === 'function' || icon instanceof external_wp_element_namespaceObject.Component);
8013 }
8014 /**
8015 * Function that receives an icon as set by the blocks during the registration
8016 * and returns a new icon object that is normalized so we can rely on just on possible icon structure
8017 * in the codebase.
8018 *
8019 * @param {WPBlockTypeIconRender} icon Render behavior of a block type icon;
8020 * one of a Dashicon slug, an element, or a
8021 * component.
8022 *
8023 * @return {WPBlockTypeIconDescriptor} Object describing the icon.
8024 */
8025
8026 function normalizeIconObject(icon) {
8027 icon = icon || BLOCK_ICON_DEFAULT;
8028
8029 if (isValidIcon(icon)) {
8030 return {
8031 src: icon
8032 };
8033 }
8034
8035 if ('background' in icon) {
8036 const colordBgColor = w(icon.background);
8037
8038 const getColorContrast = iconColor => colordBgColor.contrast(iconColor);
8039
8040 const maxContrast = Math.max(...ICON_COLORS.map(getColorContrast));
8041 return { ...icon,
8042 foreground: icon.foreground ? icon.foreground : ICON_COLORS.find(iconColor => getColorContrast(iconColor) === maxContrast),
8043 shadowColor: colordBgColor.alpha(0.3).toRgbString()
8044 };
8045 }
8046
8047 return icon;
8048 }
8049 /**
8050 * Normalizes block type passed as param. When string is passed then
8051 * it converts it to the matching block type object.
8052 * It passes the original object otherwise.
8053 *
8054 * @param {string|Object} blockTypeOrName Block type or name.
8055 *
8056 * @return {?Object} Block type.
8057 */
8058
8059 function normalizeBlockType(blockTypeOrName) {
8060 if (typeof blockTypeOrName === 'string') {
8061 return getBlockType(blockTypeOrName);
8062 }
8063
8064 return blockTypeOrName;
8065 }
8066 /**
8067 * Get the label for the block, usually this is either the block title,
8068 * or the value of the block's `label` function when that's specified.
8069 *
8070 * @param {Object} blockType The block type.
8071 * @param {Object} attributes The values of the block's attributes.
8072 * @param {Object} context The intended use for the label.
8073 *
8074 * @return {string} The block label.
8075 */
8076
8077 function getBlockLabel(blockType, attributes, context = 'visual') {
8078 const {
8079 __experimentalLabel: getLabel,
8080 title
8081 } = blockType;
8082 const label = getLabel && getLabel(attributes, {
8083 context
8084 });
8085
8086 if (!label) {
8087 return title;
8088 } // Strip any HTML (i.e. RichText formatting) before returning.
8089
8090
8091 return (0,external_wp_dom_namespaceObject.__unstableStripHTML)(label);
8092 }
8093 /**
8094 * Get a label for the block for use by screenreaders, this is more descriptive
8095 * than the visual label and includes the block title and the value of the
8096 * `getLabel` function if it's specified.
8097 *
8098 * @param {?Object} blockType The block type.
8099 * @param {Object} attributes The values of the block's attributes.
8100 * @param {?number} position The position of the block in the block list.
8101 * @param {string} [direction='vertical'] The direction of the block layout.
8102 *
8103 * @return {string} The block label.
8104 */
8105
8106 function getAccessibleBlockLabel(blockType, attributes, position, direction = 'vertical') {
8107 // `title` is already localized, `label` is a user-supplied value.
8108 const title = blockType?.title;
8109 const label = blockType ? getBlockLabel(blockType, attributes, 'accessibility') : '';
8110 const hasPosition = position !== undefined; // getBlockLabel returns the block title as a fallback when there's no label,
8111 // if it did return the title, this function needs to avoid adding the
8112 // title twice within the accessible label. Use this `hasLabel` boolean to
8113 // handle that.
8114
8115 const hasLabel = label && label !== title;
8116
8117 if (hasPosition && direction === 'vertical') {
8118 if (hasLabel) {
8119 return (0,external_wp_i18n_namespaceObject.sprintf)(
8120 /* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */
8121 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d. %3$s'), title, position, label);
8122 }
8123
8124 return (0,external_wp_i18n_namespaceObject.sprintf)(
8125 /* translators: accessibility text. 1: The block title. 2: The block row number. */
8126 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d'), title, position);
8127 } else if (hasPosition && direction === 'horizontal') {
8128 if (hasLabel) {
8129 return (0,external_wp_i18n_namespaceObject.sprintf)(
8130 /* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */
8131 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d. %3$s'), title, position, label);
8132 }
8133
8134 return (0,external_wp_i18n_namespaceObject.sprintf)(
8135 /* translators: accessibility text. 1: The block title. 2: The block column number. */
8136 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d'), title, position);
8137 }
8138
8139 if (hasLabel) {
8140 return (0,external_wp_i18n_namespaceObject.sprintf)(
8141 /* translators: accessibility text. %1: The block title. %2: The block label. */
8142 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. %2$s'), title, label);
8143 }
8144
8145 return (0,external_wp_i18n_namespaceObject.sprintf)(
8146 /* translators: accessibility text. %s: The block title. */
8147 (0,external_wp_i18n_namespaceObject.__)('%s Block'), title);
8148 }
8149 /**
8150 * Ensure attributes contains only values defined by block type, and merge
8151 * default values for missing attributes.
8152 *
8153 * @param {string} name The block's name.
8154 * @param {Object} attributes The block's attributes.
8155 * @return {Object} The sanitized attributes.
8156 */
8157
8158 function __experimentalSanitizeBlockAttributes(name, attributes) {
8159 // Get the type definition associated with a registered block.
8160 const blockType = getBlockType(name);
8161
8162 if (undefined === blockType) {
8163 throw new Error(`Block type '${name}' is not registered.`);
8164 }
8165
8166 return Object.entries(blockType.attributes).reduce((accumulator, [key, schema]) => {
8167 const value = attributes[key];
8168
8169 if (undefined !== value) {
8170 accumulator[key] = value;
8171 } else if (schema.hasOwnProperty('default')) {
8172 accumulator[key] = schema.default;
8173 }
8174
8175 if (['node', 'children'].indexOf(schema.source) !== -1) {
8176 // Ensure value passed is always an array, which we're expecting in
8177 // the RichText component to handle the deprecated value.
8178 if (typeof accumulator[key] === 'string') {
8179 accumulator[key] = [accumulator[key]];
8180 } else if (!Array.isArray(accumulator[key])) {
8181 accumulator[key] = [];
8182 }
8183 }
8184
8185 return accumulator;
8186 }, {});
8187 }
8188 /**
8189 * Filter block attributes by `role` and return their names.
8190 *
8191 * @param {string} name Block attribute's name.
8192 * @param {string} role The role of a block attribute.
8193 *
8194 * @return {string[]} The attribute names that have the provided role.
8195 */
8196
8197 function __experimentalGetBlockAttributesNamesByRole(name, role) {
8198 const attributes = getBlockType(name)?.attributes;
8199 if (!attributes) return [];
8200 const attributesNames = Object.keys(attributes);
8201 if (!role) return attributesNames;
8202 return attributesNames.filter(attributeName => attributes[attributeName]?.__experimentalRole === role);
8203 }
8204 /**
8205 * Return a new object with the specified keys omitted.
8206 *
8207 * @param {Object} object Original object.
8208 * @param {Array} keys Keys to be omitted.
8209 *
8210 * @return {Object} Object with omitted keys.
8211 */
8212
8213 function omit(object, keys) {
8214 return Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key)));
8215 }
8216
8217 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/reducer.js
8218 /**
8219 * WordPress dependencies
8220 */
8221
8222
8223 /**
8224 * Internal dependencies
8225 */
8226
8227
8228 /**
8229 * @typedef {Object} WPBlockCategory
8230 *
8231 * @property {string} slug Unique category slug.
8232 * @property {string} title Category label, for display in user interface.
8233 */
8234
8235 /**
8236 * Default set of categories.
8237 *
8238 * @type {WPBlockCategory[]}
8239 */
8240
8241 const DEFAULT_CATEGORIES = [{
8242 slug: 'text',
8243 title: (0,external_wp_i18n_namespaceObject.__)('Text')
8244 }, {
8245 slug: 'media',
8246 title: (0,external_wp_i18n_namespaceObject.__)('Media')
8247 }, {
8248 slug: 'design',
8249 title: (0,external_wp_i18n_namespaceObject.__)('Design')
8250 }, {
8251 slug: 'widgets',
8252 title: (0,external_wp_i18n_namespaceObject.__)('Widgets')
8253 }, {
8254 slug: 'theme',
8255 title: (0,external_wp_i18n_namespaceObject.__)('Theme')
8256 }, {
8257 slug: 'embed',
8258 title: (0,external_wp_i18n_namespaceObject.__)('Embeds')
8259 }, {
8260 slug: 'reusable',
8261 title: (0,external_wp_i18n_namespaceObject.__)('Reusable blocks')
8262 }]; // Key block types by their name.
8263
8264 function keyBlockTypesByName(types) {
8265 return types.reduce((newBlockTypes, block) => ({ ...newBlockTypes,
8266 [block.name]: block
8267 }), {});
8268 } // Filter items to ensure they're unique by their name.
8269
8270
8271 function getUniqueItemsByName(items) {
8272 return items.reduce((acc, currentItem) => {
8273 if (!acc.some(item => item.name === currentItem.name)) {
8274 acc.push(currentItem);
8275 }
8276
8277 return acc;
8278 }, []);
8279 }
8280 /**
8281 * Reducer managing the unprocessed block types in a form passed when registering the by block.
8282 * It's for internal use only. It allows recomputing the processed block types on-demand after block type filters
8283 * get added or removed.
8284 *
8285 * @param {Object} state Current state.
8286 * @param {Object} action Dispatched action.
8287 *
8288 * @return {Object} Updated state.
8289 */
8290
8291
8292 function unprocessedBlockTypes(state = {}, action) {
8293 switch (action.type) {
8294 case 'ADD_UNPROCESSED_BLOCK_TYPE':
8295 return { ...state,
8296 [action.blockType.name]: action.blockType
8297 };
8298
8299 case 'REMOVE_BLOCK_TYPES':
8300 return omit(state, action.names);
8301 }
8302
8303 return state;
8304 }
8305 /**
8306 * Reducer managing the processed block types with all filters applied.
8307 * The state is derived from the `unprocessedBlockTypes` reducer.
8308 *
8309 * @param {Object} state Current state.
8310 * @param {Object} action Dispatched action.
8311 *
8312 * @return {Object} Updated state.
8313 */
8314
8315 function blockTypes(state = {}, action) {
8316 switch (action.type) {
8317 case 'ADD_BLOCK_TYPES':
8318 return { ...state,
8319 ...keyBlockTypesByName(action.blockTypes)
8320 };
8321
8322 case 'REMOVE_BLOCK_TYPES':
8323 return omit(state, action.names);
8324 }
8325
8326 return state;
8327 }
8328 /**
8329 * Reducer managing the block styles.
8330 *
8331 * @param {Object} state Current state.
8332 * @param {Object} action Dispatched action.
8333 *
8334 * @return {Object} Updated state.
8335 */
8336
8337 function blockStyles(state = {}, action) {
8338 var _state$action$blockNa, _state$action$blockNa2;
8339
8340 switch (action.type) {
8341 case 'ADD_BLOCK_TYPES':
8342 return { ...state,
8343 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8344 var _blockType$styles, _state$blockType$name;
8345
8346 return [name, getUniqueItemsByName([...((_blockType$styles = blockType.styles) !== null && _blockType$styles !== void 0 ? _blockType$styles : []).map(style => ({ ...style,
8347 source: 'block'
8348 })), ...((_state$blockType$name = state[blockType.name]) !== null && _state$blockType$name !== void 0 ? _state$blockType$name : []).filter(({
8349 source
8350 }) => 'block' !== source)])];
8351 }))
8352 };
8353
8354 case 'ADD_BLOCK_STYLES':
8355 return { ...state,
8356 [action.blockName]: getUniqueItemsByName([...((_state$action$blockNa = state[action.blockName]) !== null && _state$action$blockNa !== void 0 ? _state$action$blockNa : []), ...action.styles])
8357 };
8358
8359 case 'REMOVE_BLOCK_STYLES':
8360 return { ...state,
8361 [action.blockName]: ((_state$action$blockNa2 = state[action.blockName]) !== null && _state$action$blockNa2 !== void 0 ? _state$action$blockNa2 : []).filter(style => action.styleNames.indexOf(style.name) === -1)
8362 };
8363 }
8364
8365 return state;
8366 }
8367 /**
8368 * Reducer managing the block variations.
8369 *
8370 * @param {Object} state Current state.
8371 * @param {Object} action Dispatched action.
8372 *
8373 * @return {Object} Updated state.
8374 */
8375
8376 function blockVariations(state = {}, action) {
8377 var _state$action$blockNa3, _state$action$blockNa4;
8378
8379 switch (action.type) {
8380 case 'ADD_BLOCK_TYPES':
8381 return { ...state,
8382 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8383 var _blockType$variations, _state$blockType$name2;
8384
8385 return [name, getUniqueItemsByName([...((_blockType$variations = blockType.variations) !== null && _blockType$variations !== void 0 ? _blockType$variations : []).map(variation => ({ ...variation,
8386 source: 'block'
8387 })), ...((_state$blockType$name2 = state[blockType.name]) !== null && _state$blockType$name2 !== void 0 ? _state$blockType$name2 : []).filter(({
8388 source
8389 }) => 'block' !== source)])];
8390 }))
8391 };
8392
8393 case 'ADD_BLOCK_VARIATIONS':
8394 return { ...state,
8395 [action.blockName]: getUniqueItemsByName([...((_state$action$blockNa3 = state[action.blockName]) !== null && _state$action$blockNa3 !== void 0 ? _state$action$blockNa3 : []), ...action.variations])
8396 };
8397
8398 case 'REMOVE_BLOCK_VARIATIONS':
8399 return { ...state,
8400 [action.blockName]: ((_state$action$blockNa4 = state[action.blockName]) !== null && _state$action$blockNa4 !== void 0 ? _state$action$blockNa4 : []).filter(variation => action.variationNames.indexOf(variation.name) === -1)
8401 };
8402 }
8403
8404 return state;
8405 }
8406 /**
8407 * Higher-order Reducer creating a reducer keeping track of given block name.
8408 *
8409 * @param {string} setActionType Action type.
8410 *
8411 * @return {Function} Reducer.
8412 */
8413
8414 function createBlockNameSetterReducer(setActionType) {
8415 return (state = null, action) => {
8416 switch (action.type) {
8417 case 'REMOVE_BLOCK_TYPES':
8418 if (action.names.indexOf(state) !== -1) {
8419 return null;
8420 }
8421
8422 return state;
8423
8424 case setActionType:
8425 return action.name || null;
8426 }
8427
8428 return state;
8429 };
8430 }
8431 const defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
8432 const freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
8433 const unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
8434 const groupingBlockName = createBlockNameSetterReducer('SET_GROUPING_BLOCK_NAME');
8435 /**
8436 * Reducer managing the categories
8437 *
8438 * @param {WPBlockCategory[]} state Current state.
8439 * @param {Object} action Dispatched action.
8440 *
8441 * @return {WPBlockCategory[]} Updated state.
8442 */
8443
8444 function categories(state = DEFAULT_CATEGORIES, action) {
8445 switch (action.type) {
8446 case 'SET_CATEGORIES':
8447 return action.categories || [];
8448
8449 case 'UPDATE_CATEGORY':
8450 {
8451 if (!action.category || !Object.keys(action.category).length) {
8452 return state;
8453 }
8454
8455 const categoryToChange = state.find(({
8456 slug
8457 }) => slug === action.slug);
8458
8459 if (categoryToChange) {
8460 return state.map(category => {
8461 if (category.slug === action.slug) {
8462 return { ...category,
8463 ...action.category
8464 };
8465 }
8466
8467 return category;
8468 });
8469 }
8470 }
8471 }
8472
8473 return state;
8474 }
8475 function collections(state = {}, action) {
8476 switch (action.type) {
8477 case 'ADD_BLOCK_COLLECTION':
8478 return { ...state,
8479 [action.namespace]: {
8480 title: action.title,
8481 icon: action.icon
8482 }
8483 };
8484
8485 case 'REMOVE_BLOCK_COLLECTION':
8486 return omit(state, action.namespace);
8487 }
8488
8489 return state;
8490 }
8491 /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
8492 unprocessedBlockTypes,
8493 blockTypes,
8494 blockStyles,
8495 blockVariations,
8496 defaultBlockName,
8497 freeformFallbackBlockName,
8498 unregisteredFallbackBlockName,
8499 groupingBlockName,
8500 categories,
8501 collections
8502 }));
8503
8504 ;// CONCATENATED MODULE: ./node_modules/rememo/rememo.js
8505
8506
8507 /** @typedef {(...args: any[]) => *[]} GetDependants */
8508
8509 /** @typedef {() => void} Clear */
8510
8511 /**
8512 * @typedef {{
8513 * getDependants: GetDependants,
8514 * clear: Clear
8515 * }} EnhancedSelector
8516 */
8517
8518 /**
8519 * Internal cache entry.
8520 *
8521 * @typedef CacheNode
8522 *
8523 * @property {?CacheNode|undefined} [prev] Previous node.
8524 * @property {?CacheNode|undefined} [next] Next node.
8525 * @property {*[]} args Function arguments for cache entry.
8526 * @property {*} val Function result.
8527 */
8528
8529 /**
8530 * @typedef Cache
8531 *
8532 * @property {Clear} clear Function to clear cache.
8533 * @property {boolean} [isUniqueByDependants] Whether dependants are valid in
8534 * considering cache uniqueness. A cache is unique if dependents are all arrays
8535 * or objects.
8536 * @property {CacheNode?} [head] Cache head.
8537 * @property {*[]} [lastDependants] Dependants from previous invocation.
8538 */
8539
8540 /**
8541 * Arbitrary value used as key for referencing cache object in WeakMap tree.
8542 *
8543 * @type {{}}
8544 */
8545 var LEAF_KEY = {};
8546
8547 /**
8548 * Returns the first argument as the sole entry in an array.
8549 *
8550 * @template T
8551 *
8552 * @param {T} value Value to return.
8553 *
8554 * @return {[T]} Value returned as entry in array.
8555 */
8556 function arrayOf(value) {
8557 return [value];
8558 }
8559
8560 /**
8561 * Returns true if the value passed is object-like, or false otherwise. A value
8562 * is object-like if it can support property assignment, e.g. object or array.
8563 *
8564 * @param {*} value Value to test.
8565 *
8566 * @return {boolean} Whether value is object-like.
8567 */
8568 function isObjectLike(value) {
8569 return !!value && 'object' === typeof value;
8570 }
8571
8572 /**
8573 * Creates and returns a new cache object.
8574 *
8575 * @return {Cache} Cache object.
8576 */
8577 function createCache() {
8578 /** @type {Cache} */
8579 var cache = {
8580 clear: function () {
8581 cache.head = null;
8582 },
8583 };
8584
8585 return cache;
8586 }
8587
8588 /**
8589 * Returns true if entries within the two arrays are strictly equal by
8590 * reference from a starting index.
8591 *
8592 * @param {*[]} a First array.
8593 * @param {*[]} b Second array.
8594 * @param {number} fromIndex Index from which to start comparison.
8595 *
8596 * @return {boolean} Whether arrays are shallowly equal.
8597 */
8598 function isShallowEqual(a, b, fromIndex) {
8599 var i;
8600
8601 if (a.length !== b.length) {
8602 return false;
8603 }
8604
8605 for (i = fromIndex; i < a.length; i++) {
8606 if (a[i] !== b[i]) {
8607 return false;
8608 }
8609 }
8610
8611 return true;
8612 }
8613
8614 /**
8615 * Returns a memoized selector function. The getDependants function argument is
8616 * called before the memoized selector and is expected to return an immutable
8617 * reference or array of references on which the selector depends for computing
8618 * its own return value. The memoize cache is preserved only as long as those
8619 * dependant references remain the same. If getDependants returns a different
8620 * reference(s), the cache is cleared and the selector value regenerated.
8621 *
8622 * @template {(...args: *[]) => *} S
8623 *
8624 * @param {S} selector Selector function.
8625 * @param {GetDependants=} getDependants Dependant getter returning an array of
8626 * references used in cache bust consideration.
8627 */
8628 /* harmony default export */ function rememo(selector, getDependants) {
8629 /** @type {WeakMap<*,*>} */
8630 var rootCache;
8631
8632 /** @type {GetDependants} */
8633 var normalizedGetDependants = getDependants ? getDependants : arrayOf;
8634
8635 /**
8636 * Returns the cache for a given dependants array. When possible, a WeakMap
8637 * will be used to create a unique cache for each set of dependants. This
8638 * is feasible due to the nature of WeakMap in allowing garbage collection
8639 * to occur on entries where the key object is no longer referenced. Since
8640 * WeakMap requires the key to be an object, this is only possible when the
8641 * dependant is object-like. The root cache is created as a hierarchy where
8642 * each top-level key is the first entry in a dependants set, the value a
8643 * WeakMap where each key is the next dependant, and so on. This continues
8644 * so long as the dependants are object-like. If no dependants are object-
8645 * like, then the cache is shared across all invocations.
8646 *
8647 * @see isObjectLike
8648 *
8649 * @param {*[]} dependants Selector dependants.
8650 *
8651 * @return {Cache} Cache object.
8652 */
8653 function getCache(dependants) {
8654 var caches = rootCache,
8655 isUniqueByDependants = true,
8656 i,
8657 dependant,
8658 map,
8659 cache;
8660
8661 for (i = 0; i < dependants.length; i++) {
8662 dependant = dependants[i];
8663
8664 // Can only compose WeakMap from object-like key.
8665 if (!isObjectLike(dependant)) {
8666 isUniqueByDependants = false;
8667 break;
8668 }
8669
8670 // Does current segment of cache already have a WeakMap?
8671 if (caches.has(dependant)) {
8672 // Traverse into nested WeakMap.
8673 caches = caches.get(dependant);
8674 } else {
8675 // Create, set, and traverse into a new one.
8676 map = new WeakMap();
8677 caches.set(dependant, map);
8678 caches = map;
8679 }
8680 }
8681
8682 // We use an arbitrary (but consistent) object as key for the last item
8683 // in the WeakMap to serve as our running cache.
8684 if (!caches.has(LEAF_KEY)) {
8685 cache = createCache();
8686 cache.isUniqueByDependants = isUniqueByDependants;
8687 caches.set(LEAF_KEY, cache);
8688 }
8689
8690 return caches.get(LEAF_KEY);
8691 }
8692
8693 /**
8694 * Resets root memoization cache.
8695 */
8696 function clear() {
8697 rootCache = new WeakMap();
8698 }
8699
8700 /* eslint-disable jsdoc/check-param-names */
8701 /**
8702 * The augmented selector call, considering first whether dependants have
8703 * changed before passing it to underlying memoize function.
8704 *
8705 * @param {*} source Source object for derivation.
8706 * @param {...*} extraArgs Additional arguments to pass to selector.
8707 *
8708 * @return {*} Selector result.
8709 */
8710 /* eslint-enable jsdoc/check-param-names */
8711 function callSelector(/* source, ...extraArgs */) {
8712 var len = arguments.length,
8713 cache,
8714 node,
8715 i,
8716 args,
8717 dependants;
8718
8719 // Create copy of arguments (avoid leaking deoptimization).
8720 args = new Array(len);
8721 for (i = 0; i < len; i++) {
8722 args[i] = arguments[i];
8723 }
8724
8725 dependants = normalizedGetDependants.apply(null, args);
8726 cache = getCache(dependants);
8727
8728 // If not guaranteed uniqueness by dependants (primitive type), shallow
8729 // compare against last dependants and, if references have changed,
8730 // destroy cache to recalculate result.
8731 if (!cache.isUniqueByDependants) {
8732 if (
8733 cache.lastDependants &&
8734 !isShallowEqual(dependants, cache.lastDependants, 0)
8735 ) {
8736 cache.clear();
8737 }
8738
8739 cache.lastDependants = dependants;
8740 }
8741
8742 node = cache.head;
8743 while (node) {
8744 // Check whether node arguments match arguments
8745 if (!isShallowEqual(node.args, args, 1)) {
8746 node = node.next;
8747 continue;
8748 }
8749
8750 // At this point we can assume we've found a match
8751
8752 // Surface matched node to head if not already
8753 if (node !== cache.head) {
8754 // Adjust siblings to point to each other.
8755 /** @type {CacheNode} */ (node.prev).next = node.next;
8756 if (node.next) {
8757 node.next.prev = node.prev;
8758 }
8759
8760 node.next = cache.head;
8761 node.prev = null;
8762 /** @type {CacheNode} */ (cache.head).prev = node;
8763 cache.head = node;
8764 }
8765
8766 // Return immediately
8767 return node.val;
8768 }
8769
8770 // No cached value found. Continue to insertion phase:
8771
8772 node = /** @type {CacheNode} */ ({
8773 // Generate the result from original function
8774 val: selector.apply(null, args),
8775 });
8776
8777 // Avoid including the source object in the cache.
8778 args[0] = null;
8779 node.args = args;
8780
8781 // Don't need to check whether node is already head, since it would
8782 // have been returned above already if it was
8783
8784 // Shift existing head down list
8785 if (cache.head) {
8786 cache.head.prev = node;
8787 node.next = cache.head;
8788 }
8789
8790 cache.head = node;
8791
8792 return node.val;
8793 }
8794
8795 callSelector.getDependants = normalizedGetDependants;
8796 callSelector.clear = clear;
8797 clear();
8798
8799 return /** @type {S & EnhancedSelector} */ (callSelector);
8800 }
8801
8802 // EXTERNAL MODULE: ./node_modules/remove-accents/index.js
8803 var remove_accents = __webpack_require__(4793);
8804 var remove_accents_default = /*#__PURE__*/__webpack_require__.n(remove_accents);
8805 ;// CONCATENATED MODULE: external ["wp","compose"]
8806 const external_wp_compose_namespaceObject = window["wp"]["compose"];
8807 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/utils.js
8808 /**
8809 * Helper util to return a value from a certain path of the object.
8810 * Path is specified as either:
8811 * - a string of properties, separated by dots, for example: "x.y".
8812 * - an array of properties, for example `[ 'x', 'y' ]`.
8813 * You can also specify a default value in case the result is nullish.
8814 *
8815 * @param {Object} object Input object.
8816 * @param {string|Array} path Path to the object property.
8817 * @param {*} defaultValue Default value if the value at the specified path is nullish.
8818 * @return {*} Value of the object property at the specified path.
8819 */
8820 const getValueFromObjectPath = (object, path, defaultValue) => {
8821 var _value;
8822
8823 const normalizedPath = Array.isArray(path) ? path : path.split('.');
8824 let value = object;
8825 normalizedPath.forEach(fieldName => {
8826 value = value?.[fieldName];
8827 });
8828 return (_value = value) !== null && _value !== void 0 ? _value : defaultValue;
8829 };
8830
8831 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/selectors.js
8832 /**
8833 * External dependencies
8834 */
8835
8836
8837 /**
8838 * WordPress dependencies
8839 */
8840
8841
8842 /**
8843 * Internal dependencies
8844 */
8845
8846
8847 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
8848
8849 /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
8850
8851 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
8852
8853 /**
8854 * Given a block name or block type object, returns the corresponding
8855 * normalized block type object.
8856 *
8857 * @param {Object} state Blocks state.
8858 * @param {(string|Object)} nameOrType Block name or type object
8859 *
8860 * @return {Object} Block type object.
8861 */
8862
8863 const getNormalizedBlockType = (state, nameOrType) => 'string' === typeof nameOrType ? selectors_getBlockType(state, nameOrType) : nameOrType;
8864 /**
8865 * Returns all the unprocessed block types as passed during the registration.
8866 *
8867 * @param {Object} state Data state.
8868 *
8869 * @return {Array} Unprocessed block types.
8870 */
8871
8872
8873 function __experimentalGetUnprocessedBlockTypes(state) {
8874 return state.unprocessedBlockTypes;
8875 }
8876 /**
8877 * Returns all the available block types.
8878 *
8879 * @param {Object} state Data state.
8880 *
8881 * @example
8882 * ```js
8883 * import { store as blocksStore } from '@wordpress/blocks';
8884 * import { useSelect } from '@wordpress/data';
8885 *
8886 * const ExampleComponent = () => {
8887 * const blockTypes = useSelect(
8888 * ( select ) => select( blocksStore ).getBlockTypes(),
8889 * []
8890 * );
8891 *
8892 * return (
8893 * <ul>
8894 * { blockTypes.map( ( block ) => (
8895 * <li key={ block.name }>{ block.title }</li>
8896 * ) ) }
8897 * </ul>
8898 * );
8899 * };
8900 * ```
8901 *
8902 * @return {Array} Block Types.
8903 */
8904
8905 const selectors_getBlockTypes = rememo(state => Object.values(state.blockTypes), state => [state.blockTypes]);
8906 /**
8907 * Returns a block type by name.
8908 *
8909 * @param {Object} state Data state.
8910 * @param {string} name Block type name.
8911 *
8912 * @example
8913 * ```js
8914 * import { store as blocksStore } from '@wordpress/blocks';
8915 * import { useSelect } from '@wordpress/data';
8916 *
8917 * const ExampleComponent = () => {
8918 * const paragraphBlock = useSelect( ( select ) =>
8919 * ( select ) => select( blocksStore ).getBlockType( 'core/paragraph' ),
8920 * []
8921 * );
8922 *
8923 * return (
8924 * <ul>
8925 * { paragraphBlock &&
8926 * Object.entries( paragraphBlock.supports ).map(
8927 * ( blockSupportsEntry ) => {
8928 * const [ propertyName, value ] = blockSupportsEntry;
8929 * return (
8930 * <li
8931 * key={ propertyName }
8932 * >{ `${ propertyName } : ${ value }` }</li>
8933 * );
8934 * }
8935 * ) }
8936 * </ul>
8937 * );
8938 * };
8939 * ```
8940 *
8941 * @return {Object?} Block Type.
8942 */
8943
8944 function selectors_getBlockType(state, name) {
8945 return state.blockTypes[name];
8946 }
8947 /**
8948 * Returns block styles by block name.
8949 *
8950 * @param {Object} state Data state.
8951 * @param {string} name Block type name.
8952 *
8953 * @example
8954 * ```js
8955 * import { store as blocksStore } from '@wordpress/blocks';
8956 * import { useSelect } from '@wordpress/data';
8957 *
8958 * const ExampleComponent = () => {
8959 * const buttonBlockStyles = useSelect( ( select ) =>
8960 * select( blocksStore ).getBlockStyles( 'core/button' ),
8961 * []
8962 * );
8963 *
8964 * return (
8965 * <ul>
8966 * { buttonBlockStyles &&
8967 * buttonBlockStyles.map( ( style ) => (
8968 * <li key={ style.name }>{ style.label }</li>
8969 * ) ) }
8970 * </ul>
8971 * );
8972 * };
8973 * ```
8974 *
8975 * @return {Array?} Block Styles.
8976 */
8977
8978 function getBlockStyles(state, name) {
8979 return state.blockStyles[name];
8980 }
8981 /**
8982 * Returns block variations by block name.
8983 *
8984 * @param {Object} state Data state.
8985 * @param {string} blockName Block type name.
8986 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8987 *
8988 * @example
8989 * ```js
8990 * import { store as blocksStore } from '@wordpress/blocks';
8991 * import { useSelect } from '@wordpress/data';
8992 *
8993 * const ExampleComponent = () => {
8994 * const socialLinkVariations = useSelect( ( select ) =>
8995 * select( blocksStore ).getBlockVariations( 'core/social-link' ),
8996 * []
8997 * );
8998 *
8999 * return (
9000 * <ul>
9001 * { socialLinkVariations &&
9002 * socialLinkVariations.map( ( variation ) => (
9003 * <li key={ variation.name }>{ variation.title }</li>
9004 * ) ) }
9005 * </ul>
9006 * );
9007 * };
9008 * ```
9009 *
9010 * @return {(WPBlockVariation[]|void)} Block variations.
9011 */
9012
9013 const selectors_getBlockVariations = rememo((state, blockName, scope) => {
9014 const variations = state.blockVariations[blockName];
9015
9016 if (!variations || !scope) {
9017 return variations;
9018 }
9019
9020 return variations.filter(variation => {
9021 // For backward compatibility reasons, variation's scope defaults to
9022 // `block` and `inserter` when not set.
9023 return (variation.scope || ['block', 'inserter']).includes(scope);
9024 });
9025 }, (state, blockName) => [state.blockVariations[blockName]]);
9026 /**
9027 * Returns the active block variation for a given block based on its attributes.
9028 * Variations are determined by their `isActive` property.
9029 * Which is either an array of block attribute keys or a function.
9030 *
9031 * In case of an array of block attribute keys, the `attributes` are compared
9032 * to the variation's attributes using strict equality check.
9033 *
9034 * In case of function type, the function should accept a block's attributes
9035 * and the variation's attributes and determines if a variation is active.
9036 * A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
9037 *
9038 * @param {Object} state Data state.
9039 * @param {string} blockName Name of block (example: “core/columns”).
9040 * @param {Object} attributes Block attributes used to determine active variation.
9041 * @param {WPBlockVariationScope} [scope] Block variation scope name.
9042 *
9043 * @example
9044 * ```js
9045 * import { __ } from '@wordpress/i18n';
9046 * import { store as blocksStore } from '@wordpress/blocks';
9047 * import { store as blockEditorStore } from '@wordpress/block-editor';
9048 * import { useSelect } from '@wordpress/data';
9049 *
9050 * const ExampleComponent = () => {
9051 * // This example assumes that a core/embed block is the first block in the Block Editor.
9052 * const activeBlockVariation = useSelect( ( select ) => {
9053 * // Retrieve the list of blocks.
9054 * const [ firstBlock ] = select( blockEditorStore ).getBlocks()
9055 *
9056 * // Return the active block variation for the first block.
9057 * return select( blocksStore ).getActiveBlockVariation(
9058 * firstBlock.name,
9059 * firstBlock.attributes
9060 * );
9061 * }, [] );
9062 *
9063 * return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
9064 * <p>{ __( 'Spotify variation' ) }</p>
9065 * ) : (
9066 * <p>{ __( 'Other variation' ) }</p>
9067 * );
9068 * };
9069 * ```
9070 *
9071 * @return {(WPBlockVariation|undefined)} Active block variation.
9072 */
9073
9074 function getActiveBlockVariation(state, blockName, attributes, scope) {
9075 const variations = selectors_getBlockVariations(state, blockName, scope);
9076 const match = variations?.find(variation => {
9077 if (Array.isArray(variation.isActive)) {
9078 const blockType = selectors_getBlockType(state, blockName);
9079 const attributeKeys = Object.keys(blockType?.attributes || {});
9080 const definedAttributes = variation.isActive.filter(attribute => attributeKeys.includes(attribute));
9081
9082 if (definedAttributes.length === 0) {
9083 return false;
9084 }
9085
9086 return definedAttributes.every(attribute => attributes[attribute] === variation.attributes[attribute]);
9087 }
9088
9089 return variation.isActive?.(attributes, variation.attributes);
9090 });
9091 return match;
9092 }
9093 /**
9094 * Returns the default block variation for the given block type.
9095 * When there are multiple variations annotated as the default one,
9096 * the last added item is picked. This simplifies registering overrides.
9097 * When there is no default variation set, it returns the first item.
9098 *
9099 * @param {Object} state Data state.
9100 * @param {string} blockName Block type name.
9101 * @param {WPBlockVariationScope} [scope] Block variation scope name.
9102 *
9103 * @example
9104 * ```js
9105 * import { __, sprintf } from '@wordpress/i18n';
9106 * import { store as blocksStore } from '@wordpress/blocks';
9107 * import { useSelect } from '@wordpress/data';
9108 *
9109 * const ExampleComponent = () => {
9110 * const defaultEmbedBlockVariation = useSelect( ( select ) =>
9111 * select( blocksStore ).getDefaultBlockVariation( 'core/embed' ),
9112 * []
9113 * );
9114 *
9115 * return (
9116 * defaultEmbedBlockVariation && (
9117 * <p>
9118 * { sprintf(
9119 * __( 'core/embed default variation: %s' ),
9120 * defaultEmbedBlockVariation.title
9121 * ) }
9122 * </p>
9123 * )
9124 * );
9125 * };
9126 * ```
9127 *
9128 * @return {?WPBlockVariation} The default block variation.
9129 */
9130
9131 function getDefaultBlockVariation(state, blockName, scope) {
9132 const variations = selectors_getBlockVariations(state, blockName, scope);
9133 const defaultVariation = [...variations].reverse().find(({
9134 isDefault
9135 }) => !!isDefault);
9136 return defaultVariation || variations[0];
9137 }
9138 /**
9139 * Returns all the available block categories.
9140 *
9141 * @param {Object} state Data state.
9142 *
9143 * @example
9144 * ```js
9145 * import { store as blocksStore } from '@wordpress/blocks';
9146 * import { useSelect, } from '@wordpress/data';
9147 *
9148 * const ExampleComponent = () => {
9149 * const blockCategories = useSelect( ( select ) =>
9150 * select( blocksStore ).getCategories(),
9151 * []
9152 * );
9153 *
9154 * return (
9155 * <ul>
9156 * { blockCategories.map( ( category ) => (
9157 * <li key={ category.slug }>{ category.title }</li>
9158 * ) ) }
9159 * </ul>
9160 * );
9161 * };
9162 * ```
9163 *
9164 * @return {WPBlockCategory[]} Categories list.
9165 */
9166
9167 function getCategories(state) {
9168 return state.categories;
9169 }
9170 /**
9171 * Returns all the available collections.
9172 *
9173 * @param {Object} state Data state.
9174 *
9175 * @example
9176 * ```js
9177 * import { store as blocksStore } from '@wordpress/blocks';
9178 * import { useSelect } from '@wordpress/data';
9179 *
9180 * const ExampleComponent = () => {
9181 * const blockCollections = useSelect( ( select ) =>
9182 * select( blocksStore ).getCollections(),
9183 * []
9184 * );
9185 *
9186 * return (
9187 * <ul>
9188 * { Object.values( blockCollections ).length > 0 &&
9189 * Object.values( blockCollections ).map( ( collection ) => (
9190 * <li key={ collection.title }>{ collection.title }</li>
9191 * ) ) }
9192 * </ul>
9193 * );
9194 * };
9195 * ```
9196 *
9197 * @return {Object} Collections list.
9198 */
9199
9200 function getCollections(state) {
9201 return state.collections;
9202 }
9203 /**
9204 * Returns the name of the default block name.
9205 *
9206 * @param {Object} state Data state.
9207 *
9208 * @example
9209 * ```js
9210 * import { __, sprintf } from '@wordpress/i18n';
9211 * import { store as blocksStore } from '@wordpress/blocks';
9212 * import { useSelect } from '@wordpress/data';
9213 *
9214 * const ExampleComponent = () => {
9215 * const defaultBlockName = useSelect( ( select ) =>
9216 * select( blocksStore ).getDefaultBlockName(),
9217 * []
9218 * );
9219 *
9220 * return (
9221 * defaultBlockName && (
9222 * <p>
9223 * { sprintf( __( 'Default block name: %s' ), defaultBlockName ) }
9224 * </p>
9225 * )
9226 * );
9227 * };
9228 * ```
9229 *
9230 * @return {string?} Default block name.
9231 */
9232
9233 function selectors_getDefaultBlockName(state) {
9234 return state.defaultBlockName;
9235 }
9236 /**
9237 * Returns the name of the block for handling non-block content.
9238 *
9239 * @param {Object} state Data state.
9240 *
9241 * @example
9242 * ```js
9243 * import { __, sprintf } from '@wordpress/i18n';
9244 * import { store as blocksStore } from '@wordpress/blocks';
9245 * import { useSelect } from '@wordpress/data';
9246 *
9247 * const ExampleComponent = () => {
9248 * const freeformFallbackBlockName = useSelect( ( select ) =>
9249 * select( blocksStore ).getFreeformFallbackBlockName(),
9250 * []
9251 * );
9252 *
9253 * return (
9254 * freeformFallbackBlockName && (
9255 * <p>
9256 * { sprintf( __(
9257 * 'Freeform fallback block name: %s' ),
9258 * freeformFallbackBlockName
9259 * ) }
9260 * </p>
9261 * )
9262 * );
9263 * };
9264 * ```
9265 *
9266 * @return {string?} Name of the block for handling non-block content.
9267 */
9268
9269 function getFreeformFallbackBlockName(state) {
9270 return state.freeformFallbackBlockName;
9271 }
9272 /**
9273 * Returns the name of the block for handling unregistered blocks.
9274 *
9275 * @param {Object} state Data state.
9276 *
9277 * @example
9278 * ```js
9279 * import { __, sprintf } from '@wordpress/i18n';
9280 * import { store as blocksStore } from '@wordpress/blocks';
9281 * import { useSelect } from '@wordpress/data';
9282 *
9283 * const ExampleComponent = () => {
9284 * const unregisteredFallbackBlockName = useSelect( ( select ) =>
9285 * select( blocksStore ).getUnregisteredFallbackBlockName(),
9286 * []
9287 * );
9288 *
9289 * return (
9290 * unregisteredFallbackBlockName && (
9291 * <p>
9292 * { sprintf( __(
9293 * 'Unregistered fallback block name: %s' ),
9294 * unregisteredFallbackBlockName
9295 * ) }
9296 * </p>
9297 * )
9298 * );
9299 * };
9300 * ```
9301 *
9302 * @return {string?} Name of the block for handling unregistered blocks.
9303 */
9304
9305 function getUnregisteredFallbackBlockName(state) {
9306 return state.unregisteredFallbackBlockName;
9307 }
9308 /**
9309 * Returns the name of the block for handling the grouping of blocks.
9310 *
9311 * @param {Object} state Data state.
9312 *
9313 * @example
9314 * ```js
9315 * import { __, sprintf } from '@wordpress/i18n';
9316 * import { store as blocksStore } from '@wordpress/blocks';
9317 * import { useSelect } from '@wordpress/data';
9318 *
9319 * const ExampleComponent = () => {
9320 * const groupingBlockName = useSelect( ( select ) =>
9321 * select( blocksStore ).getGroupingBlockName(),
9322 * []
9323 * );
9324 *
9325 * return (
9326 * groupingBlockName && (
9327 * <p>
9328 * { sprintf(
9329 * __( 'Default grouping block name: %s' ),
9330 * groupingBlockName
9331 * ) }
9332 * </p>
9333 * )
9334 * );
9335 * };
9336 * ```
9337 *
9338 * @return {string?} Name of the block for handling the grouping of blocks.
9339 */
9340
9341 function selectors_getGroupingBlockName(state) {
9342 return state.groupingBlockName;
9343 }
9344 /**
9345 * Returns an array with the child blocks of a given block.
9346 *
9347 * @param {Object} state Data state.
9348 * @param {string} blockName Block type name.
9349 *
9350 * @example
9351 * ```js
9352 * import { store as blocksStore } from '@wordpress/blocks';
9353 * import { useSelect } from '@wordpress/data';
9354 *
9355 * const ExampleComponent = () => {
9356 * const childBlockNames = useSelect( ( select ) =>
9357 * select( blocksStore ).getChildBlockNames( 'core/navigation' ),
9358 * []
9359 * );
9360 *
9361 * return (
9362 * <ul>
9363 * { childBlockNames &&
9364 * childBlockNames.map( ( child ) => (
9365 * <li key={ child }>{ child }</li>
9366 * ) ) }
9367 * </ul>
9368 * );
9369 * };
9370 * ```
9371 *
9372 * @return {Array} Array of child block names.
9373 */
9374
9375 const selectors_getChildBlockNames = rememo((state, blockName) => {
9376 return selectors_getBlockTypes(state).filter(blockType => {
9377 return blockType.parent?.includes(blockName);
9378 }).map(({
9379 name
9380 }) => name);
9381 }, state => [state.blockTypes]);
9382 /**
9383 * Returns the block support value for a feature, if defined.
9384 *
9385 * @param {Object} state Data state.
9386 * @param {(string|Object)} nameOrType Block name or type object
9387 * @param {Array|string} feature Feature to retrieve
9388 * @param {*} defaultSupports Default value to return if not
9389 * explicitly defined
9390 *
9391 * @example
9392 * ```js
9393 * import { __, sprintf } from '@wordpress/i18n';
9394 * import { store as blocksStore } from '@wordpress/blocks';
9395 * import { useSelect } from '@wordpress/data';
9396 *
9397 * const ExampleComponent = () => {
9398 * const paragraphBlockSupportValue = useSelect( ( select ) =>
9399 * select( blocksStore ).getBlockSupport( 'core/paragraph', 'anchor' ),
9400 * []
9401 * );
9402 *
9403 * return (
9404 * <p>
9405 * { sprintf(
9406 * __( 'core/paragraph supports.anchor value: %s' ),
9407 * paragraphBlockSupportValue
9408 * ) }
9409 * </p>
9410 * );
9411 * };
9412 * ```
9413 *
9414 * @return {?*} Block support value
9415 */
9416
9417 const selectors_getBlockSupport = (state, nameOrType, feature, defaultSupports) => {
9418 const blockType = getNormalizedBlockType(state, nameOrType);
9419
9420 if (!blockType?.supports) {
9421 return defaultSupports;
9422 }
9423
9424 return getValueFromObjectPath(blockType.supports, feature, defaultSupports);
9425 };
9426 /**
9427 * Returns true if the block defines support for a feature, or false otherwise.
9428 *
9429 * @param {Object} state Data state.
9430 * @param {(string|Object)} nameOrType Block name or type object.
9431 * @param {string} feature Feature to test.
9432 * @param {boolean} defaultSupports Whether feature is supported by
9433 * default if not explicitly defined.
9434 *
9435 * @example
9436 * ```js
9437 * import { __, sprintf } from '@wordpress/i18n';
9438 * import { store as blocksStore } from '@wordpress/blocks';
9439 * import { useSelect } from '@wordpress/data';
9440 *
9441 * const ExampleComponent = () => {
9442 * const paragraphBlockSupportClassName = useSelect( ( select ) =>
9443 * select( blocksStore ).hasBlockSupport( 'core/paragraph', 'className' ),
9444 * []
9445 * );
9446 *
9447 * return (
9448 * <p>
9449 * { sprintf(
9450 * __( 'core/paragraph supports custom class name?: %s' ),
9451 * paragraphBlockSupportClassName
9452 * ) }
9453 * /p>
9454 * );
9455 * };
9456 * ```
9457 *
9458 * @return {boolean} Whether block supports feature.
9459 */
9460
9461 function selectors_hasBlockSupport(state, nameOrType, feature, defaultSupports) {
9462 return !!selectors_getBlockSupport(state, nameOrType, feature, defaultSupports);
9463 }
9464 /**
9465 * Returns true if the block type by the given name or object value matches a
9466 * search term, or false otherwise.
9467 *
9468 * @param {Object} state Blocks state.
9469 * @param {(string|Object)} nameOrType Block name or type object.
9470 * @param {string} searchTerm Search term by which to filter.
9471 *
9472 * @example
9473 * ```js
9474 * import { __, sprintf } from '@wordpress/i18n';
9475 * import { store as blocksStore } from '@wordpress/blocks';
9476 * import { useSelect } from '@wordpress/data';
9477 *
9478 * const ExampleComponent = () => {
9479 * const termFound = useSelect(
9480 * ( select ) =>
9481 * select( blocksStore ).isMatchingSearchTerm(
9482 * 'core/navigation',
9483 * 'theme'
9484 * ),
9485 * []
9486 * );
9487 *
9488 * return (
9489 * <p>
9490 * { sprintf(
9491 * __(
9492 * 'Search term was found in the title, keywords, category or description in block.json: %s'
9493 * ),
9494 * termFound
9495 * ) }
9496 * </p>
9497 * );
9498 * };
9499 * ```
9500 *
9501 * @return {Object[]} Whether block type matches search term.
9502 */
9503
9504 function isMatchingSearchTerm(state, nameOrType, searchTerm) {
9505 const blockType = getNormalizedBlockType(state, nameOrType);
9506 const getNormalizedSearchTerm = (0,external_wp_compose_namespaceObject.pipe)([// Disregard diacritics.
9507 // Input: "média"
9508 term => remove_accents_default()(term !== null && term !== void 0 ? term : ''), // Lowercase.
9509 // Input: "MEDIA"
9510 term => term.toLowerCase(), // Strip leading and trailing whitespace.
9511 // Input: " media "
9512 term => term.trim()]);
9513 const normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
9514 const isSearchMatch = (0,external_wp_compose_namespaceObject.pipe)([getNormalizedSearchTerm, normalizedCandidate => normalizedCandidate.includes(normalizedSearchTerm)]);
9515 return isSearchMatch(blockType.title) || blockType.keywords?.some(isSearchMatch) || isSearchMatch(blockType.category) || typeof blockType.description === 'string' && isSearchMatch(blockType.description);
9516 }
9517 /**
9518 * Returns a boolean indicating if a block has child blocks or not.
9519 *
9520 * @param {Object} state Data state.
9521 * @param {string} blockName Block type name.
9522 *
9523 * @example
9524 * ```js
9525 * import { __, sprintf } from '@wordpress/i18n';
9526 * import { store as blocksStore } from '@wordpress/blocks';
9527 * import { useSelect } from '@wordpress/data';
9528 *
9529 * const ExampleComponent = () => {
9530 * const navigationBlockHasChildBlocks = useSelect( ( select ) =>
9531 * select( blocksStore ).hasChildBlocks( 'core/navigation' ),
9532 * []
9533 * );
9534 *
9535 * return (
9536 * <p>
9537 * { sprintf(
9538 * __( 'core/navigation has child blocks: %s' ),
9539 * navigationBlockHasChildBlocks
9540 * ) }
9541 * </p>
9542 * );
9543 * };
9544 * ```
9545 *
9546 * @return {boolean} True if a block contains child blocks and false otherwise.
9547 */
9548
9549 const selectors_hasChildBlocks = (state, blockName) => {
9550 return selectors_getChildBlockNames(state, blockName).length > 0;
9551 };
9552 /**
9553 * Returns a boolean indicating if a block has at least one child block with inserter support.
9554 *
9555 * @param {Object} state Data state.
9556 * @param {string} blockName Block type name.
9557 *
9558 * @example
9559 * ```js
9560 * import { __, sprintf } from '@wordpress/i18n';
9561 * import { store as blocksStore } from '@wordpress/blocks';
9562 * import { useSelect } from '@wordpress/data';
9563 *
9564 * const ExampleComponent = () => {
9565 * const navigationBlockHasChildBlocksWithInserterSupport = useSelect( ( select ) =>
9566 * select( blocksStore ).hasChildBlocksWithInserterSupport(
9567 * 'core/navigation'
9568 * ),
9569 * []
9570 * );
9571 *
9572 * return (
9573 * <p>
9574 * { sprintf(
9575 * __( 'core/navigation has child blocks with inserter support: %s' ),
9576 * navigationBlockHasChildBlocksWithInserterSupport
9577 * ) }
9578 * </p>
9579 * );
9580 * };
9581 * ```
9582 *
9583 * @return {boolean} True if a block contains at least one child blocks with inserter support
9584 * and false otherwise.
9585 */
9586
9587 const selectors_hasChildBlocksWithInserterSupport = (state, blockName) => {
9588 return selectors_getChildBlockNames(state, blockName).some(childBlockName => {
9589 return selectors_hasBlockSupport(state, childBlockName, 'inserter', true);
9590 });
9591 };
9592 /**
9593 * DO-NOT-USE in production.
9594 * This selector is created for internal/experimental only usage and may be
9595 * removed anytime without any warning, causing breakage on any plugin or theme invoking it.
9596 */
9597
9598 const __experimentalHasContentRoleAttribute = rememo((state, blockTypeName) => {
9599 const blockType = selectors_getBlockType(state, blockTypeName);
9600
9601 if (!blockType) {
9602 return false;
9603 }
9604
9605 return Object.entries(blockType.attributes).some(([, {
9606 __experimentalRole
9607 }]) => __experimentalRole === 'content');
9608 }, (state, blockTypeName) => [state.blockTypes[blockTypeName]?.attributes]);
9609
9610 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/private-selectors.js
9611 /**
9612 * External dependencies
9613 */
9614
9615 /**
9616 * Internal dependencies
9617 */
9618
9619
9620
9621
9622 const ROOT_BLOCK_SUPPORTS = ['background', 'backgroundColor', 'color', 'linkColor', 'captionColor', 'buttonColor', 'headingColor', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'lineHeight', 'padding', 'contentSize', 'wideSize', 'blockGap', 'textDecoration', 'textTransform', 'letterSpacing'];
9623 /**
9624 * Filters the list of supported styles for a given element.
9625 *
9626 * @param {string[]} blockSupports list of supported styles.
9627 * @param {string|undefined} name block name.
9628 * @param {string|undefined} element element name.
9629 *
9630 * @return {string[]} filtered list of supported styles.
9631 */
9632
9633 function filterElementBlockSupports(blockSupports, name, element) {
9634 return blockSupports.filter(support => {
9635 if (support === 'fontSize' && element === 'heading') {
9636 return false;
9637 } // This is only available for links
9638
9639
9640 if (support === 'textDecoration' && !name && element !== 'link') {
9641 return false;
9642 } // This is only available for heading
9643
9644
9645 if (support === 'textTransform' && !name && !['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element)) {
9646 return false;
9647 } // This is only available for headings
9648
9649
9650 if (support === 'letterSpacing' && !name && !['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element)) {
9651 return false;
9652 } // Text columns is only available for blocks.
9653
9654
9655 if (support === 'textColumns' && !name) {
9656 return false;
9657 }
9658
9659 return true;
9660 });
9661 }
9662 /**
9663 * Returns the list of supported styles for a given block name and element.
9664 */
9665
9666
9667 const getSupportedStyles = rememo((state, name, element) => {
9668 if (!name) {
9669 return filterElementBlockSupports(ROOT_BLOCK_SUPPORTS, name, element);
9670 }
9671
9672 const blockType = selectors_getBlockType(state, name);
9673
9674 if (!blockType) {
9675 return [];
9676 }
9677
9678 const supportKeys = []; // Check for blockGap support.
9679 // Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
9680 // Also, only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied.
9681
9682 if (blockType?.supports?.spacing?.blockGap && blockType?.supports?.spacing?.__experimentalSkipSerialization !== true && !blockType?.supports?.spacing?.__experimentalSkipSerialization?.some?.(spacingType => spacingType === 'blockGap')) {
9683 supportKeys.push('blockGap');
9684 } // check for shadow support
9685
9686
9687 if (blockType?.supports?.shadow) {
9688 supportKeys.push('shadow');
9689 }
9690
9691 Object.keys(__EXPERIMENTAL_STYLE_PROPERTY).forEach(styleName => {
9692 if (!__EXPERIMENTAL_STYLE_PROPERTY[styleName].support) {
9693 return;
9694 } // Opting out means that, for certain support keys like background color,
9695 // blocks have to explicitly set the support value false. If the key is
9696 // unset, we still enable it.
9697
9698
9699 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].requiresOptOut) {
9700 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].support[0] in blockType.supports && getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support) !== false) {
9701 supportKeys.push(styleName);
9702 return;
9703 }
9704 }
9705
9706 if (getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support, false)) {
9707 supportKeys.push(styleName);
9708 }
9709 });
9710 return filterElementBlockSupports(supportKeys, name, element);
9711 }, (state, name) => [state.blockTypes[name]]);
9712
9713 ;// CONCATENATED MODULE: ./node_modules/is-plain-object/dist/is-plain-object.mjs
9714 /*!
9715 * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
9716 *
9717 * Copyright (c) 2014-2017, Jon Schlinkert.
9718 * Released under the MIT License.
9719 */
9720
9721 function is_plain_object_isObject(o) {
9722 return Object.prototype.toString.call(o) === '[object Object]';
9723 }
9724
9725 function isPlainObject(o) {
9726 var ctor,prot;
9727
9728 if (is_plain_object_isObject(o) === false) return false;
9729
9730 // If has modified constructor
9731 ctor = o.constructor;
9732 if (ctor === undefined) return true;
9733
9734 // If has modified prototype
9735 prot = ctor.prototype;
9736 if (is_plain_object_isObject(prot) === false) return false;
9737
9738 // If constructor does not have an Object-specific method
9739 if (prot.hasOwnProperty('isPrototypeOf') === false) {
9740 return false;
9741 }
9742
9743 // Most likely a plain Object
9744 return true;
9745 }
9746
9747
9748
9749 ;// CONCATENATED MODULE: external ["wp","deprecated"]
9750 const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
9751 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
9752 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/actions.js
9753 /**
9754 * External dependencies
9755 */
9756
9757 /**
9758 * WordPress dependencies
9759 */
9760
9761
9762
9763 /**
9764 * Internal dependencies
9765 */
9766
9767
9768
9769 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
9770
9771 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9772
9773 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
9774
9775 const {
9776 error,
9777 warn
9778 } = window.console;
9779 /**
9780 * Mapping of legacy category slugs to their latest normal values, used to
9781 * accommodate updates of the default set of block categories.
9782 *
9783 * @type {Record<string,string>}
9784 */
9785
9786 const LEGACY_CATEGORY_MAPPING = {
9787 common: 'text',
9788 formatting: 'text',
9789 layout: 'design'
9790 };
9791 /**
9792 * Whether the argument is a function.
9793 *
9794 * @param {*} maybeFunc The argument to check.
9795 * @return {boolean} True if the argument is a function, false otherwise.
9796 */
9797
9798 function isFunction(maybeFunc) {
9799 return typeof maybeFunc === 'function';
9800 }
9801 /**
9802 * Takes the unprocessed block type data and applies all the existing filters for the registered block type.
9803 * Next, it validates all the settings and performs additional processing to the block type definition.
9804 *
9805 * @param {WPBlockType} blockType Unprocessed block type settings.
9806 * @param {Object} thunkArgs Argument object for the thunk middleware.
9807 * @param {Function} thunkArgs.select Function to select from the store.
9808 *
9809 * @return {WPBlockType | undefined} The block, if it has been successfully registered; otherwise `undefined`.
9810 */
9811
9812
9813 const processBlockType = (blockType, {
9814 select
9815 }) => {
9816 const {
9817 name
9818 } = blockType;
9819 const settings = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', { ...blockType
9820 }, name, null);
9821
9822 if (settings.description && typeof settings.description !== 'string') {
9823 external_wp_deprecated_default()('Declaring non-string block descriptions', {
9824 since: '6.2'
9825 });
9826 }
9827
9828 if (settings.deprecated) {
9829 settings.deprecated = settings.deprecated.map(deprecation => Object.fromEntries(Object.entries( // Only keep valid deprecation keys.
9830 (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', // Merge deprecation keys with pre-filter settings
9831 // so that filters that depend on specific keys being
9832 // present don't fail.
9833 { // Omit deprecation keys here so that deprecations
9834 // can opt out of specific keys like "supports".
9835 ...omit(blockType, DEPRECATED_ENTRY_KEYS),
9836 ...deprecation
9837 }, name, deprecation)).filter(([key]) => DEPRECATED_ENTRY_KEYS.includes(key))));
9838 }
9839
9840 if (!isPlainObject(settings)) {
9841 error('Block settings must be a valid object.');
9842 return;
9843 }
9844
9845 if (!isFunction(settings.save)) {
9846 error('The "save" property must be a valid function.');
9847 return;
9848 }
9849
9850 if ('edit' in settings && !isFunction(settings.edit)) {
9851 error('The "edit" property must be a valid function.');
9852 return;
9853 } // Canonicalize legacy categories to equivalent fallback.
9854
9855
9856 if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) {
9857 settings.category = LEGACY_CATEGORY_MAPPING[settings.category];
9858 }
9859
9860 if ('category' in settings && !select.getCategories().some(({
9861 slug
9862 }) => slug === settings.category)) {
9863 warn('The block "' + name + '" is registered with an invalid category "' + settings.category + '".');
9864 delete settings.category;
9865 }
9866
9867 if (!('title' in settings) || settings.title === '') {
9868 error('The block "' + name + '" must have a title.');
9869 return;
9870 }
9871
9872 if (typeof settings.title !== 'string') {
9873 error('Block titles must be strings.');
9874 return;
9875 }
9876
9877 settings.icon = normalizeIconObject(settings.icon);
9878
9879 if (!isValidIcon(settings.icon.src)) {
9880 error('The icon passed is invalid. ' + 'The icon should be a string, an element, a function, or an object following the specifications documented in https://developer.wordpress.org/block-editor/developers/block-api/block-registration/#icon-optional');
9881 return;
9882 }
9883
9884 return settings;
9885 };
9886 /**
9887 * Returns an action object used in signalling that block types have been added.
9888 * Ignored from documentation as the recommended usage for this action through registerBlockType from @wordpress/blocks.
9889 *
9890 * @ignore
9891 *
9892 * @param {WPBlockType|WPBlockType[]} blockTypes Object or array of objects representing blocks to added.
9893 *
9894 *
9895 * @return {Object} Action object.
9896 */
9897
9898
9899 function addBlockTypes(blockTypes) {
9900 return {
9901 type: 'ADD_BLOCK_TYPES',
9902 blockTypes: Array.isArray(blockTypes) ? blockTypes : [blockTypes]
9903 };
9904 }
9905 /**
9906 * Signals that the passed block type's settings should be stored in the state.
9907 *
9908 * @param {WPBlockType} blockType Unprocessed block type settings.
9909 */
9910
9911 const __experimentalRegisterBlockType = blockType => ({
9912 dispatch,
9913 select
9914 }) => {
9915 dispatch({
9916 type: 'ADD_UNPROCESSED_BLOCK_TYPE',
9917 blockType
9918 });
9919 const processedBlockType = processBlockType(blockType, {
9920 select
9921 });
9922
9923 if (!processedBlockType) {
9924 return;
9925 }
9926
9927 dispatch.addBlockTypes(processedBlockType);
9928 };
9929 /**
9930 * Signals that all block types should be computed again.
9931 * It uses stored unprocessed block types and all the most recent list of registered filters.
9932 *
9933 * It addresses the issue where third party block filters get registered after third party blocks. A sample sequence:
9934 * 1. Filter A.
9935 * 2. Block B.
9936 * 3. Block C.
9937 * 4. Filter D.
9938 * 5. Filter E.
9939 * 6. Block F.
9940 * 7. Filter G.
9941 * In this scenario some filters would not get applied for all blocks because they are registered too late.
9942 */
9943
9944 const __experimentalReapplyBlockTypeFilters = () => ({
9945 dispatch,
9946 select
9947 }) => {
9948 const unprocessedBlockTypes = select.__experimentalGetUnprocessedBlockTypes();
9949
9950 const processedBlockTypes = Object.keys(unprocessedBlockTypes).reduce((accumulator, blockName) => {
9951 const result = processBlockType(unprocessedBlockTypes[blockName], {
9952 select
9953 });
9954
9955 if (result) {
9956 accumulator.push(result);
9957 }
9958
9959 return accumulator;
9960 }, []);
9961
9962 if (!processedBlockTypes.length) {
9963 return;
9964 }
9965
9966 dispatch.addBlockTypes(processedBlockTypes);
9967 };
9968 /**
9969 * Returns an action object used to remove a registered block type.
9970 * Ignored from documentation as the recommended usage for this action through unregisterBlockType from @wordpress/blocks.
9971 *
9972 * @ignore
9973 *
9974 * @param {string|string[]} names Block name or array of block names to be removed.
9975 *
9976 *
9977 * @return {Object} Action object.
9978 */
9979
9980 function removeBlockTypes(names) {
9981 return {
9982 type: 'REMOVE_BLOCK_TYPES',
9983 names: Array.isArray(names) ? names : [names]
9984 };
9985 }
9986 /**
9987 * Returns an action object used in signalling that new block styles have been added.
9988 * Ignored from documentation as the recommended usage for this action through registerBlockStyle from @wordpress/blocks.
9989 *
9990 * @param {string} blockName Block name.
9991 * @param {Array|Object} styles Block style object or array of block style objects.
9992 *
9993 * @ignore
9994 *
9995 * @return {Object} Action object.
9996 */
9997
9998 function addBlockStyles(blockName, styles) {
9999 return {
10000 type: 'ADD_BLOCK_STYLES',
10001 styles: Array.isArray(styles) ? styles : [styles],
10002 blockName
10003 };
10004 }
10005 /**
10006 * Returns an action object used in signalling that block styles have been removed.
10007 * Ignored from documentation as the recommended usage for this action through unregisterBlockStyle from @wordpress/blocks.
10008 *
10009 * @ignore
10010 *
10011 * @param {string} blockName Block name.
10012 * @param {Array|string} styleNames Block style names or array of block style names.
10013 *
10014 * @return {Object} Action object.
10015 */
10016
10017 function removeBlockStyles(blockName, styleNames) {
10018 return {
10019 type: 'REMOVE_BLOCK_STYLES',
10020 styleNames: Array.isArray(styleNames) ? styleNames : [styleNames],
10021 blockName
10022 };
10023 }
10024 /**
10025 * Returns an action object used in signalling that new block variations have been added.
10026 * Ignored from documentation as the recommended usage for this action through registerBlockVariation from @wordpress/blocks.
10027 *
10028 * @ignore
10029 *
10030 * @param {string} blockName Block name.
10031 * @param {WPBlockVariation|WPBlockVariation[]} variations Block variations.
10032 *
10033 * @return {Object} Action object.
10034 */
10035
10036 function addBlockVariations(blockName, variations) {
10037 return {
10038 type: 'ADD_BLOCK_VARIATIONS',
10039 variations: Array.isArray(variations) ? variations : [variations],
10040 blockName
10041 };
10042 }
10043 /**
10044 * Returns an action object used in signalling that block variations have been removed.
10045 * Ignored from documentation as the recommended usage for this action through unregisterBlockVariation from @wordpress/blocks.
10046 *
10047 * @ignore
10048 *
10049 * @param {string} blockName Block name.
10050 * @param {string|string[]} variationNames Block variation names.
10051 *
10052 * @return {Object} Action object.
10053 */
10054
10055 function removeBlockVariations(blockName, variationNames) {
10056 return {
10057 type: 'REMOVE_BLOCK_VARIATIONS',
10058 variationNames: Array.isArray(variationNames) ? variationNames : [variationNames],
10059 blockName
10060 };
10061 }
10062 /**
10063 * Returns an action object used to set the default block name.
10064 * Ignored from documentation as the recommended usage for this action through setDefaultBlockName from @wordpress/blocks.
10065 *
10066 * @ignore
10067 *
10068 * @param {string} name Block name.
10069 *
10070 * @return {Object} Action object.
10071 */
10072
10073 function actions_setDefaultBlockName(name) {
10074 return {
10075 type: 'SET_DEFAULT_BLOCK_NAME',
10076 name
10077 };
10078 }
10079 /**
10080 * Returns an action object used to set the name of the block used as a fallback
10081 * for non-block content.
10082 * Ignored from documentation as the recommended usage for this action through setFreeformContentHandlerName from @wordpress/blocks.
10083 *
10084 * @ignore
10085 *
10086 * @param {string} name Block name.
10087 *
10088 * @return {Object} Action object.
10089 */
10090
10091 function setFreeformFallbackBlockName(name) {
10092 return {
10093 type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
10094 name
10095 };
10096 }
10097 /**
10098 * Returns an action object used to set the name of the block used as a fallback
10099 * for unregistered blocks.
10100 * Ignored from documentation as the recommended usage for this action through setUnregisteredTypeHandlerName from @wordpress/blocks.
10101 *
10102 * @ignore
10103 *
10104 * @param {string} name Block name.
10105 *
10106 * @return {Object} Action object.
10107 */
10108
10109 function setUnregisteredFallbackBlockName(name) {
10110 return {
10111 type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
10112 name
10113 };
10114 }
10115 /**
10116 * Returns an action object used to set the name of the block used
10117 * when grouping other blocks
10118 * eg: in "Group/Ungroup" interactions
10119 * Ignored from documentation as the recommended usage for this action through setGroupingBlockName from @wordpress/blocks.
10120 *
10121 * @ignore
10122 *
10123 * @param {string} name Block name.
10124 *
10125 * @return {Object} Action object.
10126 */
10127
10128 function actions_setGroupingBlockName(name) {
10129 return {
10130 type: 'SET_GROUPING_BLOCK_NAME',
10131 name
10132 };
10133 }
10134 /**
10135 * Returns an action object used to set block categories.
10136 * Ignored from documentation as the recommended usage for this action through setCategories from @wordpress/blocks.
10137 *
10138 * @ignore
10139 *
10140 * @param {WPBlockCategory[]} categories Block categories.
10141 *
10142 * @return {Object} Action object.
10143 */
10144
10145 function setCategories(categories) {
10146 return {
10147 type: 'SET_CATEGORIES',
10148 categories
10149 };
10150 }
10151 /**
10152 * Returns an action object used to update a category.
10153 * Ignored from documentation as the recommended usage for this action through updateCategory from @wordpress/blocks.
10154 *
10155 * @ignore
10156 *
10157 * @param {string} slug Block category slug.
10158 * @param {Object} category Object containing the category properties that should be updated.
10159 *
10160 * @return {Object} Action object.
10161 */
10162
10163 function updateCategory(slug, category) {
10164 return {
10165 type: 'UPDATE_CATEGORY',
10166 slug,
10167 category
10168 };
10169 }
10170 /**
10171 * Returns an action object used to add block collections
10172 * Ignored from documentation as the recommended usage for this action through registerBlockCollection from @wordpress/blocks.
10173 *
10174 * @ignore
10175 *
10176 * @param {string} namespace The namespace of the blocks to put in the collection
10177 * @param {string} title The title to display in the block inserter
10178 * @param {Object} icon (optional) The icon to display in the block inserter
10179 *
10180 * @return {Object} Action object.
10181 */
10182
10183 function addBlockCollection(namespace, title, icon) {
10184 return {
10185 type: 'ADD_BLOCK_COLLECTION',
10186 namespace,
10187 title,
10188 icon
10189 };
10190 }
10191 /**
10192 * Returns an action object used to remove block collections
10193 * Ignored from documentation as the recommended usage for this action through unregisterBlockCollection from @wordpress/blocks.
10194 *
10195 * @ignore
10196 *
10197 * @param {string} namespace The namespace of the blocks to put in the collection
10198 *
10199 * @return {Object} Action object.
10200 */
10201
10202 function removeBlockCollection(namespace) {
10203 return {
10204 type: 'REMOVE_BLOCK_COLLECTION',
10205 namespace
10206 };
10207 }
10208
10209 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/constants.js
10210 const STORE_NAME = 'core/blocks';
10211
10212 ;// CONCATENATED MODULE: external ["wp","privateApis"]
10213 const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
10214 ;// CONCATENATED MODULE: ./packages/blocks/build-module/lock-unlock.js
10215 /**
10216 * WordPress dependencies
10217 */
10218
10219 const {
10220 lock,
10221 unlock
10222 } = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', '@wordpress/blocks');
10223
10224 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/index.js
10225 /**
10226 * WordPress dependencies
10227 */
10228
10229 /**
10230 * Internal dependencies
10231 */
10232
10233
10234
10235
10236
10237
10238
10239 /**
10240 * Store definition for the blocks namespace.
10241 *
10242 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
10243 *
10244 * @type {Object}
10245 */
10246
10247 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
10248 reducer: reducer,
10249 selectors: selectors_namespaceObject,
10250 actions: actions_namespaceObject
10251 });
10252 (0,external_wp_data_namespaceObject.register)(store);
10253 unlock(store).registerPrivateSelectors(private_selectors_namespaceObject);
10254
10255 ;// CONCATENATED MODULE: external ["wp","blockSerializationDefaultParser"]
10256 const external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
10257 ;// CONCATENATED MODULE: external ["wp","autop"]
10258 const external_wp_autop_namespaceObject = window["wp"]["autop"];
10259 ;// CONCATENATED MODULE: external ["wp","isShallowEqual"]
10260 const external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"];
10261 var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject);
10262 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/serialize-raw-block.js
10263 /**
10264 * Internal dependencies
10265 */
10266
10267 /**
10268 * @typedef {Object} Options Serialization options.
10269 * @property {boolean} [isCommentDelimited=true] Whether to output HTML comments around blocks.
10270 */
10271
10272 /** @typedef {import("./").WPRawBlock} WPRawBlock */
10273
10274 /**
10275 * Serializes a block node into the native HTML-comment-powered block format.
10276 * CAVEAT: This function is intended for re-serializing blocks as parsed by
10277 * valid parsers and skips any validation steps. This is NOT a generic
10278 * serialization function for in-memory blocks. For most purposes, see the
10279 * following functions available in the `@wordpress/blocks` package:
10280 *
10281 * @see serializeBlock
10282 * @see serialize
10283 *
10284 * For more on the format of block nodes as returned by valid parsers:
10285 *
10286 * @see `@wordpress/block-serialization-default-parser` package
10287 * @see `@wordpress/block-serialization-spec-parser` package
10288 *
10289 * @param {WPRawBlock} rawBlock A block node as returned by a valid parser.
10290 * @param {Options} [options={}] Serialization options.
10291 *
10292 * @return {string} An HTML string representing a block.
10293 */
10294
10295 function serializeRawBlock(rawBlock, options = {}) {
10296 const {
10297 isCommentDelimited = true
10298 } = options;
10299 const {
10300 blockName,
10301 attrs = {},
10302 innerBlocks = [],
10303 innerContent = []
10304 } = rawBlock;
10305 let childIndex = 0;
10306 const content = innerContent.map(item => // `null` denotes a nested block, otherwise we have an HTML fragment.
10307 item !== null ? item : serializeRawBlock(innerBlocks[childIndex++], options)).join('\n').replace(/\n+/g, '\n').trim();
10308 return isCommentDelimited ? getCommentDelimitedContent(blockName, attrs, content) : content;
10309 }
10310
10311 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/serializer.js
10312
10313
10314 /**
10315 * WordPress dependencies
10316 */
10317
10318
10319
10320
10321 /**
10322 * Internal dependencies
10323 */
10324
10325
10326
10327
10328 /** @typedef {import('./parser').WPBlock} WPBlock */
10329
10330 /**
10331 * @typedef {Object} WPBlockSerializationOptions Serialization Options.
10332 *
10333 * @property {boolean} isInnerBlocks Whether we are serializing inner blocks.
10334 */
10335
10336 /**
10337 * Returns the block's default classname from its name.
10338 *
10339 * @param {string} blockName The block name.
10340 *
10341 * @return {string} The block's default class.
10342 */
10343
10344 function getBlockDefaultClassName(blockName) {
10345 // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
10346 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10347 const className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10348 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockDefaultClassName', className, blockName);
10349 }
10350 /**
10351 * Returns the block's default menu item classname from its name.
10352 *
10353 * @param {string} blockName The block name.
10354 *
10355 * @return {string} The block's default menu item class.
10356 */
10357
10358 function getBlockMenuDefaultClassName(blockName) {
10359 // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
10360 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10361 const className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10362 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockMenuDefaultClassName', className, blockName);
10363 }
10364 const blockPropsProvider = {};
10365 const innerBlocksPropsProvider = {};
10366 /**
10367 * Call within a save function to get the props for the block wrapper.
10368 *
10369 * @param {Object} props Optional. Props to pass to the element.
10370 */
10371
10372 function getBlockProps(props = {}) {
10373 const {
10374 blockType,
10375 attributes
10376 } = blockPropsProvider;
10377 return getBlockProps.skipFilters ? props : (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...props
10378 }, blockType, attributes);
10379 }
10380 /**
10381 * Call within a save function to get the props for the inner blocks wrapper.
10382 *
10383 * @param {Object} props Optional. Props to pass to the element.
10384 */
10385
10386 function getInnerBlocksProps(props = {}) {
10387 const {
10388 innerBlocks
10389 } = innerBlocksPropsProvider;
10390 const [firstBlock] = innerBlocks !== null && innerBlocks !== void 0 ? innerBlocks : [];
10391 if (!firstBlock) return props; // If the innerBlocks passed to `getSaveElement` are not blocks but already
10392 // components, return the props as is. This is the case for
10393 // `getRichTextValues`.
10394
10395 if (!firstBlock.clientId) return { ...props,
10396 children: innerBlocks
10397 }; // Value is an array of blocks, so defer to block serializer.
10398
10399 const html = serialize(innerBlocks, {
10400 isInnerBlocks: true
10401 }); // Use special-cased raw HTML tag to avoid default escaping.
10402
10403 const children = (0,external_wp_element_namespaceObject.createElement)(external_wp_element_namespaceObject.RawHTML, null, html);
10404 return { ...props,
10405 children
10406 };
10407 }
10408 /**
10409 * Given a block type containing a save render implementation and attributes, returns the
10410 * enhanced element to be saved or string when raw HTML expected.
10411 *
10412 * @param {string|Object} blockTypeOrName Block type or name.
10413 * @param {Object} attributes Block attributes.
10414 * @param {?Array} innerBlocks Nested blocks.
10415 *
10416 * @return {Object|string} Save element or raw HTML string.
10417 */
10418
10419 function getSaveElement(blockTypeOrName, attributes, innerBlocks = []) {
10420 const blockType = normalizeBlockType(blockTypeOrName);
10421 if (!blockType?.save) return null;
10422 let {
10423 save
10424 } = blockType; // Component classes are unsupported for save since serialization must
10425 // occur synchronously. For improved interoperability with higher-order
10426 // components which often return component class, emulate basic support.
10427
10428 if (save.prototype instanceof external_wp_element_namespaceObject.Component) {
10429 const instance = new save({
10430 attributes
10431 });
10432 save = instance.render.bind(instance);
10433 }
10434
10435 blockPropsProvider.blockType = blockType;
10436 blockPropsProvider.attributes = attributes;
10437 innerBlocksPropsProvider.innerBlocks = innerBlocks;
10438 let element = save({
10439 attributes,
10440 innerBlocks
10441 });
10442
10443 if (element !== null && typeof element === 'object' && (0,external_wp_hooks_namespaceObject.hasFilter)('blocks.getSaveContent.extraProps') && !(blockType.apiVersion > 1)) {
10444 /**
10445 * Filters the props applied to the block save result element.
10446 *
10447 * @param {Object} props Props applied to save element.
10448 * @param {WPBlock} blockType Block type definition.
10449 * @param {Object} attributes Block attributes.
10450 */
10451 const props = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...element.props
10452 }, blockType, attributes);
10453
10454 if (!external_wp_isShallowEqual_default()(props, element.props)) {
10455 element = (0,external_wp_element_namespaceObject.cloneElement)(element, props);
10456 }
10457 }
10458 /**
10459 * Filters the save result of a block during serialization.
10460 *
10461 * @param {WPElement} element Block save result.
10462 * @param {WPBlock} blockType Block type definition.
10463 * @param {Object} attributes Block attributes.
10464 */
10465
10466
10467 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveElement', element, blockType, attributes);
10468 }
10469 /**
10470 * Given a block type containing a save render implementation and attributes, returns the
10471 * static markup to be saved.
10472 *
10473 * @param {string|Object} blockTypeOrName Block type or name.
10474 * @param {Object} attributes Block attributes.
10475 * @param {?Array} innerBlocks Nested blocks.
10476 *
10477 * @return {string} Save content.
10478 */
10479
10480 function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
10481 const blockType = normalizeBlockType(blockTypeOrName);
10482 return (0,external_wp_element_namespaceObject.renderToString)(getSaveElement(blockType, attributes, innerBlocks));
10483 }
10484 /**
10485 * Returns attributes which are to be saved and serialized into the block
10486 * comment delimiter.
10487 *
10488 * When a block exists in memory it contains as its attributes both those
10489 * parsed the block comment delimiter _and_ those which matched from the
10490 * contents of the block.
10491 *
10492 * This function returns only those attributes which are needed to persist and
10493 * which cannot be matched from the block content.
10494 *
10495 * @param {Object<string,*>} blockType Block type.
10496 * @param {Object<string,*>} attributes Attributes from in-memory block data.
10497 *
10498 * @return {Object<string,*>} Subset of attributes for comment serialization.
10499 */
10500
10501 function getCommentAttributes(blockType, attributes) {
10502 var _blockType$attributes;
10503
10504 return Object.entries((_blockType$attributes = blockType.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}).reduce((accumulator, [key, attributeSchema]) => {
10505 const value = attributes[key]; // Ignore undefined values.
10506
10507 if (undefined === value) {
10508 return accumulator;
10509 } // Ignore all attributes but the ones with an "undefined" source
10510 // "undefined" source refers to attributes saved in the block comment.
10511
10512
10513 if (attributeSchema.source !== undefined) {
10514 return accumulator;
10515 } // Ignore default value.
10516
10517
10518 if ('default' in attributeSchema && attributeSchema.default === value) {
10519 return accumulator;
10520 } // Otherwise, include in comment set.
10521
10522
10523 accumulator[key] = value;
10524 return accumulator;
10525 }, {});
10526 }
10527 /**
10528 * Given an attributes object, returns a string in the serialized attributes
10529 * format prepared for post content.
10530 *
10531 * @param {Object} attributes Attributes object.
10532 *
10533 * @return {string} Serialized attributes.
10534 */
10535
10536 function serializeAttributes(attributes) {
10537 return JSON.stringify(attributes) // Don't break HTML comments.
10538 .replace(/--/g, '\\u002d\\u002d') // Don't break non-standard-compliant tools.
10539 .replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026') // Bypass server stripslashes behavior which would unescape stringify's
10540 // escaping of quotation mark.
10541 //
10542 // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
10543 .replace(/\\"/g, '\\u0022');
10544 }
10545 /**
10546 * Given a block object, returns the Block's Inner HTML markup.
10547 *
10548 * @param {Object} block Block instance.
10549 *
10550 * @return {string} HTML.
10551 */
10552
10553 function getBlockInnerHTML(block) {
10554 // If block was parsed as invalid or encounters an error while generating
10555 // save content, use original content instead to avoid content loss. If a
10556 // block contains nested content, exempt it from this condition because we
10557 // otherwise have no access to its original content and content loss would
10558 // still occur.
10559 let saveContent = block.originalContent;
10560
10561 if (block.isValid || block.innerBlocks.length) {
10562 try {
10563 saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
10564 } catch (error) {}
10565 }
10566
10567 return saveContent;
10568 }
10569 /**
10570 * Returns the content of a block, including comment delimiters.
10571 *
10572 * @param {string} rawBlockName Block name.
10573 * @param {Object} attributes Block attributes.
10574 * @param {string} content Block save content.
10575 *
10576 * @return {string} Comment-delimited block content.
10577 */
10578
10579 function getCommentDelimitedContent(rawBlockName, attributes, content) {
10580 const serializedAttributes = attributes && Object.entries(attributes).length ? serializeAttributes(attributes) + ' ' : ''; // Strip core blocks of their namespace prefix.
10581
10582 const blockName = rawBlockName?.startsWith('core/') ? rawBlockName.slice(5) : rawBlockName; // @todo make the `wp:` prefix potentially configurable.
10583
10584 if (!content) {
10585 return `<!-- wp:${blockName} ${serializedAttributes}/-->`;
10586 }
10587
10588 return `<!-- wp:${blockName} ${serializedAttributes}-->\n` + content + `\n<!-- /wp:${blockName} -->`;
10589 }
10590 /**
10591 * Returns the content of a block, including comment delimiters, determining
10592 * serialized attributes and content form from the current state of the block.
10593 *
10594 * @param {WPBlock} block Block instance.
10595 * @param {WPBlockSerializationOptions} options Serialization options.
10596 *
10597 * @return {string} Serialized block.
10598 */
10599
10600 function serializeBlock(block, {
10601 isInnerBlocks = false
10602 } = {}) {
10603 if (!block.isValid && block.__unstableBlockSource) {
10604 return serializeRawBlock(block.__unstableBlockSource);
10605 }
10606
10607 const blockName = block.name;
10608 const saveContent = getBlockInnerHTML(block);
10609
10610 if (blockName === getUnregisteredTypeHandlerName() || !isInnerBlocks && blockName === getFreeformContentHandlerName()) {
10611 return saveContent;
10612 }
10613
10614 const blockType = getBlockType(blockName);
10615
10616 if (!blockType) {
10617 return saveContent;
10618 }
10619
10620 const saveAttributes = getCommentAttributes(blockType, block.attributes);
10621 return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
10622 }
10623 function __unstableSerializeAndClean(blocks) {
10624 // A single unmodified default block is assumed to
10625 // be equivalent to an empty post.
10626 if (blocks.length === 1 && isUnmodifiedDefaultBlock(blocks[0])) {
10627 blocks = [];
10628 }
10629
10630 let content = serialize(blocks); // For compatibility, treat a post consisting of a
10631 // single freeform block as legacy content and apply
10632 // pre-block-editor removep'd content formatting.
10633
10634 if (blocks.length === 1 && blocks[0].name === getFreeformContentHandlerName()) {
10635 content = (0,external_wp_autop_namespaceObject.removep)(content);
10636 }
10637
10638 return content;
10639 }
10640 /**
10641 * Takes a block or set of blocks and returns the serialized post content.
10642 *
10643 * @param {Array} blocks Block(s) to serialize.
10644 * @param {WPBlockSerializationOptions} options Serialization options.
10645 *
10646 * @return {string} The post content.
10647 */
10648
10649 function serialize(blocks, options) {
10650 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
10651 return blocksArray.map(block => serializeBlock(block, options)).join('\n\n');
10652 }
10653
10654 ;// CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/index.js
10655 /**
10656 * generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
10657 * do not edit
10658 */
10659 var namedCharRefs = {
10660 Aacute: "Á", aacute: "á", Abreve: "Ă", abreve: "ă", ac: "∾", acd: "∿", acE: "∾̳", Acirc: "Â", acirc: "â", acute: "´", Acy: "А", acy: "а", AElig: "Æ", aelig: "æ", af: "\u2061", Afr: "𝔄", afr: "𝔞", Agrave: "À", agrave: "à", alefsym: "ℵ", aleph: "ℵ", Alpha: "Α", alpha: "α", Amacr: "Ā", amacr: "ā", amalg: "⨿", amp: "&", AMP: "&", andand: "⩕", And: "⩓", and: "∧", andd: "⩜", andslope: "⩘", andv: "⩚", ang: "∠", ange: "⦤", angle: "∠", angmsdaa: "⦨", angmsdab: "⦩", angmsdac: "⦪", angmsdad: "⦫", angmsdae: "⦬", angmsdaf: "⦭", angmsdag: "⦮", angmsdah: "⦯", angmsd: "∡", angrt: "∟", angrtvb: "⊾", angrtvbd: "⦝", angsph: "∢", angst: "Å", angzarr: "⍼", Aogon: "Ą", aogon: "ą", Aopf: "𝔸", aopf: "𝕒", apacir: "⩯", ap: "≈", apE: "⩰", ape: "≊", apid: "≋", apos: "'", ApplyFunction: "\u2061", approx: "≈", approxeq: "≊", Aring: "Å", aring: "å", Ascr: "𝒜", ascr: "𝒶", Assign: "≔", ast: "*", asymp: "≈", asympeq: "≍", Atilde: "Ã", atilde: "ã", Auml: "Ä", auml: "ä", awconint: "∳", awint: "⨑", backcong: "≌", backepsilon: "϶", backprime: "‵", backsim: "∽", backsimeq: "⋍", Backslash: "∖", Barv: "⫧", barvee: "⊽", barwed: "⌅", Barwed: "⌆", barwedge: "⌅", bbrk: "⎵", bbrktbrk: "⎶", bcong: "≌", Bcy: "Б", bcy: "б", bdquo: "„", becaus: "∵", because: "∵", Because: "∵", bemptyv: "⦰", bepsi: "϶", bernou: "ℬ", Bernoullis: "ℬ", Beta: "Β", beta: "β", beth: "ℶ", between: "≬", Bfr: "𝔅", bfr: "𝔟", bigcap: "⋂", bigcirc: "◯", bigcup: "⋃", bigodot: "⨀", bigoplus: "⨁", bigotimes: "⨂", bigsqcup: "⨆", bigstar: "★", bigtriangledown: "▽", bigtriangleup: "△", biguplus: "⨄", bigvee: "⋁", bigwedge: "⋀", bkarow: "⤍", blacklozenge: "⧫", blacksquare: "▪", blacktriangle: "▴", blacktriangledown: "▾", blacktriangleleft: "◂", blacktriangleright: "▸", blank: "␣", blk12: "▒", blk14: "░", blk34: "▓", block: "█", bne: "=⃥", bnequiv: "≡⃥", bNot: "⫭", bnot: "⌐", Bopf: "𝔹", bopf: "𝕓", bot: "⊥", bottom: "⊥", bowtie: "⋈", boxbox: "⧉", boxdl: "┐", boxdL: "╕", boxDl: "╖", boxDL: "╗", boxdr: "┌", boxdR: "╒", boxDr: "╓", boxDR: "╔", boxh: "─", boxH: "═", boxhd: "┬", boxHd: "╤", boxhD: "╥", boxHD: "╦", boxhu: "┴", boxHu: "╧", boxhU: "╨", boxHU: "╩", boxminus: "⊟", boxplus: "⊞", boxtimes: "⊠", boxul: "┘", boxuL: "╛", boxUl: "╜", boxUL: "╝", boxur: "└", boxuR: "╘", boxUr: "╙", boxUR: "╚", boxv: "│", boxV: "║", boxvh: "┼", boxvH: "╪", boxVh: "╫", boxVH: "╬", boxvl: "┤", boxvL: "╡", boxVl: "╢", boxVL: "╣", boxvr: "├", boxvR: "╞", boxVr: "╟", boxVR: "╠", bprime: "‵", breve: "˘", Breve: "˘", brvbar: "¦", bscr: "𝒷", Bscr: "ℬ", bsemi: "⁏", bsim: "∽", bsime: "⋍", bsolb: "⧅", bsol: "\\", bsolhsub: "⟈", bull: "•", bullet: "•", bump: "≎", bumpE: "⪮", bumpe: "≏", Bumpeq: "≎", bumpeq: "≏", Cacute: "Ć", cacute: "ć", capand: "⩄", capbrcup: "⩉", capcap: "⩋", cap: "∩", Cap: "⋒", capcup: "⩇", capdot: "⩀", CapitalDifferentialD: "ⅅ", caps: "∩︀", caret: "⁁", caron: "ˇ", Cayleys: "ℭ", ccaps: "⩍", Ccaron: "Č", ccaron: "č", Ccedil: "Ç", ccedil: "ç", Ccirc: "Ĉ", ccirc: "ĉ", Cconint: "∰", ccups: "⩌", ccupssm: "⩐", Cdot: "Ċ", cdot: "ċ", cedil: "¸", Cedilla: "¸", cemptyv: "⦲", cent: "¢", centerdot: "·", CenterDot: "·", cfr: "𝔠", Cfr: "ℭ", CHcy: "Ч", chcy: "ч", check: "✓", checkmark: "✓", Chi: "Χ", chi: "χ", circ: "ˆ", circeq: "≗", circlearrowleft: "↺", circlearrowright: "↻", circledast: "⊛", circledcirc: "⊚", circleddash: "⊝", CircleDot: "⊙", circledR: "®", circledS: "Ⓢ", CircleMinus: "⊖", CirclePlus: "⊕", CircleTimes: "⊗", cir: "○", cirE: "⧃", cire: "≗", cirfnint: "⨐", cirmid: "⫯", cirscir: "⧂", ClockwiseContourIntegral: "∲", CloseCurlyDoubleQuote: "”", CloseCurlyQuote: "’", clubs: "♣", clubsuit: "♣", colon: ":", Colon: "∷", Colone: "⩴", colone: "≔", coloneq: "≔", comma: ",", commat: "@", comp: "∁", compfn: "∘", complement: "∁", complexes: "ℂ", cong: "≅", congdot: "⩭", Congruent: "≡", conint: "∮", Conint: "∯", ContourIntegral: "∮", copf: "𝕔", Copf: "ℂ", coprod: "∐", Coproduct: "∐", copy: "©", COPY: "©", copysr: "℗", CounterClockwiseContourIntegral: "∳", crarr: "↵", cross: "✗", Cross: "⨯", Cscr: "𝒞", cscr: "𝒸", csub: "⫏", csube: "⫑", csup: "⫐", csupe: "⫒", ctdot: "⋯", cudarrl: "⤸", cudarrr: "⤵", cuepr: "⋞", cuesc: "⋟", cularr: "↶", cularrp: "⤽", cupbrcap: "⩈", cupcap: "⩆", CupCap: "≍", cup: "∪", Cup: "⋓", cupcup: "⩊", cupdot: "⊍", cupor: "⩅", cups: "∪︀", curarr: "↷", curarrm: "⤼", curlyeqprec: "⋞", curlyeqsucc: "⋟", curlyvee: "⋎", curlywedge: "⋏", curren: "¤", curvearrowleft: "↶", curvearrowright: "↷", cuvee: "⋎", cuwed: "⋏", cwconint: "∲", cwint: "∱", cylcty: "⌭", dagger: "†", Dagger: "‡", daleth: "ℸ", darr: "↓", Darr: "↡", dArr: "⇓", dash: "‐", Dashv: "⫤", dashv: "⊣", dbkarow: "⤏", dblac: "˝", Dcaron: "Ď", dcaron: "ď", Dcy: "Д", dcy: "д", ddagger: "‡", ddarr: "⇊", DD: "ⅅ", dd: "ⅆ", DDotrahd: "⤑", ddotseq: "⩷", deg: "°", Del: "∇", Delta: "Δ", delta: "δ", demptyv: "⦱", dfisht: "⥿", Dfr: "𝔇", dfr: "𝔡", dHar: "⥥", dharl: "⇃", dharr: "⇂", DiacriticalAcute: "´", DiacriticalDot: "˙", DiacriticalDoubleAcute: "˝", DiacriticalGrave: "`", DiacriticalTilde: "˜", diam: "⋄", diamond: "⋄", Diamond: "⋄", diamondsuit: "♦", diams: "♦", die: "¨", DifferentialD: "ⅆ", digamma: "ϝ", disin: "⋲", div: "÷", divide: "÷", divideontimes: "⋇", divonx: "⋇", DJcy: "Ђ", djcy: "ђ", dlcorn: "⌞", dlcrop: "⌍", dollar: "$", Dopf: "𝔻", dopf: "𝕕", Dot: "¨", dot: "˙", DotDot: "⃜", doteq: "≐", doteqdot: "≑", DotEqual: "≐", dotminus: "∸", dotplus: "∔", dotsquare: "⊡", doublebarwedge: "⌆", DoubleContourIntegral: "∯", DoubleDot: "¨", DoubleDownArrow: "⇓", DoubleLeftArrow: "⇐", DoubleLeftRightArrow: "⇔", DoubleLeftTee: "⫤", DoubleLongLeftArrow: "⟸", DoubleLongLeftRightArrow: "⟺", DoubleLongRightArrow: "⟹", DoubleRightArrow: "⇒", DoubleRightTee: "⊨", DoubleUpArrow: "⇑", DoubleUpDownArrow: "⇕", DoubleVerticalBar: "∥", DownArrowBar: "⤓", downarrow: "↓", DownArrow: "↓", Downarrow: "⇓", DownArrowUpArrow: "⇵", DownBreve: "̑", downdownarrows: "⇊", downharpoonleft: "⇃", downharpoonright: "⇂", DownLeftRightVector: "⥐", DownLeftTeeVector: "⥞", DownLeftVectorBar: "⥖", DownLeftVector: "↽", DownRightTeeVector: "⥟", DownRightVectorBar: "⥗", DownRightVector: "⇁", DownTeeArrow: "↧", DownTee: "⊤", drbkarow: "⤐", drcorn: "⌟", drcrop: "⌌", Dscr: "𝒟", dscr: "𝒹", DScy: "Ѕ", dscy: "ѕ", dsol: "⧶", Dstrok: "Đ", dstrok: "đ", dtdot: "⋱", dtri: "▿", dtrif: "▾", duarr: "⇵", duhar: "⥯", dwangle: "⦦", DZcy: "Џ", dzcy: "џ", dzigrarr: "⟿", Eacute: "É", eacute: "é", easter: "⩮", Ecaron: "Ě", ecaron: "ě", Ecirc: "Ê", ecirc: "ê", ecir: "≖", ecolon: "≕", Ecy: "Э", ecy: "э", eDDot: "⩷", Edot: "Ė", edot: "ė", eDot: "≑", ee: "ⅇ", efDot: "≒", Efr: "𝔈", efr: "𝔢", eg: "⪚", Egrave: "È", egrave: "è", egs: "⪖", egsdot: "⪘", el: "⪙", Element: "∈", elinters: "⏧", ell: "ℓ", els: "⪕", elsdot: "⪗", Emacr: "Ē", emacr: "ē", empty: "∅", emptyset: "∅", EmptySmallSquare: "◻", emptyv: "∅", EmptyVerySmallSquare: "▫", emsp13: " ", emsp14: " ", emsp: " ", ENG: "Ŋ", eng: "ŋ", ensp: " ", Eogon: "Ę", eogon: "ę", Eopf: "𝔼", eopf: "𝕖", epar: "⋕", eparsl: "⧣", eplus: "⩱", epsi: "ε", Epsilon: "Ε", epsilon: "ε", epsiv: "ϵ", eqcirc: "≖", eqcolon: "≕", eqsim: "≂", eqslantgtr: "⪖", eqslantless: "⪕", Equal: "⩵", equals: "=", EqualTilde: "≂", equest: "≟", Equilibrium: "⇌", equiv: "≡", equivDD: "⩸", eqvparsl: "⧥", erarr: "⥱", erDot: "≓", escr: "ℯ", Escr: "ℰ", esdot: "≐", Esim: "⩳", esim: "≂", Eta: "Η", eta: "η", ETH: "Ð", eth: "ð", Euml: "Ë", euml: "ë", euro: "€", excl: "!", exist: "∃", Exists: "∃", expectation: "ℰ", exponentiale: "ⅇ", ExponentialE: "ⅇ", fallingdotseq: "≒", Fcy: "Ф", fcy: "ф", female: "♀", ffilig: "ffi", fflig: "ff", ffllig: "ffl", Ffr: "𝔉", ffr: "𝔣", filig: "fi", FilledSmallSquare: "◼", FilledVerySmallSquare: "▪", fjlig: "fj", flat: "♭", fllig: "fl", fltns: "▱", fnof: "ƒ", Fopf: "𝔽", fopf: "𝕗", forall: "∀", ForAll: "∀", fork: "⋔", forkv: "⫙", Fouriertrf: "ℱ", fpartint: "⨍", frac12: "½", frac13: "⅓", frac14: "¼", frac15: "⅕", frac16: "⅙", frac18: "⅛", frac23: "⅔", frac25: "⅖", frac34: "¾", frac35: "⅗", frac38: "⅜", frac45: "⅘", frac56: "⅚", frac58: "⅝", frac78: "⅞", frasl: "⁄", frown: "⌢", fscr: "𝒻", Fscr: "ℱ", gacute: "ǵ", Gamma: "Γ", gamma: "γ", Gammad: "Ϝ", gammad: "ϝ", gap: "⪆", Gbreve: "Ğ", gbreve: "ğ", Gcedil: "Ģ", Gcirc: "Ĝ", gcirc: "ĝ", Gcy: "Г", gcy: "г", Gdot: "Ġ", gdot: "ġ", ge: "≥", gE: "≧", gEl: "⪌", gel: "⋛", geq: "≥", geqq: "≧", geqslant: "⩾", gescc: "⪩", ges: "⩾", gesdot: "⪀", gesdoto: "⪂", gesdotol: "⪄", gesl: "⋛︀", gesles: "⪔", Gfr: "𝔊", gfr: "𝔤", gg: "≫", Gg: "⋙", ggg: "⋙", gimel: "ℷ", GJcy: "Ѓ", gjcy: "ѓ", gla: "⪥", gl: "≷", glE: "⪒", glj: "⪤", gnap: "⪊", gnapprox: "⪊", gne: "⪈", gnE: "≩", gneq: "⪈", gneqq: "≩", gnsim: "⋧", Gopf: "𝔾", gopf: "𝕘", grave: "`", GreaterEqual: "≥", GreaterEqualLess: "⋛", GreaterFullEqual: "≧", GreaterGreater: "⪢", GreaterLess: "≷", GreaterSlantEqual: "⩾", GreaterTilde: "≳", Gscr: "𝒢", gscr: "ℊ", gsim: "≳", gsime: "⪎", gsiml: "⪐", gtcc: "⪧", gtcir: "⩺", gt: ">", GT: ">", Gt: "≫", gtdot: "⋗", gtlPar: "⦕", gtquest: "⩼", gtrapprox: "⪆", gtrarr: "⥸", gtrdot: "⋗", gtreqless: "⋛", gtreqqless: "⪌", gtrless: "≷", gtrsim: "≳", gvertneqq: "≩︀", gvnE: "≩︀", Hacek: "ˇ", hairsp: " ", half: "½", hamilt: "ℋ", HARDcy: "Ъ", hardcy: "ъ", harrcir: "⥈", harr: "↔", hArr: "⇔", harrw: "↭", Hat: "^", hbar: "ℏ", Hcirc: "Ĥ", hcirc: "ĥ", hearts: "♥", heartsuit: "♥", hellip: "…", hercon: "⊹", hfr: "𝔥", Hfr: "ℌ", HilbertSpace: "ℋ", hksearow: "⤥", hkswarow: "⤦", hoarr: "⇿", homtht: "∻", hookleftarrow: "↩", hookrightarrow: "↪", hopf: "𝕙", Hopf: "ℍ", horbar: "―", HorizontalLine: "─", hscr: "𝒽", Hscr: "ℋ", hslash: "ℏ", Hstrok: "Ħ", hstrok: "ħ", HumpDownHump: "≎", HumpEqual: "≏", hybull: "⁃", hyphen: "‐", Iacute: "Í", iacute: "í", ic: "\u2063", Icirc: "Î", icirc: "î", Icy: "И", icy: "и", Idot: "İ", IEcy: "Е", iecy: "е", iexcl: "¡", iff: "⇔", ifr: "𝔦", Ifr: "ℑ", Igrave: "Ì", igrave: "ì", ii: "ⅈ", iiiint: "⨌", iiint: "∭", iinfin: "⧜", iiota: "℩", IJlig: "IJ", ijlig: "ij", Imacr: "Ī", imacr: "ī", image: "ℑ", ImaginaryI: "ⅈ", imagline: "ℐ", imagpart: "ℑ", imath: "ı", Im: "ℑ", imof: "⊷", imped: "Ƶ", Implies: "⇒", incare: "℅", in: "∈", infin: "∞", infintie: "⧝", inodot: "ı", intcal: "⊺", int: "∫", Int: "∬", integers: "ℤ", Integral: "∫", intercal: "⊺", Intersection: "⋂", intlarhk: "⨗", intprod: "⨼", InvisibleComma: "\u2063", InvisibleTimes: "\u2062", IOcy: "Ё", iocy: "ё", Iogon: "Į", iogon: "į", Iopf: "𝕀", iopf: "𝕚", Iota: "Ι", iota: "ι", iprod: "⨼", iquest: "¿", iscr: "𝒾", Iscr: "ℐ", isin: "∈", isindot: "⋵", isinE: "⋹", isins: "⋴", isinsv: "⋳", isinv: "∈", it: "\u2062", Itilde: "Ĩ", itilde: "ĩ", Iukcy: "І", iukcy: "і", Iuml: "Ï", iuml: "ï", Jcirc: "Ĵ", jcirc: "ĵ", Jcy: "Й", jcy: "й", Jfr: "𝔍", jfr: "𝔧", jmath: "ȷ", Jopf: "𝕁", jopf: "𝕛", Jscr: "𝒥", jscr: "𝒿", Jsercy: "Ј", jsercy: "ј", Jukcy: "Є", jukcy: "є", Kappa: "Κ", kappa: "κ", kappav: "ϰ", Kcedil: "Ķ", kcedil: "ķ", Kcy: "К", kcy: "к", Kfr: "𝔎", kfr: "𝔨", kgreen: "ĸ", KHcy: "Х", khcy: "х", KJcy: "Ќ", kjcy: "ќ", Kopf: "𝕂", kopf: "𝕜", Kscr: "𝒦", kscr: "𝓀", lAarr: "⇚", Lacute: "Ĺ", lacute: "ĺ", laemptyv: "⦴", lagran: "ℒ", Lambda: "Λ", lambda: "λ", lang: "⟨", Lang: "⟪", langd: "⦑", langle: "⟨", lap: "⪅", Laplacetrf: "ℒ", laquo: "«", larrb: "⇤", larrbfs: "⤟", larr: "←", Larr: "↞", lArr: "⇐", larrfs: "⤝", larrhk: "↩", larrlp: "↫", larrpl: "⤹", larrsim: "⥳", larrtl: "↢", latail: "⤙", lAtail: "⤛", lat: "⪫", late: "⪭", lates: "⪭︀", lbarr: "⤌", lBarr: "⤎", lbbrk: "❲", lbrace: "{", lbrack: "[", lbrke: "⦋", lbrksld: "⦏", lbrkslu: "⦍", Lcaron: "Ľ", lcaron: "ľ", Lcedil: "Ļ", lcedil: "ļ", lceil: "⌈", lcub: "{", Lcy: "Л", lcy: "л", ldca: "⤶", ldquo: "“", ldquor: "„", ldrdhar: "⥧", ldrushar: "⥋", ldsh: "↲", le: "≤", lE: "≦", LeftAngleBracket: "⟨", LeftArrowBar: "⇤", leftarrow: "←", LeftArrow: "←", Leftarrow: "⇐", LeftArrowRightArrow: "⇆", leftarrowtail: "↢", LeftCeiling: "⌈", LeftDoubleBracket: "⟦", LeftDownTeeVector: "⥡", LeftDownVectorBar: "⥙", LeftDownVector: "⇃", LeftFloor: "⌊", leftharpoondown: "↽", leftharpoonup: "↼", leftleftarrows: "⇇", leftrightarrow: "↔", LeftRightArrow: "↔", Leftrightarrow: "⇔", leftrightarrows: "⇆", leftrightharpoons: "⇋", leftrightsquigarrow: "↭", LeftRightVector: "⥎", LeftTeeArrow: "↤", LeftTee: "⊣", LeftTeeVector: "⥚", leftthreetimes: "⋋", LeftTriangleBar: "⧏", LeftTriangle: "⊲", LeftTriangleEqual: "⊴", LeftUpDownVector: "⥑", LeftUpTeeVector: "⥠", LeftUpVectorBar: "⥘", LeftUpVector: "↿", LeftVectorBar: "⥒", LeftVector: "↼", lEg: "⪋", leg: "⋚", leq: "≤", leqq: "≦", leqslant: "⩽", lescc: "⪨", les: "⩽", lesdot: "⩿", lesdoto: "⪁", lesdotor: "⪃", lesg: "⋚︀", lesges: "⪓", lessapprox: "⪅", lessdot: "⋖", lesseqgtr: "⋚", lesseqqgtr: "⪋", LessEqualGreater: "⋚", LessFullEqual: "≦", LessGreater: "≶", lessgtr: "≶", LessLess: "⪡", lesssim: "≲", LessSlantEqual: "⩽", LessTilde: "≲", lfisht: "⥼", lfloor: "⌊", Lfr: "𝔏", lfr: "𝔩", lg: "≶", lgE: "⪑", lHar: "⥢", lhard: "↽", lharu: "↼", lharul: "⥪", lhblk: "▄", LJcy: "Љ", ljcy: "љ", llarr: "⇇", ll: "≪", Ll: "⋘", llcorner: "⌞", Lleftarrow: "⇚", llhard: "⥫", lltri: "◺", Lmidot: "Ŀ", lmidot: "ŀ", lmoustache: "⎰", lmoust: "⎰", lnap: "⪉", lnapprox: "⪉", lne: "⪇", lnE: "≨", lneq: "⪇", lneqq: "≨", lnsim: "⋦", loang: "⟬", loarr: "⇽", lobrk: "⟦", longleftarrow: "⟵", LongLeftArrow: "⟵", Longleftarrow: "⟸", longleftrightarrow: "⟷", LongLeftRightArrow: "⟷", Longleftrightarrow: "⟺", longmapsto: "⟼", longrightarrow: "⟶", LongRightArrow: "⟶", Longrightarrow: "⟹", looparrowleft: "↫", looparrowright: "↬", lopar: "⦅", Lopf: "𝕃", lopf: "𝕝", loplus: "⨭", lotimes: "⨴", lowast: "∗", lowbar: "_", LowerLeftArrow: "↙", LowerRightArrow: "↘", loz: "◊", lozenge: "◊", lozf: "⧫", lpar: "(", lparlt: "⦓", lrarr: "⇆", lrcorner: "⌟", lrhar: "⇋", lrhard: "⥭", lrm: "\u200e", lrtri: "⊿", lsaquo: "‹", lscr: "𝓁", Lscr: "ℒ", lsh: "↰", Lsh: "↰", lsim: "≲", lsime: "⪍", lsimg: "⪏", lsqb: "[", lsquo: "‘", lsquor: "‚", Lstrok: "Ł", lstrok: "ł", ltcc: "⪦", ltcir: "⩹", lt: "<", LT: "<", Lt: "≪", ltdot: "⋖", lthree: "⋋", ltimes: "⋉", ltlarr: "⥶", ltquest: "⩻", ltri: "◃", ltrie: "⊴", ltrif: "◂", ltrPar: "⦖", lurdshar: "⥊", luruhar: "⥦", lvertneqq: "≨︀", lvnE: "≨︀", macr: "¯", male: "♂", malt: "✠", maltese: "✠", Map: "⤅", map: "↦", mapsto: "↦", mapstodown: "↧", mapstoleft: "↤", mapstoup: "↥", marker: "▮", mcomma: "⨩", Mcy: "М", mcy: "м", mdash: "—", mDDot: "∺", measuredangle: "∡", MediumSpace: " ", Mellintrf: "ℳ", Mfr: "𝔐", mfr: "𝔪", mho: "℧", micro: "µ", midast: "*", midcir: "⫰", mid: "∣", middot: "·", minusb: "⊟", minus: "−", minusd: "∸", minusdu: "⨪", MinusPlus: "∓", mlcp: "⫛", mldr: "…", mnplus: "∓", models: "⊧", Mopf: "𝕄", mopf: "𝕞", mp: "∓", mscr: "𝓂", Mscr: "ℳ", mstpos: "∾", Mu: "Μ", mu: "μ", multimap: "⊸", mumap: "⊸", nabla: "∇", Nacute: "Ń", nacute: "ń", nang: "∠⃒", nap: "≉", napE: "⩰̸", napid: "≋̸", napos: "ʼn", napprox: "≉", natural: "♮", naturals: "ℕ", natur: "♮", nbsp: " ", nbump: "≎̸", nbumpe: "≏̸", ncap: "⩃", Ncaron: "Ň", ncaron: "ň", Ncedil: "Ņ", ncedil: "ņ", ncong: "≇", ncongdot: "⩭̸", ncup: "⩂", Ncy: "Н", ncy: "н", ndash: "–", nearhk: "⤤", nearr: "↗", neArr: "⇗", nearrow: "↗", ne: "≠", nedot: "≐̸", NegativeMediumSpace: "​", NegativeThickSpace: "​", NegativeThinSpace: "​", NegativeVeryThinSpace: "​", nequiv: "≢", nesear: "⤨", nesim: "≂̸", NestedGreaterGreater: "≫", NestedLessLess: "≪", NewLine: "\u000a", nexist: "∄", nexists: "∄", Nfr: "𝔑", nfr: "𝔫", ngE: "≧̸", nge: "≱", ngeq: "≱", ngeqq: "≧̸", ngeqslant: "⩾̸", nges: "⩾̸", nGg: "⋙̸", ngsim: "≵", nGt: "≫⃒", ngt: "≯", ngtr: "≯", nGtv: "≫̸", nharr: "↮", nhArr: "⇎", nhpar: "⫲", ni: "∋", nis: "⋼", nisd: "⋺", niv: "∋", NJcy: "Њ", njcy: "њ", nlarr: "↚", nlArr: "⇍", nldr: "‥", nlE: "≦̸", nle: "≰", nleftarrow: "↚", nLeftarrow: "⇍", nleftrightarrow: "↮", nLeftrightarrow: "⇎", nleq: "≰", nleqq: "≦̸", nleqslant: "⩽̸", nles: "⩽̸", nless: "≮", nLl: "⋘̸", nlsim: "≴", nLt: "≪⃒", nlt: "≮", nltri: "⋪", nltrie: "⋬", nLtv: "≪̸", nmid: "∤", NoBreak: "\u2060", NonBreakingSpace: " ", nopf: "𝕟", Nopf: "ℕ", Not: "⫬", not: "¬", NotCongruent: "≢", NotCupCap: "≭", NotDoubleVerticalBar: "∦", NotElement: "∉", NotEqual: "≠", NotEqualTilde: "≂̸", NotExists: "∄", NotGreater: "≯", NotGreaterEqual: "≱", NotGreaterFullEqual: "≧̸", NotGreaterGreater: "≫̸", NotGreaterLess: "≹", NotGreaterSlantEqual: "⩾̸", NotGreaterTilde: "≵", NotHumpDownHump: "≎̸", NotHumpEqual: "≏̸", notin: "∉", notindot: "⋵̸", notinE: "⋹̸", notinva: "∉", notinvb: "⋷", notinvc: "⋶", NotLeftTriangleBar: "⧏̸", NotLeftTriangle: "⋪", NotLeftTriangleEqual: "⋬", NotLess: "≮", NotLessEqual: "≰", NotLessGreater: "≸", NotLessLess: "≪̸", NotLessSlantEqual: "⩽̸", NotLessTilde: "≴", NotNestedGreaterGreater: "⪢̸", NotNestedLessLess: "⪡̸", notni: "∌", notniva: "∌", notnivb: "⋾", notnivc: "⋽", NotPrecedes: "⊀", NotPrecedesEqual: "⪯̸", NotPrecedesSlantEqual: "⋠", NotReverseElement: "∌", NotRightTriangleBar: "⧐̸", NotRightTriangle: "⋫", NotRightTriangleEqual: "⋭", NotSquareSubset: "⊏̸", NotSquareSubsetEqual: "⋢", NotSquareSuperset: "⊐̸", NotSquareSupersetEqual: "⋣", NotSubset: "⊂⃒", NotSubsetEqual: "⊈", NotSucceeds: "⊁", NotSucceedsEqual: "⪰̸", NotSucceedsSlantEqual: "⋡", NotSucceedsTilde: "≿̸", NotSuperset: "⊃⃒", NotSupersetEqual: "⊉", NotTilde: "≁", NotTildeEqual: "≄", NotTildeFullEqual: "≇", NotTildeTilde: "≉", NotVerticalBar: "∤", nparallel: "∦", npar: "∦", nparsl: "⫽⃥", npart: "∂̸", npolint: "⨔", npr: "⊀", nprcue: "⋠", nprec: "⊀", npreceq: "⪯̸", npre: "⪯̸", nrarrc: "⤳̸", nrarr: "↛", nrArr: "⇏", nrarrw: "↝̸", nrightarrow: "↛", nRightarrow: "⇏", nrtri: "⋫", nrtrie: "⋭", nsc: "⊁", nsccue: "⋡", nsce: "⪰̸", Nscr: "𝒩", nscr: "𝓃", nshortmid: "∤", nshortparallel: "∦", nsim: "≁", nsime: "≄", nsimeq: "≄", nsmid: "∤", nspar: "∦", nsqsube: "⋢", nsqsupe: "⋣", nsub: "⊄", nsubE: "⫅̸", nsube: "⊈", nsubset: "⊂⃒", nsubseteq: "⊈", nsubseteqq: "⫅̸", nsucc: "⊁", nsucceq: "⪰̸", nsup: "⊅", nsupE: "⫆̸", nsupe: "⊉", nsupset: "⊃⃒", nsupseteq: "⊉", nsupseteqq: "⫆̸", ntgl: "≹", Ntilde: "Ñ", ntilde: "ñ", ntlg: "≸", ntriangleleft: "⋪", ntrianglelefteq: "⋬", ntriangleright: "⋫", ntrianglerighteq: "⋭", Nu: "Ν", nu: "ν", num: "#", numero: "№", numsp: " ", nvap: "≍⃒", nvdash: "⊬", nvDash: "⊭", nVdash: "⊮", nVDash: "⊯", nvge: "≥⃒", nvgt: ">⃒", nvHarr: "⤄", nvinfin: "⧞", nvlArr: "⤂", nvle: "≤⃒", nvlt: "<⃒", nvltrie: "⊴⃒", nvrArr: "⤃", nvrtrie: "⊵⃒", nvsim: "∼⃒", nwarhk: "⤣", nwarr: "↖", nwArr: "⇖", nwarrow: "↖", nwnear: "⤧", Oacute: "Ó", oacute: "ó", oast: "⊛", Ocirc: "Ô", ocirc: "ô", ocir: "⊚", Ocy: "О", ocy: "о", odash: "⊝", Odblac: "Ő", odblac: "ő", odiv: "⨸", odot: "⊙", odsold: "⦼", OElig: "Œ", oelig: "œ", ofcir: "⦿", Ofr: "𝔒", ofr: "𝔬", ogon: "˛", Ograve: "Ò", ograve: "ò", ogt: "⧁", ohbar: "⦵", ohm: "Ω", oint: "∮", olarr: "↺", olcir: "⦾", olcross: "⦻", oline: "‾", olt: "⧀", Omacr: "Ō", omacr: "ō", Omega: "Ω", omega: "ω", Omicron: "Ο", omicron: "ο", omid: "⦶", ominus: "⊖", Oopf: "𝕆", oopf: "𝕠", opar: "⦷", OpenCurlyDoubleQuote: "“", OpenCurlyQuote: "‘", operp: "⦹", oplus: "⊕", orarr: "↻", Or: "⩔", or: "∨", ord: "⩝", order: "ℴ", orderof: "ℴ", ordf: "ª", ordm: "º", origof: "⊶", oror: "⩖", orslope: "⩗", orv: "⩛", oS: "Ⓢ", Oscr: "𝒪", oscr: "ℴ", Oslash: "Ø", oslash: "ø", osol: "⊘", Otilde: "Õ", otilde: "õ", otimesas: "⨶", Otimes: "⨷", otimes: "⊗", Ouml: "Ö", ouml: "ö", ovbar: "⌽", OverBar: "‾", OverBrace: "⏞", OverBracket: "⎴", OverParenthesis: "⏜", para: "¶", parallel: "∥", par: "∥", parsim: "⫳", parsl: "⫽", part: "∂", PartialD: "∂", Pcy: "П", pcy: "п", percnt: "%", period: ".", permil: "‰", perp: "⊥", pertenk: "‱", Pfr: "𝔓", pfr: "𝔭", Phi: "Φ", phi: "φ", phiv: "ϕ", phmmat: "ℳ", phone: "☎", Pi: "Π", pi: "π", pitchfork: "⋔", piv: "ϖ", planck: "ℏ", planckh: "ℎ", plankv: "ℏ", plusacir: "⨣", plusb: "⊞", pluscir: "⨢", plus: "+", plusdo: "∔", plusdu: "⨥", pluse: "⩲", PlusMinus: "±", plusmn: "±", plussim: "⨦", plustwo: "⨧", pm: "±", Poincareplane: "ℌ", pointint: "⨕", popf: "𝕡", Popf: "ℙ", pound: "£", prap: "⪷", Pr: "⪻", pr: "≺", prcue: "≼", precapprox: "⪷", prec: "≺", preccurlyeq: "≼", Precedes: "≺", PrecedesEqual: "⪯", PrecedesSlantEqual: "≼", PrecedesTilde: "≾", preceq: "⪯", precnapprox: "⪹", precneqq: "⪵", precnsim: "⋨", pre: "⪯", prE: "⪳", precsim: "≾", prime: "′", Prime: "″", primes: "ℙ", prnap: "⪹", prnE: "⪵", prnsim: "⋨", prod: "∏", Product: "∏", profalar: "⌮", profline: "⌒", profsurf: "⌓", prop: "∝", Proportional: "∝", Proportion: "∷", propto: "∝", prsim: "≾", prurel: "⊰", Pscr: "𝒫", pscr: "𝓅", Psi: "Ψ", psi: "ψ", puncsp: " ", Qfr: "𝔔", qfr: "𝔮", qint: "⨌", qopf: "𝕢", Qopf: "ℚ", qprime: "⁗", Qscr: "𝒬", qscr: "𝓆", quaternions: "ℍ", quatint: "⨖", quest: "?", questeq: "≟", quot: "\"", QUOT: "\"", rAarr: "⇛", race: "∽̱", Racute: "Ŕ", racute: "ŕ", radic: "√", raemptyv: "⦳", rang: "⟩", Rang: "⟫", rangd: "⦒", range: "⦥", rangle: "⟩", raquo: "»", rarrap: "⥵", rarrb: "⇥", rarrbfs: "⤠", rarrc: "⤳", rarr: "→", Rarr: "↠", rArr: "⇒", rarrfs: "⤞", rarrhk: "↪", rarrlp: "↬", rarrpl: "⥅", rarrsim: "⥴", Rarrtl: "⤖", rarrtl: "↣", rarrw: "↝", ratail: "⤚", rAtail: "⤜", ratio: "∶", rationals: "ℚ", rbarr: "⤍", rBarr: "⤏", RBarr: "⤐", rbbrk: "❳", rbrace: "}", rbrack: "]", rbrke: "⦌", rbrksld: "⦎", rbrkslu: "⦐", Rcaron: "Ř", rcaron: "ř", Rcedil: "Ŗ", rcedil: "ŗ", rceil: "⌉", rcub: "}", Rcy: "Р", rcy: "р", rdca: "⤷", rdldhar: "⥩", rdquo: "”", rdquor: "”", rdsh: "↳", real: "ℜ", realine: "ℛ", realpart: "ℜ", reals: "ℝ", Re: "ℜ", rect: "▭", reg: "®", REG: "®", ReverseElement: "∋", ReverseEquilibrium: "⇋", ReverseUpEquilibrium: "⥯", rfisht: "⥽", rfloor: "⌋", rfr: "𝔯", Rfr: "ℜ", rHar: "⥤", rhard: "⇁", rharu: "⇀", rharul: "⥬", Rho: "Ρ", rho: "ρ", rhov: "ϱ", RightAngleBracket: "⟩", RightArrowBar: "⇥", rightarrow: "→", RightArrow: "→", Rightarrow: "⇒", RightArrowLeftArrow: "⇄", rightarrowtail: "↣", RightCeiling: "⌉", RightDoubleBracket: "⟧", RightDownTeeVector: "⥝", RightDownVectorBar: "⥕", RightDownVector: "⇂", RightFloor: "⌋", rightharpoondown: "⇁", rightharpoonup: "⇀", rightleftarrows: "⇄", rightleftharpoons: "⇌", rightrightarrows: "⇉", rightsquigarrow: "↝", RightTeeArrow: "↦", RightTee: "⊢", RightTeeVector: "⥛", rightthreetimes: "⋌", RightTriangleBar: "⧐", RightTriangle: "⊳", RightTriangleEqual: "⊵", RightUpDownVector: "⥏", RightUpTeeVector: "⥜", RightUpVectorBar: "⥔", RightUpVector: "↾", RightVectorBar: "⥓", RightVector: "⇀", ring: "˚", risingdotseq: "≓", rlarr: "⇄", rlhar: "⇌", rlm: "\u200f", rmoustache: "⎱", rmoust: "⎱", rnmid: "⫮", roang: "⟭", roarr: "⇾", robrk: "⟧", ropar: "⦆", ropf: "𝕣", Ropf: "ℝ", roplus: "⨮", rotimes: "⨵", RoundImplies: "⥰", rpar: ")", rpargt: "⦔", rppolint: "⨒", rrarr: "⇉", Rrightarrow: "⇛", rsaquo: "›", rscr: "𝓇", Rscr: "ℛ", rsh: "↱", Rsh: "↱", rsqb: "]", rsquo: "’", rsquor: "’", rthree: "⋌", rtimes: "⋊", rtri: "▹", rtrie: "⊵", rtrif: "▸", rtriltri: "⧎", RuleDelayed: "⧴", ruluhar: "⥨", rx: "℞", Sacute: "Ś", sacute: "ś", sbquo: "‚", scap: "⪸", Scaron: "Š", scaron: "š", Sc: "⪼", sc: "≻", sccue: "≽", sce: "⪰", scE: "⪴", Scedil: "Ş", scedil: "ş", Scirc: "Ŝ", scirc: "ŝ", scnap: "⪺", scnE: "⪶", scnsim: "⋩", scpolint: "⨓", scsim: "≿", Scy: "С", scy: "с", sdotb: "⊡", sdot: "⋅", sdote: "⩦", searhk: "⤥", searr: "↘", seArr: "⇘", searrow: "↘", sect: "§", semi: ";", seswar: "⤩", setminus: "∖", setmn: "∖", sext: "✶", Sfr: "𝔖", sfr: "𝔰", sfrown: "⌢", sharp: "♯", SHCHcy: "Щ", shchcy: "щ", SHcy: "Ш", shcy: "ш", ShortDownArrow: "↓", ShortLeftArrow: "←", shortmid: "∣", shortparallel: "∥", ShortRightArrow: "→", ShortUpArrow: "↑", shy: "\u00ad", Sigma: "Σ", sigma: "σ", sigmaf: "ς", sigmav: "ς", sim: "∼", simdot: "⩪", sime: "≃", simeq: "≃", simg: "⪞", simgE: "⪠", siml: "⪝", simlE: "⪟", simne: "≆", simplus: "⨤", simrarr: "⥲", slarr: "←", SmallCircle: "∘", smallsetminus: "∖", smashp: "⨳", smeparsl: "⧤", smid: "∣", smile: "⌣", smt: "⪪", smte: "⪬", smtes: "⪬︀", SOFTcy: "Ь", softcy: "ь", solbar: "⌿", solb: "⧄", sol: "/", Sopf: "𝕊", sopf: "𝕤", spades: "♠", spadesuit: "♠", spar: "∥", sqcap: "⊓", sqcaps: "⊓︀", sqcup: "⊔", sqcups: "⊔︀", Sqrt: "√", sqsub: "⊏", sqsube: "⊑", sqsubset: "⊏", sqsubseteq: "⊑", sqsup: "⊐", sqsupe: "⊒", sqsupset: "⊐", sqsupseteq: "⊒", square: "□", Square: "□", SquareIntersection: "⊓", SquareSubset: "⊏", SquareSubsetEqual: "⊑", SquareSuperset: "⊐", SquareSupersetEqual: "⊒", SquareUnion: "⊔", squarf: "▪", squ: "□", squf: "▪", srarr: "→", Sscr: "𝒮", sscr: "𝓈", ssetmn: "∖", ssmile: "⌣", sstarf: "⋆", Star: "⋆", star: "☆", starf: "★", straightepsilon: "ϵ", straightphi: "ϕ", strns: "¯", sub: "⊂", Sub: "⋐", subdot: "⪽", subE: "⫅", sube: "⊆", subedot: "⫃", submult: "⫁", subnE: "⫋", subne: "⊊", subplus: "⪿", subrarr: "⥹", subset: "⊂", Subset: "⋐", subseteq: "⊆", subseteqq: "⫅", SubsetEqual: "⊆", subsetneq: "⊊", subsetneqq: "⫋", subsim: "⫇", subsub: "⫕", subsup: "⫓", succapprox: "⪸", succ: "≻", succcurlyeq: "≽", Succeeds: "≻", SucceedsEqual: "⪰", SucceedsSlantEqual: "≽", SucceedsTilde: "≿", succeq: "⪰", succnapprox: "⪺", succneqq: "⪶", succnsim: "⋩", succsim: "≿", SuchThat: "∋", sum: "∑", Sum: "∑", sung: "♪", sup1: "¹", sup2: "²", sup3: "³", sup: "⊃", Sup: "⋑", supdot: "⪾", supdsub: "⫘", supE: "⫆", supe: "⊇", supedot: "⫄", Superset: "⊃", SupersetEqual: "⊇", suphsol: "⟉", suphsub: "⫗", suplarr: "⥻", supmult: "⫂", supnE: "⫌", supne: "⊋", supplus: "⫀", supset: "⊃", Supset: "⋑", supseteq: "⊇", supseteqq: "⫆", supsetneq: "⊋", supsetneqq: "⫌", supsim: "⫈", supsub: "⫔", supsup: "⫖", swarhk: "⤦", swarr: "↙", swArr: "⇙", swarrow: "↙", swnwar: "⤪", szlig: "ß", Tab: "\u0009", target: "⌖", Tau: "Τ", tau: "τ", tbrk: "⎴", Tcaron: "Ť", tcaron: "ť", Tcedil: "Ţ", tcedil: "ţ", Tcy: "Т", tcy: "т", tdot: "⃛", telrec: "⌕", Tfr: "𝔗", tfr: "𝔱", there4: "∴", therefore: "∴", Therefore: "∴", Theta: "Θ", theta: "θ", thetasym: "ϑ", thetav: "ϑ", thickapprox: "≈", thicksim: "∼", ThickSpace: "  ", ThinSpace: " ", thinsp: " ", thkap: "≈", thksim: "∼", THORN: "Þ", thorn: "þ", tilde: "˜", Tilde: "∼", TildeEqual: "≃", TildeFullEqual: "≅", TildeTilde: "≈", timesbar: "⨱", timesb: "⊠", times: "×", timesd: "⨰", tint: "∭", toea: "⤨", topbot: "⌶", topcir: "⫱", top: "⊤", Topf: "𝕋", topf: "𝕥", topfork: "⫚", tosa: "⤩", tprime: "‴", trade: "™", TRADE: "™", triangle: "▵", triangledown: "▿", triangleleft: "◃", trianglelefteq: "⊴", triangleq: "≜", triangleright: "▹", trianglerighteq: "⊵", tridot: "◬", trie: "≜", triminus: "⨺", TripleDot: "⃛", triplus: "⨹", trisb: "⧍", tritime: "⨻", trpezium: "⏢", Tscr: "𝒯", tscr: "𝓉", TScy: "Ц", tscy: "ц", TSHcy: "Ћ", tshcy: "ћ", Tstrok: "Ŧ", tstrok: "ŧ", twixt: "≬", twoheadleftarrow: "↞", twoheadrightarrow: "↠", Uacute: "Ú", uacute: "ú", uarr: "↑", Uarr: "↟", uArr: "⇑", Uarrocir: "⥉", Ubrcy: "Ў", ubrcy: "ў", Ubreve: "Ŭ", ubreve: "ŭ", Ucirc: "Û", ucirc: "û", Ucy: "У", ucy: "у", udarr: "⇅", Udblac: "Ű", udblac: "ű", udhar: "⥮", ufisht: "⥾", Ufr: "𝔘", ufr: "𝔲", Ugrave: "Ù", ugrave: "ù", uHar: "⥣", uharl: "↿", uharr: "↾", uhblk: "▀", ulcorn: "⌜", ulcorner: "⌜", ulcrop: "⌏", ultri: "◸", Umacr: "Ū", umacr: "ū", uml: "¨", UnderBar: "_", UnderBrace: "⏟", UnderBracket: "⎵", UnderParenthesis: "⏝", Union: "⋃", UnionPlus: "⊎", Uogon: "Ų", uogon: "ų", Uopf: "𝕌", uopf: "𝕦", UpArrowBar: "⤒", uparrow: "↑", UpArrow: "↑", Uparrow: "⇑", UpArrowDownArrow: "⇅", updownarrow: "↕", UpDownArrow: "↕", Updownarrow: "⇕", UpEquilibrium: "⥮", upharpoonleft: "↿", upharpoonright: "↾", uplus: "⊎", UpperLeftArrow: "↖", UpperRightArrow: "↗", upsi: "υ", Upsi: "ϒ", upsih: "ϒ", Upsilon: "Υ", upsilon: "υ", UpTeeArrow: "↥", UpTee: "⊥", upuparrows: "⇈", urcorn: "⌝", urcorner: "⌝", urcrop: "⌎", Uring: "Ů", uring: "ů", urtri: "◹", Uscr: "𝒰", uscr: "𝓊", utdot: "⋰", Utilde: "Ũ", utilde: "ũ", utri: "▵", utrif: "▴", uuarr: "⇈", Uuml: "Ü", uuml: "ü", uwangle: "⦧", vangrt: "⦜", varepsilon: "ϵ", varkappa: "ϰ", varnothing: "∅", varphi: "ϕ", varpi: "ϖ", varpropto: "∝", varr: "↕", vArr: "⇕", varrho: "ϱ", varsigma: "ς", varsubsetneq: "⊊︀", varsubsetneqq: "⫋︀", varsupsetneq: "⊋︀", varsupsetneqq: "⫌︀", vartheta: "ϑ", vartriangleleft: "⊲", vartriangleright: "⊳", vBar: "⫨", Vbar: "⫫", vBarv: "⫩", Vcy: "В", vcy: "в", vdash: "⊢", vDash: "⊨", Vdash: "⊩", VDash: "⊫", Vdashl: "⫦", veebar: "⊻", vee: "∨", Vee: "⋁", veeeq: "≚", vellip: "⋮", verbar: "|", Verbar: "‖", vert: "|", Vert: "‖", VerticalBar: "∣", VerticalLine: "|", VerticalSeparator: "❘", VerticalTilde: "≀", VeryThinSpace: " ", Vfr: "𝔙", vfr: "𝔳", vltri: "⊲", vnsub: "⊂⃒", vnsup: "⊃⃒", Vopf: "𝕍", vopf: "𝕧", vprop: "∝", vrtri: "⊳", Vscr: "𝒱", vscr: "𝓋", vsubnE: "⫋︀", vsubne: "⊊︀", vsupnE: "⫌︀", vsupne: "⊋︀", Vvdash: "⊪", vzigzag: "⦚", Wcirc: "Ŵ", wcirc: "ŵ", wedbar: "⩟", wedge: "∧", Wedge: "⋀", wedgeq: "≙", weierp: "℘", Wfr: "𝔚", wfr: "𝔴", Wopf: "𝕎", wopf: "𝕨", wp: "℘", wr: "≀", wreath: "≀", Wscr: "𝒲", wscr: "𝓌", xcap: "⋂", xcirc: "◯", xcup: "⋃", xdtri: "▽", Xfr: "𝔛", xfr: "𝔵", xharr: "⟷", xhArr: "⟺", Xi: "Ξ", xi: "ξ", xlarr: "⟵", xlArr: "⟸", xmap: "⟼", xnis: "⋻", xodot: "⨀", Xopf: "𝕏", xopf: "𝕩", xoplus: "⨁", xotime: "⨂", xrarr: "⟶", xrArr: "⟹", Xscr: "𝒳", xscr: "𝓍", xsqcup: "⨆", xuplus: "⨄", xutri: "△", xvee: "⋁", xwedge: "⋀", Yacute: "Ý", yacute: "ý", YAcy: "Я", yacy: "я", Ycirc: "Ŷ", ycirc: "ŷ", Ycy: "Ы", ycy: "ы", yen: "¥", Yfr: "𝔜", yfr: "𝔶", YIcy: "Ї", yicy: "ї", Yopf: "𝕐", yopf: "𝕪", Yscr: "𝒴", yscr: "𝓎", YUcy: "Ю", yucy: "ю", yuml: "ÿ", Yuml: "Ÿ", Zacute: "Ź", zacute: "ź", Zcaron: "Ž", zcaron: "ž", Zcy: "З", zcy: "з", Zdot: "Ż", zdot: "ż", zeetrf: "ℨ", ZeroWidthSpace: "​", Zeta: "Ζ", zeta: "ζ", zfr: "𝔷", Zfr: "ℨ", ZHcy: "Ж", zhcy: "ж", zigrarr: "⇝", zopf: "𝕫", Zopf: "ℤ", Zscr: "𝒵", zscr: "𝓏", zwj: "\u200d", zwnj: "\u200c"
10661 };
10662
10663 var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
10664 var CHARCODE = /^#([0-9]+)$/;
10665 var NAMED = /^([A-Za-z0-9]+)$/;
10666 var EntityParser = /** @class */ (function () {
10667 function EntityParser(named) {
10668 this.named = named;
10669 }
10670 EntityParser.prototype.parse = function (entity) {
10671 if (!entity) {
10672 return;
10673 }
10674 var matches = entity.match(HEXCHARCODE);
10675 if (matches) {
10676 return String.fromCharCode(parseInt(matches[1], 16));
10677 }
10678 matches = entity.match(CHARCODE);
10679 if (matches) {
10680 return String.fromCharCode(parseInt(matches[1], 10));
10681 }
10682 matches = entity.match(NAMED);
10683 if (matches) {
10684 return this.named[matches[1]];
10685 }
10686 };
10687 return EntityParser;
10688 }());
10689
10690 var WSP = /[\t\n\f ]/;
10691 var ALPHA = /[A-Za-z]/;
10692 var CRLF = /\r\n?/g;
10693 function isSpace(char) {
10694 return WSP.test(char);
10695 }
10696 function isAlpha(char) {
10697 return ALPHA.test(char);
10698 }
10699 function preprocessInput(input) {
10700 return input.replace(CRLF, '\n');
10701 }
10702
10703 var EventedTokenizer = /** @class */ (function () {
10704 function EventedTokenizer(delegate, entityParser) {
10705 this.delegate = delegate;
10706 this.entityParser = entityParser;
10707 this.state = "beforeData" /* beforeData */;
10708 this.line = -1;
10709 this.column = -1;
10710 this.input = '';
10711 this.index = -1;
10712 this.tagNameBuffer = '';
10713 this.states = {
10714 beforeData: function () {
10715 var char = this.peek();
10716 if (char === '<') {
10717 this.transitionTo("tagOpen" /* tagOpen */);
10718 this.markTagStart();
10719 this.consume();
10720 }
10721 else {
10722 if (char === '\n') {
10723 var tag = this.tagNameBuffer.toLowerCase();
10724 if (tag === 'pre' || tag === 'textarea') {
10725 this.consume();
10726 }
10727 }
10728 this.transitionTo("data" /* data */);
10729 this.delegate.beginData();
10730 }
10731 },
10732 data: function () {
10733 var char = this.peek();
10734 if (char === '<') {
10735 this.delegate.finishData();
10736 this.transitionTo("tagOpen" /* tagOpen */);
10737 this.markTagStart();
10738 this.consume();
10739 }
10740 else if (char === '&') {
10741 this.consume();
10742 this.delegate.appendToData(this.consumeCharRef() || '&');
10743 }
10744 else {
10745 this.consume();
10746 this.delegate.appendToData(char);
10747 }
10748 },
10749 tagOpen: function () {
10750 var char = this.consume();
10751 if (char === '!') {
10752 this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
10753 }
10754 else if (char === '/') {
10755 this.transitionTo("endTagOpen" /* endTagOpen */);
10756 }
10757 else if (char === '@' || char === ':' || isAlpha(char)) {
10758 this.transitionTo("tagName" /* tagName */);
10759 this.tagNameBuffer = '';
10760 this.delegate.beginStartTag();
10761 this.appendToTagName(char);
10762 }
10763 },
10764 markupDeclarationOpen: function () {
10765 var char = this.consume();
10766 if (char === '-' && this.input.charAt(this.index) === '-') {
10767 this.consume();
10768 this.transitionTo("commentStart" /* commentStart */);
10769 this.delegate.beginComment();
10770 }
10771 },
10772 commentStart: function () {
10773 var char = this.consume();
10774 if (char === '-') {
10775 this.transitionTo("commentStartDash" /* commentStartDash */);
10776 }
10777 else if (char === '>') {
10778 this.delegate.finishComment();
10779 this.transitionTo("beforeData" /* beforeData */);
10780 }
10781 else {
10782 this.delegate.appendToCommentData(char);
10783 this.transitionTo("comment" /* comment */);
10784 }
10785 },
10786 commentStartDash: function () {
10787 var char = this.consume();
10788 if (char === '-') {
10789 this.transitionTo("commentEnd" /* commentEnd */);
10790 }
10791 else if (char === '>') {
10792 this.delegate.finishComment();
10793 this.transitionTo("beforeData" /* beforeData */);
10794 }
10795 else {
10796 this.delegate.appendToCommentData('-');
10797 this.transitionTo("comment" /* comment */);
10798 }
10799 },
10800 comment: function () {
10801 var char = this.consume();
10802 if (char === '-') {
10803 this.transitionTo("commentEndDash" /* commentEndDash */);
10804 }
10805 else {
10806 this.delegate.appendToCommentData(char);
10807 }
10808 },
10809 commentEndDash: function () {
10810 var char = this.consume();
10811 if (char === '-') {
10812 this.transitionTo("commentEnd" /* commentEnd */);
10813 }
10814 else {
10815 this.delegate.appendToCommentData('-' + char);
10816 this.transitionTo("comment" /* comment */);
10817 }
10818 },
10819 commentEnd: function () {
10820 var char = this.consume();
10821 if (char === '>') {
10822 this.delegate.finishComment();
10823 this.transitionTo("beforeData" /* beforeData */);
10824 }
10825 else {
10826 this.delegate.appendToCommentData('--' + char);
10827 this.transitionTo("comment" /* comment */);
10828 }
10829 },
10830 tagName: function () {
10831 var char = this.consume();
10832 if (isSpace(char)) {
10833 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10834 }
10835 else if (char === '/') {
10836 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10837 }
10838 else if (char === '>') {
10839 this.delegate.finishTag();
10840 this.transitionTo("beforeData" /* beforeData */);
10841 }
10842 else {
10843 this.appendToTagName(char);
10844 }
10845 },
10846 beforeAttributeName: function () {
10847 var char = this.peek();
10848 if (isSpace(char)) {
10849 this.consume();
10850 return;
10851 }
10852 else if (char === '/') {
10853 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10854 this.consume();
10855 }
10856 else if (char === '>') {
10857 this.consume();
10858 this.delegate.finishTag();
10859 this.transitionTo("beforeData" /* beforeData */);
10860 }
10861 else if (char === '=') {
10862 this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
10863 this.transitionTo("attributeName" /* attributeName */);
10864 this.delegate.beginAttribute();
10865 this.consume();
10866 this.delegate.appendToAttributeName(char);
10867 }
10868 else {
10869 this.transitionTo("attributeName" /* attributeName */);
10870 this.delegate.beginAttribute();
10871 }
10872 },
10873 attributeName: function () {
10874 var char = this.peek();
10875 if (isSpace(char)) {
10876 this.transitionTo("afterAttributeName" /* afterAttributeName */);
10877 this.consume();
10878 }
10879 else if (char === '/') {
10880 this.delegate.beginAttributeValue(false);
10881 this.delegate.finishAttributeValue();
10882 this.consume();
10883 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10884 }
10885 else if (char === '=') {
10886 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
10887 this.consume();
10888 }
10889 else if (char === '>') {
10890 this.delegate.beginAttributeValue(false);
10891 this.delegate.finishAttributeValue();
10892 this.consume();
10893 this.delegate.finishTag();
10894 this.transitionTo("beforeData" /* beforeData */);
10895 }
10896 else if (char === '"' || char === "'" || char === '<') {
10897 this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
10898 this.consume();
10899 this.delegate.appendToAttributeName(char);
10900 }
10901 else {
10902 this.consume();
10903 this.delegate.appendToAttributeName(char);
10904 }
10905 },
10906 afterAttributeName: function () {
10907 var char = this.peek();
10908 if (isSpace(char)) {
10909 this.consume();
10910 return;
10911 }
10912 else if (char === '/') {
10913 this.delegate.beginAttributeValue(false);
10914 this.delegate.finishAttributeValue();
10915 this.consume();
10916 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10917 }
10918 else if (char === '=') {
10919 this.consume();
10920 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
10921 }
10922 else if (char === '>') {
10923 this.delegate.beginAttributeValue(false);
10924 this.delegate.finishAttributeValue();
10925 this.consume();
10926 this.delegate.finishTag();
10927 this.transitionTo("beforeData" /* beforeData */);
10928 }
10929 else {
10930 this.delegate.beginAttributeValue(false);
10931 this.delegate.finishAttributeValue();
10932 this.transitionTo("attributeName" /* attributeName */);
10933 this.delegate.beginAttribute();
10934 this.consume();
10935 this.delegate.appendToAttributeName(char);
10936 }
10937 },
10938 beforeAttributeValue: function () {
10939 var char = this.peek();
10940 if (isSpace(char)) {
10941 this.consume();
10942 }
10943 else if (char === '"') {
10944 this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
10945 this.delegate.beginAttributeValue(true);
10946 this.consume();
10947 }
10948 else if (char === "'") {
10949 this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
10950 this.delegate.beginAttributeValue(true);
10951 this.consume();
10952 }
10953 else if (char === '>') {
10954 this.delegate.beginAttributeValue(false);
10955 this.delegate.finishAttributeValue();
10956 this.consume();
10957 this.delegate.finishTag();
10958 this.transitionTo("beforeData" /* beforeData */);
10959 }
10960 else {
10961 this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
10962 this.delegate.beginAttributeValue(false);
10963 this.consume();
10964 this.delegate.appendToAttributeValue(char);
10965 }
10966 },
10967 attributeValueDoubleQuoted: function () {
10968 var char = this.consume();
10969 if (char === '"') {
10970 this.delegate.finishAttributeValue();
10971 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
10972 }
10973 else if (char === '&') {
10974 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
10975 }
10976 else {
10977 this.delegate.appendToAttributeValue(char);
10978 }
10979 },
10980 attributeValueSingleQuoted: function () {
10981 var char = this.consume();
10982 if (char === "'") {
10983 this.delegate.finishAttributeValue();
10984 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
10985 }
10986 else if (char === '&') {
10987 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
10988 }
10989 else {
10990 this.delegate.appendToAttributeValue(char);
10991 }
10992 },
10993 attributeValueUnquoted: function () {
10994 var char = this.peek();
10995 if (isSpace(char)) {
10996 this.delegate.finishAttributeValue();
10997 this.consume();
10998 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10999 }
11000 else if (char === '/') {
11001 this.delegate.finishAttributeValue();
11002 this.consume();
11003 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11004 }
11005 else if (char === '&') {
11006 this.consume();
11007 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11008 }
11009 else if (char === '>') {
11010 this.delegate.finishAttributeValue();
11011 this.consume();
11012 this.delegate.finishTag();
11013 this.transitionTo("beforeData" /* beforeData */);
11014 }
11015 else {
11016 this.consume();
11017 this.delegate.appendToAttributeValue(char);
11018 }
11019 },
11020 afterAttributeValueQuoted: function () {
11021 var char = this.peek();
11022 if (isSpace(char)) {
11023 this.consume();
11024 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11025 }
11026 else if (char === '/') {
11027 this.consume();
11028 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11029 }
11030 else if (char === '>') {
11031 this.consume();
11032 this.delegate.finishTag();
11033 this.transitionTo("beforeData" /* beforeData */);
11034 }
11035 else {
11036 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11037 }
11038 },
11039 selfClosingStartTag: function () {
11040 var char = this.peek();
11041 if (char === '>') {
11042 this.consume();
11043 this.delegate.markTagAsSelfClosing();
11044 this.delegate.finishTag();
11045 this.transitionTo("beforeData" /* beforeData */);
11046 }
11047 else {
11048 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11049 }
11050 },
11051 endTagOpen: function () {
11052 var char = this.consume();
11053 if (char === '@' || char === ':' || isAlpha(char)) {
11054 this.transitionTo("tagName" /* tagName */);
11055 this.tagNameBuffer = '';
11056 this.delegate.beginEndTag();
11057 this.appendToTagName(char);
11058 }
11059 }
11060 };
11061 this.reset();
11062 }
11063 EventedTokenizer.prototype.reset = function () {
11064 this.transitionTo("beforeData" /* beforeData */);
11065 this.input = '';
11066 this.index = 0;
11067 this.line = 1;
11068 this.column = 0;
11069 this.delegate.reset();
11070 };
11071 EventedTokenizer.prototype.transitionTo = function (state) {
11072 this.state = state;
11073 };
11074 EventedTokenizer.prototype.tokenize = function (input) {
11075 this.reset();
11076 this.tokenizePart(input);
11077 this.tokenizeEOF();
11078 };
11079 EventedTokenizer.prototype.tokenizePart = function (input) {
11080 this.input += preprocessInput(input);
11081 while (this.index < this.input.length) {
11082 var handler = this.states[this.state];
11083 if (handler !== undefined) {
11084 handler.call(this);
11085 }
11086 else {
11087 throw new Error("unhandled state " + this.state);
11088 }
11089 }
11090 };
11091 EventedTokenizer.prototype.tokenizeEOF = function () {
11092 this.flushData();
11093 };
11094 EventedTokenizer.prototype.flushData = function () {
11095 if (this.state === 'data') {
11096 this.delegate.finishData();
11097 this.transitionTo("beforeData" /* beforeData */);
11098 }
11099 };
11100 EventedTokenizer.prototype.peek = function () {
11101 return this.input.charAt(this.index);
11102 };
11103 EventedTokenizer.prototype.consume = function () {
11104 var char = this.peek();
11105 this.index++;
11106 if (char === '\n') {
11107 this.line++;
11108 this.column = 0;
11109 }
11110 else {
11111 this.column++;
11112 }
11113 return char;
11114 };
11115 EventedTokenizer.prototype.consumeCharRef = function () {
11116 var endIndex = this.input.indexOf(';', this.index);
11117 if (endIndex === -1) {
11118 return;
11119 }
11120 var entity = this.input.slice(this.index, endIndex);
11121 var chars = this.entityParser.parse(entity);
11122 if (chars) {
11123 var count = entity.length;
11124 // consume the entity chars
11125 while (count) {
11126 this.consume();
11127 count--;
11128 }
11129 // consume the `;`
11130 this.consume();
11131 return chars;
11132 }
11133 };
11134 EventedTokenizer.prototype.markTagStart = function () {
11135 this.delegate.tagOpen();
11136 };
11137 EventedTokenizer.prototype.appendToTagName = function (char) {
11138 this.tagNameBuffer += char;
11139 this.delegate.appendToTagName(char);
11140 };
11141 return EventedTokenizer;
11142 }());
11143
11144 var Tokenizer = /** @class */ (function () {
11145 function Tokenizer(entityParser, options) {
11146 if (options === void 0) { options = {}; }
11147 this.options = options;
11148 this.token = null;
11149 this.startLine = 1;
11150 this.startColumn = 0;
11151 this.tokens = [];
11152 this.tokenizer = new EventedTokenizer(this, entityParser);
11153 this._currentAttribute = undefined;
11154 }
11155 Tokenizer.prototype.tokenize = function (input) {
11156 this.tokens = [];
11157 this.tokenizer.tokenize(input);
11158 return this.tokens;
11159 };
11160 Tokenizer.prototype.tokenizePart = function (input) {
11161 this.tokens = [];
11162 this.tokenizer.tokenizePart(input);
11163 return this.tokens;
11164 };
11165 Tokenizer.prototype.tokenizeEOF = function () {
11166 this.tokens = [];
11167 this.tokenizer.tokenizeEOF();
11168 return this.tokens[0];
11169 };
11170 Tokenizer.prototype.reset = function () {
11171 this.token = null;
11172 this.startLine = 1;
11173 this.startColumn = 0;
11174 };
11175 Tokenizer.prototype.current = function () {
11176 var token = this.token;
11177 if (token === null) {
11178 throw new Error('token was unexpectedly null');
11179 }
11180 if (arguments.length === 0) {
11181 return token;
11182 }
11183 for (var i = 0; i < arguments.length; i++) {
11184 if (token.type === arguments[i]) {
11185 return token;
11186 }
11187 }
11188 throw new Error("token type was unexpectedly " + token.type);
11189 };
11190 Tokenizer.prototype.push = function (token) {
11191 this.token = token;
11192 this.tokens.push(token);
11193 };
11194 Tokenizer.prototype.currentAttribute = function () {
11195 return this._currentAttribute;
11196 };
11197 Tokenizer.prototype.addLocInfo = function () {
11198 if (this.options.loc) {
11199 this.current().loc = {
11200 start: {
11201 line: this.startLine,
11202 column: this.startColumn
11203 },
11204 end: {
11205 line: this.tokenizer.line,
11206 column: this.tokenizer.column
11207 }
11208 };
11209 }
11210 this.startLine = this.tokenizer.line;
11211 this.startColumn = this.tokenizer.column;
11212 };
11213 // Data
11214 Tokenizer.prototype.beginData = function () {
11215 this.push({
11216 type: "Chars" /* Chars */,
11217 chars: ''
11218 });
11219 };
11220 Tokenizer.prototype.appendToData = function (char) {
11221 this.current("Chars" /* Chars */).chars += char;
11222 };
11223 Tokenizer.prototype.finishData = function () {
11224 this.addLocInfo();
11225 };
11226 // Comment
11227 Tokenizer.prototype.beginComment = function () {
11228 this.push({
11229 type: "Comment" /* Comment */,
11230 chars: ''
11231 });
11232 };
11233 Tokenizer.prototype.appendToCommentData = function (char) {
11234 this.current("Comment" /* Comment */).chars += char;
11235 };
11236 Tokenizer.prototype.finishComment = function () {
11237 this.addLocInfo();
11238 };
11239 // Tags - basic
11240 Tokenizer.prototype.tagOpen = function () { };
11241 Tokenizer.prototype.beginStartTag = function () {
11242 this.push({
11243 type: "StartTag" /* StartTag */,
11244 tagName: '',
11245 attributes: [],
11246 selfClosing: false
11247 });
11248 };
11249 Tokenizer.prototype.beginEndTag = function () {
11250 this.push({
11251 type: "EndTag" /* EndTag */,
11252 tagName: ''
11253 });
11254 };
11255 Tokenizer.prototype.finishTag = function () {
11256 this.addLocInfo();
11257 };
11258 Tokenizer.prototype.markTagAsSelfClosing = function () {
11259 this.current("StartTag" /* StartTag */).selfClosing = true;
11260 };
11261 // Tags - name
11262 Tokenizer.prototype.appendToTagName = function (char) {
11263 this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
11264 };
11265 // Tags - attributes
11266 Tokenizer.prototype.beginAttribute = function () {
11267 this._currentAttribute = ['', '', false];
11268 };
11269 Tokenizer.prototype.appendToAttributeName = function (char) {
11270 this.currentAttribute()[0] += char;
11271 };
11272 Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
11273 this.currentAttribute()[2] = isQuoted;
11274 };
11275 Tokenizer.prototype.appendToAttributeValue = function (char) {
11276 this.currentAttribute()[1] += char;
11277 };
11278 Tokenizer.prototype.finishAttributeValue = function () {
11279 this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
11280 };
11281 Tokenizer.prototype.reportSyntaxError = function (message) {
11282 this.current().syntaxError = message;
11283 };
11284 return Tokenizer;
11285 }());
11286
11287 function tokenize(input, options) {
11288 var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);
11289 return tokenizer.tokenize(input);
11290 }
11291
11292
11293
11294 // EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js
11295 var es6 = __webpack_require__(5619);
11296 var es6_default = /*#__PURE__*/__webpack_require__.n(es6);
11297 ;// CONCATENATED MODULE: external ["wp","htmlEntities"]
11298 const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
11299 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/logger.js
11300 /**
11301 * @typedef LoggerItem
11302 * @property {Function} log Which logger recorded the message
11303 * @property {Array<any>} args White arguments were supplied to the logger
11304 */
11305 function createLogger() {
11306 /**
11307 * Creates a log handler with block validation prefix.
11308 *
11309 * @param {Function} logger Original logger function.
11310 *
11311 * @return {Function} Augmented logger function.
11312 */
11313 function createLogHandler(logger) {
11314 let log = (message, ...args) => logger('Block validation: ' + message, ...args); // In test environments, pre-process string substitutions to improve
11315 // readability of error messages. We'd prefer to avoid pulling in this
11316 // dependency in runtime environments, and it can be dropped by a combo
11317 // of Webpack env substitution + UglifyJS dead code elimination.
11318
11319
11320 if (false) {}
11321
11322 return log;
11323 }
11324
11325 return {
11326 // eslint-disable-next-line no-console
11327 error: createLogHandler(console.error),
11328 // eslint-disable-next-line no-console
11329 warning: createLogHandler(console.warn),
11330
11331 getItems() {
11332 return [];
11333 }
11334
11335 };
11336 }
11337 function createQueuedLogger() {
11338 /**
11339 * The list of enqueued log actions to print.
11340 *
11341 * @type {Array<LoggerItem>}
11342 */
11343 const queue = [];
11344 const logger = createLogger();
11345 return {
11346 error(...args) {
11347 queue.push({
11348 log: logger.error,
11349 args
11350 });
11351 },
11352
11353 warning(...args) {
11354 queue.push({
11355 log: logger.warning,
11356 args
11357 });
11358 },
11359
11360 getItems() {
11361 return queue;
11362 }
11363
11364 };
11365 }
11366
11367 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/index.js
11368 /**
11369 * External dependencies
11370 */
11371
11372
11373 /**
11374 * WordPress dependencies
11375 */
11376
11377
11378
11379 /**
11380 * Internal dependencies
11381 */
11382
11383
11384
11385
11386
11387 /** @typedef {import('../parser').WPBlock} WPBlock */
11388
11389 /** @typedef {import('../registration').WPBlockType} WPBlockType */
11390
11391 /** @typedef {import('./logger').LoggerItem} LoggerItem */
11392
11393 const identity = x => x;
11394 /**
11395 * Globally matches any consecutive whitespace
11396 *
11397 * @type {RegExp}
11398 */
11399
11400
11401 const REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
11402 /**
11403 * Matches a string containing only whitespace
11404 *
11405 * @type {RegExp}
11406 */
11407
11408 const REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
11409 /**
11410 * Matches a CSS URL type value
11411 *
11412 * @type {RegExp}
11413 */
11414
11415 const REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
11416 /**
11417 * Boolean attributes are attributes whose presence as being assigned is
11418 * meaningful, even if only empty.
11419 *
11420 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
11421 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11422 *
11423 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11424 * .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
11425 * .reduce( ( result, tr ) => Object.assign( result, {
11426 * [ tr.firstChild.textContent.trim() ]: true
11427 * } ), {} ) ).sort();
11428 *
11429 * @type {Array}
11430 */
11431
11432 const BOOLEAN_ATTRIBUTES = ['allowfullscreen', 'allowpaymentrequest', 'allowusermedia', 'async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'download', 'formnovalidate', 'hidden', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'playsinline', 'readonly', 'required', 'reversed', 'selected', 'typemustmatch'];
11433 /**
11434 * Enumerated attributes are attributes which must be of a specific value form.
11435 * Like boolean attributes, these are meaningful if specified, even if not of a
11436 * valid enumerated value.
11437 *
11438 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
11439 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11440 *
11441 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11442 * .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
11443 * .reduce( ( result, tr ) => Object.assign( result, {
11444 * [ tr.firstChild.textContent.trim() ]: true
11445 * } ), {} ) ).sort();
11446 *
11447 * @type {Array}
11448 */
11449
11450 const ENUMERATED_ATTRIBUTES = ['autocapitalize', 'autocomplete', 'charset', 'contenteditable', 'crossorigin', 'decoding', 'dir', 'draggable', 'enctype', 'formenctype', 'formmethod', 'http-equiv', 'inputmode', 'kind', 'method', 'preload', 'scope', 'shape', 'spellcheck', 'translate', 'type', 'wrap'];
11451 /**
11452 * Meaningful attributes are those who cannot be safely ignored when omitted in
11453 * one HTML markup string and not another.
11454 *
11455 * @type {Array}
11456 */
11457
11458 const MEANINGFUL_ATTRIBUTES = [...BOOLEAN_ATTRIBUTES, ...ENUMERATED_ATTRIBUTES];
11459 /**
11460 * Array of functions which receive a text string on which to apply normalizing
11461 * behavior for consideration in text token equivalence, carefully ordered from
11462 * least-to-most expensive operations.
11463 *
11464 * @type {Array}
11465 */
11466
11467 const TEXT_NORMALIZATIONS = [identity, getTextWithCollapsedWhitespace];
11468 /**
11469 * Regular expression matching a named character reference. In lieu of bundling
11470 * a full set of references, the pattern covers the minimal necessary to test
11471 * positively against the full set.
11472 *
11473 * "The ampersand must be followed by one of the names given in the named
11474 * character references section, using the same case."
11475 *
11476 * Tested aginst "12.5 Named character references":
11477 *
11478 * ```
11479 * const references = Array.from( document.querySelectorAll(
11480 * '#named-character-references-table tr[id^=entity-] td:first-child'
11481 * ) ).map( ( code ) => code.textContent )
11482 * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
11483 * ```
11484 *
11485 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11486 * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
11487 *
11488 * @type {RegExp}
11489 */
11490
11491 const REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
11492 /**
11493 * Regular expression matching a decimal character reference.
11494 *
11495 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
11496 * followed by one or more ASCII digits, representing a base-ten integer"
11497 *
11498 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11499 *
11500 * @type {RegExp}
11501 */
11502
11503 const REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
11504 /**
11505 * Regular expression matching a hexadecimal character reference.
11506 *
11507 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
11508 * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
11509 * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
11510 * one or more ASCII hex digits, representing a hexadecimal integer"
11511 *
11512 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11513 *
11514 * @type {RegExp}
11515 */
11516
11517 const REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
11518 /**
11519 * Returns true if the given string is a valid character reference segment, or
11520 * false otherwise. The text should be stripped of `&` and `;` demarcations.
11521 *
11522 * @param {string} text Text to test.
11523 *
11524 * @return {boolean} Whether text is valid character reference.
11525 */
11526
11527 function isValidCharacterReference(text) {
11528 return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
11529 }
11530 /**
11531 * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
11532 * implementation of `decodeEntities` from `html-entities`, in order to avoid
11533 * bundling a massive named character reference.
11534 *
11535 * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts
11536 */
11537
11538 class DecodeEntityParser {
11539 /**
11540 * Returns a substitute string for an entity string sequence between `&`
11541 * and `;`, or undefined if no substitution should occur.
11542 *
11543 * @param {string} entity Entity fragment discovered in HTML.
11544 *
11545 * @return {string | undefined} Entity substitute value.
11546 */
11547 parse(entity) {
11548 if (isValidCharacterReference(entity)) {
11549 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)('&' + entity + ';');
11550 }
11551 }
11552
11553 }
11554 /**
11555 * Given a specified string, returns an array of strings split by consecutive
11556 * whitespace, ignoring leading or trailing whitespace.
11557 *
11558 * @param {string} text Original text.
11559 *
11560 * @return {string[]} Text pieces split on whitespace.
11561 */
11562
11563 function getTextPiecesSplitOnWhitespace(text) {
11564 return text.trim().split(REGEXP_WHITESPACE);
11565 }
11566 /**
11567 * Given a specified string, returns a new trimmed string where all consecutive
11568 * whitespace is collapsed to a single space.
11569 *
11570 * @param {string} text Original text.
11571 *
11572 * @return {string} Trimmed text with consecutive whitespace collapsed.
11573 */
11574
11575 function getTextWithCollapsedWhitespace(text) {
11576 // This is an overly simplified whitespace comparison. The specification is
11577 // more prescriptive of whitespace behavior in inline and block contexts.
11578 //
11579 // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
11580 return getTextPiecesSplitOnWhitespace(text).join(' ');
11581 }
11582 /**
11583 * Returns attribute pairs of the given StartTag token, including only pairs
11584 * where the value is non-empty or the attribute is a boolean attribute, an
11585 * enumerated attribute, or a custom data- attribute.
11586 *
11587 * @see MEANINGFUL_ATTRIBUTES
11588 *
11589 * @param {Object} token StartTag token.
11590 *
11591 * @return {Array[]} Attribute pairs.
11592 */
11593
11594 function getMeaningfulAttributePairs(token) {
11595 return token.attributes.filter(pair => {
11596 const [key, value] = pair;
11597 return value || key.indexOf('data-') === 0 || MEANINGFUL_ATTRIBUTES.includes(key);
11598 });
11599 }
11600 /**
11601 * Returns true if two text tokens (with `chars` property) are equivalent, or
11602 * false otherwise.
11603 *
11604 * @param {Object} actual Actual token.
11605 * @param {Object} expected Expected token.
11606 * @param {Object} logger Validation logger object.
11607 *
11608 * @return {boolean} Whether two text tokens are equivalent.
11609 */
11610
11611 function isEquivalentTextTokens(actual, expected, logger = createLogger()) {
11612 // This function is intentionally written as syntactically "ugly" as a hot
11613 // path optimization. Text is progressively normalized in order from least-
11614 // to-most operationally expensive, until the earliest point at which text
11615 // can be confidently inferred as being equal.
11616 let actualChars = actual.chars;
11617 let expectedChars = expected.chars;
11618
11619 for (let i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
11620 const normalize = TEXT_NORMALIZATIONS[i];
11621 actualChars = normalize(actualChars);
11622 expectedChars = normalize(expectedChars);
11623
11624 if (actualChars === expectedChars) {
11625 return true;
11626 }
11627 }
11628
11629 logger.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
11630 return false;
11631 }
11632 /**
11633 * Given a CSS length value, returns a normalized CSS length value for strict equality
11634 * comparison.
11635 *
11636 * @param {string} value CSS length value.
11637 *
11638 * @return {string} Normalized CSS length value.
11639 */
11640
11641 function getNormalizedLength(value) {
11642 if (0 === parseFloat(value)) {
11643 return '0';
11644 } // Normalize strings with floats to always include a leading zero.
11645
11646
11647 if (value.indexOf('.') === 0) {
11648 return '0' + value;
11649 }
11650
11651 return value;
11652 }
11653 /**
11654 * Given a style value, returns a normalized style value for strict equality
11655 * comparison.
11656 *
11657 * @param {string} value Style value.
11658 *
11659 * @return {string} Normalized style value.
11660 */
11661
11662 function getNormalizedStyleValue(value) {
11663 const textPieces = getTextPiecesSplitOnWhitespace(value);
11664 const normalizedPieces = textPieces.map(getNormalizedLength);
11665 const result = normalizedPieces.join(' ');
11666 return result // Normalize URL type to omit whitespace or quotes.
11667 .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
11668 }
11669 /**
11670 * Given a style attribute string, returns an object of style properties.
11671 *
11672 * @param {string} text Style attribute.
11673 *
11674 * @return {Object} Style properties.
11675 */
11676
11677 function getStyleProperties(text) {
11678 const pairs = text // Trim ending semicolon (avoid including in split)
11679 .replace(/;?\s*$/, '') // Split on property assignment.
11680 .split(';') // For each property assignment...
11681 .map(style => {
11682 // ...split further into key-value pairs.
11683 const [key, ...valueParts] = style.split(':');
11684 const value = valueParts.join(':');
11685 return [key.trim(), getNormalizedStyleValue(value.trim())];
11686 });
11687 return Object.fromEntries(pairs);
11688 }
11689 /**
11690 * Attribute-specific equality handlers
11691 *
11692 * @type {Object}
11693 */
11694
11695 const isEqualAttributesOfName = {
11696 class: (actual, expected) => {
11697 // Class matches if members are the same, even if out of order or
11698 // superfluous whitespace between.
11699 const [actualPieces, expectedPieces] = [actual, expected].map(getTextPiecesSplitOnWhitespace);
11700 const actualDiff = actualPieces.filter(c => !expectedPieces.includes(c));
11701 const expectedDiff = expectedPieces.filter(c => !actualPieces.includes(c));
11702 return actualDiff.length === 0 && expectedDiff.length === 0;
11703 },
11704 style: (actual, expected) => {
11705 return es6_default()(...[actual, expected].map(getStyleProperties));
11706 },
11707 // For each boolean attribute, mere presence of attribute in both is enough
11708 // to assume equivalence.
11709 ...Object.fromEntries(BOOLEAN_ATTRIBUTES.map(attribute => [attribute, () => true]))
11710 };
11711 /**
11712 * Given two sets of attribute tuples, returns true if the attribute sets are
11713 * equivalent.
11714 *
11715 * @param {Array[]} actual Actual attributes tuples.
11716 * @param {Array[]} expected Expected attributes tuples.
11717 * @param {Object} logger Validation logger object.
11718 *
11719 * @return {boolean} Whether attributes are equivalent.
11720 */
11721
11722 function isEqualTagAttributePairs(actual, expected, logger = createLogger()) {
11723 // Attributes is tokenized as tuples. Their lengths should match. This also
11724 // avoids us needing to check both attributes sets, since if A has any keys
11725 // which do not exist in B, we know the sets to be different.
11726 if (actual.length !== expected.length) {
11727 logger.warning('Expected attributes %o, instead saw %o.', expected, actual);
11728 return false;
11729 } // Attributes are not guaranteed to occur in the same order. For validating
11730 // actual attributes, first convert the set of expected attribute values to
11731 // an object, for lookup by key.
11732
11733
11734 const expectedAttributes = {};
11735
11736 for (let i = 0; i < expected.length; i++) {
11737 expectedAttributes[expected[i][0].toLowerCase()] = expected[i][1];
11738 }
11739
11740 for (let i = 0; i < actual.length; i++) {
11741 const [name, actualValue] = actual[i];
11742 const nameLower = name.toLowerCase(); // As noted above, if missing member in B, assume different.
11743
11744 if (!expectedAttributes.hasOwnProperty(nameLower)) {
11745 logger.warning('Encountered unexpected attribute `%s`.', name);
11746 return false;
11747 }
11748
11749 const expectedValue = expectedAttributes[nameLower];
11750 const isEqualAttributes = isEqualAttributesOfName[nameLower];
11751
11752 if (isEqualAttributes) {
11753 // Defer custom attribute equality handling.
11754 if (!isEqualAttributes(actualValue, expectedValue)) {
11755 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11756 return false;
11757 }
11758 } else if (actualValue !== expectedValue) {
11759 // Otherwise strict inequality should bail.
11760 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11761 return false;
11762 }
11763 }
11764
11765 return true;
11766 }
11767 /**
11768 * Token-type-specific equality handlers
11769 *
11770 * @type {Object}
11771 */
11772
11773 const isEqualTokensOfType = {
11774 StartTag: (actual, expected, logger = createLogger()) => {
11775 if (actual.tagName !== expected.tagName && // Optimization: Use short-circuit evaluation to defer case-
11776 // insensitive check on the assumption that the majority case will
11777 // have exactly equal tag names.
11778 actual.tagName.toLowerCase() !== expected.tagName.toLowerCase()) {
11779 logger.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
11780 return false;
11781 }
11782
11783 return isEqualTagAttributePairs(...[actual, expected].map(getMeaningfulAttributePairs), logger);
11784 },
11785 Chars: isEquivalentTextTokens,
11786 Comment: isEquivalentTextTokens
11787 };
11788 /**
11789 * Given an array of tokens, returns the first token which is not purely
11790 * whitespace.
11791 *
11792 * Mutates the tokens array.
11793 *
11794 * @param {Object[]} tokens Set of tokens to search.
11795 *
11796 * @return {Object | undefined} Next non-whitespace token.
11797 */
11798
11799 function getNextNonWhitespaceToken(tokens) {
11800 let token;
11801
11802 while (token = tokens.shift()) {
11803 if (token.type !== 'Chars') {
11804 return token;
11805 }
11806
11807 if (!REGEXP_ONLY_WHITESPACE.test(token.chars)) {
11808 return token;
11809 }
11810 }
11811 }
11812 /**
11813 * Tokenize an HTML string, gracefully handling any errors thrown during
11814 * underlying tokenization.
11815 *
11816 * @param {string} html HTML string to tokenize.
11817 * @param {Object} logger Validation logger object.
11818 *
11819 * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error
11820 */
11821
11822 function getHTMLTokens(html, logger = createLogger()) {
11823 try {
11824 return new Tokenizer(new DecodeEntityParser()).tokenize(html);
11825 } catch (e) {
11826 logger.warning('Malformed HTML detected: %s', html);
11827 }
11828
11829 return null;
11830 }
11831 /**
11832 * Returns true if the next HTML token closes the current token.
11833 *
11834 * @param {Object} currentToken Current token to compare with.
11835 * @param {Object|undefined} nextToken Next token to compare against.
11836 *
11837 * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise
11838 */
11839
11840
11841 function isClosedByToken(currentToken, nextToken) {
11842 // Ensure this is a self closed token.
11843 if (!currentToken.selfClosing) {
11844 return false;
11845 } // Check token names and determine if nextToken is the closing tag for currentToken.
11846
11847
11848 if (nextToken && nextToken.tagName === currentToken.tagName && nextToken.type === 'EndTag') {
11849 return true;
11850 }
11851
11852 return false;
11853 }
11854 /**
11855 * Returns true if the given HTML strings are effectively equivalent, or
11856 * false otherwise. Invalid HTML is not considered equivalent, even if the
11857 * strings directly match.
11858 *
11859 * @param {string} actual Actual HTML string.
11860 * @param {string} expected Expected HTML string.
11861 * @param {Object} logger Validation logger object.
11862 *
11863 * @return {boolean} Whether HTML strings are equivalent.
11864 */
11865
11866 function isEquivalentHTML(actual, expected, logger = createLogger()) {
11867 // Short-circuit if markup is identical.
11868 if (actual === expected) {
11869 return true;
11870 } // Tokenize input content and reserialized save content.
11871
11872
11873 const [actualTokens, expectedTokens] = [actual, expected].map(html => getHTMLTokens(html, logger)); // If either is malformed then stop comparing - the strings are not equivalent.
11874
11875 if (!actualTokens || !expectedTokens) {
11876 return false;
11877 }
11878
11879 let actualToken, expectedToken;
11880
11881 while (actualToken = getNextNonWhitespaceToken(actualTokens)) {
11882 expectedToken = getNextNonWhitespaceToken(expectedTokens); // Inequal if exhausted all expected tokens.
11883
11884 if (!expectedToken) {
11885 logger.warning('Expected end of content, instead saw %o.', actualToken);
11886 return false;
11887 } // Inequal if next non-whitespace token of each set are not same type.
11888
11889
11890 if (actualToken.type !== expectedToken.type) {
11891 logger.warning('Expected token of type `%s` (%o), instead saw `%s` (%o).', expectedToken.type, expectedToken, actualToken.type, actualToken);
11892 return false;
11893 } // Defer custom token type equality handling, otherwise continue and
11894 // assume as equal.
11895
11896
11897 const isEqualTokens = isEqualTokensOfType[actualToken.type];
11898
11899 if (isEqualTokens && !isEqualTokens(actualToken, expectedToken, logger)) {
11900 return false;
11901 } // Peek at the next tokens (actual and expected) to see if they close
11902 // a self-closing tag.
11903
11904
11905 if (isClosedByToken(actualToken, expectedTokens[0])) {
11906 // Consume the next expected token that closes the current actual
11907 // self-closing token.
11908 getNextNonWhitespaceToken(expectedTokens);
11909 } else if (isClosedByToken(expectedToken, actualTokens[0])) {
11910 // Consume the next actual token that closes the current expected
11911 // self-closing token.
11912 getNextNonWhitespaceToken(actualTokens);
11913 }
11914 }
11915
11916 if (expectedToken = getNextNonWhitespaceToken(expectedTokens)) {
11917 // If any non-whitespace tokens remain in expected token set, this
11918 // indicates inequality.
11919 logger.warning('Expected %o, instead saw end of content.', expectedToken);
11920 return false;
11921 }
11922
11923 return true;
11924 }
11925 /**
11926 * Returns an object with `isValid` property set to `true` if the parsed block
11927 * is valid given the input content. A block is considered valid if, when serialized
11928 * with assumed attributes, the content matches the original value. If block is
11929 * invalid, this function returns all validations issues as well.
11930 *
11931 * @param {string|Object} blockTypeOrName Block type.
11932 * @param {Object} attributes Parsed block attributes.
11933 * @param {string} originalBlockContent Original block content.
11934 * @param {Object} logger Validation logger object.
11935 *
11936 * @return {Object} Whether block is valid and contains validation messages.
11937 */
11938
11939 /**
11940 * Returns an object with `isValid` property set to `true` if the parsed block
11941 * is valid given the input content. A block is considered valid if, when serialized
11942 * with assumed attributes, the content matches the original value. If block is
11943 * invalid, this function returns all validations issues as well.
11944 *
11945 * @param {WPBlock} block block object.
11946 * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.
11947 *
11948 * @return {[boolean,Array<LoggerItem>]} validation results.
11949 */
11950
11951 function validateBlock(block, blockTypeOrName = block.name) {
11952 const isFallbackBlock = block.name === getFreeformContentHandlerName() || block.name === getUnregisteredTypeHandlerName(); // Shortcut to avoid costly validation.
11953
11954 if (isFallbackBlock) {
11955 return [true, []];
11956 }
11957
11958 const logger = createQueuedLogger();
11959 const blockType = normalizeBlockType(blockTypeOrName);
11960 let generatedBlockContent;
11961
11962 try {
11963 generatedBlockContent = getSaveContent(blockType, block.attributes);
11964 } catch (error) {
11965 logger.error('Block validation failed because an error occurred while generating block content:\n\n%s', error.toString());
11966 return [false, logger.getItems()];
11967 }
11968
11969 const isValid = isEquivalentHTML(block.originalContent, generatedBlockContent, logger);
11970
11971 if (!isValid) {
11972 logger.error('Block validation failed for `%s` (%o).\n\nContent generated by `save` function:\n\n%s\n\nContent retrieved from post body:\n\n%s', blockType.name, blockType, generatedBlockContent, block.originalContent);
11973 }
11974
11975 return [isValid, logger.getItems()];
11976 }
11977 /**
11978 * Returns true if the parsed block is valid given the input content. A block
11979 * is considered valid if, when serialized with assumed attributes, the content
11980 * matches the original value.
11981 *
11982 * Logs to console in development environments when invalid.
11983 *
11984 * @deprecated Use validateBlock instead to avoid data loss.
11985 *
11986 * @param {string|Object} blockTypeOrName Block type.
11987 * @param {Object} attributes Parsed block attributes.
11988 * @param {string} originalBlockContent Original block content.
11989 *
11990 * @return {boolean} Whether block is valid.
11991 */
11992
11993 function isValidBlockContent(blockTypeOrName, attributes, originalBlockContent) {
11994 external_wp_deprecated_default()('isValidBlockContent introduces opportunity for data loss', {
11995 since: '12.6',
11996 plugin: 'Gutenberg',
11997 alternative: 'validateBlock'
11998 });
11999 const blockType = normalizeBlockType(blockTypeOrName);
12000 const block = {
12001 name: blockType.name,
12002 attributes,
12003 innerBlocks: [],
12004 originalContent: originalBlockContent
12005 };
12006 const [isValid] = validateBlock(block, blockType);
12007 return isValid;
12008 }
12009
12010 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/convert-legacy-block.js
12011 /**
12012 * Convert legacy blocks to their canonical form. This function is used
12013 * both in the parser level for previous content and to convert such blocks
12014 * used in Custom Post Types templates.
12015 *
12016 * @param {string} name The block's name
12017 * @param {Object} attributes The block's attributes
12018 *
12019 * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found
12020 */
12021 function convertLegacyBlockNameAndAttributes(name, attributes) {
12022 const newAttributes = { ...attributes
12023 }; // Convert 'core/cover-image' block in existing content to 'core/cover'.
12024
12025 if ('core/cover-image' === name) {
12026 name = 'core/cover';
12027 } // Convert 'core/text' blocks in existing content to 'core/paragraph'.
12028
12029
12030 if ('core/text' === name || 'core/cover-text' === name) {
12031 name = 'core/paragraph';
12032 } // Convert derivative blocks such as 'core/social-link-wordpress' to the
12033 // canonical form 'core/social-link'.
12034
12035
12036 if (name && name.indexOf('core/social-link-') === 0) {
12037 // Capture `social-link-wordpress` into `{"service":"wordpress"}`
12038 newAttributes.service = name.substring(17);
12039 name = 'core/social-link';
12040 } // Convert derivative blocks such as 'core-embed/instagram' to the
12041 // canonical form 'core/embed'.
12042
12043
12044 if (name && name.indexOf('core-embed/') === 0) {
12045 // Capture `core-embed/instagram` into `{"providerNameSlug":"instagram"}`
12046 const providerSlug = name.substring(11);
12047 const deprecated = {
12048 speaker: 'speaker-deck',
12049 polldaddy: 'crowdsignal'
12050 };
12051 newAttributes.providerNameSlug = providerSlug in deprecated ? deprecated[providerSlug] : providerSlug; // This is needed as the `responsive` attribute was passed
12052 // in a different way before the refactoring to block variations.
12053
12054 if (!['amazon-kindle', 'wordpress'].includes(providerSlug)) {
12055 newAttributes.responsive = true;
12056 }
12057
12058 name = 'core/embed';
12059 } // Convert Post Comment blocks in existing content to Comment blocks.
12060 // TODO: Remove these checks when WordPress 6.0 is released.
12061
12062
12063 if (name === 'core/post-comment-author') {
12064 name = 'core/comment-author-name';
12065 }
12066
12067 if (name === 'core/post-comment-content') {
12068 name = 'core/comment-content';
12069 }
12070
12071 if (name === 'core/post-comment-date') {
12072 name = 'core/comment-date';
12073 }
12074
12075 if (name === 'core/comments-query-loop') {
12076 name = 'core/comments';
12077 const {
12078 className = ''
12079 } = newAttributes;
12080
12081 if (!className.includes('wp-block-comments-query-loop')) {
12082 newAttributes.className = ['wp-block-comments-query-loop', className].join(' ');
12083 } // Note that we also had to add a deprecation to the block in order
12084 // for the ID change to work.
12085
12086 }
12087
12088 if (name === 'core/post-comments') {
12089 name = 'core/comments';
12090 newAttributes.legacy = true;
12091 }
12092
12093 return [name, newAttributes];
12094 }
12095
12096 ;// CONCATENATED MODULE: ./node_modules/hpq/es/get-path.js
12097 /**
12098 * Given object and string of dot-delimited path segments, returns value at
12099 * path or undefined if path cannot be resolved.
12100 *
12101 * @param {Object} object Lookup object
12102 * @param {string} path Path to resolve
12103 * @return {?*} Resolved value
12104 */
12105 function getPath(object, path) {
12106 var segments = path.split('.');
12107 var segment;
12108
12109 while (segment = segments.shift()) {
12110 if (!(segment in object)) {
12111 return;
12112 }
12113
12114 object = object[segment];
12115 }
12116
12117 return object;
12118 }
12119 ;// CONCATENATED MODULE: ./node_modules/hpq/es/index.js
12120 /**
12121 * Internal dependencies
12122 */
12123
12124 /**
12125 * Function returning a DOM document created by `createHTMLDocument`. The same
12126 * document is returned between invocations.
12127 *
12128 * @return {Document} DOM document.
12129 */
12130
12131 var getDocument = function () {
12132 var doc;
12133 return function () {
12134 if (!doc) {
12135 doc = document.implementation.createHTMLDocument('');
12136 }
12137
12138 return doc;
12139 };
12140 }();
12141 /**
12142 * Given a markup string or DOM element, creates an object aligning with the
12143 * shape of the matchers object, or the value returned by the matcher.
12144 *
12145 * @param {(string|Element)} source Source content
12146 * @param {(Object|Function)} matchers Matcher function or object of matchers
12147 * @return {(Object|*)} Matched value(s), shaped by object
12148 */
12149
12150
12151 function parse(source, matchers) {
12152 if (!matchers) {
12153 return;
12154 } // Coerce to element
12155
12156
12157 if ('string' === typeof source) {
12158 var doc = getDocument();
12159 doc.body.innerHTML = source;
12160 source = doc.body;
12161 } // Return singular value
12162
12163
12164 if ('function' === typeof matchers) {
12165 return matchers(source);
12166 } // Bail if we can't handle matchers
12167
12168
12169 if (Object !== matchers.constructor) {
12170 return;
12171 } // Shape result by matcher object
12172
12173
12174 return Object.keys(matchers).reduce(function (memo, key) {
12175 memo[key] = parse(source, matchers[key]);
12176 return memo;
12177 }, {});
12178 }
12179 /**
12180 * Generates a function which matches node of type selector, returning an
12181 * attribute by property if the attribute exists. If no selector is passed,
12182 * returns property of the query element.
12183 *
12184 * @param {?string} selector Optional selector
12185 * @param {string} name Property name
12186 * @return {*} Property value
12187 */
12188
12189 function prop(selector, name) {
12190 if (1 === arguments.length) {
12191 name = selector;
12192 selector = undefined;
12193 }
12194
12195 return function (node) {
12196 var match = node;
12197
12198 if (selector) {
12199 match = node.querySelector(selector);
12200 }
12201
12202 if (match) {
12203 return getPath(match, name);
12204 }
12205 };
12206 }
12207 /**
12208 * Generates a function which matches node of type selector, returning an
12209 * attribute by name if the attribute exists. If no selector is passed,
12210 * returns attribute of the query element.
12211 *
12212 * @param {?string} selector Optional selector
12213 * @param {string} name Attribute name
12214 * @return {?string} Attribute value
12215 */
12216
12217 function attr(selector, name) {
12218 if (1 === arguments.length) {
12219 name = selector;
12220 selector = undefined;
12221 }
12222
12223 return function (node) {
12224 var attributes = prop(selector, 'attributes')(node);
12225
12226 if (attributes && attributes.hasOwnProperty(name)) {
12227 return attributes[name].value;
12228 }
12229 };
12230 }
12231 /**
12232 * Convenience for `prop( selector, 'innerHTML' )`.
12233 *
12234 * @see prop()
12235 *
12236 * @param {?string} selector Optional selector
12237 * @return {string} Inner HTML
12238 */
12239
12240 function html(selector) {
12241 return prop(selector, 'innerHTML');
12242 }
12243 /**
12244 * Convenience for `prop( selector, 'textContent' )`.
12245 *
12246 * @see prop()
12247 *
12248 * @param {?string} selector Optional selector
12249 * @return {string} Text content
12250 */
12251
12252 function es_text(selector) {
12253 return prop(selector, 'textContent');
12254 }
12255 /**
12256 * Creates a new matching context by first finding elements matching selector
12257 * using querySelectorAll before then running another `parse` on `matchers`
12258 * scoped to the matched elements.
12259 *
12260 * @see parse()
12261 *
12262 * @param {string} selector Selector to match
12263 * @param {(Object|Function)} matchers Matcher function or object of matchers
12264 * @return {Array.<*,Object>} Array of matched value(s)
12265 */
12266
12267 function query(selector, matchers) {
12268 return function (node) {
12269 var matches = node.querySelectorAll(selector);
12270 return [].map.call(matches, function (match) {
12271 return parse(match, matchers);
12272 });
12273 };
12274 }
12275 ;// CONCATENATED MODULE: ./node_modules/memize/dist/index.js
12276 /**
12277 * Memize options object.
12278 *
12279 * @typedef MemizeOptions
12280 *
12281 * @property {number} [maxSize] Maximum size of the cache.
12282 */
12283
12284 /**
12285 * Internal cache entry.
12286 *
12287 * @typedef MemizeCacheNode
12288 *
12289 * @property {?MemizeCacheNode|undefined} [prev] Previous node.
12290 * @property {?MemizeCacheNode|undefined} [next] Next node.
12291 * @property {Array<*>} args Function arguments for cache
12292 * entry.
12293 * @property {*} val Function result.
12294 */
12295
12296 /**
12297 * Properties of the enhanced function for controlling cache.
12298 *
12299 * @typedef MemizeMemoizedFunction
12300 *
12301 * @property {()=>void} clear Clear the cache.
12302 */
12303
12304 /**
12305 * Accepts a function to be memoized, and returns a new memoized function, with
12306 * optional options.
12307 *
12308 * @template {(...args: any[]) => any} F
12309 *
12310 * @param {F} fn Function to memoize.
12311 * @param {MemizeOptions} [options] Options object.
12312 *
12313 * @return {((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction} Memoized function.
12314 */
12315 function memize(fn, options) {
12316 var size = 0;
12317
12318 /** @type {?MemizeCacheNode|undefined} */
12319 var head;
12320
12321 /** @type {?MemizeCacheNode|undefined} */
12322 var tail;
12323
12324 options = options || {};
12325
12326 function memoized(/* ...args */) {
12327 var node = head,
12328 len = arguments.length,
12329 args,
12330 i;
12331
12332 searchCache: while (node) {
12333 // Perform a shallow equality test to confirm that whether the node
12334 // under test is a candidate for the arguments passed. Two arrays
12335 // are shallowly equal if their length matches and each entry is
12336 // strictly equal between the two sets. Avoid abstracting to a
12337 // function which could incur an arguments leaking deoptimization.
12338
12339 // Check whether node arguments match arguments length
12340 if (node.args.length !== arguments.length) {
12341 node = node.next;
12342 continue;
12343 }
12344
12345 // Check whether node arguments match arguments values
12346 for (i = 0; i < len; i++) {
12347 if (node.args[i] !== arguments[i]) {
12348 node = node.next;
12349 continue searchCache;
12350 }
12351 }
12352
12353 // At this point we can assume we've found a match
12354
12355 // Surface matched node to head if not already
12356 if (node !== head) {
12357 // As tail, shift to previous. Must only shift if not also
12358 // head, since if both head and tail, there is no previous.
12359 if (node === tail) {
12360 tail = node.prev;
12361 }
12362
12363 // Adjust siblings to point to each other. If node was tail,
12364 // this also handles new tail's empty `next` assignment.
12365 /** @type {MemizeCacheNode} */ (node.prev).next = node.next;
12366 if (node.next) {
12367 node.next.prev = node.prev;
12368 }
12369
12370 node.next = head;
12371 node.prev = null;
12372 /** @type {MemizeCacheNode} */ (head).prev = node;
12373 head = node;
12374 }
12375
12376 // Return immediately
12377 return node.val;
12378 }
12379
12380 // No cached value found. Continue to insertion phase:
12381
12382 // Create a copy of arguments (avoid leaking deoptimization)
12383 args = new Array(len);
12384 for (i = 0; i < len; i++) {
12385 args[i] = arguments[i];
12386 }
12387
12388 node = {
12389 args: args,
12390
12391 // Generate the result from original function
12392 val: fn.apply(null, args),
12393 };
12394
12395 // Don't need to check whether node is already head, since it would
12396 // have been returned above already if it was
12397
12398 // Shift existing head down list
12399 if (head) {
12400 head.prev = node;
12401 node.next = head;
12402 } else {
12403 // If no head, follows that there's no tail (at initial or reset)
12404 tail = node;
12405 }
12406
12407 // Trim tail if we're reached max size and are pending cache insertion
12408 if (size === /** @type {MemizeOptions} */ (options).maxSize) {
12409 tail = /** @type {MemizeCacheNode} */ (tail).prev;
12410 /** @type {MemizeCacheNode} */ (tail).next = null;
12411 } else {
12412 size++;
12413 }
12414
12415 head = node;
12416
12417 return node.val;
12418 }
12419
12420 memoized.clear = function () {
12421 head = null;
12422 tail = null;
12423 size = 0;
12424 };
12425
12426 // Ignore reason: There's not a clear solution to create an intersection of
12427 // the function with additional properties, where the goal is to retain the
12428 // function signature of the incoming argument and add control properties
12429 // on the return value.
12430
12431 // @ts-ignore
12432 return memoized;
12433 }
12434
12435
12436
12437 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/matchers.js
12438 /**
12439 * External dependencies
12440 */
12441
12442 /**
12443 * Internal dependencies
12444 */
12445
12446
12447
12448 function matchers_html(selector, multilineTag) {
12449 return domNode => {
12450 let match = domNode;
12451
12452 if (selector) {
12453 match = domNode.querySelector(selector);
12454 }
12455
12456 if (!match) {
12457 return '';
12458 }
12459
12460 if (multilineTag) {
12461 let value = '';
12462 const length = match.children.length;
12463
12464 for (let index = 0; index < length; index++) {
12465 const child = match.children[index];
12466
12467 if (child.nodeName.toLowerCase() !== multilineTag) {
12468 continue;
12469 }
12470
12471 value += child.outerHTML;
12472 }
12473
12474 return value;
12475 }
12476
12477 return match.innerHTML;
12478 };
12479 }
12480
12481 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/node.js
12482 /**
12483 * WordPress dependencies
12484 */
12485
12486 /**
12487 * Internal dependencies
12488 */
12489
12490
12491 /**
12492 * A representation of a single node within a block's rich text value. If
12493 * representing a text node, the value is simply a string of the node value.
12494 * As representing an element node, it is an object of:
12495 *
12496 * 1. `type` (string): Tag name.
12497 * 2. `props` (object): Attributes and children array of WPBlockNode.
12498 *
12499 * @typedef {string|Object} WPBlockNode
12500 */
12501
12502 /**
12503 * Given a single node and a node type (e.g. `'br'`), returns true if the node
12504 * corresponds to that type, false otherwise.
12505 *
12506 * @param {WPBlockNode} node Block node to test
12507 * @param {string} type Node to type to test against.
12508 *
12509 * @return {boolean} Whether node is of intended type.
12510 */
12511
12512 function isNodeOfType(node, type) {
12513 external_wp_deprecated_default()('wp.blocks.node.isNodeOfType', {
12514 since: '6.1',
12515 version: '6.3',
12516 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12517 });
12518 return node && node.type === type;
12519 }
12520 /**
12521 * Given an object implementing the NamedNodeMap interface, returns a plain
12522 * object equivalent value of name, value key-value pairs.
12523 *
12524 * @see https://dom.spec.whatwg.org/#interface-namednodemap
12525 *
12526 * @param {NamedNodeMap} nodeMap NamedNodeMap to convert to object.
12527 *
12528 * @return {Object} Object equivalent value of NamedNodeMap.
12529 */
12530
12531
12532 function getNamedNodeMapAsObject(nodeMap) {
12533 const result = {};
12534
12535 for (let i = 0; i < nodeMap.length; i++) {
12536 const {
12537 name,
12538 value
12539 } = nodeMap[i];
12540 result[name] = value;
12541 }
12542
12543 return result;
12544 }
12545 /**
12546 * Given a DOM Element or Text node, returns an equivalent block node. Throws
12547 * if passed any node type other than element or text.
12548 *
12549 * @throws {TypeError} If non-element/text node is passed.
12550 *
12551 * @param {Node} domNode DOM node to convert.
12552 *
12553 * @return {WPBlockNode} Block node equivalent to DOM node.
12554 */
12555
12556 function fromDOM(domNode) {
12557 external_wp_deprecated_default()('wp.blocks.node.fromDOM', {
12558 since: '6.1',
12559 version: '6.3',
12560 alternative: 'wp.richText.create',
12561 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12562 });
12563
12564 if (domNode.nodeType === domNode.TEXT_NODE) {
12565 return domNode.nodeValue;
12566 }
12567
12568 if (domNode.nodeType !== domNode.ELEMENT_NODE) {
12569 throw new TypeError('A block node can only be created from a node of type text or ' + 'element.');
12570 }
12571
12572 return {
12573 type: domNode.nodeName.toLowerCase(),
12574 props: { ...getNamedNodeMapAsObject(domNode.attributes),
12575 children: children_fromDOM(domNode.childNodes)
12576 }
12577 };
12578 }
12579 /**
12580 * Given a block node, returns its HTML string representation.
12581 *
12582 * @param {WPBlockNode} node Block node to convert to string.
12583 *
12584 * @return {string} String HTML representation of block node.
12585 */
12586
12587 function toHTML(node) {
12588 external_wp_deprecated_default()('wp.blocks.node.toHTML', {
12589 since: '6.1',
12590 version: '6.3',
12591 alternative: 'wp.richText.toHTMLString',
12592 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12593 });
12594 return children_toHTML([node]);
12595 }
12596 /**
12597 * Given a selector, returns an hpq matcher generating a WPBlockNode value
12598 * matching the selector result.
12599 *
12600 * @param {string} selector DOM selector.
12601 *
12602 * @return {Function} hpq matcher.
12603 */
12604
12605 function node_matcher(selector) {
12606 external_wp_deprecated_default()('wp.blocks.node.matcher', {
12607 since: '6.1',
12608 version: '6.3',
12609 alternative: 'html source',
12610 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12611 });
12612 return domNode => {
12613 let match = domNode;
12614
12615 if (selector) {
12616 match = domNode.querySelector(selector);
12617 }
12618
12619 try {
12620 return fromDOM(match);
12621 } catch (error) {
12622 return null;
12623 }
12624 };
12625 }
12626 /**
12627 * Object of utility functions used in managing block attribute values of
12628 * source `node`.
12629 *
12630 * @see https://github.com/WordPress/gutenberg/pull/10439
12631 *
12632 * @deprecated since 4.0. The `node` source should not be used, and can be
12633 * replaced by the `html` source.
12634 *
12635 * @private
12636 */
12637
12638 /* harmony default export */ const node = ({
12639 isNodeOfType,
12640 fromDOM,
12641 toHTML,
12642 matcher: node_matcher
12643 });
12644
12645 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/children.js
12646 /**
12647 * WordPress dependencies
12648 */
12649
12650
12651 /**
12652 * Internal dependencies
12653 */
12654
12655
12656 /**
12657 * A representation of a block's rich text value.
12658 *
12659 * @typedef {WPBlockNode[]} WPBlockChildren
12660 */
12661
12662 /**
12663 * Given block children, returns a serialize-capable WordPress element.
12664 *
12665 * @param {WPBlockChildren} children Block children object to convert.
12666 *
12667 * @return {WPElement} A serialize-capable element.
12668 */
12669
12670 function getSerializeCapableElement(children) {
12671 // The fact that block children are compatible with the element serializer is
12672 // merely an implementation detail that currently serves to be true, but
12673 // should not be mistaken as being a guarantee on the external API. The
12674 // public API only offers guarantees to work with strings (toHTML) and DOM
12675 // elements (fromDOM), and should provide utilities to manipulate the value
12676 // rather than expect consumers to inspect or construct its shape (concat).
12677 return children;
12678 }
12679 /**
12680 * Given block children, returns an array of block nodes.
12681 *
12682 * @param {WPBlockChildren} children Block children object to convert.
12683 *
12684 * @return {Array<WPBlockNode>} An array of individual block nodes.
12685 */
12686
12687 function getChildrenArray(children) {
12688 external_wp_deprecated_default()('wp.blocks.children.getChildrenArray', {
12689 since: '6.1',
12690 version: '6.3',
12691 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12692 }); // The fact that block children are compatible with the element serializer
12693 // is merely an implementation detail that currently serves to be true, but
12694 // should not be mistaken as being a guarantee on the external API.
12695
12696 return children;
12697 }
12698 /**
12699 * Given two or more block nodes, returns a new block node representing a
12700 * concatenation of its values.
12701 *
12702 * @param {...WPBlockChildren} blockNodes Block nodes to concatenate.
12703 *
12704 * @return {WPBlockChildren} Concatenated block node.
12705 */
12706
12707
12708 function concat(...blockNodes) {
12709 external_wp_deprecated_default()('wp.blocks.children.concat', {
12710 since: '6.1',
12711 version: '6.3',
12712 alternative: 'wp.richText.concat',
12713 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12714 });
12715 const result = [];
12716
12717 for (let i = 0; i < blockNodes.length; i++) {
12718 const blockNode = Array.isArray(blockNodes[i]) ? blockNodes[i] : [blockNodes[i]];
12719
12720 for (let j = 0; j < blockNode.length; j++) {
12721 const child = blockNode[j];
12722 const canConcatToPreviousString = typeof child === 'string' && typeof result[result.length - 1] === 'string';
12723
12724 if (canConcatToPreviousString) {
12725 result[result.length - 1] += child;
12726 } else {
12727 result.push(child);
12728 }
12729 }
12730 }
12731
12732 return result;
12733 }
12734 /**
12735 * Given an iterable set of DOM nodes, returns equivalent block children.
12736 * Ignores any non-element/text nodes included in set.
12737 *
12738 * @param {Iterable.<Node>} domNodes Iterable set of DOM nodes to convert.
12739 *
12740 * @return {WPBlockChildren} Block children equivalent to DOM nodes.
12741 */
12742
12743 function children_fromDOM(domNodes) {
12744 external_wp_deprecated_default()('wp.blocks.children.fromDOM', {
12745 since: '6.1',
12746 version: '6.3',
12747 alternative: 'wp.richText.create',
12748 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12749 });
12750 const result = [];
12751
12752 for (let i = 0; i < domNodes.length; i++) {
12753 try {
12754 result.push(fromDOM(domNodes[i]));
12755 } catch (error) {// Simply ignore if DOM node could not be converted.
12756 }
12757 }
12758
12759 return result;
12760 }
12761 /**
12762 * Given a block node, returns its HTML string representation.
12763 *
12764 * @param {WPBlockChildren} children Block node(s) to convert to string.
12765 *
12766 * @return {string} String HTML representation of block node.
12767 */
12768
12769 function children_toHTML(children) {
12770 external_wp_deprecated_default()('wp.blocks.children.toHTML', {
12771 since: '6.1',
12772 version: '6.3',
12773 alternative: 'wp.richText.toHTMLString',
12774 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12775 });
12776 const element = getSerializeCapableElement(children);
12777 return (0,external_wp_element_namespaceObject.renderToString)(element);
12778 }
12779 /**
12780 * Given a selector, returns an hpq matcher generating a WPBlockChildren value
12781 * matching the selector result.
12782 *
12783 * @param {string} selector DOM selector.
12784 *
12785 * @return {Function} hpq matcher.
12786 */
12787
12788 function children_matcher(selector) {
12789 external_wp_deprecated_default()('wp.blocks.children.matcher', {
12790 since: '6.1',
12791 version: '6.3',
12792 alternative: 'html source',
12793 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12794 });
12795 return domNode => {
12796 let match = domNode;
12797
12798 if (selector) {
12799 match = domNode.querySelector(selector);
12800 }
12801
12802 if (match) {
12803 return children_fromDOM(match.childNodes);
12804 }
12805
12806 return [];
12807 };
12808 }
12809 /**
12810 * Object of utility functions used in managing block attribute values of
12811 * source `children`.
12812 *
12813 * @see https://github.com/WordPress/gutenberg/pull/10439
12814 *
12815 * @deprecated since 4.0. The `children` source should not be used, and can be
12816 * replaced by the `html` source.
12817 *
12818 * @private
12819 */
12820
12821 /* harmony default export */ const children = ({
12822 concat,
12823 getChildrenArray,
12824 fromDOM: children_fromDOM,
12825 toHTML: children_toHTML,
12826 matcher: children_matcher
12827 });
12828
12829 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/get-block-attributes.js
12830 /**
12831 * External dependencies
12832 */
12833
12834
12835 /**
12836 * WordPress dependencies
12837 */
12838
12839
12840
12841 /**
12842 * Internal dependencies
12843 */
12844
12845
12846
12847 /**
12848 * Higher-order hpq matcher which enhances an attribute matcher to return true
12849 * or false depending on whether the original matcher returns undefined. This
12850 * is useful for boolean attributes (e.g. disabled) whose attribute values may
12851 * be technically falsey (empty string), though their mere presence should be
12852 * enough to infer as true.
12853 *
12854 * @param {Function} matcher Original hpq matcher.
12855 *
12856 * @return {Function} Enhanced hpq matcher.
12857 */
12858
12859 const toBooleanAttributeMatcher = matcher => (0,external_wp_compose_namespaceObject.pipe)([matcher, // Expected values from `attr( 'disabled' )`:
12860 //
12861 // <input>
12862 // - Value: `undefined`
12863 // - Transformed: `false`
12864 //
12865 // <input disabled>
12866 // - Value: `''`
12867 // - Transformed: `true`
12868 //
12869 // <input disabled="disabled">
12870 // - Value: `'disabled'`
12871 // - Transformed: `true`
12872 value => value !== undefined]);
12873 /**
12874 * Returns true if value is of the given JSON schema type, or false otherwise.
12875 *
12876 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
12877 *
12878 * @param {*} value Value to test.
12879 * @param {string} type Type to test.
12880 *
12881 * @return {boolean} Whether value is of type.
12882 */
12883
12884 function isOfType(value, type) {
12885 switch (type) {
12886 case 'string':
12887 return typeof value === 'string';
12888
12889 case 'boolean':
12890 return typeof value === 'boolean';
12891
12892 case 'object':
12893 return !!value && value.constructor === Object;
12894
12895 case 'null':
12896 return value === null;
12897
12898 case 'array':
12899 return Array.isArray(value);
12900
12901 case 'integer':
12902 case 'number':
12903 return typeof value === 'number';
12904 }
12905
12906 return true;
12907 }
12908 /**
12909 * Returns true if value is of an array of given JSON schema types, or false
12910 * otherwise.
12911 *
12912 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
12913 *
12914 * @param {*} value Value to test.
12915 * @param {string[]} types Types to test.
12916 *
12917 * @return {boolean} Whether value is of types.
12918 */
12919
12920 function isOfTypes(value, types) {
12921 return types.some(type => isOfType(value, type));
12922 }
12923 /**
12924 * Given an attribute key, an attribute's schema, a block's raw content and the
12925 * commentAttributes returns the attribute value depending on its source
12926 * definition of the given attribute key.
12927 *
12928 * @param {string} attributeKey Attribute key.
12929 * @param {Object} attributeSchema Attribute's schema.
12930 * @param {Node} innerDOM Parsed DOM of block's inner HTML.
12931 * @param {Object} commentAttributes Block's comment attributes.
12932 * @param {string} innerHTML Raw HTML from block node's innerHTML property.
12933 *
12934 * @return {*} Attribute value.
12935 */
12936
12937 function getBlockAttribute(attributeKey, attributeSchema, innerDOM, commentAttributes, innerHTML) {
12938 let value;
12939
12940 switch (attributeSchema.source) {
12941 // An undefined source means that it's an attribute serialized to the
12942 // block's "comment".
12943 case undefined:
12944 value = commentAttributes ? commentAttributes[attributeKey] : undefined;
12945 break;
12946 // raw source means that it's the original raw block content.
12947
12948 case 'raw':
12949 value = innerHTML;
12950 break;
12951
12952 case 'attribute':
12953 case 'property':
12954 case 'html':
12955 case 'text':
12956 case 'children':
12957 case 'node':
12958 case 'query':
12959 case 'tag':
12960 value = parseWithAttributeSchema(innerDOM, attributeSchema);
12961 break;
12962 }
12963
12964 if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) {
12965 // Reject the value if it is not valid. Reverting to the undefined
12966 // value ensures the default is respected, if applicable.
12967 value = undefined;
12968 }
12969
12970 if (value === undefined) {
12971 value = attributeSchema.default;
12972 }
12973
12974 return value;
12975 }
12976 /**
12977 * Returns true if value is valid per the given block attribute schema type
12978 * definition, or false otherwise.
12979 *
12980 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1
12981 *
12982 * @param {*} value Value to test.
12983 * @param {?(Array<string>|string)} type Block attribute schema type.
12984 *
12985 * @return {boolean} Whether value is valid.
12986 */
12987
12988 function isValidByType(value, type) {
12989 return type === undefined || isOfTypes(value, Array.isArray(type) ? type : [type]);
12990 }
12991 /**
12992 * Returns true if value is valid per the given block attribute schema enum
12993 * definition, or false otherwise.
12994 *
12995 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2
12996 *
12997 * @param {*} value Value to test.
12998 * @param {?Array} enumSet Block attribute schema enum.
12999 *
13000 * @return {boolean} Whether value is valid.
13001 */
13002
13003 function isValidByEnum(value, enumSet) {
13004 return !Array.isArray(enumSet) || enumSet.includes(value);
13005 }
13006 /**
13007 * Returns an hpq matcher given a source object.
13008 *
13009 * @param {Object} sourceConfig Attribute Source object.
13010 *
13011 * @return {Function} A hpq Matcher.
13012 */
13013
13014 const matcherFromSource = memize(sourceConfig => {
13015 switch (sourceConfig.source) {
13016 case 'attribute':
13017 let matcher = attr(sourceConfig.selector, sourceConfig.attribute);
13018
13019 if (sourceConfig.type === 'boolean') {
13020 matcher = toBooleanAttributeMatcher(matcher);
13021 }
13022
13023 return matcher;
13024
13025 case 'html':
13026 return matchers_html(sourceConfig.selector, sourceConfig.multiline);
13027
13028 case 'text':
13029 return es_text(sourceConfig.selector);
13030
13031 case 'children':
13032 return children_matcher(sourceConfig.selector);
13033
13034 case 'node':
13035 return node_matcher(sourceConfig.selector);
13036
13037 case 'query':
13038 const subMatchers = Object.fromEntries(Object.entries(sourceConfig.query).map(([key, subSourceConfig]) => [key, matcherFromSource(subSourceConfig)]));
13039 return query(sourceConfig.selector, subMatchers);
13040
13041 case 'tag':
13042 return (0,external_wp_compose_namespaceObject.pipe)([prop(sourceConfig.selector, 'nodeName'), nodeName => nodeName ? nodeName.toLowerCase() : undefined]);
13043
13044 default:
13045 // eslint-disable-next-line no-console
13046 console.error(`Unknown source type "${sourceConfig.source}"`);
13047 }
13048 });
13049 /**
13050 * Parse a HTML string into DOM tree.
13051 *
13052 * @param {string|Node} innerHTML HTML string or already parsed DOM node.
13053 *
13054 * @return {Node} Parsed DOM node.
13055 */
13056
13057 function parseHtml(innerHTML) {
13058 return parse(innerHTML, h => h);
13059 }
13060 /**
13061 * Given a block's raw content and an attribute's schema returns the attribute's
13062 * value depending on its source.
13063 *
13064 * @param {string|Node} innerHTML Block's raw content.
13065 * @param {Object} attributeSchema Attribute's schema.
13066 *
13067 * @return {*} Attribute value.
13068 */
13069
13070
13071 function parseWithAttributeSchema(innerHTML, attributeSchema) {
13072 return matcherFromSource(attributeSchema)(parseHtml(innerHTML));
13073 }
13074 /**
13075 * Returns the block attributes of a registered block node given its type.
13076 *
13077 * @param {string|Object} blockTypeOrName Block type or name.
13078 * @param {string|Node} innerHTML Raw block content.
13079 * @param {?Object} attributes Known block attributes (from delimiters).
13080 *
13081 * @return {Object} All block attributes.
13082 */
13083
13084 function getBlockAttributes(blockTypeOrName, innerHTML, attributes = {}) {
13085 var _blockType$attributes;
13086
13087 const doc = parseHtml(innerHTML);
13088 const blockType = normalizeBlockType(blockTypeOrName);
13089 const blockAttributes = Object.fromEntries(Object.entries((_blockType$attributes = blockType.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}).map(([key, schema]) => [key, getBlockAttribute(key, schema, doc, attributes, innerHTML)]));
13090 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockAttributes', blockAttributes, blockType, innerHTML, attributes);
13091 }
13092
13093 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/fix-custom-classname.js
13094 /**
13095 * Internal dependencies
13096 */
13097
13098
13099
13100 const CLASS_ATTR_SCHEMA = {
13101 type: 'string',
13102 source: 'attribute',
13103 selector: '[data-custom-class-name] > *',
13104 attribute: 'class'
13105 };
13106 /**
13107 * Given an HTML string, returns an array of class names assigned to the root
13108 * element in the markup.
13109 *
13110 * @param {string} innerHTML Markup string from which to extract classes.
13111 *
13112 * @return {string[]} Array of class names assigned to the root element.
13113 */
13114
13115 function getHTMLRootElementClasses(innerHTML) {
13116 const parsed = parseWithAttributeSchema(`<div data-custom-class-name>${innerHTML}</div>`, CLASS_ATTR_SCHEMA);
13117 return parsed ? parsed.trim().split(/\s+/) : [];
13118 }
13119 /**
13120 * Given a parsed set of block attributes, if the block supports custom class
13121 * names and an unknown class (per the block's serialization behavior) is
13122 * found, the unknown classes are treated as custom classes. This prevents the
13123 * block from being considered as invalid.
13124 *
13125 * @param {Object} blockAttributes Original block attributes.
13126 * @param {Object} blockType Block type settings.
13127 * @param {string} innerHTML Original block markup.
13128 *
13129 * @return {Object} Filtered block attributes.
13130 */
13131
13132 function fixCustomClassname(blockAttributes, blockType, innerHTML) {
13133 if (hasBlockSupport(blockType, 'customClassName', true)) {
13134 // To determine difference, serialize block given the known set of
13135 // attributes, with the exception of `className`. This will determine
13136 // the default set of classes. From there, any difference in innerHTML
13137 // can be considered as custom classes.
13138 const {
13139 className: omittedClassName,
13140 ...attributesSansClassName
13141 } = blockAttributes;
13142 const serialized = getSaveContent(blockType, attributesSansClassName);
13143 const defaultClasses = getHTMLRootElementClasses(serialized);
13144 const actualClasses = getHTMLRootElementClasses(innerHTML);
13145 const customClasses = actualClasses.filter(className => !defaultClasses.includes(className));
13146
13147 if (customClasses.length) {
13148 blockAttributes.className = customClasses.join(' ');
13149 } else if (serialized) {
13150 delete blockAttributes.className;
13151 }
13152 }
13153
13154 return blockAttributes;
13155 }
13156
13157 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-built-in-validation-fixes.js
13158 /**
13159 * Internal dependencies
13160 */
13161
13162 /**
13163 * Attempts to fix block invalidation by applying build-in validation fixes
13164 * like moving all extra classNames to the className attribute.
13165 *
13166 * @param {WPBlock} block block object.
13167 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13168 * can be inferred from the block name,
13169 * but it's here for performance reasons.
13170 *
13171 * @return {WPBlock} Fixed block object
13172 */
13173
13174 function applyBuiltInValidationFixes(block, blockType) {
13175 const updatedBlockAttributes = fixCustomClassname(block.attributes, blockType, block.originalContent);
13176 return { ...block,
13177 attributes: updatedBlockAttributes
13178 };
13179 }
13180
13181 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-block-deprecated-versions.js
13182 /**
13183 * Internal dependencies
13184 */
13185
13186
13187
13188
13189
13190 /**
13191 * Function that takes no arguments and always returns false.
13192 *
13193 * @return {boolean} Always returns false.
13194 */
13195
13196 function stubFalse() {
13197 return false;
13198 }
13199 /**
13200 * Given a block object, returns a new copy of the block with any applicable
13201 * deprecated migrations applied, or the original block if it was both valid
13202 * and no eligible migrations exist.
13203 *
13204 * @param {import(".").WPBlock} block Parsed and invalid block object.
13205 * @param {import(".").WPRawBlock} rawBlock Raw block object.
13206 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13207 * can be inferred from the block name,
13208 * but it's here for performance reasons.
13209 *
13210 * @return {import(".").WPBlock} Migrated block object.
13211 */
13212
13213
13214 function applyBlockDeprecatedVersions(block, rawBlock, blockType) {
13215 const parsedAttributes = rawBlock.attrs;
13216 const {
13217 deprecated: deprecatedDefinitions
13218 } = blockType; // Bail early if there are no registered deprecations to be handled.
13219
13220 if (!deprecatedDefinitions || !deprecatedDefinitions.length) {
13221 return block;
13222 } // By design, blocks lack any sort of version tracking. Instead, to process
13223 // outdated content the system operates a queue out of all the defined
13224 // attribute shapes and tries each definition until the input produces a
13225 // valid result. This mechanism seeks to avoid polluting the user-space with
13226 // machine-specific code. An invalid block is thus a block that could not be
13227 // matched successfully with any of the registered deprecation definitions.
13228
13229
13230 for (let i = 0; i < deprecatedDefinitions.length; i++) {
13231 // A block can opt into a migration even if the block is valid by
13232 // defining `isEligible` on its deprecation. If the block is both valid
13233 // and does not opt to migrate, skip.
13234 const {
13235 isEligible = stubFalse
13236 } = deprecatedDefinitions[i];
13237
13238 if (block.isValid && !isEligible(parsedAttributes, block.innerBlocks, {
13239 blockNode: rawBlock,
13240 block
13241 })) {
13242 continue;
13243 } // Block type properties which could impact either serialization or
13244 // parsing are not considered in the deprecated block type by default,
13245 // and must be explicitly provided.
13246
13247
13248 const deprecatedBlockType = Object.assign(omit(blockType, DEPRECATED_ENTRY_KEYS), deprecatedDefinitions[i]);
13249 let migratedBlock = { ...block,
13250 attributes: getBlockAttributes(deprecatedBlockType, block.originalContent, parsedAttributes)
13251 }; // Ignore the deprecation if it produces a block which is not valid.
13252
13253 let [isValid] = validateBlock(migratedBlock, deprecatedBlockType); // If the migrated block is not valid initially, try the built-in fixes.
13254
13255 if (!isValid) {
13256 migratedBlock = applyBuiltInValidationFixes(migratedBlock, deprecatedBlockType);
13257 [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
13258 } // An invalid block does not imply incorrect HTML but the fact block
13259 // source information could be lost on re-serialization.
13260
13261
13262 if (!isValid) {
13263 continue;
13264 }
13265
13266 let migratedInnerBlocks = migratedBlock.innerBlocks;
13267 let migratedAttributes = migratedBlock.attributes; // A block may provide custom behavior to assign new attributes and/or
13268 // inner blocks.
13269
13270 const {
13271 migrate
13272 } = deprecatedBlockType;
13273
13274 if (migrate) {
13275 let migrated = migrate(migratedAttributes, block.innerBlocks);
13276
13277 if (!Array.isArray(migrated)) {
13278 migrated = [migrated];
13279 }
13280
13281 [migratedAttributes = parsedAttributes, migratedInnerBlocks = block.innerBlocks] = migrated;
13282 }
13283
13284 block = { ...block,
13285 attributes: migratedAttributes,
13286 innerBlocks: migratedInnerBlocks,
13287 isValid: true,
13288 validationIssues: []
13289 };
13290 }
13291
13292 return block;
13293 }
13294
13295 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/index.js
13296 /**
13297 * WordPress dependencies
13298 */
13299
13300
13301 /**
13302 * Internal dependencies
13303 */
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314 /**
13315 * The raw structure of a block includes its attributes, inner
13316 * blocks, and inner HTML. It is important to distinguish inner blocks from
13317 * the HTML content of the block as only the latter is relevant for block
13318 * validation and edit operations.
13319 *
13320 * @typedef WPRawBlock
13321 *
13322 * @property {string=} blockName Block name
13323 * @property {Object=} attrs Block raw or comment attributes.
13324 * @property {string} innerHTML HTML content of the block.
13325 * @property {(string|null)[]} innerContent Content without inner blocks.
13326 * @property {WPRawBlock[]} innerBlocks Inner Blocks.
13327 */
13328
13329 /**
13330 * Fully parsed block object.
13331 *
13332 * @typedef WPBlock
13333 *
13334 * @property {string} name Block name
13335 * @property {Object} attributes Block raw or comment attributes.
13336 * @property {WPBlock[]} innerBlocks Inner Blocks.
13337 * @property {string} originalContent Original content of the block before validation fixes.
13338 * @property {boolean} isValid Whether the block is valid.
13339 * @property {Object[]} validationIssues Validation issues.
13340 * @property {WPRawBlock} [__unstableBlockSource] Un-processed original copy of block if created through parser.
13341 */
13342
13343 /**
13344 * @typedef {Object} ParseOptions
13345 * @property {boolean?} __unstableSkipMigrationLogs If a block is migrated from a deprecated version, skip logging the migration details.
13346 * @property {boolean?} __unstableSkipAutop Whether to skip autop when processing freeform content.
13347 */
13348
13349 /**
13350 * Convert legacy blocks to their canonical form. This function is used
13351 * both in the parser level for previous content and to convert such blocks
13352 * used in Custom Post Types templates.
13353 *
13354 * @param {WPRawBlock} rawBlock
13355 *
13356 * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found
13357 */
13358
13359 function convertLegacyBlocks(rawBlock) {
13360 const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(rawBlock.blockName, rawBlock.attrs);
13361 return { ...rawBlock,
13362 blockName: correctName,
13363 attrs: correctedAttributes
13364 };
13365 }
13366 /**
13367 * Normalize the raw block by applying the fallback block name if none given,
13368 * sanitize the parsed HTML...
13369 *
13370 * @param {WPRawBlock} rawBlock The raw block object.
13371 * @param {ParseOptions?} options Extra options for handling block parsing.
13372 *
13373 * @return {WPRawBlock} The normalized block object.
13374 */
13375
13376
13377 function normalizeRawBlock(rawBlock, options) {
13378 const fallbackBlockName = getFreeformContentHandlerName(); // If the grammar parsing don't produce any block name, use the freeform block.
13379
13380 const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
13381 const rawAttributes = rawBlock.attrs || {};
13382 const rawInnerBlocks = rawBlock.innerBlocks || [];
13383 let rawInnerHTML = rawBlock.innerHTML.trim(); // Fallback content may be upgraded from classic content expecting implicit
13384 // automatic paragraphs, so preserve them. Assumes wpautop is idempotent,
13385 // meaning there are no negative consequences to repeated autop calls.
13386
13387 if (rawBlockName === fallbackBlockName && !options?.__unstableSkipAutop) {
13388 rawInnerHTML = (0,external_wp_autop_namespaceObject.autop)(rawInnerHTML).trim();
13389 }
13390
13391 return { ...rawBlock,
13392 blockName: rawBlockName,
13393 attrs: rawAttributes,
13394 innerHTML: rawInnerHTML,
13395 innerBlocks: rawInnerBlocks
13396 };
13397 }
13398 /**
13399 * Uses the "unregistered blockType" to create a block object.
13400 *
13401 * @param {WPRawBlock} rawBlock block.
13402 *
13403 * @return {WPRawBlock} The unregistered block object.
13404 */
13405
13406 function createMissingBlockType(rawBlock) {
13407 const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName(); // Preserve undelimited content for use by the unregistered type
13408 // handler. A block node's `innerHTML` isn't enough, as that field only
13409 // carries the block's own HTML and not its nested blocks.
13410
13411 const originalUndelimitedContent = serializeRawBlock(rawBlock, {
13412 isCommentDelimited: false
13413 }); // Preserve full block content for use by the unregistered type
13414 // handler, block boundaries included.
13415
13416 const originalContent = serializeRawBlock(rawBlock, {
13417 isCommentDelimited: true
13418 });
13419 return {
13420 blockName: unregisteredFallbackBlock,
13421 attrs: {
13422 originalName: rawBlock.blockName,
13423 originalContent,
13424 originalUndelimitedContent
13425 },
13426 innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
13427 innerBlocks: rawBlock.innerBlocks,
13428 innerContent: rawBlock.innerContent
13429 };
13430 }
13431 /**
13432 * Validates a block and wraps with validation meta.
13433 *
13434 * The name here is regrettable but `validateBlock` is already taken.
13435 *
13436 * @param {WPBlock} unvalidatedBlock
13437 * @param {import('../registration').WPBlockType} blockType
13438 * @return {WPBlock} validated block, with auto-fixes if initially invalid
13439 */
13440
13441
13442 function applyBlockValidation(unvalidatedBlock, blockType) {
13443 // Attempt to validate the block.
13444 const [isValid] = validateBlock(unvalidatedBlock, blockType);
13445
13446 if (isValid) {
13447 return { ...unvalidatedBlock,
13448 isValid,
13449 validationIssues: []
13450 };
13451 } // If the block is invalid, attempt some built-in fixes
13452 // like custom classNames handling.
13453
13454
13455 const fixedBlock = applyBuiltInValidationFixes(unvalidatedBlock, blockType); // Attempt to validate the block once again after the built-in fixes.
13456
13457 const [isFixedValid, validationIssues] = validateBlock(unvalidatedBlock, blockType);
13458 return { ...fixedBlock,
13459 isValid: isFixedValid,
13460 validationIssues
13461 };
13462 }
13463 /**
13464 * Given a raw block returned by grammar parsing, returns a fully parsed block.
13465 *
13466 * @param {WPRawBlock} rawBlock The raw block object.
13467 * @param {ParseOptions} options Extra options for handling block parsing.
13468 *
13469 * @return {WPBlock | undefined} Fully parsed block.
13470 */
13471
13472
13473 function parseRawBlock(rawBlock, options) {
13474 let normalizedBlock = normalizeRawBlock(rawBlock, options); // During the lifecycle of the project, we renamed some old blocks
13475 // and transformed others to new blocks. To avoid breaking existing content,
13476 // we added this function to properly parse the old content.
13477
13478 normalizedBlock = convertLegacyBlocks(normalizedBlock); // Try finding the type for known block name.
13479
13480 let blockType = getBlockType(normalizedBlock.blockName); // If not blockType is found for the specified name, fallback to the "unregistedBlockType".
13481
13482 if (!blockType) {
13483 normalizedBlock = createMissingBlockType(normalizedBlock);
13484 blockType = getBlockType(normalizedBlock.blockName);
13485 } // If it's an empty freeform block or there's no blockType (no missing block handler)
13486 // Then, just ignore the block.
13487 // It might be a good idea to throw a warning here.
13488 // TODO: I'm unsure about the unregisteredFallbackBlock check,
13489 // it might ignore some dynamic unregistered third party blocks wrongly.
13490
13491
13492 const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
13493
13494 if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
13495 return;
13496 } // Parse inner blocks recursively.
13497
13498
13499 const parsedInnerBlocks = normalizedBlock.innerBlocks.map(innerBlock => parseRawBlock(innerBlock, options)) // See https://github.com/WordPress/gutenberg/pull/17164.
13500 .filter(innerBlock => !!innerBlock); // Get the fully parsed block.
13501
13502 const parsedBlock = createBlock(normalizedBlock.blockName, getBlockAttributes(blockType, normalizedBlock.innerHTML, normalizedBlock.attrs), parsedInnerBlocks);
13503 parsedBlock.originalContent = normalizedBlock.innerHTML;
13504 const validatedBlock = applyBlockValidation(parsedBlock, blockType);
13505 const {
13506 validationIssues
13507 } = validatedBlock; // Run the block deprecation and migrations.
13508 // This is performed on both invalid and valid blocks because
13509 // migration using the `migrate` functions should run even
13510 // if the output is deemed valid.
13511
13512 const updatedBlock = applyBlockDeprecatedVersions(validatedBlock, normalizedBlock, blockType);
13513
13514 if (!updatedBlock.isValid) {
13515 // Preserve the original unprocessed version of the block
13516 // that we received (no fixes, no deprecations) so that
13517 // we can save it as close to exactly the same way as
13518 // we loaded it. This is important to avoid corruption
13519 // and data loss caused by block implementations trying
13520 // to process data that isn't fully recognized.
13521 updatedBlock.__unstableBlockSource = rawBlock;
13522 }
13523
13524 if (!validatedBlock.isValid && updatedBlock.isValid && !options?.__unstableSkipMigrationLogs) {
13525 /* eslint-disable no-console */
13526 console.groupCollapsed('Updated Block: %s', blockType.name);
13527 console.info('Block successfully updated for `%s` (%o).\n\nNew content generated by `save` function:\n\n%s\n\nContent retrieved from post body:\n\n%s', blockType.name, blockType, getSaveContent(blockType, updatedBlock.attributes), updatedBlock.originalContent);
13528 console.groupEnd();
13529 /* eslint-enable no-console */
13530 } else if (!validatedBlock.isValid && !updatedBlock.isValid) {
13531 validationIssues.forEach(({
13532 log,
13533 args
13534 }) => log(...args));
13535 }
13536
13537 return updatedBlock;
13538 }
13539 /**
13540 * Utilizes an optimized token-driven parser based on the Gutenberg grammar spec
13541 * defined through a parsing expression grammar to take advantage of the regular
13542 * cadence provided by block delimiters -- composed syntactically through HTML
13543 * comments -- which, given a general HTML document as an input, returns a block
13544 * list array representation.
13545 *
13546 * This is a recursive-descent parser that scans linearly once through the input
13547 * document. Instead of directly recursing it utilizes a trampoline mechanism to
13548 * prevent stack overflow. This initial pass is mainly interested in separating
13549 * and isolating the blocks serialized in the document and manifestly not in the
13550 * content within the blocks.
13551 *
13552 * @see
13553 * https://developer.wordpress.org/block-editor/packages/packages-block-serialization-default-parser/
13554 *
13555 * @param {string} content The post content.
13556 * @param {ParseOptions} options Extra options for handling block parsing.
13557 *
13558 * @return {Array} Block list.
13559 */
13560
13561 function parser_parse(content, options) {
13562 return (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(content).reduce((accumulator, rawBlock) => {
13563 const block = parseRawBlock(rawBlock, options);
13564
13565 if (block) {
13566 accumulator.push(block);
13567 }
13568
13569 return accumulator;
13570 }, []);
13571 }
13572
13573 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/get-raw-transforms.js
13574 /**
13575 * Internal dependencies
13576 */
13577
13578 function getRawTransforms() {
13579 return getBlockTransforms('from').filter(({
13580 type
13581 }) => type === 'raw').map(transform => {
13582 return transform.isMatch ? transform : { ...transform,
13583 isMatch: node => transform.selector && node.matches(transform.selector)
13584 };
13585 });
13586 }
13587
13588 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-to-blocks.js
13589 /**
13590 * Internal dependencies
13591 */
13592
13593
13594
13595 /**
13596 * Converts HTML directly to blocks. Looks for a matching transform for each
13597 * top-level tag. The HTML should be filtered to not have any text between
13598 * top-level tags and formatted in a way that blocks can handle the HTML.
13599 *
13600 * @param {string} html HTML to convert.
13601 * @param {Function} handler The handler calling htmlToBlocks: either rawHandler
13602 * or pasteHandler.
13603 *
13604 * @return {Array} An array of blocks.
13605 */
13606
13607 function htmlToBlocks(html, handler) {
13608 const doc = document.implementation.createHTMLDocument('');
13609 doc.body.innerHTML = html;
13610 return Array.from(doc.body.children).flatMap(node => {
13611 const rawTransform = findTransform(getRawTransforms(), ({
13612 isMatch
13613 }) => isMatch(node));
13614
13615 if (!rawTransform) {
13616 return createBlock( // Should not be hardcoded.
13617 'core/html', getBlockAttributes('core/html', node.outerHTML));
13618 }
13619
13620 const {
13621 transform,
13622 blockName
13623 } = rawTransform;
13624
13625 if (transform) {
13626 return transform(node, handler);
13627 }
13628
13629 return createBlock(blockName, getBlockAttributes(blockName, node.outerHTML));
13630 });
13631 }
13632
13633 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/normalise-blocks.js
13634 /**
13635 * WordPress dependencies
13636 */
13637
13638 function normaliseBlocks(HTML) {
13639 const decuDoc = document.implementation.createHTMLDocument('');
13640 const accuDoc = document.implementation.createHTMLDocument('');
13641 const decu = decuDoc.body;
13642 const accu = accuDoc.body;
13643 decu.innerHTML = HTML;
13644
13645 while (decu.firstChild) {
13646 const node = decu.firstChild; // Text nodes: wrap in a paragraph, or append to previous.
13647
13648 if (node.nodeType === node.TEXT_NODE) {
13649 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
13650 decu.removeChild(node);
13651 } else {
13652 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13653 accu.appendChild(accuDoc.createElement('P'));
13654 }
13655
13656 accu.lastChild.appendChild(node);
13657 } // Element nodes.
13658
13659 } else if (node.nodeType === node.ELEMENT_NODE) {
13660 // BR nodes: create a new paragraph on double, or append to previous.
13661 if (node.nodeName === 'BR') {
13662 if (node.nextSibling && node.nextSibling.nodeName === 'BR') {
13663 accu.appendChild(accuDoc.createElement('P'));
13664 decu.removeChild(node.nextSibling);
13665 } // Don't append to an empty paragraph.
13666
13667
13668 if (accu.lastChild && accu.lastChild.nodeName === 'P' && accu.lastChild.hasChildNodes()) {
13669 accu.lastChild.appendChild(node);
13670 } else {
13671 decu.removeChild(node);
13672 }
13673 } else if (node.nodeName === 'P') {
13674 // Only append non-empty paragraph nodes.
13675 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
13676 decu.removeChild(node);
13677 } else {
13678 accu.appendChild(node);
13679 }
13680 } else if ((0,external_wp_dom_namespaceObject.isPhrasingContent)(node)) {
13681 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13682 accu.appendChild(accuDoc.createElement('P'));
13683 }
13684
13685 accu.lastChild.appendChild(node);
13686 } else {
13687 accu.appendChild(node);
13688 }
13689 } else {
13690 decu.removeChild(node);
13691 }
13692 }
13693
13694 return accu.innerHTML;
13695 }
13696
13697 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/special-comment-converter.js
13698 /**
13699 * WordPress dependencies
13700 */
13701
13702 /**
13703 * Looks for `<!--nextpage-->` and `<!--more-->` comments and
13704 * replaces them with a custom element representing a future block.
13705 *
13706 * The custom element is a way to bypass the rest of the `raw-handling`
13707 * transforms, which would eliminate other kinds of node with which to carry
13708 * `<!--more-->`'s data: nodes with `data` attributes, empty paragraphs, etc.
13709 *
13710 * The custom element is then expected to be recognized by any registered
13711 * block's `raw` transform.
13712 *
13713 * @param {Node} node The node to be processed.
13714 * @param {Document} doc The document of the node.
13715 * @return {void}
13716 */
13717
13718 function specialCommentConverter(node, doc) {
13719 if (node.nodeType !== node.COMMENT_NODE) {
13720 return;
13721 }
13722
13723 if (node.nodeValue === 'nextpage') {
13724 (0,external_wp_dom_namespaceObject.replace)(node, createNextpage(doc));
13725 return;
13726 }
13727
13728 if (node.nodeValue.indexOf('more') === 0) {
13729 moreCommentConverter(node, doc);
13730 }
13731 }
13732 /**
13733 * Convert `<!--more-->` as well as the `<!--more Some text-->` variant
13734 * and its `<!--noteaser-->` companion into the custom element
13735 * described in `specialCommentConverter()`.
13736 *
13737 * @param {Node} node The node to be processed.
13738 * @param {Document} doc The document of the node.
13739 * @return {void}
13740 */
13741
13742 function moreCommentConverter(node, doc) {
13743 // Grab any custom text in the comment.
13744 const customText = node.nodeValue.slice(4).trim();
13745 /*
13746 * When a `<!--more-->` comment is found, we need to look for any
13747 * `<!--noteaser-->` sibling, but it may not be a direct sibling
13748 * (whitespace typically lies in between)
13749 */
13750
13751 let sibling = node;
13752 let noTeaser = false;
13753
13754 while (sibling = sibling.nextSibling) {
13755 if (sibling.nodeType === sibling.COMMENT_NODE && sibling.nodeValue === 'noteaser') {
13756 noTeaser = true;
13757 (0,external_wp_dom_namespaceObject.remove)(sibling);
13758 break;
13759 }
13760 }
13761
13762 const moreBlock = createMore(customText, noTeaser, doc); // If our `<!--more-->` comment is in the middle of a paragraph, we should
13763 // split the paragraph in two and insert the more block in between. If not,
13764 // the more block will eventually end up being inserted after the paragraph.
13765
13766 if (!node.parentNode || node.parentNode.nodeName !== 'P' || node.parentNode.childNodes.length === 1) {
13767 (0,external_wp_dom_namespaceObject.replace)(node, moreBlock);
13768 } else {
13769 const childNodes = Array.from(node.parentNode.childNodes);
13770 const nodeIndex = childNodes.indexOf(node);
13771 const wrapperNode = node.parentNode.parentNode || doc.body;
13772
13773 const paragraphBuilder = (acc, child) => {
13774 if (!acc) {
13775 acc = doc.createElement('p');
13776 }
13777
13778 acc.appendChild(child);
13779 return acc;
13780 }; // Split the original parent node and insert our more block
13781
13782
13783 [childNodes.slice(0, nodeIndex).reduce(paragraphBuilder, null), moreBlock, childNodes.slice(nodeIndex + 1).reduce(paragraphBuilder, null)].forEach(element => element && wrapperNode.insertBefore(element, node.parentNode)); // Remove the old parent paragraph
13784
13785 (0,external_wp_dom_namespaceObject.remove)(node.parentNode);
13786 }
13787 }
13788
13789 function createMore(customText, noTeaser, doc) {
13790 const node = doc.createElement('wp-block');
13791 node.dataset.block = 'core/more';
13792
13793 if (customText) {
13794 node.dataset.customText = customText;
13795 }
13796
13797 if (noTeaser) {
13798 // "Boolean" data attribute.
13799 node.dataset.noTeaser = '';
13800 }
13801
13802 return node;
13803 }
13804
13805 function createNextpage(doc) {
13806 const node = doc.createElement('wp-block');
13807 node.dataset.block = 'core/nextpage';
13808 return node;
13809 }
13810
13811 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/list-reducer.js
13812 /**
13813 * WordPress dependencies
13814 */
13815
13816
13817 function isList(node) {
13818 return node.nodeName === 'OL' || node.nodeName === 'UL';
13819 }
13820
13821 function shallowTextContent(element) {
13822 return Array.from(element.childNodes).map(({
13823 nodeValue = ''
13824 }) => nodeValue).join('');
13825 }
13826
13827 function listReducer(node) {
13828 if (!isList(node)) {
13829 return;
13830 }
13831
13832 const list = node;
13833 const prevElement = node.previousElementSibling; // Merge with previous list if:
13834 // * There is a previous list of the same type.
13835 // * There is only one list item.
13836
13837 if (prevElement && prevElement.nodeName === node.nodeName && list.children.length === 1) {
13838 // Move all child nodes, including any text nodes, if any.
13839 while (list.firstChild) {
13840 prevElement.appendChild(list.firstChild);
13841 }
13842
13843 list.parentNode.removeChild(list);
13844 }
13845
13846 const parentElement = node.parentNode; // Nested list with empty parent item.
13847
13848 if (parentElement && parentElement.nodeName === 'LI' && parentElement.children.length === 1 && !/\S/.test(shallowTextContent(parentElement))) {
13849 const parentListItem = parentElement;
13850 const prevListItem = parentListItem.previousElementSibling;
13851 const parentList = parentListItem.parentNode;
13852
13853 if (prevListItem) {
13854 prevListItem.appendChild(list);
13855 parentList.removeChild(parentListItem);
13856 } else {
13857 parentList.parentNode.insertBefore(list, parentList);
13858 parentList.parentNode.removeChild(parentList);
13859 }
13860 } // Invalid: OL/UL > OL/UL.
13861
13862
13863 if (parentElement && isList(parentElement)) {
13864 const prevListItem = node.previousElementSibling;
13865
13866 if (prevListItem) {
13867 prevListItem.appendChild(node);
13868 } else {
13869 (0,external_wp_dom_namespaceObject.unwrap)(node);
13870 }
13871 }
13872 }
13873
13874 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/blockquote-normaliser.js
13875 /**
13876 * Internal dependencies
13877 */
13878
13879 function blockquoteNormaliser(node) {
13880 if (node.nodeName !== 'BLOCKQUOTE') {
13881 return;
13882 }
13883
13884 node.innerHTML = normaliseBlocks(node.innerHTML);
13885 }
13886
13887 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/figure-content-reducer.js
13888 /**
13889 * WordPress dependencies
13890 */
13891
13892 /**
13893 * Whether or not the given node is figure content.
13894 *
13895 * @param {Node} node The node to check.
13896 * @param {Object} schema The schema to use.
13897 *
13898 * @return {boolean} True if figure content, false if not.
13899 */
13900
13901 function isFigureContent(node, schema) {
13902 var _schema$figure$childr;
13903
13904 const tag = node.nodeName.toLowerCase(); // We are looking for tags that can be a child of the figure tag, excluding
13905 // `figcaption` and any phrasing content.
13906
13907 if (tag === 'figcaption' || (0,external_wp_dom_namespaceObject.isTextContent)(node)) {
13908 return false;
13909 }
13910
13911 return tag in ((_schema$figure$childr = schema?.figure?.children) !== null && _schema$figure$childr !== void 0 ? _schema$figure$childr : {});
13912 }
13913 /**
13914 * Whether or not the given node can have an anchor.
13915 *
13916 * @param {Node} node The node to check.
13917 * @param {Object} schema The schema to use.
13918 *
13919 * @return {boolean} True if it can, false if not.
13920 */
13921
13922
13923 function canHaveAnchor(node, schema) {
13924 var _schema$figure$childr2;
13925
13926 const tag = node.nodeName.toLowerCase();
13927 return tag in ((_schema$figure$childr2 = schema?.figure?.children?.a?.children) !== null && _schema$figure$childr2 !== void 0 ? _schema$figure$childr2 : {});
13928 }
13929 /**
13930 * Wraps the given element in a figure element.
13931 *
13932 * @param {Element} element The element to wrap.
13933 * @param {Element} beforeElement The element before which to place the figure.
13934 */
13935
13936
13937 function wrapFigureContent(element, beforeElement = element) {
13938 const figure = element.ownerDocument.createElement('figure');
13939 beforeElement.parentNode.insertBefore(figure, beforeElement);
13940 figure.appendChild(element);
13941 }
13942 /**
13943 * This filter takes figure content out of paragraphs, wraps it in a figure
13944 * element, and moves any anchors with it if needed.
13945 *
13946 * @param {Node} node The node to filter.
13947 * @param {Document} doc The document of the node.
13948 * @param {Object} schema The schema to use.
13949 *
13950 * @return {void}
13951 */
13952
13953
13954 function figureContentReducer(node, doc, schema) {
13955 if (!isFigureContent(node, schema)) {
13956 return;
13957 }
13958
13959 let nodeToInsert = node;
13960 const parentNode = node.parentNode; // If the figure content can have an anchor and its parent is an anchor with
13961 // only the figure content, take the anchor out instead of just the content.
13962
13963 if (canHaveAnchor(node, schema) && parentNode.nodeName === 'A' && parentNode.childNodes.length === 1) {
13964 nodeToInsert = node.parentNode;
13965 }
13966
13967 const wrapper = nodeToInsert.closest('p,div'); // If wrapped in a paragraph or div, only extract if it's aligned or if
13968 // there is no text content.
13969 // Otherwise, if directly at the root, wrap in a figure element.
13970
13971 if (wrapper) {
13972 // In jsdom-jscore, 'node.classList' can be undefined.
13973 // In this case, default to extract as it offers a better UI experience on mobile.
13974 if (!node.classList) {
13975 wrapFigureContent(nodeToInsert, wrapper);
13976 } else if (node.classList.contains('alignright') || node.classList.contains('alignleft') || node.classList.contains('aligncenter') || !wrapper.textContent.trim()) {
13977 wrapFigureContent(nodeToInsert, wrapper);
13978 }
13979 } else if (nodeToInsert.parentNode.nodeName === 'BODY') {
13980 wrapFigureContent(nodeToInsert);
13981 }
13982 }
13983
13984 ;// CONCATENATED MODULE: external ["wp","shortcode"]
13985 const external_wp_shortcode_namespaceObject = window["wp"]["shortcode"];
13986 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/shortcode-converter.js
13987 /**
13988 * WordPress dependencies
13989 */
13990
13991 /**
13992 * Internal dependencies
13993 */
13994
13995
13996
13997
13998
13999
14000 const castArray = maybeArray => Array.isArray(maybeArray) ? maybeArray : [maybeArray];
14001
14002 function segmentHTMLToShortcodeBlock(HTML, lastIndex = 0, excludedBlockNames = []) {
14003 // Get all matches.
14004 const transformsFrom = getBlockTransforms('from');
14005 const transformation = findTransform(transformsFrom, transform => excludedBlockNames.indexOf(transform.blockName) === -1 && transform.type === 'shortcode' && castArray(transform.tag).some(tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML)));
14006
14007 if (!transformation) {
14008 return [HTML];
14009 }
14010
14011 const transformTags = castArray(transformation.tag);
14012 const transformTag = transformTags.find(tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML));
14013 let match;
14014 const previousIndex = lastIndex;
14015
14016 if (match = (0,external_wp_shortcode_namespaceObject.next)(transformTag, HTML, lastIndex)) {
14017 lastIndex = match.index + match.content.length;
14018 const beforeHTML = HTML.substr(0, match.index);
14019 const afterHTML = HTML.substr(lastIndex); // If the shortcode content does not contain HTML and the shortcode is
14020 // not on a new line (or in paragraph from Markdown converter),
14021 // consider the shortcode as inline text, and thus skip conversion for
14022 // this segment.
14023
14024 if (!match.shortcode.content?.includes('<') && !(/(\n|<p>)\s*$/.test(beforeHTML) && /^\s*(\n|<\/p>)/.test(afterHTML))) {
14025 return segmentHTMLToShortcodeBlock(HTML, lastIndex);
14026 } // If a transformation's `isMatch` predicate fails for the inbound
14027 // shortcode, try again by excluding the current block type.
14028 //
14029 // This is the only call to `segmentHTMLToShortcodeBlock` that should
14030 // ever carry over `excludedBlockNames`. Other calls in the module
14031 // should skip that argument as a way to reset the exclusion state, so
14032 // that one `isMatch` fail in an HTML fragment doesn't prevent any
14033 // valid matches in subsequent fragments.
14034
14035
14036 if (transformation.isMatch && !transformation.isMatch(match.shortcode.attrs)) {
14037 return segmentHTMLToShortcodeBlock(HTML, previousIndex, [...excludedBlockNames, transformation.blockName]);
14038 }
14039
14040 let blocks = [];
14041
14042 if (typeof transformation.transform === 'function') {
14043 // Passing all of `match` as second argument is intentionally broad
14044 // but shouldn't be too relied upon.
14045 //
14046 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14047 blocks = [].concat(transformation.transform(match.shortcode.attrs, match)); // Applying the built-in fixes can enhance the attributes with missing content like "className".
14048
14049 blocks = blocks.map(block => {
14050 block.originalContent = match.shortcode.content;
14051 return applyBuiltInValidationFixes(block, getBlockType(block.name));
14052 });
14053 } else {
14054 const attributes = Object.fromEntries(Object.entries(transformation.attributes).filter(([, schema]) => schema.shortcode) // Passing all of `match` as second argument is intentionally broad
14055 // but shouldn't be too relied upon.
14056 //
14057 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14058 .map(([key, schema]) => [key, schema.shortcode(match.shortcode.attrs, match)]));
14059 const blockType = getBlockType(transformation.blockName);
14060
14061 if (!blockType) {
14062 return [HTML];
14063 }
14064
14065 const transformationBlockType = { ...blockType,
14066 attributes: transformation.attributes
14067 };
14068 let block = createBlock(transformation.blockName, getBlockAttributes(transformationBlockType, match.shortcode.content, attributes)); // Applying the built-in fixes can enhance the attributes with missing content like "className".
14069
14070 block.originalContent = match.shortcode.content;
14071 block = applyBuiltInValidationFixes(block, transformationBlockType);
14072 blocks = [block];
14073 }
14074
14075 return [...segmentHTMLToShortcodeBlock(beforeHTML), ...blocks, ...segmentHTMLToShortcodeBlock(afterHTML)];
14076 }
14077
14078 return [HTML];
14079 }
14080
14081 /* harmony default export */ const shortcode_converter = (segmentHTMLToShortcodeBlock);
14082
14083 // EXTERNAL MODULE: ./node_modules/deepmerge/dist/cjs.js
14084 var cjs = __webpack_require__(1919);
14085 var cjs_default = /*#__PURE__*/__webpack_require__.n(cjs);
14086 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/utils.js
14087 /**
14088 * External dependencies
14089 */
14090
14091 /**
14092 * WordPress dependencies
14093 */
14094
14095
14096 /**
14097 * Internal dependencies
14098 */
14099
14100
14101
14102
14103 const customMerge = key => {
14104 return (srcValue, objValue) => {
14105 switch (key) {
14106 case 'children':
14107 {
14108 if (objValue === '*' || srcValue === '*') {
14109 return '*';
14110 }
14111
14112 return { ...objValue,
14113 ...srcValue
14114 };
14115 }
14116
14117 case 'attributes':
14118 case 'require':
14119 {
14120 return [...(objValue || []), ...(srcValue || [])];
14121 }
14122
14123 case 'isMatch':
14124 {
14125 // If one of the values being merge is undefined (matches everything),
14126 // the result of the merge will be undefined.
14127 if (!objValue || !srcValue) {
14128 return undefined;
14129 } // When merging two isMatch functions, the result is a new function
14130 // that returns if one of the source functions returns true.
14131
14132
14133 return (...args) => {
14134 return objValue(...args) || srcValue(...args);
14135 };
14136 }
14137 }
14138
14139 return cjs_default()(objValue, srcValue, {
14140 customMerge,
14141 clone: false
14142 });
14143 };
14144 };
14145
14146 function getBlockContentSchemaFromTransforms(transforms, context) {
14147 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14148 const schemaArgs = {
14149 phrasingContentSchema,
14150 isPaste: context === 'paste'
14151 };
14152 const schemas = transforms.map(({
14153 isMatch,
14154 blockName,
14155 schema
14156 }) => {
14157 const hasAnchorSupport = hasBlockSupport(blockName, 'anchor');
14158 schema = typeof schema === 'function' ? schema(schemaArgs) : schema; // If the block does not has anchor support and the transform does not
14159 // provides an isMatch we can return the schema right away.
14160
14161 if (!hasAnchorSupport && !isMatch) {
14162 return schema;
14163 }
14164
14165 if (!schema) {
14166 return {};
14167 }
14168
14169 return Object.fromEntries(Object.entries(schema).map(([key, value]) => {
14170 let attributes = value.attributes || []; // If the block supports the "anchor" functionality, it needs to keep its ID attribute.
14171
14172 if (hasAnchorSupport) {
14173 attributes = [...attributes, 'id'];
14174 }
14175
14176 return [key, { ...value,
14177 attributes,
14178 isMatch: isMatch ? isMatch : undefined
14179 }];
14180 }));
14181 });
14182 return cjs_default().all(schemas, {
14183 customMerge,
14184 clone: false
14185 });
14186 }
14187 /**
14188 * Gets the block content schema, which is extracted and merged from all
14189 * registered blocks with raw transfroms.
14190 *
14191 * @param {string} context Set to "paste" when in paste context, where the
14192 * schema is more strict.
14193 *
14194 * @return {Object} A complete block content schema.
14195 */
14196
14197 function getBlockContentSchema(context) {
14198 return getBlockContentSchemaFromTransforms(getRawTransforms(), context);
14199 }
14200 /**
14201 * Checks whether HTML can be considered plain text. That is, it does not contain
14202 * any elements that are not line breaks.
14203 *
14204 * @param {string} HTML The HTML to check.
14205 *
14206 * @return {boolean} Whether the HTML can be considered plain text.
14207 */
14208
14209 function isPlain(HTML) {
14210 return !/<(?!br[ />])/i.test(HTML);
14211 }
14212 /**
14213 * Given node filters, deeply filters and mutates a NodeList.
14214 *
14215 * @param {NodeList} nodeList The nodeList to filter.
14216 * @param {Array} filters An array of functions that can mutate with the provided node.
14217 * @param {Document} doc The document of the nodeList.
14218 * @param {Object} schema The schema to use.
14219 */
14220
14221 function deepFilterNodeList(nodeList, filters, doc, schema) {
14222 Array.from(nodeList).forEach(node => {
14223 deepFilterNodeList(node.childNodes, filters, doc, schema);
14224 filters.forEach(item => {
14225 // Make sure the node is still attached to the document.
14226 if (!doc.contains(node)) {
14227 return;
14228 }
14229
14230 item(node, doc, schema);
14231 });
14232 });
14233 }
14234 /**
14235 * Given node filters, deeply filters HTML tags.
14236 * Filters from the deepest nodes to the top.
14237 *
14238 * @param {string} HTML The HTML to filter.
14239 * @param {Array} filters An array of functions that can mutate with the provided node.
14240 * @param {Object} schema The schema to use.
14241 *
14242 * @return {string} The filtered HTML.
14243 */
14244
14245 function deepFilterHTML(HTML, filters = [], schema) {
14246 const doc = document.implementation.createHTMLDocument('');
14247 doc.body.innerHTML = HTML;
14248 deepFilterNodeList(doc.body.childNodes, filters, doc, schema);
14249 return doc.body.innerHTML;
14250 }
14251 /**
14252 * Gets a sibling within text-level context.
14253 *
14254 * @param {Element} node The subject node.
14255 * @param {string} which "next" or "previous".
14256 */
14257
14258 function getSibling(node, which) {
14259 const sibling = node[`${which}Sibling`];
14260
14261 if (sibling && (0,external_wp_dom_namespaceObject.isPhrasingContent)(sibling)) {
14262 return sibling;
14263 }
14264
14265 const {
14266 parentNode
14267 } = node;
14268
14269 if (!parentNode || !(0,external_wp_dom_namespaceObject.isPhrasingContent)(parentNode)) {
14270 return;
14271 }
14272
14273 return getSibling(parentNode, which);
14274 }
14275
14276 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/index.js
14277 /**
14278 * WordPress dependencies
14279 */
14280
14281
14282 /**
14283 * Internal dependencies
14284 */
14285
14286
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296 function deprecatedGetPhrasingContentSchema(context) {
14297 external_wp_deprecated_default()('wp.blocks.getPhrasingContentSchema', {
14298 since: '5.6',
14299 alternative: 'wp.dom.getPhrasingContentSchema'
14300 });
14301 return (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14302 }
14303 /**
14304 * Converts an HTML string to known blocks.
14305 *
14306 * @param {Object} $1
14307 * @param {string} $1.HTML The HTML to convert.
14308 *
14309 * @return {Array} A list of blocks.
14310 */
14311
14312 function rawHandler({
14313 HTML = ''
14314 }) {
14315 // If we detect block delimiters, parse entirely as blocks.
14316 if (HTML.indexOf('<!-- wp:') !== -1) {
14317 return parser_parse(HTML);
14318 } // An array of HTML strings and block objects. The blocks replace matched
14319 // shortcodes.
14320
14321
14322 const pieces = shortcode_converter(HTML);
14323 const blockContentSchema = getBlockContentSchema();
14324 return pieces.map(piece => {
14325 // Already a block from shortcode.
14326 if (typeof piece !== 'string') {
14327 return piece;
14328 } // These filters are essential for some blocks to be able to transform
14329 // from raw HTML. These filters move around some content or add
14330 // additional tags, they do not remove any content.
14331
14332
14333 const filters = [// Needed to adjust invalid lists.
14334 listReducer, // Needed to create more and nextpage blocks.
14335 specialCommentConverter, // Needed to create media blocks.
14336 figureContentReducer, // Needed to create the quote block, which cannot handle text
14337 // without wrapper paragraphs.
14338 blockquoteNormaliser];
14339 piece = deepFilterHTML(piece, filters, blockContentSchema);
14340 piece = normaliseBlocks(piece);
14341 return htmlToBlocks(piece, rawHandler);
14342 }).flat().filter(Boolean);
14343 }
14344
14345 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/comment-remover.js
14346 /**
14347 * WordPress dependencies
14348 */
14349
14350 /**
14351 * Looks for comments, and removes them.
14352 *
14353 * @param {Node} node The node to be processed.
14354 * @return {void}
14355 */
14356
14357 function commentRemover(node) {
14358 if (node.nodeType === node.COMMENT_NODE) {
14359 (0,external_wp_dom_namespaceObject.remove)(node);
14360 }
14361 }
14362
14363 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/is-inline-content.js
14364 /**
14365 * WordPress dependencies
14366 */
14367
14368 /**
14369 * Checks if the given node should be considered inline content, optionally
14370 * depending on a context tag.
14371 *
14372 * @param {Node} node Node name.
14373 * @param {string} contextTag Tag name.
14374 *
14375 * @return {boolean} True if the node is inline content, false if nohe.
14376 */
14377
14378 function isInline(node, contextTag) {
14379 if ((0,external_wp_dom_namespaceObject.isTextContent)(node)) {
14380 return true;
14381 }
14382
14383 if (!contextTag) {
14384 return false;
14385 }
14386
14387 const tag = node.nodeName.toLowerCase();
14388 const inlineAllowedTagGroups = [['ul', 'li', 'ol'], ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']];
14389 return inlineAllowedTagGroups.some(tagGroup => [tag, contextTag].filter(t => !tagGroup.includes(t)).length === 0);
14390 }
14391
14392 function deepCheck(nodes, contextTag) {
14393 return nodes.every(node => isInline(node, contextTag) && deepCheck(Array.from(node.children), contextTag));
14394 }
14395
14396 function isDoubleBR(node) {
14397 return node.nodeName === 'BR' && node.previousSibling && node.previousSibling.nodeName === 'BR';
14398 }
14399
14400 function isInlineContent(HTML, contextTag) {
14401 const doc = document.implementation.createHTMLDocument('');
14402 doc.body.innerHTML = HTML;
14403 const nodes = Array.from(doc.body.children);
14404 return !nodes.some(isDoubleBR) && deepCheck(nodes, contextTag);
14405 }
14406
14407 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/phrasing-content-reducer.js
14408 /**
14409 * WordPress dependencies
14410 */
14411
14412 function phrasingContentReducer(node, doc) {
14413 // In jsdom-jscore, 'node.style' can be null.
14414 // TODO: Explore fixing this by patching jsdom-jscore.
14415 if (node.nodeName === 'SPAN' && node.style) {
14416 const {
14417 fontWeight,
14418 fontStyle,
14419 textDecorationLine,
14420 textDecoration,
14421 verticalAlign
14422 } = node.style;
14423
14424 if (fontWeight === 'bold' || fontWeight === '700') {
14425 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('strong'), node);
14426 }
14427
14428 if (fontStyle === 'italic') {
14429 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('em'), node);
14430 } // Some DOM implementations (Safari, JSDom) don't support
14431 // style.textDecorationLine, so we check style.textDecoration as a
14432 // fallback.
14433
14434
14435 if (textDecorationLine === 'line-through' || textDecoration.includes('line-through')) {
14436 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('s'), node);
14437 }
14438
14439 if (verticalAlign === 'super') {
14440 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sup'), node);
14441 } else if (verticalAlign === 'sub') {
14442 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sub'), node);
14443 }
14444 } else if (node.nodeName === 'B') {
14445 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'strong');
14446 } else if (node.nodeName === 'I') {
14447 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'em');
14448 } else if (node.nodeName === 'A') {
14449 // In jsdom-jscore, 'node.target' can be null.
14450 // TODO: Explore fixing this by patching jsdom-jscore.
14451 if (node.target && node.target.toLowerCase() === '_blank') {
14452 node.rel = 'noreferrer noopener';
14453 } else {
14454 node.removeAttribute('target');
14455 node.removeAttribute('rel');
14456 } // Saves anchor elements name attribute as id
14457
14458
14459 if (node.name && !node.id) {
14460 node.id = node.name;
14461 } // Keeps id only if there is an internal link pointing to it
14462
14463
14464 if (node.id && !node.ownerDocument.querySelector(`[href="#${node.id}"]`)) {
14465 node.removeAttribute('id');
14466 }
14467 }
14468 }
14469
14470 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/head-remover.js
14471 function headRemover(node) {
14472 if (node.nodeName !== 'SCRIPT' && node.nodeName !== 'NOSCRIPT' && node.nodeName !== 'TEMPLATE' && node.nodeName !== 'STYLE') {
14473 return;
14474 }
14475
14476 node.parentNode.removeChild(node);
14477 }
14478
14479 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/ms-list-converter.js
14480 /**
14481 * Browser dependencies
14482 */
14483 const {
14484 parseInt: ms_list_converter_parseInt
14485 } = window;
14486
14487 function ms_list_converter_isList(node) {
14488 return node.nodeName === 'OL' || node.nodeName === 'UL';
14489 }
14490
14491 function msListConverter(node, doc) {
14492 if (node.nodeName !== 'P') {
14493 return;
14494 }
14495
14496 const style = node.getAttribute('style');
14497
14498 if (!style) {
14499 return;
14500 } // Quick check.
14501
14502
14503 if (style.indexOf('mso-list') === -1) {
14504 return;
14505 }
14506
14507 const matches = /mso-list\s*:[^;]+level([0-9]+)/i.exec(style);
14508
14509 if (!matches) {
14510 return;
14511 }
14512
14513 let level = ms_list_converter_parseInt(matches[1], 10) - 1 || 0;
14514 const prevNode = node.previousElementSibling; // Add new list if no previous.
14515
14516 if (!prevNode || !ms_list_converter_isList(prevNode)) {
14517 // See https://html.spec.whatwg.org/multipage/grouping-content.html#attr-ol-type.
14518 const type = node.textContent.trim().slice(0, 1);
14519 const isNumeric = /[1iIaA]/.test(type);
14520 const newListNode = doc.createElement(isNumeric ? 'ol' : 'ul');
14521
14522 if (isNumeric) {
14523 newListNode.setAttribute('type', type);
14524 }
14525
14526 node.parentNode.insertBefore(newListNode, node);
14527 }
14528
14529 const listNode = node.previousElementSibling;
14530 const listType = listNode.nodeName;
14531 const listItem = doc.createElement('li');
14532 let receivingNode = listNode; // Remove the first span with list info.
14533
14534 node.removeChild(node.firstChild); // Add content.
14535
14536 while (node.firstChild) {
14537 listItem.appendChild(node.firstChild);
14538 } // Change pointer depending on indentation level.
14539
14540
14541 while (level--) {
14542 receivingNode = receivingNode.lastChild || receivingNode; // If it's a list, move pointer to the last item.
14543
14544 if (ms_list_converter_isList(receivingNode)) {
14545 receivingNode = receivingNode.lastChild || receivingNode;
14546 }
14547 } // Make sure we append to a list.
14548
14549
14550 if (!ms_list_converter_isList(receivingNode)) {
14551 receivingNode = receivingNode.appendChild(doc.createElement(listType));
14552 } // Append the list item to the list.
14553
14554
14555 receivingNode.appendChild(listItem); // Remove the wrapper paragraph.
14556
14557 node.parentNode.removeChild(node);
14558 }
14559
14560 ;// CONCATENATED MODULE: external ["wp","blob"]
14561 const external_wp_blob_namespaceObject = window["wp"]["blob"];
14562 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/image-corrector.js
14563 /**
14564 * WordPress dependencies
14565 */
14566
14567 /**
14568 * Browser dependencies
14569 */
14570
14571 const {
14572 atob,
14573 File
14574 } = window;
14575 function imageCorrector(node) {
14576 if (node.nodeName !== 'IMG') {
14577 return;
14578 }
14579
14580 if (node.src.indexOf('file:') === 0) {
14581 node.src = '';
14582 } // This piece cannot be tested outside a browser env.
14583
14584
14585 if (node.src.indexOf('data:') === 0) {
14586 const [properties, data] = node.src.split(',');
14587 const [type] = properties.slice(5).split(';');
14588
14589 if (!data || !type) {
14590 node.src = '';
14591 return;
14592 }
14593
14594 let decoded; // Can throw DOMException!
14595
14596 try {
14597 decoded = atob(data);
14598 } catch (e) {
14599 node.src = '';
14600 return;
14601 }
14602
14603 const uint8Array = new Uint8Array(decoded.length);
14604
14605 for (let i = 0; i < uint8Array.length; i++) {
14606 uint8Array[i] = decoded.charCodeAt(i);
14607 }
14608
14609 const name = type.replace('/', '.');
14610 const file = new File([uint8Array], name, {
14611 type
14612 });
14613 node.src = (0,external_wp_blob_namespaceObject.createBlobURL)(file);
14614 } // Remove trackers and hardly visible images.
14615
14616
14617 if (node.height === 1 || node.width === 1) {
14618 node.parentNode.removeChild(node);
14619 }
14620 }
14621
14622 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/div-normaliser.js
14623 /**
14624 * Internal dependencies
14625 */
14626
14627 function divNormaliser(node) {
14628 if (node.nodeName !== 'DIV') {
14629 return;
14630 }
14631
14632 node.innerHTML = normaliseBlocks(node.innerHTML);
14633 }
14634
14635 // EXTERNAL MODULE: ./node_modules/showdown/dist/showdown.js
14636 var showdown = __webpack_require__(7308);
14637 var showdown_default = /*#__PURE__*/__webpack_require__.n(showdown);
14638 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/markdown-converter.js
14639 /**
14640 * External dependencies
14641 */
14642 // Reuse the same showdown converter.
14643
14644 const converter = new (showdown_default()).Converter({
14645 noHeaderId: true,
14646 tables: true,
14647 literalMidWordUnderscores: true,
14648 omitExtraWLInCodeBlocks: true,
14649 simpleLineBreaks: true,
14650 strikethrough: true
14651 });
14652 /**
14653 * Corrects the Slack Markdown variant of the code block.
14654 * If uncorrected, it will be converted to inline code.
14655 *
14656 * @see https://get.slack.help/hc/en-us/articles/202288908-how-can-i-add-formatting-to-my-messages-#code-blocks
14657 *
14658 * @param {string} text The potential Markdown text to correct.
14659 *
14660 * @return {string} The corrected Markdown.
14661 */
14662
14663 function slackMarkdownVariantCorrector(text) {
14664 return text.replace(/((?:^|\n)```)([^\n`]+)(```(?:$|\n))/, (match, p1, p2, p3) => `${p1}\n${p2}\n${p3}`);
14665 }
14666
14667 function bulletsToAsterisks(text) {
14668 return text.replace(/(^|\n)•( +)/g, '$1*$2');
14669 }
14670 /**
14671 * Converts a piece of text into HTML based on any Markdown present.
14672 * Also decodes any encoded HTML.
14673 *
14674 * @param {string} text The plain text to convert.
14675 *
14676 * @return {string} HTML.
14677 */
14678
14679
14680 function markdownConverter(text) {
14681 return converter.makeHtml(slackMarkdownVariantCorrector(bulletsToAsterisks(text)));
14682 }
14683
14684 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/iframe-remover.js
14685 /**
14686 * Removes iframes.
14687 *
14688 * @param {Node} node The node to check.
14689 *
14690 * @return {void}
14691 */
14692 function iframeRemover(node) {
14693 if (node.nodeName === 'IFRAME') {
14694 const text = node.ownerDocument.createTextNode(node.src);
14695 node.parentNode.replaceChild(text, node);
14696 }
14697 }
14698
14699 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/google-docs-uid-remover.js
14700 /**
14701 * WordPress dependencies
14702 */
14703
14704 function googleDocsUIdRemover(node) {
14705 if (!node.id || node.id.indexOf('docs-internal-guid-') !== 0) {
14706 return;
14707 } // Google Docs sometimes wraps the content in a B tag. We don't want to keep
14708 // this.
14709
14710
14711 if (node.tagName === 'B') {
14712 (0,external_wp_dom_namespaceObject.unwrap)(node);
14713 } else {
14714 node.removeAttribute('id');
14715 }
14716 }
14717
14718 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-formatting-remover.js
14719 /**
14720 * Internal dependencies
14721 */
14722
14723
14724 function isFormattingSpace(character) {
14725 return character === ' ' || character === '\r' || character === '\n' || character === '\t';
14726 }
14727 /**
14728 * Removes spacing that formats HTML.
14729 *
14730 * @see https://www.w3.org/TR/css-text-3/#white-space-processing
14731 *
14732 * @param {Node} node The node to be processed.
14733 * @return {void}
14734 */
14735
14736
14737 function htmlFormattingRemover(node) {
14738 if (node.nodeType !== node.TEXT_NODE) {
14739 return;
14740 } // Ignore pre content. Note that this does not use Element#closest due to
14741 // a combination of (a) node may not be Element and (b) node.parentElement
14742 // does not have full support in all browsers (Internet Exporer).
14743 //
14744 // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility
14745
14746 /** @type {Node?} */
14747
14748
14749 let parent = node;
14750
14751 while (parent = parent.parentNode) {
14752 if (parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE') {
14753 return;
14754 }
14755 } // First, replace any sequence of HTML formatting space with a single space.
14756
14757
14758 let newData = node.data.replace(/[ \r\n\t]+/g, ' '); // Remove the leading space if the text element is at the start of a block,
14759 // is preceded by a line break element, or has a space in the previous
14760 // node.
14761
14762 if (newData[0] === ' ') {
14763 const previousSibling = getSibling(node, 'previous');
14764
14765 if (!previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice(-1) === ' ') {
14766 newData = newData.slice(1);
14767 }
14768 } // Remove the trailing space if the text element is at the end of a block,
14769 // is succeded by a line break element, or has a space in the next text
14770 // node.
14771
14772
14773 if (newData[newData.length - 1] === ' ') {
14774 const nextSibling = getSibling(node, 'next');
14775
14776 if (!nextSibling || nextSibling.nodeName === 'BR' || nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace(nextSibling.textContent[0])) {
14777 newData = newData.slice(0, -1);
14778 }
14779 } // If there's no data left, remove the node, so `previousSibling` stays
14780 // accurate. Otherwise, update the node data.
14781
14782
14783 if (!newData) {
14784 node.parentNode.removeChild(node);
14785 } else {
14786 node.data = newData;
14787 }
14788 }
14789
14790 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/br-remover.js
14791 /**
14792 * Internal dependencies
14793 */
14794
14795 /**
14796 * Removes trailing br elements from text-level content.
14797 *
14798 * @param {Element} node Node to check.
14799 */
14800
14801 function brRemover(node) {
14802 if (node.nodeName !== 'BR') {
14803 return;
14804 }
14805
14806 if (getSibling(node, 'next')) {
14807 return;
14808 }
14809
14810 node.parentNode.removeChild(node);
14811 }
14812
14813 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/empty-paragraph-remover.js
14814 /**
14815 * Removes empty paragraph elements.
14816 *
14817 * @param {Element} node Node to check.
14818 */
14819 function emptyParagraphRemover(node) {
14820 if (node.nodeName !== 'P') {
14821 return;
14822 }
14823
14824 if (node.hasChildNodes()) {
14825 return;
14826 }
14827
14828 node.parentNode.removeChild(node);
14829 }
14830
14831 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/slack-paragraph-corrector.js
14832 /**
14833 * Replaces Slack paragraph markup with a double line break (later converted to
14834 * a proper paragraph).
14835 *
14836 * @param {Element} node Node to check.
14837 */
14838 function slackParagraphCorrector(node) {
14839 if (node.nodeName !== 'SPAN') {
14840 return;
14841 }
14842
14843 if (node.getAttribute('data-stringify-type') !== 'paragraph-break') {
14844 return;
14845 }
14846
14847 const {
14848 parentNode
14849 } = node;
14850 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
14851 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
14852 parentNode.removeChild(node);
14853 }
14854
14855 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/paste-handler.js
14856 /**
14857 * WordPress dependencies
14858 */
14859
14860 /**
14861 * Internal dependencies
14862 */
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889 /**
14890 * Browser dependencies
14891 */
14892
14893 const {
14894 console: paste_handler_console
14895 } = window;
14896 /**
14897 * Filters HTML to only contain phrasing content.
14898 *
14899 * @param {string} HTML The HTML to filter.
14900 * @param {boolean} preserveWhiteSpace Whether or not to preserve consequent white space.
14901 *
14902 * @return {string} HTML only containing phrasing content.
14903 */
14904
14905 function filterInlineHTML(HTML, preserveWhiteSpace) {
14906 HTML = deepFilterHTML(HTML, [headRemover, googleDocsUIdRemover, phrasingContentReducer, commentRemover]);
14907 HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
14908 inline: true
14909 });
14910
14911 if (!preserveWhiteSpace) {
14912 HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
14913 } // Allows us to ask for this information when we get a report.
14914
14915
14916 paste_handler_console.log('Processed inline HTML:\n\n', HTML);
14917 return HTML;
14918 }
14919 /**
14920 * Converts an HTML string to known blocks. Strips everything else.
14921 *
14922 * @param {Object} options
14923 * @param {string} [options.HTML] The HTML to convert.
14924 * @param {string} [options.plainText] Plain text version.
14925 * @param {string} [options.mode] Handle content as blocks or inline content.
14926 * * 'AUTO': Decide based on the content passed.
14927 * * 'INLINE': Always handle as inline content, and return string.
14928 * * 'BLOCKS': Always handle as blocks, and return array of blocks.
14929 * @param {Array} [options.tagName] The tag into which content will be inserted.
14930 * @param {boolean} [options.preserveWhiteSpace] Whether or not to preserve consequent white space.
14931 *
14932 * @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
14933 */
14934
14935
14936 function pasteHandler({
14937 HTML = '',
14938 plainText = '',
14939 mode = 'AUTO',
14940 tagName,
14941 preserveWhiteSpace
14942 }) {
14943 // First of all, strip any meta tags.
14944 HTML = HTML.replace(/<meta[^>]+>/g, ''); // Strip Windows markers.
14945
14946 HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
14947 HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, ''); // If we detect block delimiters in HTML, parse entirely as blocks.
14948
14949 if (mode !== 'INLINE') {
14950 // Check plain text if there is no HTML.
14951 const content = HTML ? HTML : plainText;
14952
14953 if (content.indexOf('<!-- wp:') !== -1) {
14954 return parser_parse(content);
14955 }
14956 } // Normalize unicode to use composed characters.
14957 // This is unsupported in IE 11 but it's a nice-to-have feature, not mandatory.
14958 // Not normalizing the content will only affect older browsers and won't
14959 // entirely break the app.
14960 // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
14961 // See: https://core.trac.wordpress.org/ticket/30130
14962 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
14963
14964
14965 if (String.prototype.normalize) {
14966 HTML = HTML.normalize();
14967 } // Parse Markdown (and encoded HTML) if:
14968 // * There is a plain text version.
14969 // * There is no HTML version, or it has no formatting.
14970
14971
14972 if (plainText && (!HTML || isPlain(HTML))) {
14973 HTML = plainText; // The markdown converter (Showdown) trims whitespace.
14974
14975 if (!/^\s+$/.test(plainText)) {
14976 HTML = markdownConverter(HTML);
14977 } // Switch to inline mode if:
14978 // * The current mode is AUTO.
14979 // * The original plain text had no line breaks.
14980 // * The original plain text was not an HTML paragraph.
14981 // * The converted text is just a paragraph.
14982
14983
14984 if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
14985 mode = 'INLINE';
14986 }
14987 }
14988
14989 if (mode === 'INLINE') {
14990 return filterInlineHTML(HTML, preserveWhiteSpace);
14991 } // Must be run before checking if it's inline content.
14992
14993
14994 HTML = deepFilterHTML(HTML, [slackParagraphCorrector]); // An array of HTML strings and block objects. The blocks replace matched
14995 // shortcodes.
14996
14997 const pieces = shortcode_converter(HTML); // The call to shortcodeConverter will always return more than one element
14998 // if shortcodes are matched. The reason is when shortcodes are matched
14999 // empty HTML strings are included.
15000
15001 const hasShortcodes = pieces.length > 1;
15002
15003 if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
15004 return filterInlineHTML(HTML, preserveWhiteSpace);
15005 }
15006
15007 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
15008 const blockContentSchema = getBlockContentSchema('paste');
15009 const blocks = pieces.map(piece => {
15010 // Already a block from shortcode.
15011 if (typeof piece !== 'string') {
15012 return piece;
15013 }
15014
15015 const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser, divNormaliser];
15016 const schema = { ...blockContentSchema,
15017 // Keep top-level phrasing content, normalised by `normaliseBlocks`.
15018 ...phrasingContentSchema
15019 };
15020 piece = deepFilterHTML(piece, filters, blockContentSchema);
15021 piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
15022 piece = normaliseBlocks(piece);
15023 piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema); // Allows us to ask for this information when we get a report.
15024
15025 paste_handler_console.log('Processed HTML piece:\n\n', piece);
15026 return htmlToBlocks(piece, pasteHandler);
15027 }).flat().filter(Boolean); // If we're allowed to return inline content, and there is only one
15028 // inlineable block, and the original plain text content does not have any
15029 // line breaks, then treat it as inline paste.
15030
15031 if (mode === 'AUTO' && blocks.length === 1 && hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
15032 const trimRegex = /^[\n]+|[\n]+$/g; // Don't catch line breaks at the start or end.
15033
15034 const trimmedPlainText = plainText.replace(trimRegex, '');
15035
15036 if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
15037 return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema).replace(trimRegex, '');
15038 }
15039 }
15040
15041 return blocks;
15042 }
15043
15044 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/categories.js
15045 /**
15046 * WordPress dependencies
15047 */
15048
15049 /**
15050 * Internal dependencies
15051 */
15052
15053
15054 /** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
15055
15056 /**
15057 * Returns all the block categories.
15058 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
15059 *
15060 * @ignore
15061 *
15062 * @return {WPBlockCategory[]} Block categories.
15063 */
15064
15065 function categories_getCategories() {
15066 return (0,external_wp_data_namespaceObject.select)(store).getCategories();
15067 }
15068 /**
15069 * Sets the block categories.
15070 *
15071 * @param {WPBlockCategory[]} categories Block categories.
15072 *
15073 * @example
15074 * ```js
15075 * import { __ } from '@wordpress/i18n';
15076 * import { store as blocksStore, setCategories } from '@wordpress/blocks';
15077 * import { useSelect } from '@wordpress/data';
15078 * import { Button } from '@wordpress/components';
15079 *
15080 * const ExampleComponent = () => {
15081 * // Retrieve the list of current categories.
15082 * const blockCategories = useSelect(
15083 * ( select ) => select( blocksStore ).getCategories(),
15084 * []
15085 * );
15086 *
15087 * return (
15088 * <Button
15089 * onClick={ () => {
15090 * // Add a custom category to the existing list.
15091 * setCategories( [
15092 * ...blockCategories,
15093 * { title: 'Custom Category', slug: 'custom-category' },
15094 * ] );
15095 * } }
15096 * >
15097 * { __( 'Add a new custom block category' ) }
15098 * </Button>
15099 * );
15100 * };
15101 * ```
15102 */
15103
15104 function categories_setCategories(categories) {
15105 (0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
15106 }
15107 /**
15108 * Updates a category.
15109 *
15110 * @param {string} slug Block category slug.
15111 * @param {WPBlockCategory} category Object containing the category properties
15112 * that should be updated.
15113 *
15114 * @example
15115 * ```js
15116 * import { __ } from '@wordpress/i18n';
15117 * import { updateCategory } from '@wordpress/blocks';
15118 * import { Button } from '@wordpress/components';
15119 *
15120 * const ExampleComponent = () => {
15121 * return (
15122 * <Button
15123 * onClick={ () => {
15124 * updateCategory( 'text', { title: __( 'Written Word' ) } );
15125 * } }
15126 * >
15127 * { __( 'Update Text category title' ) }
15128 * </Button>
15129 * ) ;
15130 * };
15131 * ```
15132 */
15133
15134 function categories_updateCategory(slug, category) {
15135 (0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
15136 }
15137
15138 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/templates.js
15139 /**
15140 * WordPress dependencies
15141 */
15142
15143 /**
15144 * Internal dependencies
15145 */
15146
15147
15148
15149
15150 /**
15151 * Checks whether a list of blocks matches a template by comparing the block names.
15152 *
15153 * @param {Array} blocks Block list.
15154 * @param {Array} template Block template.
15155 *
15156 * @return {boolean} Whether the list of blocks matches a templates.
15157 */
15158
15159 function doBlocksMatchTemplate(blocks = [], template = []) {
15160 return blocks.length === template.length && template.every(([name,, innerBlocksTemplate], index) => {
15161 const block = blocks[index];
15162 return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
15163 });
15164 }
15165 /**
15166 * Synchronize a block list with a block template.
15167 *
15168 * Synchronizing a block list with a block template means that we loop over the blocks
15169 * keep the block as is if it matches the block at the same position in the template
15170 * (If it has the same name) and if doesn't match, we create a new block based on the template.
15171 * Extra blocks not present in the template are removed.
15172 *
15173 * @param {Array} blocks Block list.
15174 * @param {Array} template Block template.
15175 *
15176 * @return {Array} Updated Block list.
15177 */
15178
15179 function synchronizeBlocksWithTemplate(blocks = [], template) {
15180 // If no template is provided, return blocks unmodified.
15181 if (!template) {
15182 return blocks;
15183 }
15184
15185 return template.map(([name, attributes, innerBlocksTemplate], index) => {
15186 var _blockType$attributes;
15187
15188 const block = blocks[index];
15189
15190 if (block && block.name === name) {
15191 const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
15192 return { ...block,
15193 innerBlocks
15194 };
15195 } // To support old templates that were using the "children" format
15196 // for the attributes using "html" strings now, we normalize the template attributes
15197 // before creating the blocks.
15198
15199
15200 const blockType = getBlockType(name);
15201
15202 const isHTMLAttribute = attributeDefinition => attributeDefinition?.source === 'html';
15203
15204 const isQueryAttribute = attributeDefinition => attributeDefinition?.source === 'query';
15205
15206 const normalizeAttributes = (schema, values) => {
15207 if (!values) {
15208 return {};
15209 }
15210
15211 return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, normalizeAttribute(schema[key], value)]));
15212 };
15213
15214 const normalizeAttribute = (definition, value) => {
15215 if (isHTMLAttribute(definition) && Array.isArray(value)) {
15216 // Introduce a deprecated call at this point
15217 // When we're confident that "children" format should be removed from the templates.
15218 return (0,external_wp_element_namespaceObject.renderToString)(value);
15219 }
15220
15221 if (isQueryAttribute(definition) && value) {
15222 return value.map(subValues => {
15223 return normalizeAttributes(definition.query, subValues);
15224 });
15225 }
15226
15227 return value;
15228 };
15229
15230 const normalizedAttributes = normalizeAttributes((_blockType$attributes = blockType?.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}, attributes);
15231 let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes); // If a Block is undefined at this point, use the core/missing block as
15232 // a placeholder for a better user experience.
15233
15234 if (undefined === getBlockType(blockName)) {
15235 blockAttributes = {
15236 originalName: name,
15237 originalContent: '',
15238 originalUndelimitedContent: ''
15239 };
15240 blockName = 'core/missing';
15241 }
15242
15243 return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
15244 });
15245 }
15246
15247 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/index.js
15248 // The blocktype is the most important concept within the block API. It defines
15249 // all aspects of the block configuration and its interfaces, including `edit`
15250 // and `save`. The transforms specification allows converting one blocktype to
15251 // another through formulas defined by either the source or the destination.
15252 // Switching a blocktype is to be considered a one-way operation implying a
15253 // transformation in the opposite way has to be handled explicitly.
15254 // The block tree is composed of a collection of block nodes. Blocks contained
15255 // within other blocks are called inner blocks. An important design
15256 // consideration is that inner blocks are -- conceptually -- not part of the
15257 // territory established by the parent block that contains them.
15258 //
15259 // This has multiple practical implications: when parsing, we can safely dispose
15260 // of any block boundary found within a block from the innerHTML property when
15261 // transfering to state. Not doing so would have a compounding effect on memory
15262 // and uncertainty over the source of truth. This can be illustrated in how,
15263 // given a tree of `n` nested blocks, the entry node would have to contain the
15264 // actual content of each block while each subsequent block node in the state
15265 // tree would replicate the entire chain `n-1`, meaning the extreme end node
15266 // would have been replicated `n` times as the tree is traversed and would
15267 // generate uncertainty as to which one is to hold the current value of the
15268 // block. For composition, it also means inner blocks can effectively be child
15269 // components whose mechanisms can be shielded from the `edit` implementation
15270 // and just passed along.
15271
15272
15273
15274 // While block transformations account for a specific surface of the API, there
15275 // are also raw transformations which handle arbitrary sources not made out of
15276 // blocks but producing block basaed on various heursitics. This includes
15277 // pasting rich text or HTML data.
15278
15279 // The process of serialization aims to deflate the internal memory of the block
15280 // editor and its state representation back into an HTML valid string. This
15281 // process restores the document integrity and inserts invisible delimiters
15282 // around each block with HTML comment boundaries which can contain any extra
15283 // attributes needed to operate with the block later on.
15284
15285 // Validation is the process of comparing a block source with its output before
15286 // there is any user input or interaction with a block. When this operation
15287 // fails -- for whatever reason -- the block is to be considered invalid. As
15288 // part of validating a block the system will attempt to run the source against
15289 // any provided deprecation definitions.
15290 //
15291 // Worth emphasizing that validation is not a case of whether the markup is
15292 // merely HTML spec-compliant but about how the editor knows to create such
15293 // markup and that its inability to create an identical result can be a strong
15294 // indicator of potential data loss (the invalidation is then a protective
15295 // measure).
15296 //
15297 // The invalidation process can also be deconstructed in phases: 1) validate the
15298 // block exists; 2) validate the source matches the output; 3) validate the
15299 // source matches deprecated outputs; 4) work through the significance of
15300 // differences. These are stacked in a way that favors performance and optimizes
15301 // for the majority of cases. That is to say, the evaluation logic can become
15302 // more sophisticated the further down it goes in the process as the cost is
15303 // accounted for. The first logic checks have to be extremely efficient since
15304 // they will be run for all valid and invalid blocks alike. However, once a
15305 // block is detected as invalid -- failing the three first steps -- it is
15306 // adequate to spend more time determining validity before throwing a conflict.
15307
15308
15309 // Blocks are inherently indifferent about where the data they operate with ends
15310 // up being saved. For example, all blocks can have a static and dynamic aspect
15311 // to them depending on the needs. The static nature of a block is the `save()`
15312 // definition that is meant to be serialized into HTML and which can be left
15313 // void. Any block can also register a `render_callback` on the server, which
15314 // makes its output dynamic either in part or in its totality.
15315 //
15316 // Child blocks are defined as a relationship that builds on top of the inner
15317 // blocks mechanism. A child block is a block node of a particular type that can
15318 // only exist within the inner block boundaries of a specific parent type. This
15319 // allows block authors to compose specific blocks that are not meant to be used
15320 // outside of a specified parent block context. Thus, child blocks extend the
15321 // concept of inner blocks to support a more direct relationship between sets of
15322 // blocks. The addition of parent–child would be a subset of the inner block
15323 // functionality under the premise that certain blocks only make sense as
15324 // children of another block.
15325
15326
15327 // Templates are, in a general sense, a basic collection of block nodes with any
15328 // given set of predefined attributes that are supplied as the initial state of
15329 // an inner blocks group. These nodes can, in turn, contain any number of nested
15330 // blocks within their definition. Templates allow both to specify a default
15331 // state for an editor session or a default set of blocks for any inner block
15332 // implementation within a specific block.
15333
15334
15335
15336
15337
15338
15339 ;// CONCATENATED MODULE: ./packages/blocks/build-module/deprecated.js
15340 /**
15341 * WordPress dependencies
15342 */
15343
15344 /**
15345 * A Higher Order Component used to inject BlockContent using context to the
15346 * wrapped component.
15347 *
15348 * @deprecated
15349 *
15350 * @param {WPComponent} OriginalComponent The component to enhance.
15351 * @return {WPComponent} The same component.
15352 */
15353
15354 function withBlockContentContext(OriginalComponent) {
15355 external_wp_deprecated_default()('wp.blocks.withBlockContentContext', {
15356 since: '6.1'
15357 });
15358 return OriginalComponent;
15359 }
15360
15361 ;// CONCATENATED MODULE: ./packages/blocks/build-module/index.js
15362 // A "block" is the abstract term used to describe units of markup that,
15363 // when composed together, form the content or layout of a page.
15364 // The API for blocks is exposed via `wp.blocks`.
15365 //
15366 // Supported blocks are registered by calling `registerBlockType`. Once registered,
15367 // the block is made available as an option to the editor interface.
15368 //
15369 // Blocks are inferred from the HTML source of a post through a parsing mechanism
15370 // and then stored as objects in state, from which it is then rendered for editing.
15371
15372
15373
15374
15375 })();
15376
15377 (window.wp = window.wp || {}).blocks = __webpack_exports__;
15378 /******/ })()
15379 ;