PluginProbe
Gutenberg / 18.9.0
Gutenberg v18.9.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 18.9.0, at build/blocks/index.js

15,563 lines 535.8 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 /***/ 5619:
5 /***/ ((module) => {
6
7 "use strict";
8
9
10 // do not edit .js files directly - edit src/index.jst
11
12
13 var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
14
15
16 module.exports = function equal(a, b) {
17 if (a === b) return true;
18
19 if (a && b && typeof a == 'object' && typeof b == 'object') {
20 if (a.constructor !== b.constructor) return false;
21
22 var length, i, keys;
23 if (Array.isArray(a)) {
24 length = a.length;
25 if (length != b.length) return false;
26 for (i = length; i-- !== 0;)
27 if (!equal(a[i], b[i])) return false;
28 return true;
29 }
30
31
32 if ((a instanceof Map) && (b instanceof Map)) {
33 if (a.size !== b.size) return false;
34 for (i of a.entries())
35 if (!b.has(i[0])) return false;
36 for (i of a.entries())
37 if (!equal(i[1], b.get(i[0]))) return false;
38 return true;
39 }
40
41 if ((a instanceof Set) && (b instanceof Set)) {
42 if (a.size !== b.size) return false;
43 for (i of a.entries())
44 if (!b.has(i[0])) return false;
45 return true;
46 }
47
48 if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
49 length = a.length;
50 if (length != b.length) return false;
51 for (i = length; i-- !== 0;)
52 if (a[i] !== b[i]) return false;
53 return true;
54 }
55
56
57 if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
58 if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
59 if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
60
61 keys = Object.keys(a);
62 length = keys.length;
63 if (length !== Object.keys(b).length) return false;
64
65 for (i = length; i-- !== 0;)
66 if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
67
68 for (i = length; i-- !== 0;) {
69 var key = keys[i];
70
71 if (!equal(a[key], b[key])) return false;
72 }
73
74 return true;
75 }
76
77 // true if both NaN, false otherwise
78 return a!==a && b!==b;
79 };
80
81
82 /***/ }),
83
84 /***/ 4793:
85 /***/ ((module) => {
86
87 var characterMap = {
88 "À": "A",
89 "Á": "A",
90 "Â": "A",
91 "Ã": "A",
92 "Ä": "A",
93 "Å": "A",
94 "Ấ": "A",
95 "Ắ": "A",
96 "Ẳ": "A",
97 "Ẵ": "A",
98 "Ặ": "A",
99 "Æ": "AE",
100 "Ầ": "A",
101 "Ằ": "A",
102 "Ȃ": "A",
103 "Ả": "A",
104 "Ạ": "A",
105 "Ẩ": "A",
106 "Ẫ": "A",
107 "Ậ": "A",
108 "Ç": "C",
109 "Ḉ": "C",
110 "È": "E",
111 "É": "E",
112 "Ê": "E",
113 "Ë": "E",
114 "Ế": "E",
115 "Ḗ": "E",
116 "Ề": "E",
117 "Ḕ": "E",
118 "Ḝ": "E",
119 "Ȇ": "E",
120 "Ẻ": "E",
121 "Ẽ": "E",
122 "Ẹ": "E",
123 "Ể": "E",
124 "Ễ": "E",
125 "Ệ": "E",
126 "Ì": "I",
127 "Í": "I",
128 "Î": "I",
129 "Ï": "I",
130 "Ḯ": "I",
131 "Ȋ": "I",
132 "Ỉ": "I",
133 "Ị": "I",
134 "Ð": "D",
135 "Ñ": "N",
136 "Ò": "O",
137 "Ó": "O",
138 "Ô": "O",
139 "Õ": "O",
140 "Ö": "O",
141 "Ø": "O",
142 "Ố": "O",
143 "Ṍ": "O",
144 "Ṓ": "O",
145 "Ȏ": "O",
146 "Ỏ": "O",
147 "Ọ": "O",
148 "Ổ": "O",
149 "Ỗ": "O",
150 "Ộ": "O",
151 "Ờ": "O",
152 "Ở": "O",
153 "Ỡ": "O",
154 "Ớ": "O",
155 "Ợ": "O",
156 "Ù": "U",
157 "Ú": "U",
158 "Û": "U",
159 "Ü": "U",
160 "Ủ": "U",
161 "Ụ": "U",
162 "Ử": "U",
163 "Ữ": "U",
164 "Ự": "U",
165 "Ý": "Y",
166 "à": "a",
167 "á": "a",
168 "â": "a",
169 "ã": "a",
170 "ä": "a",
171 "å": "a",
172 "ấ": "a",
173 "ắ": "a",
174 "ẳ": "a",
175 "ẵ": "a",
176 "ặ": "a",
177 "æ": "ae",
178 "ầ": "a",
179 "ằ": "a",
180 "ȃ": "a",
181 "ả": "a",
182 "ạ": "a",
183 "ẩ": "a",
184 "ẫ": "a",
185 "ậ": "a",
186 "ç": "c",
187 "ḉ": "c",
188 "è": "e",
189 "é": "e",
190 "ê": "e",
191 "ë": "e",
192 "ế": "e",
193 "ḗ": "e",
194 "ề": "e",
195 "ḕ": "e",
196 "ḝ": "e",
197 "ȇ": "e",
198 "ẻ": "e",
199 "ẽ": "e",
200 "ẹ": "e",
201 "ể": "e",
202 "ễ": "e",
203 "ệ": "e",
204 "ì": "i",
205 "í": "i",
206 "î": "i",
207 "ï": "i",
208 "ḯ": "i",
209 "ȋ": "i",
210 "ỉ": "i",
211 "ị": "i",
212 "ð": "d",
213 "ñ": "n",
214 "ò": "o",
215 "ó": "o",
216 "ô": "o",
217 "õ": "o",
218 "ö": "o",
219 "ø": "o",
220 "ố": "o",
221 "ṍ": "o",
222 "ṓ": "o",
223 "ȏ": "o",
224 "ỏ": "o",
225 "ọ": "o",
226 "ổ": "o",
227 "ỗ": "o",
228 "ộ": "o",
229 "ờ": "o",
230 "ở": "o",
231 "ỡ": "o",
232 "ớ": "o",
233 "ợ": "o",
234 "ù": "u",
235 "ú": "u",
236 "û": "u",
237 "ü": "u",
238 "ủ": "u",
239 "ụ": "u",
240 "ử": "u",
241 "ữ": "u",
242 "ự": "u",
243 "ý": "y",
244 "ÿ": "y",
245 "Ā": "A",
246 "ā": "a",
247 "Ă": "A",
248 "ă": "a",
249 "Ą": "A",
250 "ą": "a",
251 "Ć": "C",
252 "ć": "c",
253 "Ĉ": "C",
254 "ĉ": "c",
255 "Ċ": "C",
256 "ċ": "c",
257 "Č": "C",
258 "č": "c",
259 "C̆": "C",
260 "c̆": "c",
261 "Ď": "D",
262 "ď": "d",
263 "Đ": "D",
264 "đ": "d",
265 "Ē": "E",
266 "ē": "e",
267 "Ĕ": "E",
268 "ĕ": "e",
269 "Ė": "E",
270 "ė": "e",
271 "Ę": "E",
272 "ę": "e",
273 "Ě": "E",
274 "ě": "e",
275 "Ĝ": "G",
276 "Ǵ": "G",
277 "ĝ": "g",
278 "ǵ": "g",
279 "Ğ": "G",
280 "ğ": "g",
281 "Ġ": "G",
282 "ġ": "g",
283 "Ģ": "G",
284 "ģ": "g",
285 "Ĥ": "H",
286 "ĥ": "h",
287 "Ħ": "H",
288 "ħ": "h",
289 "Ḫ": "H",
290 "ḫ": "h",
291 "Ĩ": "I",
292 "ĩ": "i",
293 "Ī": "I",
294 "ī": "i",
295 "Ĭ": "I",
296 "ĭ": "i",
297 "Į": "I",
298 "į": "i",
299 "İ": "I",
300 "ı": "i",
301 "IJ": "IJ",
302 "ij": "ij",
303 "Ĵ": "J",
304 "ĵ": "j",
305 "Ķ": "K",
306 "ķ": "k",
307 "Ḱ": "K",
308 "ḱ": "k",
309 "K̆": "K",
310 "k̆": "k",
311 "Ĺ": "L",
312 "ĺ": "l",
313 "Ļ": "L",
314 "ļ": "l",
315 "Ľ": "L",
316 "ľ": "l",
317 "Ŀ": "L",
318 "ŀ": "l",
319 "Ł": "l",
320 "ł": "l",
321 "Ḿ": "M",
322 "ḿ": "m",
323 "M̆": "M",
324 "m̆": "m",
325 "Ń": "N",
326 "ń": "n",
327 "Ņ": "N",
328 "ņ": "n",
329 "Ň": "N",
330 "ň": "n",
331 "ʼn": "n",
332 "N̆": "N",
333 "n̆": "n",
334 "Ō": "O",
335 "ō": "o",
336 "Ŏ": "O",
337 "ŏ": "o",
338 "Ő": "O",
339 "ő": "o",
340 "Œ": "OE",
341 "œ": "oe",
342 "P̆": "P",
343 "p̆": "p",
344 "Ŕ": "R",
345 "ŕ": "r",
346 "Ŗ": "R",
347 "ŗ": "r",
348 "Ř": "R",
349 "ř": "r",
350 "R̆": "R",
351 "r̆": "r",
352 "Ȓ": "R",
353 "ȓ": "r",
354 "Ś": "S",
355 "ś": "s",
356 "Ŝ": "S",
357 "ŝ": "s",
358 "Ş": "S",
359 "Ș": "S",
360 "ș": "s",
361 "ş": "s",
362 "Š": "S",
363 "š": "s",
364 "Ţ": "T",
365 "ţ": "t",
366 "ț": "t",
367 "Ț": "T",
368 "Ť": "T",
369 "ť": "t",
370 "Ŧ": "T",
371 "ŧ": "t",
372 "T̆": "T",
373 "t̆": "t",
374 "Ũ": "U",
375 "ũ": "u",
376 "Ū": "U",
377 "ū": "u",
378 "Ŭ": "U",
379 "ŭ": "u",
380 "Ů": "U",
381 "ů": "u",
382 "Ű": "U",
383 "ű": "u",
384 "Ų": "U",
385 "ų": "u",
386 "Ȗ": "U",
387 "ȗ": "u",
388 "V̆": "V",
389 "v̆": "v",
390 "Ŵ": "W",
391 "ŵ": "w",
392 "Ẃ": "W",
393 "ẃ": "w",
394 "X̆": "X",
395 "x̆": "x",
396 "Ŷ": "Y",
397 "ŷ": "y",
398 "Ÿ": "Y",
399 "Y̆": "Y",
400 "y̆": "y",
401 "Ź": "Z",
402 "ź": "z",
403 "Ż": "Z",
404 "ż": "z",
405 "Ž": "Z",
406 "ž": "z",
407 "ſ": "s",
408 "ƒ": "f",
409 "Ơ": "O",
410 "ơ": "o",
411 "Ư": "U",
412 "ư": "u",
413 "Ǎ": "A",
414 "ǎ": "a",
415 "Ǐ": "I",
416 "ǐ": "i",
417 "Ǒ": "O",
418 "ǒ": "o",
419 "Ǔ": "U",
420 "ǔ": "u",
421 "Ǖ": "U",
422 "ǖ": "u",
423 "Ǘ": "U",
424 "ǘ": "u",
425 "Ǚ": "U",
426 "ǚ": "u",
427 "Ǜ": "U",
428 "ǜ": "u",
429 "Ứ": "U",
430 "ứ": "u",
431 "Ṹ": "U",
432 "ṹ": "u",
433 "Ǻ": "A",
434 "ǻ": "a",
435 "Ǽ": "AE",
436 "ǽ": "ae",
437 "Ǿ": "O",
438 "ǿ": "o",
439 "Þ": "TH",
440 "þ": "th",
441 "Ṕ": "P",
442 "ṕ": "p",
443 "Ṥ": "S",
444 "ṥ": "s",
445 "X́": "X",
446 "x́": "x",
447 "Ѓ": "Г",
448 "ѓ": "г",
449 "Ќ": "К",
450 "ќ": "к",
451 "A̋": "A",
452 "a̋": "a",
453 "E̋": "E",
454 "e̋": "e",
455 "I̋": "I",
456 "i̋": "i",
457 "Ǹ": "N",
458 "ǹ": "n",
459 "Ồ": "O",
460 "ồ": "o",
461 "Ṑ": "O",
462 "ṑ": "o",
463 "Ừ": "U",
464 "ừ": "u",
465 "Ẁ": "W",
466 "ẁ": "w",
467 "Ỳ": "Y",
468 "ỳ": "y",
469 "Ȁ": "A",
470 "ȁ": "a",
471 "Ȅ": "E",
472 "ȅ": "e",
473 "Ȉ": "I",
474 "ȉ": "i",
475 "Ȍ": "O",
476 "ȍ": "o",
477 "Ȑ": "R",
478 "ȑ": "r",
479 "Ȕ": "U",
480 "ȕ": "u",
481 "B̌": "B",
482 "b̌": "b",
483 "Č̣": "C",
484 "č̣": "c",
485 "Ê̌": "E",
486 "ê̌": "e",
487 "F̌": "F",
488 "f̌": "f",
489 "Ǧ": "G",
490 "ǧ": "g",
491 "Ȟ": "H",
492 "ȟ": "h",
493 "J̌": "J",
494 "ǰ": "j",
495 "Ǩ": "K",
496 "ǩ": "k",
497 "M̌": "M",
498 "m̌": "m",
499 "P̌": "P",
500 "p̌": "p",
501 "Q̌": "Q",
502 "q̌": "q",
503 "Ř̩": "R",
504 "ř̩": "r",
505 "Ṧ": "S",
506 "ṧ": "s",
507 "V̌": "V",
508 "v̌": "v",
509 "W̌": "W",
510 "w̌": "w",
511 "X̌": "X",
512 "x̌": "x",
513 "Y̌": "Y",
514 "y̌": "y",
515 "A̧": "A",
516 "a̧": "a",
517 "B̧": "B",
518 "b̧": "b",
519 "Ḑ": "D",
520 "ḑ": "d",
521 "Ȩ": "E",
522 "ȩ": "e",
523 "Ɛ̧": "E",
524 "ɛ̧": "e",
525 "Ḩ": "H",
526 "ḩ": "h",
527 "I̧": "I",
528 "i̧": "i",
529 "Ɨ̧": "I",
530 "ɨ̧": "i",
531 "M̧": "M",
532 "m̧": "m",
533 "O̧": "O",
534 "o̧": "o",
535 "Q̧": "Q",
536 "q̧": "q",
537 "U̧": "U",
538 "u̧": "u",
539 "X̧": "X",
540 "x̧": "x",
541 "Z̧": "Z",
542 "z̧": "z",
543 "й":"и",
544 "Й":"И",
545 "ё":"е",
546 "Ё":"Е",
547 };
548
549 var chars = Object.keys(characterMap).join('|');
550 var allAccents = new RegExp(chars, 'g');
551 var firstAccent = new RegExp(chars, '');
552
553 function matcher(match) {
554 return characterMap[match];
555 }
556
557 var removeAccents = function(string) {
558 return string.replace(allAccents, matcher);
559 };
560
561 var hasAccents = function(string) {
562 return !!string.match(firstAccent);
563 };
564
565 module.exports = removeAccents;
566 module.exports.has = hasAccents;
567 module.exports.remove = removeAccents;
568
569
570 /***/ }),
571
572 /***/ 7308:
573 /***/ (function(module, exports, __webpack_require__) {
574
575 var __WEBPACK_AMD_DEFINE_RESULT__;;/*! showdown v 1.9.1 - 02-11-2019 */
576 (function(){
577 /**
578 * Created by Tivie on 13-07-2015.
579 */
580
581 function getDefaultOpts (simple) {
582 'use strict';
583
584 var defaultOptions = {
585 omitExtraWLInCodeBlocks: {
586 defaultValue: false,
587 describe: 'Omit the default extra whiteline added to code blocks',
588 type: 'boolean'
589 },
590 noHeaderId: {
591 defaultValue: false,
592 describe: 'Turn on/off generated header id',
593 type: 'boolean'
594 },
595 prefixHeaderId: {
596 defaultValue: false,
597 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',
598 type: 'string'
599 },
600 rawPrefixHeaderId: {
601 defaultValue: false,
602 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)',
603 type: 'boolean'
604 },
605 ghCompatibleHeaderId: {
606 defaultValue: false,
607 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
608 type: 'boolean'
609 },
610 rawHeaderId: {
611 defaultValue: false,
612 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
613 type: 'boolean'
614 },
615 headerLevelStart: {
616 defaultValue: false,
617 describe: 'The header blocks level start',
618 type: 'integer'
619 },
620 parseImgDimensions: {
621 defaultValue: false,
622 describe: 'Turn on/off image dimension parsing',
623 type: 'boolean'
624 },
625 simplifiedAutoLink: {
626 defaultValue: false,
627 describe: 'Turn on/off GFM autolink style',
628 type: 'boolean'
629 },
630 excludeTrailingPunctuationFromURLs: {
631 defaultValue: false,
632 describe: 'Excludes trailing punctuation from links generated with autoLinking',
633 type: 'boolean'
634 },
635 literalMidWordUnderscores: {
636 defaultValue: false,
637 describe: 'Parse midword underscores as literal underscores',
638 type: 'boolean'
639 },
640 literalMidWordAsterisks: {
641 defaultValue: false,
642 describe: 'Parse midword asterisks as literal asterisks',
643 type: 'boolean'
644 },
645 strikethrough: {
646 defaultValue: false,
647 describe: 'Turn on/off strikethrough support',
648 type: 'boolean'
649 },
650 tables: {
651 defaultValue: false,
652 describe: 'Turn on/off tables support',
653 type: 'boolean'
654 },
655 tablesHeaderId: {
656 defaultValue: false,
657 describe: 'Add an id to table headers',
658 type: 'boolean'
659 },
660 ghCodeBlocks: {
661 defaultValue: true,
662 describe: 'Turn on/off GFM fenced code blocks support',
663 type: 'boolean'
664 },
665 tasklists: {
666 defaultValue: false,
667 describe: 'Turn on/off GFM tasklist support',
668 type: 'boolean'
669 },
670 smoothLivePreview: {
671 defaultValue: false,
672 describe: 'Prevents weird effects in live previews due to incomplete input',
673 type: 'boolean'
674 },
675 smartIndentationFix: {
676 defaultValue: false,
677 description: 'Tries to smartly fix indentation in es6 strings',
678 type: 'boolean'
679 },
680 disableForced4SpacesIndentedSublists: {
681 defaultValue: false,
682 description: 'Disables the requirement of indenting nested sublists by 4 spaces',
683 type: 'boolean'
684 },
685 simpleLineBreaks: {
686 defaultValue: false,
687 description: 'Parses simple line breaks as <br> (GFM Style)',
688 type: 'boolean'
689 },
690 requireSpaceBeforeHeadingText: {
691 defaultValue: false,
692 description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
693 type: 'boolean'
694 },
695 ghMentions: {
696 defaultValue: false,
697 description: 'Enables github @mentions',
698 type: 'boolean'
699 },
700 ghMentionsLink: {
701 defaultValue: 'https://github.com/{u}',
702 description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
703 type: 'string'
704 },
705 encodeEmails: {
706 defaultValue: true,
707 description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
708 type: 'boolean'
709 },
710 openLinksInNewWindow: {
711 defaultValue: false,
712 description: 'Open all links in new windows',
713 type: 'boolean'
714 },
715 backslashEscapesHTMLTags: {
716 defaultValue: false,
717 description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
718 type: 'boolean'
719 },
720 emoji: {
721 defaultValue: false,
722 description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
723 type: 'boolean'
724 },
725 underline: {
726 defaultValue: false,
727 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>`',
728 type: 'boolean'
729 },
730 completeHTMLDocument: {
731 defaultValue: false,
732 description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
733 type: 'boolean'
734 },
735 metadata: {
736 defaultValue: false,
737 description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
738 type: 'boolean'
739 },
740 splitAdjacentBlockquotes: {
741 defaultValue: false,
742 description: 'Split adjacent blockquote blocks',
743 type: 'boolean'
744 }
745 };
746 if (simple === false) {
747 return JSON.parse(JSON.stringify(defaultOptions));
748 }
749 var ret = {};
750 for (var opt in defaultOptions) {
751 if (defaultOptions.hasOwnProperty(opt)) {
752 ret[opt] = defaultOptions[opt].defaultValue;
753 }
754 }
755 return ret;
756 }
757
758 function allOptionsOn () {
759 'use strict';
760 var options = getDefaultOpts(true),
761 ret = {};
762 for (var opt in options) {
763 if (options.hasOwnProperty(opt)) {
764 ret[opt] = true;
765 }
766 }
767 return ret;
768 }
769
770 /**
771 * Created by Tivie on 06-01-2015.
772 */
773
774 // Private properties
775 var showdown = {},
776 parsers = {},
777 extensions = {},
778 globalOptions = getDefaultOpts(true),
779 setFlavor = 'vanilla',
780 flavor = {
781 github: {
782 omitExtraWLInCodeBlocks: true,
783 simplifiedAutoLink: true,
784 excludeTrailingPunctuationFromURLs: true,
785 literalMidWordUnderscores: true,
786 strikethrough: true,
787 tables: true,
788 tablesHeaderId: true,
789 ghCodeBlocks: true,
790 tasklists: true,
791 disableForced4SpacesIndentedSublists: true,
792 simpleLineBreaks: true,
793 requireSpaceBeforeHeadingText: true,
794 ghCompatibleHeaderId: true,
795 ghMentions: true,
796 backslashEscapesHTMLTags: true,
797 emoji: true,
798 splitAdjacentBlockquotes: true
799 },
800 original: {
801 noHeaderId: true,
802 ghCodeBlocks: false
803 },
804 ghost: {
805 omitExtraWLInCodeBlocks: true,
806 parseImgDimensions: true,
807 simplifiedAutoLink: true,
808 excludeTrailingPunctuationFromURLs: true,
809 literalMidWordUnderscores: true,
810 strikethrough: true,
811 tables: true,
812 tablesHeaderId: true,
813 ghCodeBlocks: true,
814 tasklists: true,
815 smoothLivePreview: true,
816 simpleLineBreaks: true,
817 requireSpaceBeforeHeadingText: true,
818 ghMentions: false,
819 encodeEmails: true
820 },
821 vanilla: getDefaultOpts(true),
822 allOn: allOptionsOn()
823 };
824
825 /**
826 * helper namespace
827 * @type {{}}
828 */
829 showdown.helper = {};
830
831 /**
832 * TODO LEGACY SUPPORT CODE
833 * @type {{}}
834 */
835 showdown.extensions = {};
836
837 /**
838 * Set a global option
839 * @static
840 * @param {string} key
841 * @param {*} value
842 * @returns {showdown}
843 */
844 showdown.setOption = function (key, value) {
845 'use strict';
846 globalOptions[key] = value;
847 return this;
848 };
849
850 /**
851 * Get a global option
852 * @static
853 * @param {string} key
854 * @returns {*}
855 */
856 showdown.getOption = function (key) {
857 'use strict';
858 return globalOptions[key];
859 };
860
861 /**
862 * Get the global options
863 * @static
864 * @returns {{}}
865 */
866 showdown.getOptions = function () {
867 'use strict';
868 return globalOptions;
869 };
870
871 /**
872 * Reset global options to the default values
873 * @static
874 */
875 showdown.resetOptions = function () {
876 'use strict';
877 globalOptions = getDefaultOpts(true);
878 };
879
880 /**
881 * Set the flavor showdown should use as default
882 * @param {string} name
883 */
884 showdown.setFlavor = function (name) {
885 'use strict';
886 if (!flavor.hasOwnProperty(name)) {
887 throw Error(name + ' flavor was not found');
888 }
889 showdown.resetOptions();
890 var preset = flavor[name];
891 setFlavor = name;
892 for (var option in preset) {
893 if (preset.hasOwnProperty(option)) {
894 globalOptions[option] = preset[option];
895 }
896 }
897 };
898
899 /**
900 * Get the currently set flavor
901 * @returns {string}
902 */
903 showdown.getFlavor = function () {
904 'use strict';
905 return setFlavor;
906 };
907
908 /**
909 * Get the options of a specified flavor. Returns undefined if the flavor was not found
910 * @param {string} name Name of the flavor
911 * @returns {{}|undefined}
912 */
913 showdown.getFlavorOptions = function (name) {
914 'use strict';
915 if (flavor.hasOwnProperty(name)) {
916 return flavor[name];
917 }
918 };
919
920 /**
921 * Get the default options
922 * @static
923 * @param {boolean} [simple=true]
924 * @returns {{}}
925 */
926 showdown.getDefaultOptions = function (simple) {
927 'use strict';
928 return getDefaultOpts(simple);
929 };
930
931 /**
932 * Get or set a subParser
933 *
934 * subParser(name) - Get a registered subParser
935 * subParser(name, func) - Register a subParser
936 * @static
937 * @param {string} name
938 * @param {function} [func]
939 * @returns {*}
940 */
941 showdown.subParser = function (name, func) {
942 'use strict';
943 if (showdown.helper.isString(name)) {
944 if (typeof func !== 'undefined') {
945 parsers[name] = func;
946 } else {
947 if (parsers.hasOwnProperty(name)) {
948 return parsers[name];
949 } else {
950 throw Error('SubParser named ' + name + ' not registered!');
951 }
952 }
953 }
954 };
955
956 /**
957 * Gets or registers an extension
958 * @static
959 * @param {string} name
960 * @param {object|function=} ext
961 * @returns {*}
962 */
963 showdown.extension = function (name, ext) {
964 'use strict';
965
966 if (!showdown.helper.isString(name)) {
967 throw Error('Extension \'name\' must be a string');
968 }
969
970 name = showdown.helper.stdExtName(name);
971
972 // Getter
973 if (showdown.helper.isUndefined(ext)) {
974 if (!extensions.hasOwnProperty(name)) {
975 throw Error('Extension named ' + name + ' is not registered!');
976 }
977 return extensions[name];
978
979 // Setter
980 } else {
981 // Expand extension if it's wrapped in a function
982 if (typeof ext === 'function') {
983 ext = ext();
984 }
985
986 // Ensure extension is an array
987 if (!showdown.helper.isArray(ext)) {
988 ext = [ext];
989 }
990
991 var validExtension = validate(ext, name);
992
993 if (validExtension.valid) {
994 extensions[name] = ext;
995 } else {
996 throw Error(validExtension.error);
997 }
998 }
999 };
1000
1001 /**
1002 * Gets all extensions registered
1003 * @returns {{}}
1004 */
1005 showdown.getAllExtensions = function () {
1006 'use strict';
1007 return extensions;
1008 };
1009
1010 /**
1011 * Remove an extension
1012 * @param {string} name
1013 */
1014 showdown.removeExtension = function (name) {
1015 'use strict';
1016 delete extensions[name];
1017 };
1018
1019 /**
1020 * Removes all extensions
1021 */
1022 showdown.resetExtensions = function () {
1023 'use strict';
1024 extensions = {};
1025 };
1026
1027 /**
1028 * Validate extension
1029 * @param {array} extension
1030 * @param {string} name
1031 * @returns {{valid: boolean, error: string}}
1032 */
1033 function validate (extension, name) {
1034 'use strict';
1035
1036 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
1037 ret = {
1038 valid: true,
1039 error: ''
1040 };
1041
1042 if (!showdown.helper.isArray(extension)) {
1043 extension = [extension];
1044 }
1045
1046 for (var i = 0; i < extension.length; ++i) {
1047 var baseMsg = errMsg + ' sub-extension ' + i + ': ',
1048 ext = extension[i];
1049 if (typeof ext !== 'object') {
1050 ret.valid = false;
1051 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
1052 return ret;
1053 }
1054
1055 if (!showdown.helper.isString(ext.type)) {
1056 ret.valid = false;
1057 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
1058 return ret;
1059 }
1060
1061 var type = ext.type = ext.type.toLowerCase();
1062
1063 // normalize extension type
1064 if (type === 'language') {
1065 type = ext.type = 'lang';
1066 }
1067
1068 if (type === 'html') {
1069 type = ext.type = 'output';
1070 }
1071
1072 if (type !== 'lang' && type !== 'output' && type !== 'listener') {
1073 ret.valid = false;
1074 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
1075 return ret;
1076 }
1077
1078 if (type === 'listener') {
1079 if (showdown.helper.isUndefined(ext.listeners)) {
1080 ret.valid = false;
1081 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
1082 return ret;
1083 }
1084 } else {
1085 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
1086 ret.valid = false;
1087 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
1088 return ret;
1089 }
1090 }
1091
1092 if (ext.listeners) {
1093 if (typeof ext.listeners !== 'object') {
1094 ret.valid = false;
1095 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
1096 return ret;
1097 }
1098 for (var ln in ext.listeners) {
1099 if (ext.listeners.hasOwnProperty(ln)) {
1100 if (typeof ext.listeners[ln] !== 'function') {
1101 ret.valid = false;
1102 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
1103 ' must be a function but ' + typeof ext.listeners[ln] + ' given';
1104 return ret;
1105 }
1106 }
1107 }
1108 }
1109
1110 if (ext.filter) {
1111 if (typeof ext.filter !== 'function') {
1112 ret.valid = false;
1113 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
1114 return ret;
1115 }
1116 } else if (ext.regex) {
1117 if (showdown.helper.isString(ext.regex)) {
1118 ext.regex = new RegExp(ext.regex, 'g');
1119 }
1120 if (!(ext.regex instanceof RegExp)) {
1121 ret.valid = false;
1122 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
1123 return ret;
1124 }
1125 if (showdown.helper.isUndefined(ext.replace)) {
1126 ret.valid = false;
1127 ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
1128 return ret;
1129 }
1130 }
1131 }
1132 return ret;
1133 }
1134
1135 /**
1136 * Validate extension
1137 * @param {object} ext
1138 * @returns {boolean}
1139 */
1140 showdown.validateExtension = function (ext) {
1141 'use strict';
1142
1143 var validateExtension = validate(ext, null);
1144 if (!validateExtension.valid) {
1145 console.warn(validateExtension.error);
1146 return false;
1147 }
1148 return true;
1149 };
1150
1151 /**
1152 * showdownjs helper functions
1153 */
1154
1155 if (!showdown.hasOwnProperty('helper')) {
1156 showdown.helper = {};
1157 }
1158
1159 /**
1160 * Check if var is string
1161 * @static
1162 * @param {string} a
1163 * @returns {boolean}
1164 */
1165 showdown.helper.isString = function (a) {
1166 'use strict';
1167 return (typeof a === 'string' || a instanceof String);
1168 };
1169
1170 /**
1171 * Check if var is a function
1172 * @static
1173 * @param {*} a
1174 * @returns {boolean}
1175 */
1176 showdown.helper.isFunction = function (a) {
1177 'use strict';
1178 var getType = {};
1179 return a && getType.toString.call(a) === '[object Function]';
1180 };
1181
1182 /**
1183 * isArray helper function
1184 * @static
1185 * @param {*} a
1186 * @returns {boolean}
1187 */
1188 showdown.helper.isArray = function (a) {
1189 'use strict';
1190 return Array.isArray(a);
1191 };
1192
1193 /**
1194 * Check if value is undefined
1195 * @static
1196 * @param {*} value The value to check.
1197 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
1198 */
1199 showdown.helper.isUndefined = function (value) {
1200 'use strict';
1201 return typeof value === 'undefined';
1202 };
1203
1204 /**
1205 * ForEach helper function
1206 * Iterates over Arrays and Objects (own properties only)
1207 * @static
1208 * @param {*} obj
1209 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
1210 */
1211 showdown.helper.forEach = function (obj, callback) {
1212 'use strict';
1213 // check if obj is defined
1214 if (showdown.helper.isUndefined(obj)) {
1215 throw new Error('obj param is required');
1216 }
1217
1218 if (showdown.helper.isUndefined(callback)) {
1219 throw new Error('callback param is required');
1220 }
1221
1222 if (!showdown.helper.isFunction(callback)) {
1223 throw new Error('callback param must be a function/closure');
1224 }
1225
1226 if (typeof obj.forEach === 'function') {
1227 obj.forEach(callback);
1228 } else if (showdown.helper.isArray(obj)) {
1229 for (var i = 0; i < obj.length; i++) {
1230 callback(obj[i], i, obj);
1231 }
1232 } else if (typeof (obj) === 'object') {
1233 for (var prop in obj) {
1234 if (obj.hasOwnProperty(prop)) {
1235 callback(obj[prop], prop, obj);
1236 }
1237 }
1238 } else {
1239 throw new Error('obj does not seem to be an array or an iterable object');
1240 }
1241 };
1242
1243 /**
1244 * Standardidize extension name
1245 * @static
1246 * @param {string} s extension name
1247 * @returns {string}
1248 */
1249 showdown.helper.stdExtName = function (s) {
1250 'use strict';
1251 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
1252 };
1253
1254 function escapeCharactersCallback (wholeMatch, m1) {
1255 'use strict';
1256 var charCodeToEscape = m1.charCodeAt(0);
1257 return '¨E' + charCodeToEscape + 'E';
1258 }
1259
1260 /**
1261 * Callback used to escape characters when passing through String.replace
1262 * @static
1263 * @param {string} wholeMatch
1264 * @param {string} m1
1265 * @returns {string}
1266 */
1267 showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
1268
1269 /**
1270 * Escape characters in a string
1271 * @static
1272 * @param {string} text
1273 * @param {string} charsToEscape
1274 * @param {boolean} afterBackslash
1275 * @returns {XML|string|void|*}
1276 */
1277 showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
1278 'use strict';
1279 // First we have to escape the escape characters so that
1280 // we can build a character class out of them
1281 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
1282
1283 if (afterBackslash) {
1284 regexString = '\\\\' + regexString;
1285 }
1286
1287 var regex = new RegExp(regexString, 'g');
1288 text = text.replace(regex, escapeCharactersCallback);
1289
1290 return text;
1291 };
1292
1293 /**
1294 * Unescape HTML entities
1295 * @param txt
1296 * @returns {string}
1297 */
1298 showdown.helper.unescapeHTMLEntities = function (txt) {
1299 'use strict';
1300
1301 return txt
1302 .replace(/&quot;/g, '"')
1303 .replace(/&lt;/g, '<')
1304 .replace(/&gt;/g, '>')
1305 .replace(/&amp;/g, '&');
1306 };
1307
1308 var rgxFindMatchPos = function (str, left, right, flags) {
1309 'use strict';
1310 var f = flags || '',
1311 g = f.indexOf('g') > -1,
1312 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
1313 l = new RegExp(left, f.replace(/g/g, '')),
1314 pos = [],
1315 t, s, m, start, end;
1316
1317 do {
1318 t = 0;
1319 while ((m = x.exec(str))) {
1320 if (l.test(m[0])) {
1321 if (!(t++)) {
1322 s = x.lastIndex;
1323 start = s - m[0].length;
1324 }
1325 } else if (t) {
1326 if (!--t) {
1327 end = m.index + m[0].length;
1328 var obj = {
1329 left: {start: start, end: s},
1330 match: {start: s, end: m.index},
1331 right: {start: m.index, end: end},
1332 wholeMatch: {start: start, end: end}
1333 };
1334 pos.push(obj);
1335 if (!g) {
1336 return pos;
1337 }
1338 }
1339 }
1340 }
1341 } while (t && (x.lastIndex = s));
1342
1343 return pos;
1344 };
1345
1346 /**
1347 * matchRecursiveRegExp
1348 *
1349 * (c) 2007 Steven Levithan <stevenlevithan.com>
1350 * MIT License
1351 *
1352 * Accepts a string to search, a left and right format delimiter
1353 * as regex patterns, and optional regex flags. Returns an array
1354 * of matches, allowing nested instances of left/right delimiters.
1355 * Use the "g" flag to return all matches, otherwise only the
1356 * first is returned. Be careful to ensure that the left and
1357 * right format delimiters produce mutually exclusive matches.
1358 * Backreferences are not supported within the right delimiter
1359 * due to how it is internally combined with the left delimiter.
1360 * When matching strings whose format delimiters are unbalanced
1361 * to the left or right, the output is intentionally as a
1362 * conventional regex library with recursion support would
1363 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
1364 * "<" and ">" as the delimiters (both strings contain a single,
1365 * balanced instance of "<x>").
1366 *
1367 * examples:
1368 * matchRecursiveRegExp("test", "\\(", "\\)")
1369 * returns: []
1370 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
1371 * returns: ["t<<e>><s>", ""]
1372 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
1373 * returns: ["test"]
1374 */
1375 showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
1376 'use strict';
1377
1378 var matchPos = rgxFindMatchPos (str, left, right, flags),
1379 results = [];
1380
1381 for (var i = 0; i < matchPos.length; ++i) {
1382 results.push([
1383 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1384 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1385 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1386 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1387 ]);
1388 }
1389 return results;
1390 };
1391
1392 /**
1393 *
1394 * @param {string} str
1395 * @param {string|function} replacement
1396 * @param {string} left
1397 * @param {string} right
1398 * @param {string} flags
1399 * @returns {string}
1400 */
1401 showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
1402 'use strict';
1403
1404 if (!showdown.helper.isFunction(replacement)) {
1405 var repStr = replacement;
1406 replacement = function () {
1407 return repStr;
1408 };
1409 }
1410
1411 var matchPos = rgxFindMatchPos(str, left, right, flags),
1412 finalStr = str,
1413 lng = matchPos.length;
1414
1415 if (lng > 0) {
1416 var bits = [];
1417 if (matchPos[0].wholeMatch.start !== 0) {
1418 bits.push(str.slice(0, matchPos[0].wholeMatch.start));
1419 }
1420 for (var i = 0; i < lng; ++i) {
1421 bits.push(
1422 replacement(
1423 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1424 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1425 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1426 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1427 )
1428 );
1429 if (i < lng - 1) {
1430 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
1431 }
1432 }
1433 if (matchPos[lng - 1].wholeMatch.end < str.length) {
1434 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
1435 }
1436 finalStr = bits.join('');
1437 }
1438 return finalStr;
1439 };
1440
1441 /**
1442 * Returns the index within the passed String object of the first occurrence of the specified regex,
1443 * starting the search at fromIndex. Returns -1 if the value is not found.
1444 *
1445 * @param {string} str string to search
1446 * @param {RegExp} regex Regular expression to search
1447 * @param {int} [fromIndex = 0] Index to start the search
1448 * @returns {Number}
1449 * @throws InvalidArgumentError
1450 */
1451 showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
1452 'use strict';
1453 if (!showdown.helper.isString(str)) {
1454 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1455 }
1456 if (regex instanceof RegExp === false) {
1457 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
1458 }
1459 var indexOf = str.substring(fromIndex || 0).search(regex);
1460 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
1461 };
1462
1463 /**
1464 * Splits the passed string object at the defined index, and returns an array composed of the two substrings
1465 * @param {string} str string to split
1466 * @param {int} index index to split string at
1467 * @returns {[string,string]}
1468 * @throws InvalidArgumentError
1469 */
1470 showdown.helper.splitAtIndex = function (str, index) {
1471 'use strict';
1472 if (!showdown.helper.isString(str)) {
1473 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1474 }
1475 return [str.substring(0, index), str.substring(index)];
1476 };
1477
1478 /**
1479 * Obfuscate an e-mail address through the use of Character Entities,
1480 * transforming ASCII characters into their equivalent decimal or hex entities.
1481 *
1482 * Since it has a random component, subsequent calls to this function produce different results
1483 *
1484 * @param {string} mail
1485 * @returns {string}
1486 */
1487 showdown.helper.encodeEmailAddress = function (mail) {
1488 'use strict';
1489 var encode = [
1490 function (ch) {
1491 return '&#' + ch.charCodeAt(0) + ';';
1492 },
1493 function (ch) {
1494 return '&#x' + ch.charCodeAt(0).toString(16) + ';';
1495 },
1496 function (ch) {
1497 return ch;
1498 }
1499 ];
1500
1501 mail = mail.replace(/./g, function (ch) {
1502 if (ch === '@') {
1503 // this *must* be encoded. I insist.
1504 ch = encode[Math.floor(Math.random() * 2)](ch);
1505 } else {
1506 var r = Math.random();
1507 // roughly 10% raw, 45% hex, 45% dec
1508 ch = (
1509 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1510 );
1511 }
1512 return ch;
1513 });
1514
1515 return mail;
1516 };
1517
1518 /**
1519 *
1520 * @param str
1521 * @param targetLength
1522 * @param padString
1523 * @returns {string}
1524 */
1525 showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
1526 'use strict';
1527 /*jshint bitwise: false*/
1528 // eslint-disable-next-line space-infix-ops
1529 targetLength = targetLength>>0; //floor if number or convert non-number to 0;
1530 /*jshint bitwise: true*/
1531 padString = String(padString || ' ');
1532 if (str.length > targetLength) {
1533 return String(str);
1534 } else {
1535 targetLength = targetLength - str.length;
1536 if (targetLength > padString.length) {
1537 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
1538 }
1539 return String(str) + padString.slice(0,targetLength);
1540 }
1541 };
1542
1543 /**
1544 * POLYFILLS
1545 */
1546 // use this instead of builtin is undefined for IE8 compatibility
1547 if (typeof console === 'undefined') {
1548 console = {
1549 warn: function (msg) {
1550 'use strict';
1551 alert(msg);
1552 },
1553 log: function (msg) {
1554 'use strict';
1555 alert(msg);
1556 },
1557 error: function (msg) {
1558 'use strict';
1559 throw msg;
1560 }
1561 };
1562 }
1563
1564 /**
1565 * Common regexes.
1566 * We declare some common regexes to improve performance
1567 */
1568 showdown.helper.regexes = {
1569 asteriskDashAndColon: /([*_:~])/g
1570 };
1571
1572 /**
1573 * EMOJIS LIST
1574 */
1575 showdown.helper.emojis = {
1576 '+1':'\ud83d\udc4d',
1577 '-1':'\ud83d\udc4e',
1578 '100':'\ud83d\udcaf',
1579 '1234':'\ud83d\udd22',
1580 '1st_place_medal':'\ud83e\udd47',
1581 '2nd_place_medal':'\ud83e\udd48',
1582 '3rd_place_medal':'\ud83e\udd49',
1583 '8ball':'\ud83c\udfb1',
1584 'a':'\ud83c\udd70\ufe0f',
1585 'ab':'\ud83c\udd8e',
1586 'abc':'\ud83d\udd24',
1587 'abcd':'\ud83d\udd21',
1588 'accept':'\ud83c\ude51',
1589 'aerial_tramway':'\ud83d\udea1',
1590 'airplane':'\u2708\ufe0f',
1591 'alarm_clock':'\u23f0',
1592 'alembic':'\u2697\ufe0f',
1593 'alien':'\ud83d\udc7d',
1594 'ambulance':'\ud83d\ude91',
1595 'amphora':'\ud83c\udffa',
1596 'anchor':'\u2693\ufe0f',
1597 'angel':'\ud83d\udc7c',
1598 'anger':'\ud83d\udca2',
1599 'angry':'\ud83d\ude20',
1600 'anguished':'\ud83d\ude27',
1601 'ant':'\ud83d\udc1c',
1602 'apple':'\ud83c\udf4e',
1603 'aquarius':'\u2652\ufe0f',
1604 'aries':'\u2648\ufe0f',
1605 'arrow_backward':'\u25c0\ufe0f',
1606 'arrow_double_down':'\u23ec',
1607 'arrow_double_up':'\u23eb',
1608 'arrow_down':'\u2b07\ufe0f',
1609 'arrow_down_small':'\ud83d\udd3d',
1610 'arrow_forward':'\u25b6\ufe0f',
1611 'arrow_heading_down':'\u2935\ufe0f',
1612 'arrow_heading_up':'\u2934\ufe0f',
1613 'arrow_left':'\u2b05\ufe0f',
1614 'arrow_lower_left':'\u2199\ufe0f',
1615 'arrow_lower_right':'\u2198\ufe0f',
1616 'arrow_right':'\u27a1\ufe0f',
1617 'arrow_right_hook':'\u21aa\ufe0f',
1618 'arrow_up':'\u2b06\ufe0f',
1619 'arrow_up_down':'\u2195\ufe0f',
1620 'arrow_up_small':'\ud83d\udd3c',
1621 'arrow_upper_left':'\u2196\ufe0f',
1622 'arrow_upper_right':'\u2197\ufe0f',
1623 'arrows_clockwise':'\ud83d\udd03',
1624 'arrows_counterclockwise':'\ud83d\udd04',
1625 'art':'\ud83c\udfa8',
1626 'articulated_lorry':'\ud83d\ude9b',
1627 'artificial_satellite':'\ud83d\udef0',
1628 'astonished':'\ud83d\ude32',
1629 'athletic_shoe':'\ud83d\udc5f',
1630 'atm':'\ud83c\udfe7',
1631 'atom_symbol':'\u269b\ufe0f',
1632 'avocado':'\ud83e\udd51',
1633 'b':'\ud83c\udd71\ufe0f',
1634 'baby':'\ud83d\udc76',
1635 'baby_bottle':'\ud83c\udf7c',
1636 'baby_chick':'\ud83d\udc24',
1637 'baby_symbol':'\ud83d\udebc',
1638 'back':'\ud83d\udd19',
1639 'bacon':'\ud83e\udd53',
1640 'badminton':'\ud83c\udff8',
1641 'baggage_claim':'\ud83d\udec4',
1642 'baguette_bread':'\ud83e\udd56',
1643 'balance_scale':'\u2696\ufe0f',
1644 'balloon':'\ud83c\udf88',
1645 'ballot_box':'\ud83d\uddf3',
1646 'ballot_box_with_check':'\u2611\ufe0f',
1647 'bamboo':'\ud83c\udf8d',
1648 'banana':'\ud83c\udf4c',
1649 'bangbang':'\u203c\ufe0f',
1650 'bank':'\ud83c\udfe6',
1651 'bar_chart':'\ud83d\udcca',
1652 'barber':'\ud83d\udc88',
1653 'baseball':'\u26be\ufe0f',
1654 'basketball':'\ud83c\udfc0',
1655 'basketball_man':'\u26f9\ufe0f',
1656 'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1657 'bat':'\ud83e\udd87',
1658 'bath':'\ud83d\udec0',
1659 'bathtub':'\ud83d\udec1',
1660 'battery':'\ud83d\udd0b',
1661 'beach_umbrella':'\ud83c\udfd6',
1662 'bear':'\ud83d\udc3b',
1663 'bed':'\ud83d\udecf',
1664 'bee':'\ud83d\udc1d',
1665 'beer':'\ud83c\udf7a',
1666 'beers':'\ud83c\udf7b',
1667 'beetle':'\ud83d\udc1e',
1668 'beginner':'\ud83d\udd30',
1669 'bell':'\ud83d\udd14',
1670 'bellhop_bell':'\ud83d\udece',
1671 'bento':'\ud83c\udf71',
1672 'biking_man':'\ud83d\udeb4',
1673 'bike':'\ud83d\udeb2',
1674 'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1675 'bikini':'\ud83d\udc59',
1676 'biohazard':'\u2623\ufe0f',
1677 'bird':'\ud83d\udc26',
1678 'birthday':'\ud83c\udf82',
1679 'black_circle':'\u26ab\ufe0f',
1680 'black_flag':'\ud83c\udff4',
1681 'black_heart':'\ud83d\udda4',
1682 'black_joker':'\ud83c\udccf',
1683 'black_large_square':'\u2b1b\ufe0f',
1684 'black_medium_small_square':'\u25fe\ufe0f',
1685 'black_medium_square':'\u25fc\ufe0f',
1686 'black_nib':'\u2712\ufe0f',
1687 'black_small_square':'\u25aa\ufe0f',
1688 'black_square_button':'\ud83d\udd32',
1689 'blonde_man':'\ud83d\udc71',
1690 'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1691 'blossom':'\ud83c\udf3c',
1692 'blowfish':'\ud83d\udc21',
1693 'blue_book':'\ud83d\udcd8',
1694 'blue_car':'\ud83d\ude99',
1695 'blue_heart':'\ud83d\udc99',
1696 'blush':'\ud83d\ude0a',
1697 'boar':'\ud83d\udc17',
1698 'boat':'\u26f5\ufe0f',
1699 'bomb':'\ud83d\udca3',
1700 'book':'\ud83d\udcd6',
1701 'bookmark':'\ud83d\udd16',
1702 'bookmark_tabs':'\ud83d\udcd1',
1703 'books':'\ud83d\udcda',
1704 'boom':'\ud83d\udca5',
1705 'boot':'\ud83d\udc62',
1706 'bouquet':'\ud83d\udc90',
1707 'bowing_man':'\ud83d\ude47',
1708 'bow_and_arrow':'\ud83c\udff9',
1709 'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1710 'bowling':'\ud83c\udfb3',
1711 'boxing_glove':'\ud83e\udd4a',
1712 'boy':'\ud83d\udc66',
1713 'bread':'\ud83c\udf5e',
1714 'bride_with_veil':'\ud83d\udc70',
1715 'bridge_at_night':'\ud83c\udf09',
1716 'briefcase':'\ud83d\udcbc',
1717 'broken_heart':'\ud83d\udc94',
1718 'bug':'\ud83d\udc1b',
1719 'building_construction':'\ud83c\udfd7',
1720 'bulb':'\ud83d\udca1',
1721 'bullettrain_front':'\ud83d\ude85',
1722 'bullettrain_side':'\ud83d\ude84',
1723 'burrito':'\ud83c\udf2f',
1724 'bus':'\ud83d\ude8c',
1725 'business_suit_levitating':'\ud83d\udd74',
1726 'busstop':'\ud83d\ude8f',
1727 'bust_in_silhouette':'\ud83d\udc64',
1728 'busts_in_silhouette':'\ud83d\udc65',
1729 'butterfly':'\ud83e\udd8b',
1730 'cactus':'\ud83c\udf35',
1731 'cake':'\ud83c\udf70',
1732 'calendar':'\ud83d\udcc6',
1733 'call_me_hand':'\ud83e\udd19',
1734 'calling':'\ud83d\udcf2',
1735 'camel':'\ud83d\udc2b',
1736 'camera':'\ud83d\udcf7',
1737 'camera_flash':'\ud83d\udcf8',
1738 'camping':'\ud83c\udfd5',
1739 'cancer':'\u264b\ufe0f',
1740 'candle':'\ud83d\udd6f',
1741 'candy':'\ud83c\udf6c',
1742 'canoe':'\ud83d\udef6',
1743 'capital_abcd':'\ud83d\udd20',
1744 'capricorn':'\u2651\ufe0f',
1745 'car':'\ud83d\ude97',
1746 'card_file_box':'\ud83d\uddc3',
1747 'card_index':'\ud83d\udcc7',
1748 'card_index_dividers':'\ud83d\uddc2',
1749 'carousel_horse':'\ud83c\udfa0',
1750 'carrot':'\ud83e\udd55',
1751 'cat':'\ud83d\udc31',
1752 'cat2':'\ud83d\udc08',
1753 'cd':'\ud83d\udcbf',
1754 'chains':'\u26d3',
1755 'champagne':'\ud83c\udf7e',
1756 'chart':'\ud83d\udcb9',
1757 'chart_with_downwards_trend':'\ud83d\udcc9',
1758 'chart_with_upwards_trend':'\ud83d\udcc8',
1759 'checkered_flag':'\ud83c\udfc1',
1760 'cheese':'\ud83e\uddc0',
1761 'cherries':'\ud83c\udf52',
1762 'cherry_blossom':'\ud83c\udf38',
1763 'chestnut':'\ud83c\udf30',
1764 'chicken':'\ud83d\udc14',
1765 'children_crossing':'\ud83d\udeb8',
1766 'chipmunk':'\ud83d\udc3f',
1767 'chocolate_bar':'\ud83c\udf6b',
1768 'christmas_tree':'\ud83c\udf84',
1769 'church':'\u26ea\ufe0f',
1770 'cinema':'\ud83c\udfa6',
1771 'circus_tent':'\ud83c\udfaa',
1772 'city_sunrise':'\ud83c\udf07',
1773 'city_sunset':'\ud83c\udf06',
1774 'cityscape':'\ud83c\udfd9',
1775 'cl':'\ud83c\udd91',
1776 'clamp':'\ud83d\udddc',
1777 'clap':'\ud83d\udc4f',
1778 'clapper':'\ud83c\udfac',
1779 'classical_building':'\ud83c\udfdb',
1780 'clinking_glasses':'\ud83e\udd42',
1781 'clipboard':'\ud83d\udccb',
1782 'clock1':'\ud83d\udd50',
1783 'clock10':'\ud83d\udd59',
1784 'clock1030':'\ud83d\udd65',
1785 'clock11':'\ud83d\udd5a',
1786 'clock1130':'\ud83d\udd66',
1787 'clock12':'\ud83d\udd5b',
1788 'clock1230':'\ud83d\udd67',
1789 'clock130':'\ud83d\udd5c',
1790 'clock2':'\ud83d\udd51',
1791 'clock230':'\ud83d\udd5d',
1792 'clock3':'\ud83d\udd52',
1793 'clock330':'\ud83d\udd5e',
1794 'clock4':'\ud83d\udd53',
1795 'clock430':'\ud83d\udd5f',
1796 'clock5':'\ud83d\udd54',
1797 'clock530':'\ud83d\udd60',
1798 'clock6':'\ud83d\udd55',
1799 'clock630':'\ud83d\udd61',
1800 'clock7':'\ud83d\udd56',
1801 'clock730':'\ud83d\udd62',
1802 'clock8':'\ud83d\udd57',
1803 'clock830':'\ud83d\udd63',
1804 'clock9':'\ud83d\udd58',
1805 'clock930':'\ud83d\udd64',
1806 'closed_book':'\ud83d\udcd5',
1807 'closed_lock_with_key':'\ud83d\udd10',
1808 'closed_umbrella':'\ud83c\udf02',
1809 'cloud':'\u2601\ufe0f',
1810 'cloud_with_lightning':'\ud83c\udf29',
1811 'cloud_with_lightning_and_rain':'\u26c8',
1812 'cloud_with_rain':'\ud83c\udf27',
1813 'cloud_with_snow':'\ud83c\udf28',
1814 'clown_face':'\ud83e\udd21',
1815 'clubs':'\u2663\ufe0f',
1816 'cocktail':'\ud83c\udf78',
1817 'coffee':'\u2615\ufe0f',
1818 'coffin':'\u26b0\ufe0f',
1819 'cold_sweat':'\ud83d\ude30',
1820 'comet':'\u2604\ufe0f',
1821 'computer':'\ud83d\udcbb',
1822 'computer_mouse':'\ud83d\uddb1',
1823 'confetti_ball':'\ud83c\udf8a',
1824 'confounded':'\ud83d\ude16',
1825 'confused':'\ud83d\ude15',
1826 'congratulations':'\u3297\ufe0f',
1827 'construction':'\ud83d\udea7',
1828 'construction_worker_man':'\ud83d\udc77',
1829 'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1830 'control_knobs':'\ud83c\udf9b',
1831 'convenience_store':'\ud83c\udfea',
1832 'cookie':'\ud83c\udf6a',
1833 'cool':'\ud83c\udd92',
1834 'policeman':'\ud83d\udc6e',
1835 'copyright':'\u00a9\ufe0f',
1836 'corn':'\ud83c\udf3d',
1837 'couch_and_lamp':'\ud83d\udecb',
1838 'couple':'\ud83d\udc6b',
1839 'couple_with_heart_woman_man':'\ud83d\udc91',
1840 'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1841 'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1842 'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1843 'couplekiss_man_woman':'\ud83d\udc8f',
1844 'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1845 'cow':'\ud83d\udc2e',
1846 'cow2':'\ud83d\udc04',
1847 'cowboy_hat_face':'\ud83e\udd20',
1848 'crab':'\ud83e\udd80',
1849 'crayon':'\ud83d\udd8d',
1850 'credit_card':'\ud83d\udcb3',
1851 'crescent_moon':'\ud83c\udf19',
1852 'cricket':'\ud83c\udfcf',
1853 'crocodile':'\ud83d\udc0a',
1854 'croissant':'\ud83e\udd50',
1855 'crossed_fingers':'\ud83e\udd1e',
1856 'crossed_flags':'\ud83c\udf8c',
1857 'crossed_swords':'\u2694\ufe0f',
1858 'crown':'\ud83d\udc51',
1859 'cry':'\ud83d\ude22',
1860 'crying_cat_face':'\ud83d\ude3f',
1861 'crystal_ball':'\ud83d\udd2e',
1862 'cucumber':'\ud83e\udd52',
1863 'cupid':'\ud83d\udc98',
1864 'curly_loop':'\u27b0',
1865 'currency_exchange':'\ud83d\udcb1',
1866 'curry':'\ud83c\udf5b',
1867 'custard':'\ud83c\udf6e',
1868 'customs':'\ud83d\udec3',
1869 'cyclone':'\ud83c\udf00',
1870 'dagger':'\ud83d\udde1',
1871 'dancer':'\ud83d\udc83',
1872 'dancing_women':'\ud83d\udc6f',
1873 'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1874 'dango':'\ud83c\udf61',
1875 'dark_sunglasses':'\ud83d\udd76',
1876 'dart':'\ud83c\udfaf',
1877 'dash':'\ud83d\udca8',
1878 'date':'\ud83d\udcc5',
1879 'deciduous_tree':'\ud83c\udf33',
1880 'deer':'\ud83e\udd8c',
1881 'department_store':'\ud83c\udfec',
1882 'derelict_house':'\ud83c\udfda',
1883 'desert':'\ud83c\udfdc',
1884 'desert_island':'\ud83c\udfdd',
1885 'desktop_computer':'\ud83d\udda5',
1886 'male_detective':'\ud83d\udd75\ufe0f',
1887 'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1888 'diamonds':'\u2666\ufe0f',
1889 'disappointed':'\ud83d\ude1e',
1890 'disappointed_relieved':'\ud83d\ude25',
1891 'dizzy':'\ud83d\udcab',
1892 'dizzy_face':'\ud83d\ude35',
1893 'do_not_litter':'\ud83d\udeaf',
1894 'dog':'\ud83d\udc36',
1895 'dog2':'\ud83d\udc15',
1896 'dollar':'\ud83d\udcb5',
1897 'dolls':'\ud83c\udf8e',
1898 'dolphin':'\ud83d\udc2c',
1899 'door':'\ud83d\udeaa',
1900 'doughnut':'\ud83c\udf69',
1901 'dove':'\ud83d\udd4a',
1902 'dragon':'\ud83d\udc09',
1903 'dragon_face':'\ud83d\udc32',
1904 'dress':'\ud83d\udc57',
1905 'dromedary_camel':'\ud83d\udc2a',
1906 'drooling_face':'\ud83e\udd24',
1907 'droplet':'\ud83d\udca7',
1908 'drum':'\ud83e\udd41',
1909 'duck':'\ud83e\udd86',
1910 'dvd':'\ud83d\udcc0',
1911 'e-mail':'\ud83d\udce7',
1912 'eagle':'\ud83e\udd85',
1913 'ear':'\ud83d\udc42',
1914 'ear_of_rice':'\ud83c\udf3e',
1915 'earth_africa':'\ud83c\udf0d',
1916 'earth_americas':'\ud83c\udf0e',
1917 'earth_asia':'\ud83c\udf0f',
1918 'egg':'\ud83e\udd5a',
1919 'eggplant':'\ud83c\udf46',
1920 'eight_pointed_black_star':'\u2734\ufe0f',
1921 'eight_spoked_asterisk':'\u2733\ufe0f',
1922 'electric_plug':'\ud83d\udd0c',
1923 'elephant':'\ud83d\udc18',
1924 'email':'\u2709\ufe0f',
1925 'end':'\ud83d\udd1a',
1926 'envelope_with_arrow':'\ud83d\udce9',
1927 'euro':'\ud83d\udcb6',
1928 'european_castle':'\ud83c\udff0',
1929 'european_post_office':'\ud83c\udfe4',
1930 'evergreen_tree':'\ud83c\udf32',
1931 'exclamation':'\u2757\ufe0f',
1932 'expressionless':'\ud83d\ude11',
1933 'eye':'\ud83d\udc41',
1934 'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
1935 'eyeglasses':'\ud83d\udc53',
1936 'eyes':'\ud83d\udc40',
1937 'face_with_head_bandage':'\ud83e\udd15',
1938 'face_with_thermometer':'\ud83e\udd12',
1939 'fist_oncoming':'\ud83d\udc4a',
1940 'factory':'\ud83c\udfed',
1941 'fallen_leaf':'\ud83c\udf42',
1942 'family_man_woman_boy':'\ud83d\udc6a',
1943 'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
1944 'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1945 'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1946 'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1947 'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1948 'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1949 'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1950 'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1951 'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1952 'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1953 'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1954 'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1955 'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1956 'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1957 'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1958 'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1959 'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1960 'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1961 'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1962 'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1963 'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1964 'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1965 'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1966 'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1967 'fast_forward':'\u23e9',
1968 'fax':'\ud83d\udce0',
1969 'fearful':'\ud83d\ude28',
1970 'feet':'\ud83d\udc3e',
1971 'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
1972 'ferris_wheel':'\ud83c\udfa1',
1973 'ferry':'\u26f4',
1974 'field_hockey':'\ud83c\udfd1',
1975 'file_cabinet':'\ud83d\uddc4',
1976 'file_folder':'\ud83d\udcc1',
1977 'film_projector':'\ud83d\udcfd',
1978 'film_strip':'\ud83c\udf9e',
1979 'fire':'\ud83d\udd25',
1980 'fire_engine':'\ud83d\ude92',
1981 'fireworks':'\ud83c\udf86',
1982 'first_quarter_moon':'\ud83c\udf13',
1983 'first_quarter_moon_with_face':'\ud83c\udf1b',
1984 'fish':'\ud83d\udc1f',
1985 'fish_cake':'\ud83c\udf65',
1986 'fishing_pole_and_fish':'\ud83c\udfa3',
1987 'fist_raised':'\u270a',
1988 'fist_left':'\ud83e\udd1b',
1989 'fist_right':'\ud83e\udd1c',
1990 'flags':'\ud83c\udf8f',
1991 'flashlight':'\ud83d\udd26',
1992 'fleur_de_lis':'\u269c\ufe0f',
1993 'flight_arrival':'\ud83d\udeec',
1994 'flight_departure':'\ud83d\udeeb',
1995 'floppy_disk':'\ud83d\udcbe',
1996 'flower_playing_cards':'\ud83c\udfb4',
1997 'flushed':'\ud83d\ude33',
1998 'fog':'\ud83c\udf2b',
1999 'foggy':'\ud83c\udf01',
2000 'football':'\ud83c\udfc8',
2001 'footprints':'\ud83d\udc63',
2002 'fork_and_knife':'\ud83c\udf74',
2003 'fountain':'\u26f2\ufe0f',
2004 'fountain_pen':'\ud83d\udd8b',
2005 'four_leaf_clover':'\ud83c\udf40',
2006 'fox_face':'\ud83e\udd8a',
2007 'framed_picture':'\ud83d\uddbc',
2008 'free':'\ud83c\udd93',
2009 'fried_egg':'\ud83c\udf73',
2010 'fried_shrimp':'\ud83c\udf64',
2011 'fries':'\ud83c\udf5f',
2012 'frog':'\ud83d\udc38',
2013 'frowning':'\ud83d\ude26',
2014 'frowning_face':'\u2639\ufe0f',
2015 'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
2016 'frowning_woman':'\ud83d\ude4d',
2017 'middle_finger':'\ud83d\udd95',
2018 'fuelpump':'\u26fd\ufe0f',
2019 'full_moon':'\ud83c\udf15',
2020 'full_moon_with_face':'\ud83c\udf1d',
2021 'funeral_urn':'\u26b1\ufe0f',
2022 'game_die':'\ud83c\udfb2',
2023 'gear':'\u2699\ufe0f',
2024 'gem':'\ud83d\udc8e',
2025 'gemini':'\u264a\ufe0f',
2026 'ghost':'\ud83d\udc7b',
2027 'gift':'\ud83c\udf81',
2028 'gift_heart':'\ud83d\udc9d',
2029 'girl':'\ud83d\udc67',
2030 'globe_with_meridians':'\ud83c\udf10',
2031 'goal_net':'\ud83e\udd45',
2032 'goat':'\ud83d\udc10',
2033 'golf':'\u26f3\ufe0f',
2034 'golfing_man':'\ud83c\udfcc\ufe0f',
2035 'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
2036 'gorilla':'\ud83e\udd8d',
2037 'grapes':'\ud83c\udf47',
2038 'green_apple':'\ud83c\udf4f',
2039 'green_book':'\ud83d\udcd7',
2040 'green_heart':'\ud83d\udc9a',
2041 'green_salad':'\ud83e\udd57',
2042 'grey_exclamation':'\u2755',
2043 'grey_question':'\u2754',
2044 'grimacing':'\ud83d\ude2c',
2045 'grin':'\ud83d\ude01',
2046 'grinning':'\ud83d\ude00',
2047 'guardsman':'\ud83d\udc82',
2048 'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
2049 'guitar':'\ud83c\udfb8',
2050 'gun':'\ud83d\udd2b',
2051 'haircut_woman':'\ud83d\udc87',
2052 'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
2053 'hamburger':'\ud83c\udf54',
2054 'hammer':'\ud83d\udd28',
2055 'hammer_and_pick':'\u2692',
2056 'hammer_and_wrench':'\ud83d\udee0',
2057 'hamster':'\ud83d\udc39',
2058 'hand':'\u270b',
2059 'handbag':'\ud83d\udc5c',
2060 'handshake':'\ud83e\udd1d',
2061 'hankey':'\ud83d\udca9',
2062 'hatched_chick':'\ud83d\udc25',
2063 'hatching_chick':'\ud83d\udc23',
2064 'headphones':'\ud83c\udfa7',
2065 'hear_no_evil':'\ud83d\ude49',
2066 'heart':'\u2764\ufe0f',
2067 'heart_decoration':'\ud83d\udc9f',
2068 'heart_eyes':'\ud83d\ude0d',
2069 'heart_eyes_cat':'\ud83d\ude3b',
2070 'heartbeat':'\ud83d\udc93',
2071 'heartpulse':'\ud83d\udc97',
2072 'hearts':'\u2665\ufe0f',
2073 'heavy_check_mark':'\u2714\ufe0f',
2074 'heavy_division_sign':'\u2797',
2075 'heavy_dollar_sign':'\ud83d\udcb2',
2076 'heavy_heart_exclamation':'\u2763\ufe0f',
2077 'heavy_minus_sign':'\u2796',
2078 'heavy_multiplication_x':'\u2716\ufe0f',
2079 'heavy_plus_sign':'\u2795',
2080 'helicopter':'\ud83d\ude81',
2081 'herb':'\ud83c\udf3f',
2082 'hibiscus':'\ud83c\udf3a',
2083 'high_brightness':'\ud83d\udd06',
2084 'high_heel':'\ud83d\udc60',
2085 'hocho':'\ud83d\udd2a',
2086 'hole':'\ud83d\udd73',
2087 'honey_pot':'\ud83c\udf6f',
2088 'horse':'\ud83d\udc34',
2089 'horse_racing':'\ud83c\udfc7',
2090 'hospital':'\ud83c\udfe5',
2091 'hot_pepper':'\ud83c\udf36',
2092 'hotdog':'\ud83c\udf2d',
2093 'hotel':'\ud83c\udfe8',
2094 'hotsprings':'\u2668\ufe0f',
2095 'hourglass':'\u231b\ufe0f',
2096 'hourglass_flowing_sand':'\u23f3',
2097 'house':'\ud83c\udfe0',
2098 'house_with_garden':'\ud83c\udfe1',
2099 'houses':'\ud83c\udfd8',
2100 'hugs':'\ud83e\udd17',
2101 'hushed':'\ud83d\ude2f',
2102 'ice_cream':'\ud83c\udf68',
2103 'ice_hockey':'\ud83c\udfd2',
2104 'ice_skate':'\u26f8',
2105 'icecream':'\ud83c\udf66',
2106 'id':'\ud83c\udd94',
2107 'ideograph_advantage':'\ud83c\ude50',
2108 'imp':'\ud83d\udc7f',
2109 'inbox_tray':'\ud83d\udce5',
2110 'incoming_envelope':'\ud83d\udce8',
2111 'tipping_hand_woman':'\ud83d\udc81',
2112 'information_source':'\u2139\ufe0f',
2113 'innocent':'\ud83d\ude07',
2114 'interrobang':'\u2049\ufe0f',
2115 'iphone':'\ud83d\udcf1',
2116 'izakaya_lantern':'\ud83c\udfee',
2117 'jack_o_lantern':'\ud83c\udf83',
2118 'japan':'\ud83d\uddfe',
2119 'japanese_castle':'\ud83c\udfef',
2120 'japanese_goblin':'\ud83d\udc7a',
2121 'japanese_ogre':'\ud83d\udc79',
2122 'jeans':'\ud83d\udc56',
2123 'joy':'\ud83d\ude02',
2124 'joy_cat':'\ud83d\ude39',
2125 'joystick':'\ud83d\udd79',
2126 'kaaba':'\ud83d\udd4b',
2127 'key':'\ud83d\udd11',
2128 'keyboard':'\u2328\ufe0f',
2129 'keycap_ten':'\ud83d\udd1f',
2130 'kick_scooter':'\ud83d\udef4',
2131 'kimono':'\ud83d\udc58',
2132 'kiss':'\ud83d\udc8b',
2133 'kissing':'\ud83d\ude17',
2134 'kissing_cat':'\ud83d\ude3d',
2135 'kissing_closed_eyes':'\ud83d\ude1a',
2136 'kissing_heart':'\ud83d\ude18',
2137 'kissing_smiling_eyes':'\ud83d\ude19',
2138 'kiwi_fruit':'\ud83e\udd5d',
2139 'koala':'\ud83d\udc28',
2140 'koko':'\ud83c\ude01',
2141 'label':'\ud83c\udff7',
2142 'large_blue_circle':'\ud83d\udd35',
2143 'large_blue_diamond':'\ud83d\udd37',
2144 'large_orange_diamond':'\ud83d\udd36',
2145 'last_quarter_moon':'\ud83c\udf17',
2146 'last_quarter_moon_with_face':'\ud83c\udf1c',
2147 'latin_cross':'\u271d\ufe0f',
2148 'laughing':'\ud83d\ude06',
2149 'leaves':'\ud83c\udf43',
2150 'ledger':'\ud83d\udcd2',
2151 'left_luggage':'\ud83d\udec5',
2152 'left_right_arrow':'\u2194\ufe0f',
2153 'leftwards_arrow_with_hook':'\u21a9\ufe0f',
2154 'lemon':'\ud83c\udf4b',
2155 'leo':'\u264c\ufe0f',
2156 'leopard':'\ud83d\udc06',
2157 'level_slider':'\ud83c\udf9a',
2158 'libra':'\u264e\ufe0f',
2159 'light_rail':'\ud83d\ude88',
2160 'link':'\ud83d\udd17',
2161 'lion':'\ud83e\udd81',
2162 'lips':'\ud83d\udc44',
2163 'lipstick':'\ud83d\udc84',
2164 'lizard':'\ud83e\udd8e',
2165 'lock':'\ud83d\udd12',
2166 'lock_with_ink_pen':'\ud83d\udd0f',
2167 'lollipop':'\ud83c\udf6d',
2168 'loop':'\u27bf',
2169 'loud_sound':'\ud83d\udd0a',
2170 'loudspeaker':'\ud83d\udce2',
2171 'love_hotel':'\ud83c\udfe9',
2172 'love_letter':'\ud83d\udc8c',
2173 'low_brightness':'\ud83d\udd05',
2174 'lying_face':'\ud83e\udd25',
2175 'm':'\u24c2\ufe0f',
2176 'mag':'\ud83d\udd0d',
2177 'mag_right':'\ud83d\udd0e',
2178 'mahjong':'\ud83c\udc04\ufe0f',
2179 'mailbox':'\ud83d\udceb',
2180 'mailbox_closed':'\ud83d\udcea',
2181 'mailbox_with_mail':'\ud83d\udcec',
2182 'mailbox_with_no_mail':'\ud83d\udced',
2183 'man':'\ud83d\udc68',
2184 'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
2185 'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
2186 'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
2187 'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
2188 'man_dancing':'\ud83d\udd7a',
2189 'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
2190 'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
2191 'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
2192 'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
2193 'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
2194 'man_in_tuxedo':'\ud83e\udd35',
2195 'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
2196 'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
2197 'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
2198 'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
2199 'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
2200 'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
2201 'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
2202 'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
2203 'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
2204 'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
2205 'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
2206 'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
2207 'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
2208 'man_with_gua_pi_mao':'\ud83d\udc72',
2209 'man_with_turban':'\ud83d\udc73',
2210 'tangerine':'\ud83c\udf4a',
2211 'mans_shoe':'\ud83d\udc5e',
2212 'mantelpiece_clock':'\ud83d\udd70',
2213 'maple_leaf':'\ud83c\udf41',
2214 'martial_arts_uniform':'\ud83e\udd4b',
2215 'mask':'\ud83d\ude37',
2216 'massage_woman':'\ud83d\udc86',
2217 'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
2218 'meat_on_bone':'\ud83c\udf56',
2219 'medal_military':'\ud83c\udf96',
2220 'medal_sports':'\ud83c\udfc5',
2221 'mega':'\ud83d\udce3',
2222 'melon':'\ud83c\udf48',
2223 'memo':'\ud83d\udcdd',
2224 'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
2225 'menorah':'\ud83d\udd4e',
2226 'mens':'\ud83d\udeb9',
2227 'metal':'\ud83e\udd18',
2228 'metro':'\ud83d\ude87',
2229 'microphone':'\ud83c\udfa4',
2230 'microscope':'\ud83d\udd2c',
2231 'milk_glass':'\ud83e\udd5b',
2232 'milky_way':'\ud83c\udf0c',
2233 'minibus':'\ud83d\ude90',
2234 'minidisc':'\ud83d\udcbd',
2235 'mobile_phone_off':'\ud83d\udcf4',
2236 'money_mouth_face':'\ud83e\udd11',
2237 'money_with_wings':'\ud83d\udcb8',
2238 'moneybag':'\ud83d\udcb0',
2239 'monkey':'\ud83d\udc12',
2240 'monkey_face':'\ud83d\udc35',
2241 'monorail':'\ud83d\ude9d',
2242 'moon':'\ud83c\udf14',
2243 'mortar_board':'\ud83c\udf93',
2244 'mosque':'\ud83d\udd4c',
2245 'motor_boat':'\ud83d\udee5',
2246 'motor_scooter':'\ud83d\udef5',
2247 'motorcycle':'\ud83c\udfcd',
2248 'motorway':'\ud83d\udee3',
2249 'mount_fuji':'\ud83d\uddfb',
2250 'mountain':'\u26f0',
2251 'mountain_biking_man':'\ud83d\udeb5',
2252 'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
2253 'mountain_cableway':'\ud83d\udea0',
2254 'mountain_railway':'\ud83d\ude9e',
2255 'mountain_snow':'\ud83c\udfd4',
2256 'mouse':'\ud83d\udc2d',
2257 'mouse2':'\ud83d\udc01',
2258 'movie_camera':'\ud83c\udfa5',
2259 'moyai':'\ud83d\uddff',
2260 'mrs_claus':'\ud83e\udd36',
2261 'muscle':'\ud83d\udcaa',
2262 'mushroom':'\ud83c\udf44',
2263 'musical_keyboard':'\ud83c\udfb9',
2264 'musical_note':'\ud83c\udfb5',
2265 'musical_score':'\ud83c\udfbc',
2266 'mute':'\ud83d\udd07',
2267 'nail_care':'\ud83d\udc85',
2268 'name_badge':'\ud83d\udcdb',
2269 'national_park':'\ud83c\udfde',
2270 'nauseated_face':'\ud83e\udd22',
2271 'necktie':'\ud83d\udc54',
2272 'negative_squared_cross_mark':'\u274e',
2273 'nerd_face':'\ud83e\udd13',
2274 'neutral_face':'\ud83d\ude10',
2275 'new':'\ud83c\udd95',
2276 'new_moon':'\ud83c\udf11',
2277 'new_moon_with_face':'\ud83c\udf1a',
2278 'newspaper':'\ud83d\udcf0',
2279 'newspaper_roll':'\ud83d\uddde',
2280 'next_track_button':'\u23ed',
2281 'ng':'\ud83c\udd96',
2282 'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
2283 'no_good_woman':'\ud83d\ude45',
2284 'night_with_stars':'\ud83c\udf03',
2285 'no_bell':'\ud83d\udd15',
2286 'no_bicycles':'\ud83d\udeb3',
2287 'no_entry':'\u26d4\ufe0f',
2288 'no_entry_sign':'\ud83d\udeab',
2289 'no_mobile_phones':'\ud83d\udcf5',
2290 'no_mouth':'\ud83d\ude36',
2291 'no_pedestrians':'\ud83d\udeb7',
2292 'no_smoking':'\ud83d\udead',
2293 'non-potable_water':'\ud83d\udeb1',
2294 'nose':'\ud83d\udc43',
2295 'notebook':'\ud83d\udcd3',
2296 'notebook_with_decorative_cover':'\ud83d\udcd4',
2297 'notes':'\ud83c\udfb6',
2298 'nut_and_bolt':'\ud83d\udd29',
2299 'o':'\u2b55\ufe0f',
2300 'o2':'\ud83c\udd7e\ufe0f',
2301 'ocean':'\ud83c\udf0a',
2302 'octopus':'\ud83d\udc19',
2303 'oden':'\ud83c\udf62',
2304 'office':'\ud83c\udfe2',
2305 'oil_drum':'\ud83d\udee2',
2306 'ok':'\ud83c\udd97',
2307 'ok_hand':'\ud83d\udc4c',
2308 'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
2309 'ok_woman':'\ud83d\ude46',
2310 'old_key':'\ud83d\udddd',
2311 'older_man':'\ud83d\udc74',
2312 'older_woman':'\ud83d\udc75',
2313 'om':'\ud83d\udd49',
2314 'on':'\ud83d\udd1b',
2315 'oncoming_automobile':'\ud83d\ude98',
2316 'oncoming_bus':'\ud83d\ude8d',
2317 'oncoming_police_car':'\ud83d\ude94',
2318 'oncoming_taxi':'\ud83d\ude96',
2319 'open_file_folder':'\ud83d\udcc2',
2320 'open_hands':'\ud83d\udc50',
2321 'open_mouth':'\ud83d\ude2e',
2322 'open_umbrella':'\u2602\ufe0f',
2323 'ophiuchus':'\u26ce',
2324 'orange_book':'\ud83d\udcd9',
2325 'orthodox_cross':'\u2626\ufe0f',
2326 'outbox_tray':'\ud83d\udce4',
2327 'owl':'\ud83e\udd89',
2328 'ox':'\ud83d\udc02',
2329 'package':'\ud83d\udce6',
2330 'page_facing_up':'\ud83d\udcc4',
2331 'page_with_curl':'\ud83d\udcc3',
2332 'pager':'\ud83d\udcdf',
2333 'paintbrush':'\ud83d\udd8c',
2334 'palm_tree':'\ud83c\udf34',
2335 'pancakes':'\ud83e\udd5e',
2336 'panda_face':'\ud83d\udc3c',
2337 'paperclip':'\ud83d\udcce',
2338 'paperclips':'\ud83d\udd87',
2339 'parasol_on_ground':'\u26f1',
2340 'parking':'\ud83c\udd7f\ufe0f',
2341 'part_alternation_mark':'\u303d\ufe0f',
2342 'partly_sunny':'\u26c5\ufe0f',
2343 'passenger_ship':'\ud83d\udef3',
2344 'passport_control':'\ud83d\udec2',
2345 'pause_button':'\u23f8',
2346 'peace_symbol':'\u262e\ufe0f',
2347 'peach':'\ud83c\udf51',
2348 'peanuts':'\ud83e\udd5c',
2349 'pear':'\ud83c\udf50',
2350 'pen':'\ud83d\udd8a',
2351 'pencil2':'\u270f\ufe0f',
2352 'penguin':'\ud83d\udc27',
2353 'pensive':'\ud83d\ude14',
2354 'performing_arts':'\ud83c\udfad',
2355 'persevere':'\ud83d\ude23',
2356 'person_fencing':'\ud83e\udd3a',
2357 'pouting_woman':'\ud83d\ude4e',
2358 'phone':'\u260e\ufe0f',
2359 'pick':'\u26cf',
2360 'pig':'\ud83d\udc37',
2361 'pig2':'\ud83d\udc16',
2362 'pig_nose':'\ud83d\udc3d',
2363 'pill':'\ud83d\udc8a',
2364 'pineapple':'\ud83c\udf4d',
2365 'ping_pong':'\ud83c\udfd3',
2366 'pisces':'\u2653\ufe0f',
2367 'pizza':'\ud83c\udf55',
2368 'place_of_worship':'\ud83d\uded0',
2369 'plate_with_cutlery':'\ud83c\udf7d',
2370 'play_or_pause_button':'\u23ef',
2371 'point_down':'\ud83d\udc47',
2372 'point_left':'\ud83d\udc48',
2373 'point_right':'\ud83d\udc49',
2374 'point_up':'\u261d\ufe0f',
2375 'point_up_2':'\ud83d\udc46',
2376 'police_car':'\ud83d\ude93',
2377 'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
2378 'poodle':'\ud83d\udc29',
2379 'popcorn':'\ud83c\udf7f',
2380 'post_office':'\ud83c\udfe3',
2381 'postal_horn':'\ud83d\udcef',
2382 'postbox':'\ud83d\udcee',
2383 'potable_water':'\ud83d\udeb0',
2384 'potato':'\ud83e\udd54',
2385 'pouch':'\ud83d\udc5d',
2386 'poultry_leg':'\ud83c\udf57',
2387 'pound':'\ud83d\udcb7',
2388 'rage':'\ud83d\ude21',
2389 'pouting_cat':'\ud83d\ude3e',
2390 'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
2391 'pray':'\ud83d\ude4f',
2392 'prayer_beads':'\ud83d\udcff',
2393 'pregnant_woman':'\ud83e\udd30',
2394 'previous_track_button':'\u23ee',
2395 'prince':'\ud83e\udd34',
2396 'princess':'\ud83d\udc78',
2397 'printer':'\ud83d\udda8',
2398 'purple_heart':'\ud83d\udc9c',
2399 'purse':'\ud83d\udc5b',
2400 'pushpin':'\ud83d\udccc',
2401 'put_litter_in_its_place':'\ud83d\udeae',
2402 'question':'\u2753',
2403 'rabbit':'\ud83d\udc30',
2404 'rabbit2':'\ud83d\udc07',
2405 'racehorse':'\ud83d\udc0e',
2406 'racing_car':'\ud83c\udfce',
2407 'radio':'\ud83d\udcfb',
2408 'radio_button':'\ud83d\udd18',
2409 'radioactive':'\u2622\ufe0f',
2410 'railway_car':'\ud83d\ude83',
2411 'railway_track':'\ud83d\udee4',
2412 'rainbow':'\ud83c\udf08',
2413 'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
2414 'raised_back_of_hand':'\ud83e\udd1a',
2415 'raised_hand_with_fingers_splayed':'\ud83d\udd90',
2416 'raised_hands':'\ud83d\ude4c',
2417 'raising_hand_woman':'\ud83d\ude4b',
2418 'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
2419 'ram':'\ud83d\udc0f',
2420 'ramen':'\ud83c\udf5c',
2421 'rat':'\ud83d\udc00',
2422 'record_button':'\u23fa',
2423 'recycle':'\u267b\ufe0f',
2424 'red_circle':'\ud83d\udd34',
2425 'registered':'\u00ae\ufe0f',
2426 'relaxed':'\u263a\ufe0f',
2427 'relieved':'\ud83d\ude0c',
2428 'reminder_ribbon':'\ud83c\udf97',
2429 'repeat':'\ud83d\udd01',
2430 'repeat_one':'\ud83d\udd02',
2431 'rescue_worker_helmet':'\u26d1',
2432 'restroom':'\ud83d\udebb',
2433 'revolving_hearts':'\ud83d\udc9e',
2434 'rewind':'\u23ea',
2435 'rhinoceros':'\ud83e\udd8f',
2436 'ribbon':'\ud83c\udf80',
2437 'rice':'\ud83c\udf5a',
2438 'rice_ball':'\ud83c\udf59',
2439 'rice_cracker':'\ud83c\udf58',
2440 'rice_scene':'\ud83c\udf91',
2441 'right_anger_bubble':'\ud83d\uddef',
2442 'ring':'\ud83d\udc8d',
2443 'robot':'\ud83e\udd16',
2444 'rocket':'\ud83d\ude80',
2445 'rofl':'\ud83e\udd23',
2446 'roll_eyes':'\ud83d\ude44',
2447 'roller_coaster':'\ud83c\udfa2',
2448 'rooster':'\ud83d\udc13',
2449 'rose':'\ud83c\udf39',
2450 'rosette':'\ud83c\udff5',
2451 'rotating_light':'\ud83d\udea8',
2452 'round_pushpin':'\ud83d\udccd',
2453 'rowing_man':'\ud83d\udea3',
2454 'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
2455 'rugby_football':'\ud83c\udfc9',
2456 'running_man':'\ud83c\udfc3',
2457 'running_shirt_with_sash':'\ud83c\udfbd',
2458 'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
2459 'sa':'\ud83c\ude02\ufe0f',
2460 'sagittarius':'\u2650\ufe0f',
2461 'sake':'\ud83c\udf76',
2462 'sandal':'\ud83d\udc61',
2463 'santa':'\ud83c\udf85',
2464 'satellite':'\ud83d\udce1',
2465 'saxophone':'\ud83c\udfb7',
2466 'school':'\ud83c\udfeb',
2467 'school_satchel':'\ud83c\udf92',
2468 'scissors':'\u2702\ufe0f',
2469 'scorpion':'\ud83e\udd82',
2470 'scorpius':'\u264f\ufe0f',
2471 'scream':'\ud83d\ude31',
2472 'scream_cat':'\ud83d\ude40',
2473 'scroll':'\ud83d\udcdc',
2474 'seat':'\ud83d\udcba',
2475 'secret':'\u3299\ufe0f',
2476 'see_no_evil':'\ud83d\ude48',
2477 'seedling':'\ud83c\udf31',
2478 'selfie':'\ud83e\udd33',
2479 'shallow_pan_of_food':'\ud83e\udd58',
2480 'shamrock':'\u2618\ufe0f',
2481 'shark':'\ud83e\udd88',
2482 'shaved_ice':'\ud83c\udf67',
2483 'sheep':'\ud83d\udc11',
2484 'shell':'\ud83d\udc1a',
2485 'shield':'\ud83d\udee1',
2486 'shinto_shrine':'\u26e9',
2487 'ship':'\ud83d\udea2',
2488 'shirt':'\ud83d\udc55',
2489 'shopping':'\ud83d\udecd',
2490 'shopping_cart':'\ud83d\uded2',
2491 'shower':'\ud83d\udebf',
2492 'shrimp':'\ud83e\udd90',
2493 'signal_strength':'\ud83d\udcf6',
2494 'six_pointed_star':'\ud83d\udd2f',
2495 'ski':'\ud83c\udfbf',
2496 'skier':'\u26f7',
2497 'skull':'\ud83d\udc80',
2498 'skull_and_crossbones':'\u2620\ufe0f',
2499 'sleeping':'\ud83d\ude34',
2500 'sleeping_bed':'\ud83d\udecc',
2501 'sleepy':'\ud83d\ude2a',
2502 'slightly_frowning_face':'\ud83d\ude41',
2503 'slightly_smiling_face':'\ud83d\ude42',
2504 'slot_machine':'\ud83c\udfb0',
2505 'small_airplane':'\ud83d\udee9',
2506 'small_blue_diamond':'\ud83d\udd39',
2507 'small_orange_diamond':'\ud83d\udd38',
2508 'small_red_triangle':'\ud83d\udd3a',
2509 'small_red_triangle_down':'\ud83d\udd3b',
2510 'smile':'\ud83d\ude04',
2511 'smile_cat':'\ud83d\ude38',
2512 'smiley':'\ud83d\ude03',
2513 'smiley_cat':'\ud83d\ude3a',
2514 'smiling_imp':'\ud83d\ude08',
2515 'smirk':'\ud83d\ude0f',
2516 'smirk_cat':'\ud83d\ude3c',
2517 'smoking':'\ud83d\udeac',
2518 'snail':'\ud83d\udc0c',
2519 'snake':'\ud83d\udc0d',
2520 'sneezing_face':'\ud83e\udd27',
2521 'snowboarder':'\ud83c\udfc2',
2522 'snowflake':'\u2744\ufe0f',
2523 'snowman':'\u26c4\ufe0f',
2524 'snowman_with_snow':'\u2603\ufe0f',
2525 'sob':'\ud83d\ude2d',
2526 'soccer':'\u26bd\ufe0f',
2527 'soon':'\ud83d\udd1c',
2528 'sos':'\ud83c\udd98',
2529 'sound':'\ud83d\udd09',
2530 'space_invader':'\ud83d\udc7e',
2531 'spades':'\u2660\ufe0f',
2532 'spaghetti':'\ud83c\udf5d',
2533 'sparkle':'\u2747\ufe0f',
2534 'sparkler':'\ud83c\udf87',
2535 'sparkles':'\u2728',
2536 'sparkling_heart':'\ud83d\udc96',
2537 'speak_no_evil':'\ud83d\ude4a',
2538 'speaker':'\ud83d\udd08',
2539 'speaking_head':'\ud83d\udde3',
2540 'speech_balloon':'\ud83d\udcac',
2541 'speedboat':'\ud83d\udea4',
2542 'spider':'\ud83d\udd77',
2543 'spider_web':'\ud83d\udd78',
2544 'spiral_calendar':'\ud83d\uddd3',
2545 'spiral_notepad':'\ud83d\uddd2',
2546 'spoon':'\ud83e\udd44',
2547 'squid':'\ud83e\udd91',
2548 'stadium':'\ud83c\udfdf',
2549 'star':'\u2b50\ufe0f',
2550 'star2':'\ud83c\udf1f',
2551 'star_and_crescent':'\u262a\ufe0f',
2552 'star_of_david':'\u2721\ufe0f',
2553 'stars':'\ud83c\udf20',
2554 'station':'\ud83d\ude89',
2555 'statue_of_liberty':'\ud83d\uddfd',
2556 'steam_locomotive':'\ud83d\ude82',
2557 'stew':'\ud83c\udf72',
2558 'stop_button':'\u23f9',
2559 'stop_sign':'\ud83d\uded1',
2560 'stopwatch':'\u23f1',
2561 'straight_ruler':'\ud83d\udccf',
2562 'strawberry':'\ud83c\udf53',
2563 'stuck_out_tongue':'\ud83d\ude1b',
2564 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2565 'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2566 'studio_microphone':'\ud83c\udf99',
2567 'stuffed_flatbread':'\ud83e\udd59',
2568 'sun_behind_large_cloud':'\ud83c\udf25',
2569 'sun_behind_rain_cloud':'\ud83c\udf26',
2570 'sun_behind_small_cloud':'\ud83c\udf24',
2571 'sun_with_face':'\ud83c\udf1e',
2572 'sunflower':'\ud83c\udf3b',
2573 'sunglasses':'\ud83d\ude0e',
2574 'sunny':'\u2600\ufe0f',
2575 'sunrise':'\ud83c\udf05',
2576 'sunrise_over_mountains':'\ud83c\udf04',
2577 'surfing_man':'\ud83c\udfc4',
2578 'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2579 'sushi':'\ud83c\udf63',
2580 'suspension_railway':'\ud83d\ude9f',
2581 'sweat':'\ud83d\ude13',
2582 'sweat_drops':'\ud83d\udca6',
2583 'sweat_smile':'\ud83d\ude05',
2584 'sweet_potato':'\ud83c\udf60',
2585 'swimming_man':'\ud83c\udfca',
2586 'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2587 'symbols':'\ud83d\udd23',
2588 'synagogue':'\ud83d\udd4d',
2589 'syringe':'\ud83d\udc89',
2590 'taco':'\ud83c\udf2e',
2591 'tada':'\ud83c\udf89',
2592 'tanabata_tree':'\ud83c\udf8b',
2593 'taurus':'\u2649\ufe0f',
2594 'taxi':'\ud83d\ude95',
2595 'tea':'\ud83c\udf75',
2596 'telephone_receiver':'\ud83d\udcde',
2597 'telescope':'\ud83d\udd2d',
2598 'tennis':'\ud83c\udfbe',
2599 'tent':'\u26fa\ufe0f',
2600 'thermometer':'\ud83c\udf21',
2601 'thinking':'\ud83e\udd14',
2602 'thought_balloon':'\ud83d\udcad',
2603 'ticket':'\ud83c\udfab',
2604 'tickets':'\ud83c\udf9f',
2605 'tiger':'\ud83d\udc2f',
2606 'tiger2':'\ud83d\udc05',
2607 'timer_clock':'\u23f2',
2608 'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2609 'tired_face':'\ud83d\ude2b',
2610 'tm':'\u2122\ufe0f',
2611 'toilet':'\ud83d\udebd',
2612 'tokyo_tower':'\ud83d\uddfc',
2613 'tomato':'\ud83c\udf45',
2614 'tongue':'\ud83d\udc45',
2615 'top':'\ud83d\udd1d',
2616 'tophat':'\ud83c\udfa9',
2617 'tornado':'\ud83c\udf2a',
2618 'trackball':'\ud83d\uddb2',
2619 'tractor':'\ud83d\ude9c',
2620 'traffic_light':'\ud83d\udea5',
2621 'train':'\ud83d\ude8b',
2622 'train2':'\ud83d\ude86',
2623 'tram':'\ud83d\ude8a',
2624 'triangular_flag_on_post':'\ud83d\udea9',
2625 'triangular_ruler':'\ud83d\udcd0',
2626 'trident':'\ud83d\udd31',
2627 'triumph':'\ud83d\ude24',
2628 'trolleybus':'\ud83d\ude8e',
2629 'trophy':'\ud83c\udfc6',
2630 'tropical_drink':'\ud83c\udf79',
2631 'tropical_fish':'\ud83d\udc20',
2632 'truck':'\ud83d\ude9a',
2633 'trumpet':'\ud83c\udfba',
2634 'tulip':'\ud83c\udf37',
2635 'tumbler_glass':'\ud83e\udd43',
2636 'turkey':'\ud83e\udd83',
2637 'turtle':'\ud83d\udc22',
2638 'tv':'\ud83d\udcfa',
2639 'twisted_rightwards_arrows':'\ud83d\udd00',
2640 'two_hearts':'\ud83d\udc95',
2641 'two_men_holding_hands':'\ud83d\udc6c',
2642 'two_women_holding_hands':'\ud83d\udc6d',
2643 'u5272':'\ud83c\ude39',
2644 'u5408':'\ud83c\ude34',
2645 'u55b6':'\ud83c\ude3a',
2646 'u6307':'\ud83c\ude2f\ufe0f',
2647 'u6708':'\ud83c\ude37\ufe0f',
2648 'u6709':'\ud83c\ude36',
2649 'u6e80':'\ud83c\ude35',
2650 'u7121':'\ud83c\ude1a\ufe0f',
2651 'u7533':'\ud83c\ude38',
2652 'u7981':'\ud83c\ude32',
2653 'u7a7a':'\ud83c\ude33',
2654 'umbrella':'\u2614\ufe0f',
2655 'unamused':'\ud83d\ude12',
2656 'underage':'\ud83d\udd1e',
2657 'unicorn':'\ud83e\udd84',
2658 'unlock':'\ud83d\udd13',
2659 'up':'\ud83c\udd99',
2660 'upside_down_face':'\ud83d\ude43',
2661 'v':'\u270c\ufe0f',
2662 'vertical_traffic_light':'\ud83d\udea6',
2663 'vhs':'\ud83d\udcfc',
2664 'vibration_mode':'\ud83d\udcf3',
2665 'video_camera':'\ud83d\udcf9',
2666 'video_game':'\ud83c\udfae',
2667 'violin':'\ud83c\udfbb',
2668 'virgo':'\u264d\ufe0f',
2669 'volcano':'\ud83c\udf0b',
2670 'volleyball':'\ud83c\udfd0',
2671 'vs':'\ud83c\udd9a',
2672 'vulcan_salute':'\ud83d\udd96',
2673 'walking_man':'\ud83d\udeb6',
2674 'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2675 'waning_crescent_moon':'\ud83c\udf18',
2676 'waning_gibbous_moon':'\ud83c\udf16',
2677 'warning':'\u26a0\ufe0f',
2678 'wastebasket':'\ud83d\uddd1',
2679 'watch':'\u231a\ufe0f',
2680 'water_buffalo':'\ud83d\udc03',
2681 'watermelon':'\ud83c\udf49',
2682 'wave':'\ud83d\udc4b',
2683 'wavy_dash':'\u3030\ufe0f',
2684 'waxing_crescent_moon':'\ud83c\udf12',
2685 'wc':'\ud83d\udebe',
2686 'weary':'\ud83d\ude29',
2687 'wedding':'\ud83d\udc92',
2688 'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2689 'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2690 'whale':'\ud83d\udc33',
2691 'whale2':'\ud83d\udc0b',
2692 'wheel_of_dharma':'\u2638\ufe0f',
2693 'wheelchair':'\u267f\ufe0f',
2694 'white_check_mark':'\u2705',
2695 'white_circle':'\u26aa\ufe0f',
2696 'white_flag':'\ud83c\udff3\ufe0f',
2697 'white_flower':'\ud83d\udcae',
2698 'white_large_square':'\u2b1c\ufe0f',
2699 'white_medium_small_square':'\u25fd\ufe0f',
2700 'white_medium_square':'\u25fb\ufe0f',
2701 'white_small_square':'\u25ab\ufe0f',
2702 'white_square_button':'\ud83d\udd33',
2703 'wilted_flower':'\ud83e\udd40',
2704 'wind_chime':'\ud83c\udf90',
2705 'wind_face':'\ud83c\udf2c',
2706 'wine_glass':'\ud83c\udf77',
2707 'wink':'\ud83d\ude09',
2708 'wolf':'\ud83d\udc3a',
2709 'woman':'\ud83d\udc69',
2710 'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2711 'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2712 'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2713 'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2714 'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2715 'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2716 'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2717 'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2718 'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2719 'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2720 'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2721 'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2722 'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2723 'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2724 'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2725 'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2726 'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2727 'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2728 'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2729 'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2730 'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2731 'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2732 'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2733 'womans_clothes':'\ud83d\udc5a',
2734 'womans_hat':'\ud83d\udc52',
2735 'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2736 'womens':'\ud83d\udeba',
2737 'world_map':'\ud83d\uddfa',
2738 'worried':'\ud83d\ude1f',
2739 'wrench':'\ud83d\udd27',
2740 'writing_hand':'\u270d\ufe0f',
2741 'x':'\u274c',
2742 'yellow_heart':'\ud83d\udc9b',
2743 'yen':'\ud83d\udcb4',
2744 'yin_yang':'\u262f\ufe0f',
2745 'yum':'\ud83d\ude0b',
2746 'zap':'\u26a1\ufe0f',
2747 'zipper_mouth_face':'\ud83e\udd10',
2748 'zzz':'\ud83d\udca4',
2749
2750 /* special emojis :P */
2751 'octocat': '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
2752 '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>'
2753 };
2754
2755 /**
2756 * Created by Estevao on 31-05-2015.
2757 */
2758
2759 /**
2760 * Showdown Converter class
2761 * @class
2762 * @param {object} [converterOptions]
2763 * @returns {Converter}
2764 */
2765 showdown.Converter = function (converterOptions) {
2766 'use strict';
2767
2768 var
2769 /**
2770 * Options used by this converter
2771 * @private
2772 * @type {{}}
2773 */
2774 options = {},
2775
2776 /**
2777 * Language extensions used by this converter
2778 * @private
2779 * @type {Array}
2780 */
2781 langExtensions = [],
2782
2783 /**
2784 * Output modifiers extensions used by this converter
2785 * @private
2786 * @type {Array}
2787 */
2788 outputModifiers = [],
2789
2790 /**
2791 * Event listeners
2792 * @private
2793 * @type {{}}
2794 */
2795 listeners = {},
2796
2797 /**
2798 * The flavor set in this converter
2799 */
2800 setConvFlavor = setFlavor,
2801
2802 /**
2803 * Metadata of the document
2804 * @type {{parsed: {}, raw: string, format: string}}
2805 */
2806 metadata = {
2807 parsed: {},
2808 raw: '',
2809 format: ''
2810 };
2811
2812 _constructor();
2813
2814 /**
2815 * Converter constructor
2816 * @private
2817 */
2818 function _constructor () {
2819 converterOptions = converterOptions || {};
2820
2821 for (var gOpt in globalOptions) {
2822 if (globalOptions.hasOwnProperty(gOpt)) {
2823 options[gOpt] = globalOptions[gOpt];
2824 }
2825 }
2826
2827 // Merge options
2828 if (typeof converterOptions === 'object') {
2829 for (var opt in converterOptions) {
2830 if (converterOptions.hasOwnProperty(opt)) {
2831 options[opt] = converterOptions[opt];
2832 }
2833 }
2834 } else {
2835 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
2836 ' was passed instead.');
2837 }
2838
2839 if (options.extensions) {
2840 showdown.helper.forEach(options.extensions, _parseExtension);
2841 }
2842 }
2843
2844 /**
2845 * Parse extension
2846 * @param {*} ext
2847 * @param {string} [name='']
2848 * @private
2849 */
2850 function _parseExtension (ext, name) {
2851
2852 name = name || null;
2853 // If it's a string, the extension was previously loaded
2854 if (showdown.helper.isString(ext)) {
2855 ext = showdown.helper.stdExtName(ext);
2856 name = ext;
2857
2858 // LEGACY_SUPPORT CODE
2859 if (showdown.extensions[ext]) {
2860 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
2861 'Please inform the developer that the extension should be updated!');
2862 legacyExtensionLoading(showdown.extensions[ext], ext);
2863 return;
2864 // END LEGACY SUPPORT CODE
2865
2866 } else if (!showdown.helper.isUndefined(extensions[ext])) {
2867 ext = extensions[ext];
2868
2869 } else {
2870 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
2871 }
2872 }
2873
2874 if (typeof ext === 'function') {
2875 ext = ext();
2876 }
2877
2878 if (!showdown.helper.isArray(ext)) {
2879 ext = [ext];
2880 }
2881
2882 var validExt = validate(ext, name);
2883 if (!validExt.valid) {
2884 throw Error(validExt.error);
2885 }
2886
2887 for (var i = 0; i < ext.length; ++i) {
2888 switch (ext[i].type) {
2889
2890 case 'lang':
2891 langExtensions.push(ext[i]);
2892 break;
2893
2894 case 'output':
2895 outputModifiers.push(ext[i]);
2896 break;
2897 }
2898 if (ext[i].hasOwnProperty('listeners')) {
2899 for (var ln in ext[i].listeners) {
2900 if (ext[i].listeners.hasOwnProperty(ln)) {
2901 listen(ln, ext[i].listeners[ln]);
2902 }
2903 }
2904 }
2905 }
2906
2907 }
2908
2909 /**
2910 * LEGACY_SUPPORT
2911 * @param {*} ext
2912 * @param {string} name
2913 */
2914 function legacyExtensionLoading (ext, name) {
2915 if (typeof ext === 'function') {
2916 ext = ext(new showdown.Converter());
2917 }
2918 if (!showdown.helper.isArray(ext)) {
2919 ext = [ext];
2920 }
2921 var valid = validate(ext, name);
2922
2923 if (!valid.valid) {
2924 throw Error(valid.error);
2925 }
2926
2927 for (var i = 0; i < ext.length; ++i) {
2928 switch (ext[i].type) {
2929 case 'lang':
2930 langExtensions.push(ext[i]);
2931 break;
2932 case 'output':
2933 outputModifiers.push(ext[i]);
2934 break;
2935 default:// should never reach here
2936 throw Error('Extension loader error: Type unrecognized!!!');
2937 }
2938 }
2939 }
2940
2941 /**
2942 * Listen to an event
2943 * @param {string} name
2944 * @param {function} callback
2945 */
2946 function listen (name, callback) {
2947 if (!showdown.helper.isString(name)) {
2948 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
2949 }
2950
2951 if (typeof callback !== 'function') {
2952 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
2953 }
2954
2955 if (!listeners.hasOwnProperty(name)) {
2956 listeners[name] = [];
2957 }
2958 listeners[name].push(callback);
2959 }
2960
2961 function rTrimInputText (text) {
2962 var rsp = text.match(/^\s*/)[0].length,
2963 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
2964 return text.replace(rgx, '');
2965 }
2966
2967 /**
2968 * Dispatch an event
2969 * @private
2970 * @param {string} evtName Event name
2971 * @param {string} text Text
2972 * @param {{}} options Converter Options
2973 * @param {{}} globals
2974 * @returns {string}
2975 */
2976 this._dispatch = function dispatch (evtName, text, options, globals) {
2977 if (listeners.hasOwnProperty(evtName)) {
2978 for (var ei = 0; ei < listeners[evtName].length; ++ei) {
2979 var nText = listeners[evtName][ei](evtName, text, this, options, globals);
2980 if (nText && typeof nText !== 'undefined') {
2981 text = nText;
2982 }
2983 }
2984 }
2985 return text;
2986 };
2987
2988 /**
2989 * Listen to an event
2990 * @param {string} name
2991 * @param {function} callback
2992 * @returns {showdown.Converter}
2993 */
2994 this.listen = function (name, callback) {
2995 listen(name, callback);
2996 return this;
2997 };
2998
2999 /**
3000 * Converts a markdown string into HTML
3001 * @param {string} text
3002 * @returns {*}
3003 */
3004 this.makeHtml = function (text) {
3005 //check if text is not falsy
3006 if (!text) {
3007 return text;
3008 }
3009
3010 var globals = {
3011 gHtmlBlocks: [],
3012 gHtmlMdBlocks: [],
3013 gHtmlSpans: [],
3014 gUrls: {},
3015 gTitles: {},
3016 gDimensions: {},
3017 gListLevel: 0,
3018 hashLinkCounts: {},
3019 langExtensions: langExtensions,
3020 outputModifiers: outputModifiers,
3021 converter: this,
3022 ghCodeBlocks: [],
3023 metadata: {
3024 parsed: {},
3025 raw: '',
3026 format: ''
3027 }
3028 };
3029
3030 // This lets us use ¨ trema as an escape char to avoid md5 hashes
3031 // The choice of character is arbitrary; anything that isn't
3032 // magic in Markdown will work.
3033 text = text.replace(/¨/g, '¨T');
3034
3035 // Replace $ with ¨D
3036 // RegExp interprets $ as a special character
3037 // when it's in a replacement string
3038 text = text.replace(/\$/g, '¨D');
3039
3040 // Standardize line endings
3041 text = text.replace(/\r\n/g, '\n'); // DOS to Unix
3042 text = text.replace(/\r/g, '\n'); // Mac to Unix
3043
3044 // Stardardize line spaces
3045 text = text.replace(/\u00A0/g, '&nbsp;');
3046
3047 if (options.smartIndentationFix) {
3048 text = rTrimInputText(text);
3049 }
3050
3051 // Make sure text begins and ends with a couple of newlines:
3052 text = '\n\n' + text + '\n\n';
3053
3054 // detab
3055 text = showdown.subParser('detab')(text, options, globals);
3056
3057 /**
3058 * Strip any lines consisting only of spaces and tabs.
3059 * This makes subsequent regexs easier to write, because we can
3060 * match consecutive blank lines with /\n+/ instead of something
3061 * contorted like /[ \t]*\n+/
3062 */
3063 text = text.replace(/^[ \t]+$/mg, '');
3064
3065 //run languageExtensions
3066 showdown.helper.forEach(langExtensions, function (ext) {
3067 text = showdown.subParser('runExtension')(ext, text, options, globals);
3068 });
3069
3070 // run the sub parsers
3071 text = showdown.subParser('metadata')(text, options, globals);
3072 text = showdown.subParser('hashPreCodeTags')(text, options, globals);
3073 text = showdown.subParser('githubCodeBlocks')(text, options, globals);
3074 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3075 text = showdown.subParser('hashCodeTags')(text, options, globals);
3076 text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
3077 text = showdown.subParser('blockGamut')(text, options, globals);
3078 text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
3079 text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
3080
3081 // attacklab: Restore dollar signs
3082 text = text.replace(/¨D/g, '$$');
3083
3084 // attacklab: Restore tremas
3085 text = text.replace(/¨T/g, '¨');
3086
3087 // render a complete html document instead of a partial if the option is enabled
3088 text = showdown.subParser('completeHTMLDocument')(text, options, globals);
3089
3090 // Run output modifiers
3091 showdown.helper.forEach(outputModifiers, function (ext) {
3092 text = showdown.subParser('runExtension')(ext, text, options, globals);
3093 });
3094
3095 // update metadata
3096 metadata = globals.metadata;
3097 return text;
3098 };
3099
3100 /**
3101 * Converts an HTML string into a markdown string
3102 * @param src
3103 * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
3104 * @returns {string}
3105 */
3106 this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
3107
3108 // replace \r\n with \n
3109 src = src.replace(/\r\n/g, '\n');
3110 src = src.replace(/\r/g, '\n'); // old macs
3111
3112 // due to an edge case, we need to find this: > <
3113 // to prevent removing of non silent white spaces
3114 // ex: <em>this is</em> <strong>sparta</strong>
3115 src = src.replace(/>[ \t]+</, '>¨NBSP;<');
3116
3117 if (!HTMLParser) {
3118 if (window && window.document) {
3119 HTMLParser = window.document;
3120 } else {
3121 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');
3122 }
3123 }
3124
3125 var doc = HTMLParser.createElement('div');
3126 doc.innerHTML = src;
3127
3128 var globals = {
3129 preList: substitutePreCodeTags(doc)
3130 };
3131
3132 // remove all newlines and collapse spaces
3133 clean(doc);
3134
3135 // some stuff, like accidental reference links must now be escaped
3136 // TODO
3137 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
3138
3139 var nodes = doc.childNodes,
3140 mdDoc = '';
3141
3142 for (var i = 0; i < nodes.length; i++) {
3143 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
3144 }
3145
3146 function clean (node) {
3147 for (var n = 0; n < node.childNodes.length; ++n) {
3148 var child = node.childNodes[n];
3149 if (child.nodeType === 3) {
3150 if (!/\S/.test(child.nodeValue)) {
3151 node.removeChild(child);
3152 --n;
3153 } else {
3154 child.nodeValue = child.nodeValue.split('\n').join(' ');
3155 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
3156 }
3157 } else if (child.nodeType === 1) {
3158 clean(child);
3159 }
3160 }
3161 }
3162
3163 // find all pre tags and replace contents with placeholder
3164 // we need this so that we can remove all indentation from html
3165 // to ease up parsing
3166 function substitutePreCodeTags (doc) {
3167
3168 var pres = doc.querySelectorAll('pre'),
3169 presPH = [];
3170
3171 for (var i = 0; i < pres.length; ++i) {
3172
3173 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
3174 var content = pres[i].firstChild.innerHTML.trim(),
3175 language = pres[i].firstChild.getAttribute('data-language') || '';
3176
3177 // if data-language attribute is not defined, then we look for class language-*
3178 if (language === '') {
3179 var classes = pres[i].firstChild.className.split(' ');
3180 for (var c = 0; c < classes.length; ++c) {
3181 var matches = classes[c].match(/^language-(.+)$/);
3182 if (matches !== null) {
3183 language = matches[1];
3184 break;
3185 }
3186 }
3187 }
3188
3189 // unescape html entities in content
3190 content = showdown.helper.unescapeHTMLEntities(content);
3191
3192 presPH.push(content);
3193 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
3194 } else {
3195 presPH.push(pres[i].innerHTML);
3196 pres[i].innerHTML = '';
3197 pres[i].setAttribute('prenum', i.toString());
3198 }
3199 }
3200 return presPH;
3201 }
3202
3203 return mdDoc;
3204 };
3205
3206 /**
3207 * Set an option of this Converter instance
3208 * @param {string} key
3209 * @param {*} value
3210 */
3211 this.setOption = function (key, value) {
3212 options[key] = value;
3213 };
3214
3215 /**
3216 * Get the option of this Converter instance
3217 * @param {string} key
3218 * @returns {*}
3219 */
3220 this.getOption = function (key) {
3221 return options[key];
3222 };
3223
3224 /**
3225 * Get the options of this Converter instance
3226 * @returns {{}}
3227 */
3228 this.getOptions = function () {
3229 return options;
3230 };
3231
3232 /**
3233 * Add extension to THIS converter
3234 * @param {{}} extension
3235 * @param {string} [name=null]
3236 */
3237 this.addExtension = function (extension, name) {
3238 name = name || null;
3239 _parseExtension(extension, name);
3240 };
3241
3242 /**
3243 * Use a global registered extension with THIS converter
3244 * @param {string} extensionName Name of the previously registered extension
3245 */
3246 this.useExtension = function (extensionName) {
3247 _parseExtension(extensionName);
3248 };
3249
3250 /**
3251 * Set the flavor THIS converter should use
3252 * @param {string} name
3253 */
3254 this.setFlavor = function (name) {
3255 if (!flavor.hasOwnProperty(name)) {
3256 throw Error(name + ' flavor was not found');
3257 }
3258 var preset = flavor[name];
3259 setConvFlavor = name;
3260 for (var option in preset) {
3261 if (preset.hasOwnProperty(option)) {
3262 options[option] = preset[option];
3263 }
3264 }
3265 };
3266
3267 /**
3268 * Get the currently set flavor of this converter
3269 * @returns {string}
3270 */
3271 this.getFlavor = function () {
3272 return setConvFlavor;
3273 };
3274
3275 /**
3276 * Remove an extension from THIS converter.
3277 * Note: This is a costly operation. It's better to initialize a new converter
3278 * and specify the extensions you wish to use
3279 * @param {Array} extension
3280 */
3281 this.removeExtension = function (extension) {
3282 if (!showdown.helper.isArray(extension)) {
3283 extension = [extension];
3284 }
3285 for (var a = 0; a < extension.length; ++a) {
3286 var ext = extension[a];
3287 for (var i = 0; i < langExtensions.length; ++i) {
3288 if (langExtensions[i] === ext) {
3289 langExtensions[i].splice(i, 1);
3290 }
3291 }
3292 for (var ii = 0; ii < outputModifiers.length; ++i) {
3293 if (outputModifiers[ii] === ext) {
3294 outputModifiers[ii].splice(i, 1);
3295 }
3296 }
3297 }
3298 };
3299
3300 /**
3301 * Get all extension of THIS converter
3302 * @returns {{language: Array, output: Array}}
3303 */
3304 this.getAllExtensions = function () {
3305 return {
3306 language: langExtensions,
3307 output: outputModifiers
3308 };
3309 };
3310
3311 /**
3312 * Get the metadata of the previously parsed document
3313 * @param raw
3314 * @returns {string|{}}
3315 */
3316 this.getMetadata = function (raw) {
3317 if (raw) {
3318 return metadata.raw;
3319 } else {
3320 return metadata.parsed;
3321 }
3322 };
3323
3324 /**
3325 * Get the metadata format of the previously parsed document
3326 * @returns {string}
3327 */
3328 this.getMetadataFormat = function () {
3329 return metadata.format;
3330 };
3331
3332 /**
3333 * Private: set a single key, value metadata pair
3334 * @param {string} key
3335 * @param {string} value
3336 */
3337 this._setMetadataPair = function (key, value) {
3338 metadata.parsed[key] = value;
3339 };
3340
3341 /**
3342 * Private: set metadata format
3343 * @param {string} format
3344 */
3345 this._setMetadataFormat = function (format) {
3346 metadata.format = format;
3347 };
3348
3349 /**
3350 * Private: set metadata raw text
3351 * @param {string} raw
3352 */
3353 this._setMetadataRaw = function (raw) {
3354 metadata.raw = raw;
3355 };
3356 };
3357
3358 /**
3359 * Turn Markdown link shortcuts into XHTML <a> tags.
3360 */
3361 showdown.subParser('anchors', function (text, options, globals) {
3362 'use strict';
3363
3364 text = globals.converter._dispatch('anchors.before', text, options, globals);
3365
3366 var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
3367 if (showdown.helper.isUndefined(title)) {
3368 title = '';
3369 }
3370 linkId = linkId.toLowerCase();
3371
3372 // Special case for explicit empty url
3373 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3374 url = '';
3375 } else if (!url) {
3376 if (!linkId) {
3377 // lower-case and turn embedded newlines into spaces
3378 linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
3379 }
3380 url = '#' + linkId;
3381
3382 if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
3383 url = globals.gUrls[linkId];
3384 if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
3385 title = globals.gTitles[linkId];
3386 }
3387 } else {
3388 return wholeMatch;
3389 }
3390 }
3391
3392 //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
3393 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3394
3395 var result = '<a href="' + url + '"';
3396
3397 if (title !== '' && title !== null) {
3398 title = title.replace(/"/g, '&quot;');
3399 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3400 title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3401 result += ' title="' + title + '"';
3402 }
3403
3404 // optionLinksInNewWindow only applies
3405 // to external links. Hash links (#) open in same page
3406 if (options.openLinksInNewWindow && !/^#/.test(url)) {
3407 // escaped _
3408 result += ' rel="noopener noreferrer" target="¨E95Eblank"';
3409 }
3410
3411 result += '>' + linkText + '</a>';
3412
3413 return result;
3414 };
3415
3416 // First, handle reference-style links: [link text] [id]
3417 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
3418
3419 // Next, inline-style links: [link text](url "optional title")
3420 // cases with crazy urls like ./image/cat1).png
3421 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3422 writeAnchorTag);
3423
3424 // normal cases
3425 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3426 writeAnchorTag);
3427
3428 // handle reference-style shortcuts: [link text]
3429 // These must come last in case you've also got [link test][1]
3430 // or [link test](/foo)
3431 text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
3432
3433 // Lastly handle GithubMentions if option is enabled
3434 if (options.ghMentions) {
3435 text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
3436 if (escape === '\\') {
3437 return st + mentions;
3438 }
3439
3440 //check if options.ghMentionsLink is a string
3441 if (!showdown.helper.isString(options.ghMentionsLink)) {
3442 throw new Error('ghMentionsLink option must be a string');
3443 }
3444 var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
3445 target = '';
3446 if (options.openLinksInNewWindow) {
3447 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3448 }
3449 return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
3450 });
3451 }
3452
3453 text = globals.converter._dispatch('anchors.after', text, options, globals);
3454 return text;
3455 });
3456
3457 // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
3458
3459 var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
3460 simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
3461 delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
3462 simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
3463 delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
3464
3465 replaceLink = function (options) {
3466 'use strict';
3467 return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
3468 link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3469 var lnkTxt = link,
3470 append = '',
3471 target = '',
3472 lmc = leadingMagicChars || '',
3473 tmc = trailingMagicChars || '';
3474 if (/^www\./i.test(link)) {
3475 link = link.replace(/^www\./i, 'http://www.');
3476 }
3477 if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
3478 append = trailingPunctuation;
3479 }
3480 if (options.openLinksInNewWindow) {
3481 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3482 }
3483 return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
3484 };
3485 },
3486
3487 replaceMail = function (options, globals) {
3488 'use strict';
3489 return function (wholeMatch, b, mail) {
3490 var href = 'mailto:';
3491 b = b || '';
3492 mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
3493 if (options.encodeEmails) {
3494 href = showdown.helper.encodeEmailAddress(href + mail);
3495 mail = showdown.helper.encodeEmailAddress(mail);
3496 } else {
3497 href = href + mail;
3498 }
3499 return b + '<a href="' + href + '">' + mail + '</a>';
3500 };
3501 };
3502
3503 showdown.subParser('autoLinks', function (text, options, globals) {
3504 'use strict';
3505
3506 text = globals.converter._dispatch('autoLinks.before', text, options, globals);
3507
3508 text = text.replace(delimUrlRegex, replaceLink(options));
3509 text = text.replace(delimMailRegex, replaceMail(options, globals));
3510
3511 text = globals.converter._dispatch('autoLinks.after', text, options, globals);
3512
3513 return text;
3514 });
3515
3516 showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
3517 'use strict';
3518
3519 if (!options.simplifiedAutoLink) {
3520 return text;
3521 }
3522
3523 text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
3524
3525 if (options.excludeTrailingPunctuationFromURLs) {
3526 text = text.replace(simpleURLRegex2, replaceLink(options));
3527 } else {
3528 text = text.replace(simpleURLRegex, replaceLink(options));
3529 }
3530 text = text.replace(simpleMailRegex, replaceMail(options, globals));
3531
3532 text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
3533
3534 return text;
3535 });
3536
3537 /**
3538 * These are all the transformations that form block-level
3539 * tags like paragraphs, headers, and list items.
3540 */
3541 showdown.subParser('blockGamut', function (text, options, globals) {
3542 'use strict';
3543
3544 text = globals.converter._dispatch('blockGamut.before', text, options, globals);
3545
3546 // we parse blockquotes first so that we can have headings and hrs
3547 // inside blockquotes
3548 text = showdown.subParser('blockQuotes')(text, options, globals);
3549 text = showdown.subParser('headers')(text, options, globals);
3550
3551 // Do Horizontal Rules:
3552 text = showdown.subParser('horizontalRule')(text, options, globals);
3553
3554 text = showdown.subParser('lists')(text, options, globals);
3555 text = showdown.subParser('codeBlocks')(text, options, globals);
3556 text = showdown.subParser('tables')(text, options, globals);
3557
3558 // We already ran _HashHTMLBlocks() before, in Markdown(), but that
3559 // was to escape raw HTML in the original Markdown source. This time,
3560 // we're escaping the markup we've just created, so that we don't wrap
3561 // <p> tags around block-level tags.
3562 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3563 text = showdown.subParser('paragraphs')(text, options, globals);
3564
3565 text = globals.converter._dispatch('blockGamut.after', text, options, globals);
3566
3567 return text;
3568 });
3569
3570 showdown.subParser('blockQuotes', function (text, options, globals) {
3571 'use strict';
3572
3573 text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
3574
3575 // add a couple extra lines after the text and endtext mark
3576 text = text + '\n\n';
3577
3578 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
3579
3580 if (options.splitAdjacentBlockquotes) {
3581 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
3582 }
3583
3584 text = text.replace(rgx, function (bq) {
3585 // attacklab: hack around Konqueror 3.5.4 bug:
3586 // "----------bug".replace(/^-/g,"") == "bug"
3587 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
3588
3589 // attacklab: clean up hack
3590 bq = bq.replace(/¨0/g, '');
3591
3592 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
3593 bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
3594 bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
3595
3596 bq = bq.replace(/(^|\n)/g, '$1 ');
3597 // These leading spaces screw with <pre> content, so we need to fix that:
3598 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
3599 var pre = m1;
3600 // attacklab: hack around Konqueror 3.5.4 bug:
3601 pre = pre.replace(/^ /mg, '¨0');
3602 pre = pre.replace(/¨0/g, '');
3603 return pre;
3604 });
3605
3606 return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
3607 });
3608
3609 text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
3610 return text;
3611 });
3612
3613 /**
3614 * Process Markdown `<pre><code>` blocks.
3615 */
3616 showdown.subParser('codeBlocks', function (text, options, globals) {
3617 'use strict';
3618
3619 text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
3620
3621 // sentinel workarounds for lack of \A and \Z, safari\khtml bug
3622 text += '¨0';
3623
3624 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
3625 text = text.replace(pattern, function (wholeMatch, m1, m2) {
3626 var codeblock = m1,
3627 nextChar = m2,
3628 end = '\n';
3629
3630 codeblock = showdown.subParser('outdent')(codeblock, options, globals);
3631 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3632 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3633 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3634 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
3635
3636 if (options.omitExtraWLInCodeBlocks) {
3637 end = '';
3638 }
3639
3640 codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
3641
3642 return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
3643 });
3644
3645 // strip sentinel
3646 text = text.replace(/¨0/, '');
3647
3648 text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
3649 return text;
3650 });
3651
3652 /**
3653 *
3654 * * Backtick quotes are used for <code></code> spans.
3655 *
3656 * * You can use multiple backticks as the delimiters if you want to
3657 * include literal backticks in the code span. So, this input:
3658 *
3659 * Just type ``foo `bar` baz`` at the prompt.
3660 *
3661 * Will translate to:
3662 *
3663 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
3664 *
3665 * There's no arbitrary limit to the number of backticks you
3666 * can use as delimters. If you need three consecutive backticks
3667 * in your code, use four for delimiters, etc.
3668 *
3669 * * You can use spaces to get literal backticks at the edges:
3670 *
3671 * ... type `` `bar` `` ...
3672 *
3673 * Turns to:
3674 *
3675 * ... type <code>`bar`</code> ...
3676 */
3677 showdown.subParser('codeSpans', function (text, options, globals) {
3678 'use strict';
3679
3680 text = globals.converter._dispatch('codeSpans.before', text, options, globals);
3681
3682 if (typeof text === 'undefined') {
3683 text = '';
3684 }
3685 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
3686 function (wholeMatch, m1, m2, m3) {
3687 var c = m3;
3688 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
3689 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
3690 c = showdown.subParser('encodeCode')(c, options, globals);
3691 c = m1 + '<code>' + c + '</code>';
3692 c = showdown.subParser('hashHTMLSpans')(c, options, globals);
3693 return c;
3694 }
3695 );
3696
3697 text = globals.converter._dispatch('codeSpans.after', text, options, globals);
3698 return text;
3699 });
3700
3701 /**
3702 * Create a full HTML document from the processed markdown
3703 */
3704 showdown.subParser('completeHTMLDocument', function (text, options, globals) {
3705 'use strict';
3706
3707 if (!options.completeHTMLDocument) {
3708 return text;
3709 }
3710
3711 text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
3712
3713 var doctype = 'html',
3714 doctypeParsed = '<!DOCTYPE HTML>\n',
3715 title = '',
3716 charset = '<meta charset="utf-8">\n',
3717 lang = '',
3718 metadata = '';
3719
3720 if (typeof globals.metadata.parsed.doctype !== 'undefined') {
3721 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n';
3722 doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
3723 if (doctype === 'html' || doctype === 'html5') {
3724 charset = '<meta charset="utf-8">';
3725 }
3726 }
3727
3728 for (var meta in globals.metadata.parsed) {
3729 if (globals.metadata.parsed.hasOwnProperty(meta)) {
3730 switch (meta.toLowerCase()) {
3731 case 'doctype':
3732 break;
3733
3734 case 'title':
3735 title = '<title>' + globals.metadata.parsed.title + '</title>\n';
3736 break;
3737
3738 case 'charset':
3739 if (doctype === 'html' || doctype === 'html5') {
3740 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
3741 } else {
3742 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
3743 }
3744 break;
3745
3746 case 'language':
3747 case 'lang':
3748 lang = ' lang="' + globals.metadata.parsed[meta] + '"';
3749 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3750 break;
3751
3752 default:
3753 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3754 }
3755 }
3756 }
3757
3758 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
3759
3760 text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
3761 return text;
3762 });
3763
3764 /**
3765 * Convert all tabs to spaces
3766 */
3767 showdown.subParser('detab', function (text, options, globals) {
3768 'use strict';
3769 text = globals.converter._dispatch('detab.before', text, options, globals);
3770
3771 // expand first n-1 tabs
3772 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
3773
3774 // replace the nth with two sentinels
3775 text = text.replace(/\t/g, '¨A¨B');
3776
3777 // use the sentinel to anchor our regex so it doesn't explode
3778 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
3779 var leadingText = m1,
3780 numSpaces = 4 - leadingText.length % 4; // g_tab_width
3781
3782 // there *must* be a better way to do this:
3783 for (var i = 0; i < numSpaces; i++) {
3784 leadingText += ' ';
3785 }
3786
3787 return leadingText;
3788 });
3789
3790 // clean up sentinels
3791 text = text.replace(/¨A/g, ' '); // g_tab_width
3792 text = text.replace(/¨B/g, '');
3793
3794 text = globals.converter._dispatch('detab.after', text, options, globals);
3795 return text;
3796 });
3797
3798 showdown.subParser('ellipsis', function (text, options, globals) {
3799 'use strict';
3800
3801 text = globals.converter._dispatch('ellipsis.before', text, options, globals);
3802
3803 text = text.replace(/\.\.\./g, '…');
3804
3805 text = globals.converter._dispatch('ellipsis.after', text, options, globals);
3806
3807 return text;
3808 });
3809
3810 /**
3811 * Turn emoji codes into emojis
3812 *
3813 * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
3814 */
3815 showdown.subParser('emoji', function (text, options, globals) {
3816 'use strict';
3817
3818 if (!options.emoji) {
3819 return text;
3820 }
3821
3822 text = globals.converter._dispatch('emoji.before', text, options, globals);
3823
3824 var emojiRgx = /:([\S]+?):/g;
3825
3826 text = text.replace(emojiRgx, function (wm, emojiCode) {
3827 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
3828 return showdown.helper.emojis[emojiCode];
3829 }
3830 return wm;
3831 });
3832
3833 text = globals.converter._dispatch('emoji.after', text, options, globals);
3834
3835 return text;
3836 });
3837
3838 /**
3839 * Smart processing for ampersands and angle brackets that need to be encoded.
3840 */
3841 showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
3842 'use strict';
3843 text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
3844
3845 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
3846 // http://bumppo.net/projects/amputator/
3847 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
3848
3849 // Encode naked <'s
3850 text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3851
3852 // Encode <
3853 text = text.replace(/</g, '&lt;');
3854
3855 // Encode >
3856 text = text.replace(/>/g, '&gt;');
3857
3858 text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
3859 return text;
3860 });
3861
3862 /**
3863 * Returns the string, with after processing the following backslash escape sequences.
3864 *
3865 * attacklab: The polite way to do this is with the new escapeCharacters() function:
3866 *
3867 * text = escapeCharacters(text,"\\",true);
3868 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
3869 *
3870 * ...but we're sidestepping its use of the (slow) RegExp constructor
3871 * as an optimization for Firefox. This function gets called a LOT.
3872 */
3873 showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
3874 'use strict';
3875 text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
3876
3877 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
3878 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
3879
3880 text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
3881 return text;
3882 });
3883
3884 /**
3885 * Encode/escape certain characters inside Markdown code runs.
3886 * The point is that in code, these characters are literals,
3887 * and lose their special Markdown meanings.
3888 */
3889 showdown.subParser('encodeCode', function (text, options, globals) {
3890 'use strict';
3891
3892 text = globals.converter._dispatch('encodeCode.before', text, options, globals);
3893
3894 // Encode all ampersands; HTML entities are not
3895 // entities within a Markdown code span.
3896 text = text
3897 .replace(/&/g, '&amp;')
3898 // Do the angle bracket song and dance:
3899 .replace(/</g, '&lt;')
3900 .replace(/>/g, '&gt;')
3901 // Now, escape characters that are magic in Markdown:
3902 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
3903
3904 text = globals.converter._dispatch('encodeCode.after', text, options, globals);
3905 return text;
3906 });
3907
3908 /**
3909 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
3910 * don't conflict with their use in Markdown for code, italics and strong.
3911 */
3912 showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
3913 'use strict';
3914 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
3915
3916 // Build a regex to find HTML tags.
3917 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
3918 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
3919
3920 text = text.replace(tags, function (wholeMatch) {
3921 return wholeMatch
3922 .replace(/(.)<\/?code>(?=.)/g, '$1`')
3923 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3924 });
3925
3926 text = text.replace(comments, function (wholeMatch) {
3927 return wholeMatch
3928 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3929 });
3930
3931 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
3932 return text;
3933 });
3934
3935 /**
3936 * Handle github codeblocks prior to running HashHTML so that
3937 * HTML contained within the codeblock gets escaped properly
3938 * Example:
3939 * ```ruby
3940 * def hello_world(x)
3941 * puts "Hello, #{x}"
3942 * end
3943 * ```
3944 */
3945 showdown.subParser('githubCodeBlocks', function (text, options, globals) {
3946 'use strict';
3947
3948 // early exit if option is not enabled
3949 if (!options.ghCodeBlocks) {
3950 return text;
3951 }
3952
3953 text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
3954
3955 text += '¨0';
3956
3957 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
3958 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
3959
3960 // First parse the github code block
3961 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3962 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3963 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3964 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
3965
3966 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
3967
3968 codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
3969
3970 // Since GHCodeblocks can be false positives, we need to
3971 // store the primitive text and the parsed text in a global var,
3972 // and then return a token
3973 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
3974 });
3975
3976 // attacklab: strip sentinel
3977 text = text.replace(/¨0/, '');
3978
3979 return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
3980 });
3981
3982 showdown.subParser('hashBlock', function (text, options, globals) {
3983 'use strict';
3984 text = globals.converter._dispatch('hashBlock.before', text, options, globals);
3985 text = text.replace(/(^\n+|\n+$)/g, '');
3986 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
3987 text = globals.converter._dispatch('hashBlock.after', text, options, globals);
3988 return text;
3989 });
3990
3991 /**
3992 * Hash and escape <code> elements that should not be parsed as markdown
3993 */
3994 showdown.subParser('hashCodeTags', function (text, options, globals) {
3995 'use strict';
3996 text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
3997
3998 var repFunc = function (wholeMatch, match, left, right) {
3999 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4000 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
4001 };
4002
4003 // Hash naked <code>
4004 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
4005
4006 text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
4007 return text;
4008 });
4009
4010 showdown.subParser('hashElement', function (text, options, globals) {
4011 'use strict';
4012
4013 return function (wholeMatch, m1) {
4014 var blockText = m1;
4015
4016 // Undo double lines
4017 blockText = blockText.replace(/\n\n/g, '\n');
4018 blockText = blockText.replace(/^\n/, '');
4019
4020 // strip trailing blank lines
4021 blockText = blockText.replace(/\n+$/g, '');
4022
4023 // Replace the element text with a marker ("¨KxK" where x is its key)
4024 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
4025
4026 return blockText;
4027 };
4028 });
4029
4030 showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
4031 'use strict';
4032 text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
4033
4034 var blockTags = [
4035 'pre',
4036 'div',
4037 'h1',
4038 'h2',
4039 'h3',
4040 'h4',
4041 'h5',
4042 'h6',
4043 'blockquote',
4044 'table',
4045 'dl',
4046 'ol',
4047 'ul',
4048 'script',
4049 'noscript',
4050 'form',
4051 'fieldset',
4052 'iframe',
4053 'math',
4054 'style',
4055 'section',
4056 'header',
4057 'footer',
4058 'nav',
4059 'article',
4060 'aside',
4061 'address',
4062 'audio',
4063 'canvas',
4064 'figure',
4065 'hgroup',
4066 'output',
4067 'video',
4068 'p'
4069 ],
4070 repFunc = function (wholeMatch, match, left, right) {
4071 var txt = wholeMatch;
4072 // check if this html element is marked as markdown
4073 // if so, it's contents should be parsed as markdown
4074 if (left.search(/\bmarkdown\b/) !== -1) {
4075 txt = left + globals.converter.makeHtml(match) + right;
4076 }
4077 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4078 };
4079
4080 if (options.backslashEscapesHTMLTags) {
4081 // encode backslash escaped HTML tags
4082 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
4083 return '&lt;' + inside + '&gt;';
4084 });
4085 }
4086
4087 // hash HTML Blocks
4088 for (var i = 0; i < blockTags.length; ++i) {
4089
4090 var opTagPos,
4091 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
4092 patLeft = '<' + blockTags[i] + '\\b[^>]*>',
4093 patRight = '</' + blockTags[i] + '>';
4094 // 1. Look for the first position of the first opening HTML tag in the text
4095 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
4096
4097 // if the HTML tag is \ escaped, we need to escape it and break
4098
4099
4100 //2. Split the text in that position
4101 var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
4102 //3. Match recursively
4103 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
4104
4105 // prevent an infinite loop
4106 if (newSubText1 === subTexts[1]) {
4107 break;
4108 }
4109 text = subTexts[0].concat(newSubText1);
4110 }
4111 }
4112 // HR SPECIAL CASE
4113 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
4114 showdown.subParser('hashElement')(text, options, globals));
4115
4116 // Special case for standalone HTML comments
4117 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
4118 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4119 }, '^ {0,3}<!--', '-->', 'gm');
4120
4121 // PHP and ASP-style processor instructions (<?...?> and <%...%>)
4122 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
4123 showdown.subParser('hashElement')(text, options, globals));
4124
4125 text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
4126 return text;
4127 });
4128
4129 /**
4130 * Hash span elements that should not be parsed as markdown
4131 */
4132 showdown.subParser('hashHTMLSpans', function (text, options, globals) {
4133 'use strict';
4134 text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
4135
4136 function hashHTMLSpan (html) {
4137 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
4138 }
4139
4140 // Hash Self Closing tags
4141 text = text.replace(/<[^>]+?\/>/gi, function (wm) {
4142 return hashHTMLSpan(wm);
4143 });
4144
4145 // Hash tags without properties
4146 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
4147 return hashHTMLSpan(wm);
4148 });
4149
4150 // Hash tags with properties
4151 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
4152 return hashHTMLSpan(wm);
4153 });
4154
4155 // Hash self closing tags without />
4156 text = text.replace(/<[^>]+?>/gi, function (wm) {
4157 return hashHTMLSpan(wm);
4158 });
4159
4160 /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
4161
4162 text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
4163 return text;
4164 });
4165
4166 /**
4167 * Unhash HTML spans
4168 */
4169 showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
4170 'use strict';
4171 text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
4172
4173 for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
4174 var repText = globals.gHtmlSpans[i],
4175 // limiter to prevent infinite loop (assume 10 as limit for recurse)
4176 limit = 0;
4177
4178 while (/¨C(\d+)C/.test(repText)) {
4179 var num = RegExp.$1;
4180 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
4181 if (limit === 10) {
4182 console.error('maximum nesting of 10 spans reached!!!');
4183 break;
4184 }
4185 ++limit;
4186 }
4187 text = text.replace('¨C' + i + 'C', repText);
4188 }
4189
4190 text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
4191 return text;
4192 });
4193
4194 /**
4195 * Hash and escape <pre><code> elements that should not be parsed as markdown
4196 */
4197 showdown.subParser('hashPreCodeTags', function (text, options, globals) {
4198 'use strict';
4199 text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
4200
4201 var repFunc = function (wholeMatch, match, left, right) {
4202 // encode html entities
4203 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4204 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
4205 };
4206
4207 // Hash <pre><code>
4208 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
4209
4210 text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
4211 return text;
4212 });
4213
4214 showdown.subParser('headers', function (text, options, globals) {
4215 'use strict';
4216
4217 text = globals.converter._dispatch('headers.before', text, options, globals);
4218
4219 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
4220
4221 // Set text-style headers:
4222 // Header 1
4223 // ========
4224 //
4225 // Header 2
4226 // --------
4227 //
4228 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
4229 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
4230
4231 text = text.replace(setextRegexH1, function (wholeMatch, m1) {
4232
4233 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4234 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4235 hLevel = headerLevelStart,
4236 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4237 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4238 });
4239
4240 text = text.replace(setextRegexH2, function (matchFound, m1) {
4241 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4242 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4243 hLevel = headerLevelStart + 1,
4244 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4245 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4246 });
4247
4248 // atx-style headers:
4249 // # Header 1
4250 // ## Header 2
4251 // ## Header 2 with closing hashes ##
4252 // ...
4253 // ###### Header 6
4254 //
4255 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
4256
4257 text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
4258 var hText = m2;
4259 if (options.customizedHeaderId) {
4260 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
4261 }
4262
4263 var span = showdown.subParser('spanGamut')(hText, options, globals),
4264 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
4265 hLevel = headerLevelStart - 1 + m1.length,
4266 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
4267
4268 return showdown.subParser('hashBlock')(header, options, globals);
4269 });
4270
4271 function headerId (m) {
4272 var title,
4273 prefix;
4274
4275 // It is separate from other options to allow combining prefix and customized
4276 if (options.customizedHeaderId) {
4277 var match = m.match(/\{([^{]+?)}\s*$/);
4278 if (match && match[1]) {
4279 m = match[1];
4280 }
4281 }
4282
4283 title = m;
4284
4285 // Prefix id to prevent causing inadvertent pre-existing style matches.
4286 if (showdown.helper.isString(options.prefixHeaderId)) {
4287 prefix = options.prefixHeaderId;
4288 } else if (options.prefixHeaderId === true) {
4289 prefix = 'section-';
4290 } else {
4291 prefix = '';
4292 }
4293
4294 if (!options.rawPrefixHeaderId) {
4295 title = prefix + title;
4296 }
4297
4298 if (options.ghCompatibleHeaderId) {
4299 title = title
4300 .replace(/ /g, '-')
4301 // replace previously escaped chars (&, ¨ and $)
4302 .replace(/&amp;/g, '')
4303 .replace(/¨T/g, '')
4304 .replace(/¨D/g, '')
4305 // replace rest of the chars (&~$ are repeated as they might have been escaped)
4306 // borrowed from github's redcarpet (some they should produce similar results)
4307 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
4308 .toLowerCase();
4309 } else if (options.rawHeaderId) {
4310 title = title
4311 .replace(/ /g, '-')
4312 // replace previously escaped chars (&, ¨ and $)
4313 .replace(/&amp;/g, '&')
4314 .replace(/¨T/g, '¨')
4315 .replace(/¨D/g, '$')
4316 // replace " and '
4317 .replace(/["']/g, '-')
4318 .toLowerCase();
4319 } else {
4320 title = title
4321 .replace(/[^\w]/g, '')
4322 .toLowerCase();
4323 }
4324
4325 if (options.rawPrefixHeaderId) {
4326 title = prefix + title;
4327 }
4328
4329 if (globals.hashLinkCounts[title]) {
4330 title = title + '-' + (globals.hashLinkCounts[title]++);
4331 } else {
4332 globals.hashLinkCounts[title] = 1;
4333 }
4334 return title;
4335 }
4336
4337 text = globals.converter._dispatch('headers.after', text, options, globals);
4338 return text;
4339 });
4340
4341 /**
4342 * Turn Markdown link shortcuts into XHTML <a> tags.
4343 */
4344 showdown.subParser('horizontalRule', function (text, options, globals) {
4345 'use strict';
4346 text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
4347
4348 var key = showdown.subParser('hashBlock')('<hr />', options, globals);
4349 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
4350 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
4351 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
4352
4353 text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
4354 return text;
4355 });
4356
4357 /**
4358 * Turn Markdown image shortcuts into <img> tags.
4359 */
4360 showdown.subParser('images', function (text, options, globals) {
4361 'use strict';
4362
4363 text = globals.converter._dispatch('images.before', text, options, globals);
4364
4365 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
4366 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
4367 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,
4368 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
4369 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
4370
4371 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
4372 url = url.replace(/\s/g, '');
4373 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
4374 }
4375
4376 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
4377
4378 var gUrls = globals.gUrls,
4379 gTitles = globals.gTitles,
4380 gDims = globals.gDimensions;
4381
4382 linkId = linkId.toLowerCase();
4383
4384 if (!title) {
4385 title = '';
4386 }
4387 // Special case for explicit empty url
4388 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
4389 url = '';
4390
4391 } else if (url === '' || url === null) {
4392 if (linkId === '' || linkId === null) {
4393 // lower-case and turn embedded newlines into spaces
4394 linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
4395 }
4396 url = '#' + linkId;
4397
4398 if (!showdown.helper.isUndefined(gUrls[linkId])) {
4399 url = gUrls[linkId];
4400 if (!showdown.helper.isUndefined(gTitles[linkId])) {
4401 title = gTitles[linkId];
4402 }
4403 if (!showdown.helper.isUndefined(gDims[linkId])) {
4404 width = gDims[linkId].width;
4405 height = gDims[linkId].height;
4406 }
4407 } else {
4408 return wholeMatch;
4409 }
4410 }
4411
4412 altText = altText
4413 .replace(/"/g, '&quot;')
4414 //altText = showdown.helper.escapeCharacters(altText, '*_', false);
4415 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4416 //url = showdown.helper.escapeCharacters(url, '*_', false);
4417 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4418 var result = '<img src="' + url + '" alt="' + altText + '"';
4419
4420 if (title && showdown.helper.isString(title)) {
4421 title = title
4422 .replace(/"/g, '&quot;')
4423 //title = showdown.helper.escapeCharacters(title, '*_', false);
4424 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4425 result += ' title="' + title + '"';
4426 }
4427
4428 if (width && height) {
4429 width = (width === '*') ? 'auto' : width;
4430 height = (height === '*') ? 'auto' : height;
4431
4432 result += ' width="' + width + '"';
4433 result += ' height="' + height + '"';
4434 }
4435
4436 result += ' />';
4437
4438 return result;
4439 }
4440
4441 // First, handle reference-style labeled images: ![alt text][id]
4442 text = text.replace(referenceRegExp, writeImageTag);
4443
4444 // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
4445
4446 // base64 encoded images
4447 text = text.replace(base64RegExp, writeImageTagBase64);
4448
4449 // cases with crazy urls like ./image/cat1).png
4450 text = text.replace(crazyRegExp, writeImageTag);
4451
4452 // normal cases
4453 text = text.replace(inlineRegExp, writeImageTag);
4454
4455 // handle reference-style shortcuts: ![img text]
4456 text = text.replace(refShortcutRegExp, writeImageTag);
4457
4458 text = globals.converter._dispatch('images.after', text, options, globals);
4459 return text;
4460 });
4461
4462 showdown.subParser('italicsAndBold', function (text, options, globals) {
4463 'use strict';
4464
4465 text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
4466
4467 // it's faster to have 3 separate regexes for each case than have just one
4468 // because of backtracing, in some cases, it could lead to an exponential effect
4469 // called "catastrophic backtrace". Ominous!
4470
4471 function parseInside (txt, left, right) {
4472 /*
4473 if (options.simplifiedAutoLink) {
4474 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4475 }
4476 */
4477 return left + txt + right;
4478 }
4479
4480 // Parse underscores
4481 if (options.literalMidWordUnderscores) {
4482 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4483 return parseInside (txt, '<strong><em>', '</em></strong>');
4484 });
4485 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4486 return parseInside (txt, '<strong>', '</strong>');
4487 });
4488 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
4489 return parseInside (txt, '<em>', '</em>');
4490 });
4491 } else {
4492 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4493 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4494 });
4495 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4496 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4497 });
4498 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
4499 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
4500 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4501 });
4502 }
4503
4504 // Now parse asterisks
4505 if (options.literalMidWordAsterisks) {
4506 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
4507 return parseInside (txt, lead + '<strong><em>', '</em></strong>');
4508 });
4509 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
4510 return parseInside (txt, lead + '<strong>', '</strong>');
4511 });
4512 text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
4513 return parseInside (txt, lead + '<em>', '</em>');
4514 });
4515 } else {
4516 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
4517 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4518 });
4519 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
4520 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4521 });
4522 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
4523 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
4524 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4525 });
4526 }
4527
4528
4529 text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
4530 return text;
4531 });
4532
4533 /**
4534 * Form HTML ordered (numbered) and unordered (bulleted) lists.
4535 */
4536 showdown.subParser('lists', function (text, options, globals) {
4537 'use strict';
4538
4539 /**
4540 * Process the contents of a single ordered or unordered list, splitting it
4541 * into individual list items.
4542 * @param {string} listStr
4543 * @param {boolean} trimTrailing
4544 * @returns {string}
4545 */
4546 function processListItems (listStr, trimTrailing) {
4547 // The $g_list_level global keeps track of when we're inside a list.
4548 // Each time we enter a list, we increment it; when we leave a list,
4549 // we decrement. If it's zero, we're not in a list anymore.
4550 //
4551 // We do this because when we're not inside a list, we want to treat
4552 // something like this:
4553 //
4554 // I recommend upgrading to version
4555 // 8. Oops, now this line is treated
4556 // as a sub-list.
4557 //
4558 // As a single paragraph, despite the fact that the second line starts
4559 // with a digit-period-space sequence.
4560 //
4561 // Whereas when we're inside a list (or sub-list), that line will be
4562 // treated as the start of a sub-list. What a kludge, huh? This is
4563 // an aspect of Markdown's syntax that's hard to parse perfectly
4564 // without resorting to mind-reading. Perhaps the solution is to
4565 // change the syntax rules such that sub-lists must start with a
4566 // starting cardinal number; e.g. "1." or "a.".
4567 globals.gListLevel++;
4568
4569 // trim trailing blank lines:
4570 listStr = listStr.replace(/\n{2,}$/, '\n');
4571
4572 // attacklab: add sentinel to emulate \z
4573 listStr += '¨0';
4574
4575 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
4576 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
4577
4578 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
4579 // which is a syntax breaking change
4580 // activating this option reverts to old behavior
4581 if (options.disableForced4SpacesIndentedSublists) {
4582 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
4583 }
4584
4585 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
4586 checked = (checked && checked.trim() !== '');
4587
4588 var item = showdown.subParser('outdent')(m4, options, globals),
4589 bulletStyle = '';
4590
4591 // Support for github tasklists
4592 if (taskbtn && options.tasklists) {
4593 bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
4594 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
4595 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
4596 if (checked) {
4597 otp += ' checked';
4598 }
4599 otp += '>';
4600 return otp;
4601 });
4602 }
4603
4604 // ISSUE #312
4605 // This input: - - - a
4606 // causes trouble to the parser, since it interprets it as:
4607 // <ul><li><li><li>a</li></li></li></ul>
4608 // instead of:
4609 // <ul><li>- - a</li></ul>
4610 // So, to prevent it, we will put a marker (¨A)in the beginning of the line
4611 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
4612 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
4613 return '¨A' + wm2;
4614 });
4615
4616 // m1 - Leading line or
4617 // Has a double return (multi paragraph) or
4618 // Has sublist
4619 if (m1 || (item.search(/\n{2,}/) > -1)) {
4620 item = showdown.subParser('githubCodeBlocks')(item, options, globals);
4621 item = showdown.subParser('blockGamut')(item, options, globals);
4622 } else {
4623 // Recursion for sub-lists:
4624 item = showdown.subParser('lists')(item, options, globals);
4625 item = item.replace(/\n$/, ''); // chomp(item)
4626 item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
4627
4628 // Colapse double linebreaks
4629 item = item.replace(/\n\n+/g, '\n\n');
4630 if (isParagraphed) {
4631 item = showdown.subParser('paragraphs')(item, options, globals);
4632 } else {
4633 item = showdown.subParser('spanGamut')(item, options, globals);
4634 }
4635 }
4636
4637 // now we need to remove the marker (¨A)
4638 item = item.replace('¨A', '');
4639 // we can finally wrap the line in list item tags
4640 item = '<li' + bulletStyle + '>' + item + '</li>\n';
4641
4642 return item;
4643 });
4644
4645 // attacklab: strip sentinel
4646 listStr = listStr.replace(/¨0/g, '');
4647
4648 globals.gListLevel--;
4649
4650 if (trimTrailing) {
4651 listStr = listStr.replace(/\s+$/, '');
4652 }
4653
4654 return listStr;
4655 }
4656
4657 function styleStartNumber (list, listType) {
4658 // check if ol and starts by a number different than 1
4659 if (listType === 'ol') {
4660 var res = list.match(/^ *(\d+)\./);
4661 if (res && res[1] !== '1') {
4662 return ' start="' + res[1] + '"';
4663 }
4664 }
4665 return '';
4666 }
4667
4668 /**
4669 * Check and parse consecutive lists (better fix for issue #142)
4670 * @param {string} list
4671 * @param {string} listType
4672 * @param {boolean} trimTrailing
4673 * @returns {string}
4674 */
4675 function parseConsecutiveLists (list, listType, trimTrailing) {
4676 // check if we caught 2 or more consecutive lists by mistake
4677 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
4678 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
4679 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
4680 counterRxg = (listType === 'ul') ? olRgx : ulRgx,
4681 result = '';
4682
4683 if (list.search(counterRxg) !== -1) {
4684 (function parseCL (txt) {
4685 var pos = txt.search(counterRxg),
4686 style = styleStartNumber(list, listType);
4687 if (pos !== -1) {
4688 // slice
4689 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
4690
4691 // invert counterType and listType
4692 listType = (listType === 'ul') ? 'ol' : 'ul';
4693 counterRxg = (listType === 'ul') ? olRgx : ulRgx;
4694
4695 //recurse
4696 parseCL(txt.slice(pos));
4697 } else {
4698 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
4699 }
4700 })(list);
4701 } else {
4702 var style = styleStartNumber(list, listType);
4703 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
4704 }
4705
4706 return result;
4707 }
4708
4709 /** Start of list parsing **/
4710 text = globals.converter._dispatch('lists.before', text, options, globals);
4711 // add sentinel to hack around khtml/safari bug:
4712 // http://bugs.webkit.org/show_bug.cgi?id=11231
4713 text += '¨0';
4714
4715 if (globals.gListLevel) {
4716 text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4717 function (wholeMatch, list, m2) {
4718 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4719 return parseConsecutiveLists(list, listType, true);
4720 }
4721 );
4722 } else {
4723 text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4724 function (wholeMatch, m1, list, m3) {
4725 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4726 return parseConsecutiveLists(list, listType, false);
4727 }
4728 );
4729 }
4730
4731 // strip sentinel
4732 text = text.replace(/¨0/, '');
4733 text = globals.converter._dispatch('lists.after', text, options, globals);
4734 return text;
4735 });
4736
4737 /**
4738 * Parse metadata at the top of the document
4739 */
4740 showdown.subParser('metadata', function (text, options, globals) {
4741 'use strict';
4742
4743 if (!options.metadata) {
4744 return text;
4745 }
4746
4747 text = globals.converter._dispatch('metadata.before', text, options, globals);
4748
4749 function parseMetadataContents (content) {
4750 // raw is raw so it's not changed in any way
4751 globals.metadata.raw = content;
4752
4753 // escape chars forbidden in html attributes
4754 // double quotes
4755 content = content
4756 // ampersand first
4757 .replace(/&/g, '&amp;')
4758 // double quotes
4759 .replace(/"/g, '&quot;');
4760
4761 content = content.replace(/\n {4}/g, ' ');
4762 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
4763 globals.metadata.parsed[key] = value;
4764 return '';
4765 });
4766 }
4767
4768 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
4769 parseMetadataContents(content);
4770 return '¨M';
4771 });
4772
4773 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
4774 if (format) {
4775 globals.metadata.format = format;
4776 }
4777 parseMetadataContents(content);
4778 return '¨M';
4779 });
4780
4781 text = text.replace(/¨M/g, '');
4782
4783 text = globals.converter._dispatch('metadata.after', text, options, globals);
4784 return text;
4785 });
4786
4787 /**
4788 * Remove one level of line-leading tabs or spaces
4789 */
4790 showdown.subParser('outdent', function (text, options, globals) {
4791 'use strict';
4792 text = globals.converter._dispatch('outdent.before', text, options, globals);
4793
4794 // attacklab: hack around Konqueror 3.5.4 bug:
4795 // "----------bug".replace(/^-/g,"") == "bug"
4796 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
4797
4798 // attacklab: clean up hack
4799 text = text.replace(/¨0/g, '');
4800
4801 text = globals.converter._dispatch('outdent.after', text, options, globals);
4802 return text;
4803 });
4804
4805 /**
4806 *
4807 */
4808 showdown.subParser('paragraphs', function (text, options, globals) {
4809 'use strict';
4810
4811 text = globals.converter._dispatch('paragraphs.before', text, options, globals);
4812 // Strip leading and trailing lines:
4813 text = text.replace(/^\n+/g, '');
4814 text = text.replace(/\n+$/g, '');
4815
4816 var grafs = text.split(/\n{2,}/g),
4817 grafsOut = [],
4818 end = grafs.length; // Wrap <p> tags
4819
4820 for (var i = 0; i < end; i++) {
4821 var str = grafs[i];
4822 // if this is an HTML marker, copy it
4823 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
4824 grafsOut.push(str);
4825
4826 // test for presence of characters to prevent empty lines being parsed
4827 // as paragraphs (resulting in undesired extra empty paragraphs)
4828 } else if (str.search(/\S/) >= 0) {
4829 str = showdown.subParser('spanGamut')(str, options, globals);
4830 str = str.replace(/^([ \t]*)/g, '<p>');
4831 str += '</p>';
4832 grafsOut.push(str);
4833 }
4834 }
4835
4836 /** Unhashify HTML blocks */
4837 end = grafsOut.length;
4838 for (i = 0; i < end; i++) {
4839 var blockText = '',
4840 grafsOutIt = grafsOut[i],
4841 codeFlag = false;
4842 // if this is a marker for an html block...
4843 // use RegExp.test instead of string.search because of QML bug
4844 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
4845 var delim = RegExp.$1,
4846 num = RegExp.$2;
4847
4848 if (delim === 'K') {
4849 blockText = globals.gHtmlBlocks[num];
4850 } else {
4851 // we need to check if ghBlock is a false positive
4852 if (codeFlag) {
4853 // use encoded version of all text
4854 blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4855 } else {
4856 blockText = globals.ghCodeBlocks[num].codeblock;
4857 }
4858 }
4859 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4860
4861 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4862 // Check if grafsOutIt is a pre->code
4863 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4864 codeFlag = true;
4865 }
4866 }
4867 grafsOut[i] = grafsOutIt;
4868 }
4869 text = grafsOut.join('\n');
4870 // Strip leading and trailing lines:
4871 text = text.replace(/^\n+/g, '');
4872 text = text.replace(/\n+$/g, '');
4873 return globals.converter._dispatch('paragraphs.after', text, options, globals);
4874 });
4875
4876 /**
4877 * Run extension
4878 */
4879 showdown.subParser('runExtension', function (ext, text, options, globals) {
4880 'use strict';
4881
4882 if (ext.filter) {
4883 text = ext.filter(text, globals.converter, options);
4884
4885 } else if (ext.regex) {
4886 // TODO remove this when old extension loading mechanism is deprecated
4887 var re = ext.regex;
4888 if (!(re instanceof RegExp)) {
4889 re = new RegExp(re, 'g');
4890 }
4891 text = text.replace(re, ext.replace);
4892 }
4893
4894 return text;
4895 });
4896
4897 /**
4898 * These are all the transformations that occur *within* block-level
4899 * tags like paragraphs, headers, and list items.
4900 */
4901 showdown.subParser('spanGamut', function (text, options, globals) {
4902 'use strict';
4903
4904 text = globals.converter._dispatch('spanGamut.before', text, options, globals);
4905 text = showdown.subParser('codeSpans')(text, options, globals);
4906 text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4907 text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
4908
4909 // Process anchor and image tags. Images must come first,
4910 // because ![foo][f] looks like an anchor.
4911 text = showdown.subParser('images')(text, options, globals);
4912 text = showdown.subParser('anchors')(text, options, globals);
4913
4914 // Make links out of things like `<http://example.com/>`
4915 // Must come after anchors, because you can use < and >
4916 // delimiters in inline links like [this](<url>).
4917 text = showdown.subParser('autoLinks')(text, options, globals);
4918 text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
4919 text = showdown.subParser('emoji')(text, options, globals);
4920 text = showdown.subParser('underline')(text, options, globals);
4921 text = showdown.subParser('italicsAndBold')(text, options, globals);
4922 text = showdown.subParser('strikethrough')(text, options, globals);
4923 text = showdown.subParser('ellipsis')(text, options, globals);
4924
4925 // we need to hash HTML tags inside spans
4926 text = showdown.subParser('hashHTMLSpans')(text, options, globals);
4927
4928 // now we encode amps and angles
4929 text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
4930
4931 // Do hard breaks
4932 if (options.simpleLineBreaks) {
4933 // GFM style hard breaks
4934 // only add line breaks if the text does not contain a block (special case for lists)
4935 if (!/\n\n¨K/.test(text)) {
4936 text = text.replace(/\n+/g, '<br />\n');
4937 }
4938 } else {
4939 // Vanilla hard breaks
4940 text = text.replace(/ +\n/g, '<br />\n');
4941 }
4942
4943 text = globals.converter._dispatch('spanGamut.after', text, options, globals);
4944 return text;
4945 });
4946
4947 showdown.subParser('strikethrough', function (text, options, globals) {
4948 'use strict';
4949
4950 function parseInside (txt) {
4951 if (options.simplifiedAutoLink) {
4952 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4953 }
4954 return '<del>' + txt + '</del>';
4955 }
4956
4957 if (options.strikethrough) {
4958 text = globals.converter._dispatch('strikethrough.before', text, options, globals);
4959 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
4960 text = globals.converter._dispatch('strikethrough.after', text, options, globals);
4961 }
4962
4963 return text;
4964 });
4965
4966 /**
4967 * Strips link definitions from text, stores the URLs and titles in
4968 * hash references.
4969 * Link defs are in the form: ^[id]: url "optional title"
4970 */
4971 showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
4972 'use strict';
4973
4974 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,
4975 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;
4976
4977 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
4978 text += '¨0';
4979
4980 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
4981 linkId = linkId.toLowerCase();
4982 if (url.match(/^data:.+?\/.+?;base64,/)) {
4983 // remove newlines
4984 globals.gUrls[linkId] = url.replace(/\s/g, '');
4985 } else {
4986 globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
4987 }
4988
4989 if (blankLines) {
4990 // Oops, found blank lines, so it's not a title.
4991 // Put back the parenthetical statement we stole.
4992 return blankLines + title;
4993
4994 } else {
4995 if (title) {
4996 globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
4997 }
4998 if (options.parseImgDimensions && width && height) {
4999 globals.gDimensions[linkId] = {
5000 width: width,
5001 height: height
5002 };
5003 }
5004 }
5005 // Completely remove the definition from the text
5006 return '';
5007 };
5008
5009 // first we try to find base64 link references
5010 text = text.replace(base64Regex, replaceFunc);
5011
5012 text = text.replace(regex, replaceFunc);
5013
5014 // attacklab: strip sentinel
5015 text = text.replace(/¨0/, '');
5016
5017 return text;
5018 });
5019
5020 showdown.subParser('tables', function (text, options, globals) {
5021 'use strict';
5022
5023 if (!options.tables) {
5024 return text;
5025 }
5026
5027 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
5028 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
5029 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
5030
5031 function parseStyles (sLine) {
5032 if (/^:[ \t]*--*$/.test(sLine)) {
5033 return ' style="text-align:left;"';
5034 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
5035 return ' style="text-align:right;"';
5036 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
5037 return ' style="text-align:center;"';
5038 } else {
5039 return '';
5040 }
5041 }
5042
5043 function parseHeaders (header, style) {
5044 var id = '';
5045 header = header.trim();
5046 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
5047 if (options.tablesHeaderId || options.tableHeaderId) {
5048 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
5049 }
5050 header = showdown.subParser('spanGamut')(header, options, globals);
5051
5052 return '<th' + id + style + '>' + header + '</th>\n';
5053 }
5054
5055 function parseCells (cell, style) {
5056 var subText = showdown.subParser('spanGamut')(cell, options, globals);
5057 return '<td' + style + '>' + subText + '</td>\n';
5058 }
5059
5060 function buildTable (headers, cells) {
5061 var tb = '<table>\n<thead>\n<tr>\n',
5062 tblLgn = headers.length;
5063
5064 for (var i = 0; i < tblLgn; ++i) {
5065 tb += headers[i];
5066 }
5067 tb += '</tr>\n</thead>\n<tbody>\n';
5068
5069 for (i = 0; i < cells.length; ++i) {
5070 tb += '<tr>\n';
5071 for (var ii = 0; ii < tblLgn; ++ii) {
5072 tb += cells[i][ii];
5073 }
5074 tb += '</tr>\n';
5075 }
5076 tb += '</tbody>\n</table>\n';
5077 return tb;
5078 }
5079
5080 function parseTable (rawTable) {
5081 var i, tableLines = rawTable.split('\n');
5082
5083 for (i = 0; i < tableLines.length; ++i) {
5084 // strip wrong first and last column if wrapped tables are used
5085 if (/^ {0,3}\|/.test(tableLines[i])) {
5086 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
5087 }
5088 if (/\|[ \t]*$/.test(tableLines[i])) {
5089 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
5090 }
5091 // parse code spans first, but we only support one line code spans
5092 tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
5093 }
5094
5095 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
5096 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
5097 rawCells = [],
5098 headers = [],
5099 styles = [],
5100 cells = [];
5101
5102 tableLines.shift();
5103 tableLines.shift();
5104
5105 for (i = 0; i < tableLines.length; ++i) {
5106 if (tableLines[i].trim() === '') {
5107 continue;
5108 }
5109 rawCells.push(
5110 tableLines[i]
5111 .split('|')
5112 .map(function (s) {
5113 return s.trim();
5114 })
5115 );
5116 }
5117
5118 if (rawHeaders.length < rawStyles.length) {
5119 return rawTable;
5120 }
5121
5122 for (i = 0; i < rawStyles.length; ++i) {
5123 styles.push(parseStyles(rawStyles[i]));
5124 }
5125
5126 for (i = 0; i < rawHeaders.length; ++i) {
5127 if (showdown.helper.isUndefined(styles[i])) {
5128 styles[i] = '';
5129 }
5130 headers.push(parseHeaders(rawHeaders[i], styles[i]));
5131 }
5132
5133 for (i = 0; i < rawCells.length; ++i) {
5134 var row = [];
5135 for (var ii = 0; ii < headers.length; ++ii) {
5136 if (showdown.helper.isUndefined(rawCells[i][ii])) {
5137
5138 }
5139 row.push(parseCells(rawCells[i][ii], styles[ii]));
5140 }
5141 cells.push(row);
5142 }
5143
5144 return buildTable(headers, cells);
5145 }
5146
5147 text = globals.converter._dispatch('tables.before', text, options, globals);
5148
5149 // find escaped pipe characters
5150 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
5151
5152 // parse multi column tables
5153 text = text.replace(tableRgx, parseTable);
5154
5155 // parse one column tables
5156 text = text.replace(singeColTblRgx, parseTable);
5157
5158 text = globals.converter._dispatch('tables.after', text, options, globals);
5159
5160 return text;
5161 });
5162
5163 showdown.subParser('underline', function (text, options, globals) {
5164 'use strict';
5165
5166 if (!options.underline) {
5167 return text;
5168 }
5169
5170 text = globals.converter._dispatch('underline.before', text, options, globals);
5171
5172 if (options.literalMidWordUnderscores) {
5173 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
5174 return '<u>' + txt + '</u>';
5175 });
5176 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
5177 return '<u>' + txt + '</u>';
5178 });
5179 } else {
5180 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
5181 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5182 });
5183 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
5184 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5185 });
5186 }
5187
5188 // escape remaining underscores to prevent them being parsed by italic and bold
5189 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
5190
5191 text = globals.converter._dispatch('underline.after', text, options, globals);
5192
5193 return text;
5194 });
5195
5196 /**
5197 * Swap back in all the special characters we've hidden.
5198 */
5199 showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
5200 'use strict';
5201 text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
5202
5203 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
5204 var charCodeToReplace = parseInt(m1);
5205 return String.fromCharCode(charCodeToReplace);
5206 });
5207
5208 text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
5209 return text;
5210 });
5211
5212 showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
5213 'use strict';
5214
5215 var txt = '';
5216 if (node.hasChildNodes()) {
5217 var children = node.childNodes,
5218 childrenLength = children.length;
5219
5220 for (var i = 0; i < childrenLength; ++i) {
5221 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
5222
5223 if (innerTxt === '') {
5224 continue;
5225 }
5226 txt += innerTxt;
5227 }
5228 }
5229 // cleanup
5230 txt = txt.trim();
5231 txt = '> ' + txt.split('\n').join('\n> ');
5232 return txt;
5233 });
5234
5235 showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
5236 'use strict';
5237
5238 var lang = node.getAttribute('language'),
5239 num = node.getAttribute('precodenum');
5240 return '```' + lang + '\n' + globals.preList[num] + '\n```';
5241 });
5242
5243 showdown.subParser('makeMarkdown.codeSpan', function (node) {
5244 'use strict';
5245
5246 return '`' + node.innerHTML + '`';
5247 });
5248
5249 showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
5250 'use strict';
5251
5252 var txt = '';
5253 if (node.hasChildNodes()) {
5254 txt += '*';
5255 var children = node.childNodes,
5256 childrenLength = children.length;
5257 for (var i = 0; i < childrenLength; ++i) {
5258 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5259 }
5260 txt += '*';
5261 }
5262 return txt;
5263 });
5264
5265 showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
5266 'use strict';
5267
5268 var headerMark = new Array(headerLevel + 1).join('#'),
5269 txt = '';
5270
5271 if (node.hasChildNodes()) {
5272 txt = headerMark + ' ';
5273 var children = node.childNodes,
5274 childrenLength = children.length;
5275
5276 for (var i = 0; i < childrenLength; ++i) {
5277 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5278 }
5279 }
5280 return txt;
5281 });
5282
5283 showdown.subParser('makeMarkdown.hr', function () {
5284 'use strict';
5285
5286 return '---';
5287 });
5288
5289 showdown.subParser('makeMarkdown.image', function (node) {
5290 'use strict';
5291
5292 var txt = '';
5293 if (node.hasAttribute('src')) {
5294 txt += '![' + node.getAttribute('alt') + '](';
5295 txt += '<' + node.getAttribute('src') + '>';
5296 if (node.hasAttribute('width') && node.hasAttribute('height')) {
5297 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
5298 }
5299
5300 if (node.hasAttribute('title')) {
5301 txt += ' "' + node.getAttribute('title') + '"';
5302 }
5303 txt += ')';
5304 }
5305 return txt;
5306 });
5307
5308 showdown.subParser('makeMarkdown.links', function (node, globals) {
5309 'use strict';
5310
5311 var txt = '';
5312 if (node.hasChildNodes() && node.hasAttribute('href')) {
5313 var children = node.childNodes,
5314 childrenLength = children.length;
5315 txt = '[';
5316 for (var i = 0; i < childrenLength; ++i) {
5317 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5318 }
5319 txt += '](';
5320 txt += '<' + node.getAttribute('href') + '>';
5321 if (node.hasAttribute('title')) {
5322 txt += ' "' + node.getAttribute('title') + '"';
5323 }
5324 txt += ')';
5325 }
5326 return txt;
5327 });
5328
5329 showdown.subParser('makeMarkdown.list', function (node, globals, type) {
5330 'use strict';
5331
5332 var txt = '';
5333 if (!node.hasChildNodes()) {
5334 return '';
5335 }
5336 var listItems = node.childNodes,
5337 listItemsLenght = listItems.length,
5338 listNum = node.getAttribute('start') || 1;
5339
5340 for (var i = 0; i < listItemsLenght; ++i) {
5341 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
5342 continue;
5343 }
5344
5345 // define the bullet to use in list
5346 var bullet = '';
5347 if (type === 'ol') {
5348 bullet = listNum.toString() + '. ';
5349 } else {
5350 bullet = '- ';
5351 }
5352
5353 // parse list item
5354 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
5355 ++listNum;
5356 }
5357
5358 // add comment at the end to prevent consecutive lists to be parsed as one
5359 txt += '\n<!-- -->\n';
5360 return txt.trim();
5361 });
5362
5363 showdown.subParser('makeMarkdown.listItem', function (node, globals) {
5364 'use strict';
5365
5366 var listItemTxt = '';
5367
5368 var children = node.childNodes,
5369 childrenLenght = children.length;
5370
5371 for (var i = 0; i < childrenLenght; ++i) {
5372 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5373 }
5374 // if it's only one liner, we need to add a newline at the end
5375 if (!/\n$/.test(listItemTxt)) {
5376 listItemTxt += '\n';
5377 } else {
5378 // it's multiparagraph, so we need to indent
5379 listItemTxt = listItemTxt
5380 .split('\n')
5381 .join('\n ')
5382 .replace(/^ {4}$/gm, '')
5383 .replace(/\n\n+/g, '\n\n');
5384 }
5385
5386 return listItemTxt;
5387 });
5388
5389
5390
5391 showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
5392 'use strict';
5393
5394 spansOnly = spansOnly || false;
5395
5396 var txt = '';
5397
5398 // edge case of text without wrapper paragraph
5399 if (node.nodeType === 3) {
5400 return showdown.subParser('makeMarkdown.txt')(node, globals);
5401 }
5402
5403 // HTML comment
5404 if (node.nodeType === 8) {
5405 return '<!--' + node.data + '-->\n\n';
5406 }
5407
5408 // process only node elements
5409 if (node.nodeType !== 1) {
5410 return '';
5411 }
5412
5413 var tagName = node.tagName.toLowerCase();
5414
5415 switch (tagName) {
5416
5417 //
5418 // BLOCKS
5419 //
5420 case 'h1':
5421 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
5422 break;
5423 case 'h2':
5424 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
5425 break;
5426 case 'h3':
5427 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
5428 break;
5429 case 'h4':
5430 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
5431 break;
5432 case 'h5':
5433 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
5434 break;
5435 case 'h6':
5436 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
5437 break;
5438
5439 case 'p':
5440 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
5441 break;
5442
5443 case 'blockquote':
5444 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
5445 break;
5446
5447 case 'hr':
5448 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
5449 break;
5450
5451 case 'ol':
5452 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
5453 break;
5454
5455 case 'ul':
5456 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
5457 break;
5458
5459 case 'precode':
5460 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
5461 break;
5462
5463 case 'pre':
5464 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
5465 break;
5466
5467 case 'table':
5468 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
5469 break;
5470
5471 //
5472 // SPANS
5473 //
5474 case 'code':
5475 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
5476 break;
5477
5478 case 'em':
5479 case 'i':
5480 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
5481 break;
5482
5483 case 'strong':
5484 case 'b':
5485 txt = showdown.subParser('makeMarkdown.strong')(node, globals);
5486 break;
5487
5488 case 'del':
5489 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
5490 break;
5491
5492 case 'a':
5493 txt = showdown.subParser('makeMarkdown.links')(node, globals);
5494 break;
5495
5496 case 'img':
5497 txt = showdown.subParser('makeMarkdown.image')(node, globals);
5498 break;
5499
5500 default:
5501 txt = node.outerHTML + '\n\n';
5502 }
5503
5504 // common normalization
5505 // TODO eventually
5506
5507 return txt;
5508 });
5509
5510 showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
5511 'use strict';
5512
5513 var txt = '';
5514 if (node.hasChildNodes()) {
5515 var children = node.childNodes,
5516 childrenLength = children.length;
5517 for (var i = 0; i < childrenLength; ++i) {
5518 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5519 }
5520 }
5521
5522 // some text normalization
5523 txt = txt.trim();
5524
5525 return txt;
5526 });
5527
5528 showdown.subParser('makeMarkdown.pre', function (node, globals) {
5529 'use strict';
5530
5531 var num = node.getAttribute('prenum');
5532 return '<pre>' + globals.preList[num] + '</pre>';
5533 });
5534
5535 showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
5536 'use strict';
5537
5538 var txt = '';
5539 if (node.hasChildNodes()) {
5540 txt += '~~';
5541 var children = node.childNodes,
5542 childrenLength = children.length;
5543 for (var i = 0; i < childrenLength; ++i) {
5544 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5545 }
5546 txt += '~~';
5547 }
5548 return txt;
5549 });
5550
5551 showdown.subParser('makeMarkdown.strong', function (node, globals) {
5552 'use strict';
5553
5554 var txt = '';
5555 if (node.hasChildNodes()) {
5556 txt += '**';
5557 var children = node.childNodes,
5558 childrenLength = children.length;
5559 for (var i = 0; i < childrenLength; ++i) {
5560 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5561 }
5562 txt += '**';
5563 }
5564 return txt;
5565 });
5566
5567 showdown.subParser('makeMarkdown.table', function (node, globals) {
5568 'use strict';
5569
5570 var txt = '',
5571 tableArray = [[], []],
5572 headings = node.querySelectorAll('thead>tr>th'),
5573 rows = node.querySelectorAll('tbody>tr'),
5574 i, ii;
5575 for (i = 0; i < headings.length; ++i) {
5576 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
5577 allign = '---';
5578
5579 if (headings[i].hasAttribute('style')) {
5580 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
5581 switch (style) {
5582 case 'text-align:left;':
5583 allign = ':---';
5584 break;
5585 case 'text-align:right;':
5586 allign = '---:';
5587 break;
5588 case 'text-align:center;':
5589 allign = ':---:';
5590 break;
5591 }
5592 }
5593 tableArray[0][i] = headContent.trim();
5594 tableArray[1][i] = allign;
5595 }
5596
5597 for (i = 0; i < rows.length; ++i) {
5598 var r = tableArray.push([]) - 1,
5599 cols = rows[i].getElementsByTagName('td');
5600
5601 for (ii = 0; ii < headings.length; ++ii) {
5602 var cellContent = ' ';
5603 if (typeof cols[ii] !== 'undefined') {
5604 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
5605 }
5606 tableArray[r].push(cellContent);
5607 }
5608 }
5609
5610 var cellSpacesCount = 3;
5611 for (i = 0; i < tableArray.length; ++i) {
5612 for (ii = 0; ii < tableArray[i].length; ++ii) {
5613 var strLen = tableArray[i][ii].length;
5614 if (strLen > cellSpacesCount) {
5615 cellSpacesCount = strLen;
5616 }
5617 }
5618 }
5619
5620 for (i = 0; i < tableArray.length; ++i) {
5621 for (ii = 0; ii < tableArray[i].length; ++ii) {
5622 if (i === 1) {
5623 if (tableArray[i][ii].slice(-1) === ':') {
5624 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
5625 } else {
5626 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
5627 }
5628 } else {
5629 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
5630 }
5631 }
5632 txt += '| ' + tableArray[i].join(' | ') + ' |\n';
5633 }
5634
5635 return txt.trim();
5636 });
5637
5638 showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
5639 'use strict';
5640
5641 var txt = '';
5642 if (!node.hasChildNodes()) {
5643 return '';
5644 }
5645 var children = node.childNodes,
5646 childrenLength = children.length;
5647
5648 for (var i = 0; i < childrenLength; ++i) {
5649 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
5650 }
5651 return txt.trim();
5652 });
5653
5654 showdown.subParser('makeMarkdown.txt', function (node) {
5655 'use strict';
5656
5657 var txt = node.nodeValue;
5658
5659 // multiple spaces are collapsed
5660 txt = txt.replace(/ +/g, ' ');
5661
5662 // replace the custom ¨NBSP; with a space
5663 txt = txt.replace(/¨NBSP;/g, ' ');
5664
5665 // ", <, > and & should replace escaped html entities
5666 txt = showdown.helper.unescapeHTMLEntities(txt);
5667
5668 // escape markdown magic characters
5669 // emphasis, strong and strikethrough - can appear everywhere
5670 // we also escape pipe (|) because of tables
5671 // and escape ` because of code blocks and spans
5672 txt = txt.replace(/([*_~|`])/g, '\\$1');
5673
5674 // escape > because of blockquotes
5675 txt = txt.replace(/^(\s*)>/g, '\\$1>');
5676
5677 // hash character, only troublesome at the beginning of a line because of headers
5678 txt = txt.replace(/^#/gm, '\\#');
5679
5680 // horizontal rules
5681 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
5682
5683 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
5684 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
5685
5686 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
5687 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
5688
5689 // images and links, ] followed by ( is problematic, so we escape it
5690 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
5691
5692 // reference URIs must also be escaped
5693 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
5694
5695 return txt;
5696 });
5697
5698 var root = this;
5699
5700 // AMD Loader
5701 if (true) {
5702 !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {
5703 'use strict';
5704 return showdown;
5705 }).call(exports, __webpack_require__, exports, module),
5706 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5707
5708 // CommonJS/nodeJS Loader
5709 } else {}
5710 }).call(this);
5711
5712
5713
5714
5715 /***/ }),
5716
5717 /***/ 7957:
5718 /***/ ((__unused_webpack_module, exports) => {
5719
5720 "use strict";
5721 var __webpack_unused_export__;
5722 /**
5723 * @license React
5724 * react-is.production.min.js
5725 *
5726 * Copyright (c) Facebook, Inc. and its affiliates.
5727 *
5728 * This source code is licensed under the MIT license found in the
5729 * LICENSE file in the root directory of this source tree.
5730 */
5731 var b=Symbol.for("react.element"),c=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),e=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),g=Symbol.for("react.provider"),h=Symbol.for("react.context"),k=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),n=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),t=Symbol.for("react.offscreen"),u;u=Symbol.for("react.module.reference");
5732 function v(a){if("object"===typeof a&&null!==a){var r=a.$$typeof;switch(r){case b:switch(a=a.type,a){case d:case f:case e:case m:case n:return a;default:switch(a=a&&a.$$typeof,a){case k:case h:case l:case q:case p:case g:return a;default:return r}}case c:return r}}}__webpack_unused_export__=h;__webpack_unused_export__=g;__webpack_unused_export__=b;__webpack_unused_export__=l;__webpack_unused_export__=d;__webpack_unused_export__=q;__webpack_unused_export__=p;__webpack_unused_export__=c;__webpack_unused_export__=f;__webpack_unused_export__=e;__webpack_unused_export__=m;
5733 __webpack_unused_export__=n;__webpack_unused_export__=function(){return!1};__webpack_unused_export__=function(){return!1};__webpack_unused_export__=function(a){return v(a)===h};__webpack_unused_export__=function(a){return v(a)===g};__webpack_unused_export__=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===b};__webpack_unused_export__=function(a){return v(a)===l};__webpack_unused_export__=function(a){return v(a)===d};__webpack_unused_export__=function(a){return v(a)===q};__webpack_unused_export__=function(a){return v(a)===p};
5734 __webpack_unused_export__=function(a){return v(a)===c};__webpack_unused_export__=function(a){return v(a)===f};__webpack_unused_export__=function(a){return v(a)===e};__webpack_unused_export__=function(a){return v(a)===m};__webpack_unused_export__=function(a){return v(a)===n};
5735 exports.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===d||a===f||a===e||a===m||a===n||a===t||"object"===typeof a&&null!==a&&(a.$$typeof===q||a.$$typeof===p||a.$$typeof===g||a.$$typeof===h||a.$$typeof===l||a.$$typeof===u||void 0!==a.getModuleId)?!0:!1};__webpack_unused_export__=v;
5736
5737
5738 /***/ }),
5739
5740 /***/ 8243:
5741 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
5742
5743 "use strict";
5744
5745
5746 if (true) {
5747 module.exports = __webpack_require__(7957);
5748 } else {}
5749
5750
5751 /***/ })
5752
5753 /******/ });
5754 /************************************************************************/
5755 /******/ // The module cache
5756 /******/ var __webpack_module_cache__ = {};
5757 /******/
5758 /******/ // The require function
5759 /******/ function __webpack_require__(moduleId) {
5760 /******/ // Check if module is in cache
5761 /******/ var cachedModule = __webpack_module_cache__[moduleId];
5762 /******/ if (cachedModule !== undefined) {
5763 /******/ return cachedModule.exports;
5764 /******/ }
5765 /******/ // Create a new module (and put it into the cache)
5766 /******/ var module = __webpack_module_cache__[moduleId] = {
5767 /******/ // no module.id needed
5768 /******/ // no module.loaded needed
5769 /******/ exports: {}
5770 /******/ };
5771 /******/
5772 /******/ // Execute the module function
5773 /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5774 /******/
5775 /******/ // Return the exports of the module
5776 /******/ return module.exports;
5777 /******/ }
5778 /******/
5779 /************************************************************************/
5780 /******/ /* webpack/runtime/compat get default export */
5781 /******/ (() => {
5782 /******/ // getDefaultExport function for compatibility with non-harmony modules
5783 /******/ __webpack_require__.n = (module) => {
5784 /******/ var getter = module && module.__esModule ?
5785 /******/ () => (module['default']) :
5786 /******/ () => (module);
5787 /******/ __webpack_require__.d(getter, { a: getter });
5788 /******/ return getter;
5789 /******/ };
5790 /******/ })();
5791 /******/
5792 /******/ /* webpack/runtime/define property getters */
5793 /******/ (() => {
5794 /******/ // define getter functions for harmony exports
5795 /******/ __webpack_require__.d = (exports, definition) => {
5796 /******/ for(var key in definition) {
5797 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
5798 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
5799 /******/ }
5800 /******/ }
5801 /******/ };
5802 /******/ })();
5803 /******/
5804 /******/ /* webpack/runtime/hasOwnProperty shorthand */
5805 /******/ (() => {
5806 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
5807 /******/ })();
5808 /******/
5809 /******/ /* webpack/runtime/make namespace object */
5810 /******/ (() => {
5811 /******/ // define __esModule on exports
5812 /******/ __webpack_require__.r = (exports) => {
5813 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
5814 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5815 /******/ }
5816 /******/ Object.defineProperty(exports, '__esModule', { value: true });
5817 /******/ };
5818 /******/ })();
5819 /******/
5820 /************************************************************************/
5821 var __webpack_exports__ = {};
5822 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
5823 (() => {
5824 "use strict";
5825 // ESM COMPAT FLAG
5826 __webpack_require__.r(__webpack_exports__);
5827
5828 // EXPORTS
5829 __webpack_require__.d(__webpack_exports__, {
5830 __EXPERIMENTAL_ELEMENTS: () => (/* reexport */ __EXPERIMENTAL_ELEMENTS),
5831 __EXPERIMENTAL_PATHS_WITH_OVERRIDE: () => (/* reexport */ __EXPERIMENTAL_PATHS_WITH_OVERRIDE),
5832 __EXPERIMENTAL_STYLE_PROPERTY: () => (/* reexport */ __EXPERIMENTAL_STYLE_PROPERTY),
5833 __experimentalCloneSanitizedBlock: () => (/* reexport */ __experimentalCloneSanitizedBlock),
5834 __experimentalGetAccessibleBlockLabel: () => (/* reexport */ getAccessibleBlockLabel),
5835 __experimentalGetBlockAttributesNamesByRole: () => (/* reexport */ __experimentalGetBlockAttributesNamesByRole),
5836 __experimentalGetBlockLabel: () => (/* reexport */ getBlockLabel),
5837 __experimentalSanitizeBlockAttributes: () => (/* reexport */ __experimentalSanitizeBlockAttributes),
5838 __unstableGetBlockProps: () => (/* reexport */ getBlockProps),
5839 __unstableGetInnerBlocksProps: () => (/* reexport */ getInnerBlocksProps),
5840 __unstableSerializeAndClean: () => (/* reexport */ __unstableSerializeAndClean),
5841 children: () => (/* reexport */ children),
5842 cloneBlock: () => (/* reexport */ cloneBlock),
5843 createBlock: () => (/* reexport */ createBlock),
5844 createBlocksFromInnerBlocksTemplate: () => (/* reexport */ createBlocksFromInnerBlocksTemplate),
5845 doBlocksMatchTemplate: () => (/* reexport */ doBlocksMatchTemplate),
5846 findTransform: () => (/* reexport */ findTransform),
5847 getBlockAttributes: () => (/* reexport */ getBlockAttributes),
5848 getBlockContent: () => (/* reexport */ getBlockInnerHTML),
5849 getBlockDefaultClassName: () => (/* reexport */ getBlockDefaultClassName),
5850 getBlockFromExample: () => (/* reexport */ getBlockFromExample),
5851 getBlockMenuDefaultClassName: () => (/* reexport */ getBlockMenuDefaultClassName),
5852 getBlockSupport: () => (/* reexport */ getBlockSupport),
5853 getBlockTransforms: () => (/* reexport */ getBlockTransforms),
5854 getBlockType: () => (/* reexport */ getBlockType),
5855 getBlockTypes: () => (/* reexport */ getBlockTypes),
5856 getBlockVariations: () => (/* reexport */ getBlockVariations),
5857 getCategories: () => (/* reexport */ categories_getCategories),
5858 getChildBlockNames: () => (/* reexport */ getChildBlockNames),
5859 getDefaultBlockName: () => (/* reexport */ getDefaultBlockName),
5860 getFreeformContentHandlerName: () => (/* reexport */ getFreeformContentHandlerName),
5861 getGroupingBlockName: () => (/* reexport */ getGroupingBlockName),
5862 getPhrasingContentSchema: () => (/* reexport */ deprecatedGetPhrasingContentSchema),
5863 getPossibleBlockTransformations: () => (/* reexport */ getPossibleBlockTransformations),
5864 getSaveContent: () => (/* reexport */ getSaveContent),
5865 getSaveElement: () => (/* reexport */ getSaveElement),
5866 getUnregisteredTypeHandlerName: () => (/* reexport */ getUnregisteredTypeHandlerName),
5867 hasBlockSupport: () => (/* reexport */ hasBlockSupport),
5868 hasChildBlocks: () => (/* reexport */ hasChildBlocks),
5869 hasChildBlocksWithInserterSupport: () => (/* reexport */ hasChildBlocksWithInserterSupport),
5870 isReusableBlock: () => (/* reexport */ isReusableBlock),
5871 isTemplatePart: () => (/* reexport */ isTemplatePart),
5872 isUnmodifiedBlock: () => (/* reexport */ isUnmodifiedBlock),
5873 isUnmodifiedDefaultBlock: () => (/* reexport */ isUnmodifiedDefaultBlock),
5874 isValidBlockContent: () => (/* reexport */ isValidBlockContent),
5875 isValidIcon: () => (/* reexport */ isValidIcon),
5876 node: () => (/* reexport */ node),
5877 normalizeIconObject: () => (/* reexport */ normalizeIconObject),
5878 parse: () => (/* reexport */ parser_parse),
5879 parseWithAttributeSchema: () => (/* reexport */ parseWithAttributeSchema),
5880 pasteHandler: () => (/* reexport */ pasteHandler),
5881 privateApis: () => (/* reexport */ privateApis),
5882 rawHandler: () => (/* reexport */ rawHandler),
5883 registerBlockCollection: () => (/* reexport */ registerBlockCollection),
5884 registerBlockStyle: () => (/* reexport */ registerBlockStyle),
5885 registerBlockType: () => (/* reexport */ registerBlockType),
5886 registerBlockVariation: () => (/* reexport */ registerBlockVariation),
5887 serialize: () => (/* reexport */ serialize),
5888 serializeRawBlock: () => (/* reexport */ serializeRawBlock),
5889 setCategories: () => (/* reexport */ categories_setCategories),
5890 setDefaultBlockName: () => (/* reexport */ setDefaultBlockName),
5891 setFreeformContentHandlerName: () => (/* reexport */ setFreeformContentHandlerName),
5892 setGroupingBlockName: () => (/* reexport */ setGroupingBlockName),
5893 setUnregisteredTypeHandlerName: () => (/* reexport */ setUnregisteredTypeHandlerName),
5894 store: () => (/* reexport */ store),
5895 switchToBlockType: () => (/* reexport */ switchToBlockType),
5896 synchronizeBlocksWithTemplate: () => (/* reexport */ synchronizeBlocksWithTemplate),
5897 unregisterBlockStyle: () => (/* reexport */ unregisterBlockStyle),
5898 unregisterBlockType: () => (/* reexport */ unregisterBlockType),
5899 unregisterBlockVariation: () => (/* reexport */ unregisterBlockVariation),
5900 unstable__bootstrapServerSideBlockDefinitions: () => (/* reexport */ unstable__bootstrapServerSideBlockDefinitions),
5901 updateCategory: () => (/* reexport */ categories_updateCategory),
5902 validateBlock: () => (/* reexport */ validateBlock),
5903 withBlockContentContext: () => (/* reexport */ withBlockContentContext)
5904 });
5905
5906 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/selectors.js
5907 var selectors_namespaceObject = {};
5908 __webpack_require__.r(selectors_namespaceObject);
5909 __webpack_require__.d(selectors_namespaceObject, {
5910 __experimentalHasContentRoleAttribute: () => (__experimentalHasContentRoleAttribute),
5911 getActiveBlockVariation: () => (getActiveBlockVariation),
5912 getBlockStyles: () => (getBlockStyles),
5913 getBlockSupport: () => (selectors_getBlockSupport),
5914 getBlockType: () => (selectors_getBlockType),
5915 getBlockTypes: () => (selectors_getBlockTypes),
5916 getBlockVariations: () => (selectors_getBlockVariations),
5917 getCategories: () => (getCategories),
5918 getChildBlockNames: () => (selectors_getChildBlockNames),
5919 getCollections: () => (getCollections),
5920 getDefaultBlockName: () => (selectors_getDefaultBlockName),
5921 getDefaultBlockVariation: () => (getDefaultBlockVariation),
5922 getFreeformFallbackBlockName: () => (getFreeformFallbackBlockName),
5923 getGroupingBlockName: () => (selectors_getGroupingBlockName),
5924 getUnregisteredFallbackBlockName: () => (getUnregisteredFallbackBlockName),
5925 hasBlockSupport: () => (selectors_hasBlockSupport),
5926 hasChildBlocks: () => (selectors_hasChildBlocks),
5927 hasChildBlocksWithInserterSupport: () => (selectors_hasChildBlocksWithInserterSupport),
5928 isMatchingSearchTerm: () => (isMatchingSearchTerm)
5929 });
5930
5931 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/private-selectors.js
5932 var private_selectors_namespaceObject = {};
5933 __webpack_require__.r(private_selectors_namespaceObject);
5934 __webpack_require__.d(private_selectors_namespaceObject, {
5935 getAllBlockBindingsSources: () => (getAllBlockBindingsSources),
5936 getBlockBindingsSource: () => (private_selectors_getBlockBindingsSource),
5937 getBootstrappedBlockType: () => (getBootstrappedBlockType),
5938 getSupportedStyles: () => (getSupportedStyles),
5939 getUnprocessedBlockTypes: () => (getUnprocessedBlockTypes)
5940 });
5941
5942 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/actions.js
5943 var actions_namespaceObject = {};
5944 __webpack_require__.r(actions_namespaceObject);
5945 __webpack_require__.d(actions_namespaceObject, {
5946 __experimentalReapplyBlockFilters: () => (__experimentalReapplyBlockFilters),
5947 addBlockCollection: () => (addBlockCollection),
5948 addBlockStyles: () => (addBlockStyles),
5949 addBlockTypes: () => (addBlockTypes),
5950 addBlockVariations: () => (addBlockVariations),
5951 reapplyBlockTypeFilters: () => (reapplyBlockTypeFilters),
5952 removeBlockCollection: () => (removeBlockCollection),
5953 removeBlockStyles: () => (removeBlockStyles),
5954 removeBlockTypes: () => (removeBlockTypes),
5955 removeBlockVariations: () => (removeBlockVariations),
5956 setCategories: () => (setCategories),
5957 setDefaultBlockName: () => (actions_setDefaultBlockName),
5958 setFreeformFallbackBlockName: () => (setFreeformFallbackBlockName),
5959 setGroupingBlockName: () => (actions_setGroupingBlockName),
5960 setUnregisteredFallbackBlockName: () => (setUnregisteredFallbackBlockName),
5961 updateCategory: () => (updateCategory)
5962 });
5963
5964 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/private-actions.js
5965 var private_actions_namespaceObject = {};
5966 __webpack_require__.r(private_actions_namespaceObject);
5967 __webpack_require__.d(private_actions_namespaceObject, {
5968 addBlockBindingsSource: () => (addBlockBindingsSource),
5969 addBootstrappedBlockBindingsSource: () => (addBootstrappedBlockBindingsSource),
5970 addBootstrappedBlockType: () => (addBootstrappedBlockType),
5971 addUnprocessedBlockType: () => (addUnprocessedBlockType),
5972 removeBlockBindingsSource: () => (removeBlockBindingsSource)
5973 });
5974
5975 ;// CONCATENATED MODULE: external ["wp","data"]
5976 const external_wp_data_namespaceObject = window["wp"]["data"];
5977 ;// CONCATENATED MODULE: ./node_modules/tslib/tslib.es6.mjs
5978 /******************************************************************************
5979 Copyright (c) Microsoft Corporation.
5980
5981 Permission to use, copy, modify, and/or distribute this software for any
5982 purpose with or without fee is hereby granted.
5983
5984 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
5985 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
5986 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
5987 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
5988 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
5989 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5990 PERFORMANCE OF THIS SOFTWARE.
5991 ***************************************************************************** */
5992 /* global Reflect, Promise, SuppressedError, Symbol */
5993
5994 var extendStatics = function(d, b) {
5995 extendStatics = Object.setPrototypeOf ||
5996 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5997 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
5998 return extendStatics(d, b);
5999 };
6000
6001 function __extends(d, b) {
6002 if (typeof b !== "function" && b !== null)
6003 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
6004 extendStatics(d, b);
6005 function __() { this.constructor = d; }
6006 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6007 }
6008
6009 var __assign = function() {
6010 __assign = Object.assign || function __assign(t) {
6011 for (var s, i = 1, n = arguments.length; i < n; i++) {
6012 s = arguments[i];
6013 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
6014 }
6015 return t;
6016 }
6017 return __assign.apply(this, arguments);
6018 }
6019
6020 function __rest(s, e) {
6021 var t = {};
6022 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6023 t[p] = s[p];
6024 if (s != null && typeof Object.getOwnPropertySymbols === "function")
6025 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
6026 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
6027 t[p[i]] = s[p[i]];
6028 }
6029 return t;
6030 }
6031
6032 function __decorate(decorators, target, key, desc) {
6033 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6034 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6035 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;
6036 return c > 3 && r && Object.defineProperty(target, key, r), r;
6037 }
6038
6039 function __param(paramIndex, decorator) {
6040 return function (target, key) { decorator(target, key, paramIndex); }
6041 }
6042
6043 function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
6044 function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
6045 var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
6046 var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6047 var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6048 var _, done = false;
6049 for (var i = decorators.length - 1; i >= 0; i--) {
6050 var context = {};
6051 for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
6052 for (var p in contextIn.access) context.access[p] = contextIn.access[p];
6053 context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
6054 var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
6055 if (kind === "accessor") {
6056 if (result === void 0) continue;
6057 if (result === null || typeof result !== "object") throw new TypeError("Object expected");
6058 if (_ = accept(result.get)) descriptor.get = _;
6059 if (_ = accept(result.set)) descriptor.set = _;
6060 if (_ = accept(result.init)) initializers.unshift(_);
6061 }
6062 else if (_ = accept(result)) {
6063 if (kind === "field") initializers.unshift(_);
6064 else descriptor[key] = _;
6065 }
6066 }
6067 if (target) Object.defineProperty(target, contextIn.name, descriptor);
6068 done = true;
6069 };
6070
6071 function __runInitializers(thisArg, initializers, value) {
6072 var useValue = arguments.length > 2;
6073 for (var i = 0; i < initializers.length; i++) {
6074 value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6075 }
6076 return useValue ? value : void 0;
6077 };
6078
6079 function __propKey(x) {
6080 return typeof x === "symbol" ? x : "".concat(x);
6081 };
6082
6083 function __setFunctionName(f, name, prefix) {
6084 if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
6085 return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
6086 };
6087
6088 function __metadata(metadataKey, metadataValue) {
6089 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
6090 }
6091
6092 function __awaiter(thisArg, _arguments, P, generator) {
6093 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6094 return new (P || (P = Promise))(function (resolve, reject) {
6095 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6096 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6097 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
6098 step((generator = generator.apply(thisArg, _arguments || [])).next());
6099 });
6100 }
6101
6102 function __generator(thisArg, body) {
6103 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
6104 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
6105 function verb(n) { return function (v) { return step([n, v]); }; }
6106 function step(op) {
6107 if (f) throw new TypeError("Generator is already executing.");
6108 while (g && (g = 0, op[0] && (_ = 0)), _) try {
6109 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;
6110 if (y = 0, t) op = [op[0] & 2, t.value];
6111 switch (op[0]) {
6112 case 0: case 1: t = op; break;
6113 case 4: _.label++; return { value: op[1], done: false };
6114 case 5: _.label++; y = op[1]; op = [0]; continue;
6115 case 7: op = _.ops.pop(); _.trys.pop(); continue;
6116 default:
6117 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
6118 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
6119 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
6120 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
6121 if (t[2]) _.ops.pop();
6122 _.trys.pop(); continue;
6123 }
6124 op = body.call(thisArg, _);
6125 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
6126 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
6127 }
6128 }
6129
6130 var __createBinding = Object.create ? (function(o, m, k, k2) {
6131 if (k2 === undefined) k2 = k;
6132 var desc = Object.getOwnPropertyDescriptor(m, k);
6133 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6134 desc = { enumerable: true, get: function() { return m[k]; } };
6135 }
6136 Object.defineProperty(o, k2, desc);
6137 }) : (function(o, m, k, k2) {
6138 if (k2 === undefined) k2 = k;
6139 o[k2] = m[k];
6140 });
6141
6142 function __exportStar(m, o) {
6143 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
6144 }
6145
6146 function __values(o) {
6147 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
6148 if (m) return m.call(o);
6149 if (o && typeof o.length === "number") return {
6150 next: function () {
6151 if (o && i >= o.length) o = void 0;
6152 return { value: o && o[i++], done: !o };
6153 }
6154 };
6155 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
6156 }
6157
6158 function __read(o, n) {
6159 var m = typeof Symbol === "function" && o[Symbol.iterator];
6160 if (!m) return o;
6161 var i = m.call(o), r, ar = [], e;
6162 try {
6163 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
6164 }
6165 catch (error) { e = { error: error }; }
6166 finally {
6167 try {
6168 if (r && !r.done && (m = i["return"])) m.call(i);
6169 }
6170 finally { if (e) throw e.error; }
6171 }
6172 return ar;
6173 }
6174
6175 /** @deprecated */
6176 function __spread() {
6177 for (var ar = [], i = 0; i < arguments.length; i++)
6178 ar = ar.concat(__read(arguments[i]));
6179 return ar;
6180 }
6181
6182 /** @deprecated */
6183 function __spreadArrays() {
6184 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
6185 for (var r = Array(s), k = 0, i = 0; i < il; i++)
6186 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
6187 r[k] = a[j];
6188 return r;
6189 }
6190
6191 function __spreadArray(to, from, pack) {
6192 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
6193 if (ar || !(i in from)) {
6194 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6195 ar[i] = from[i];
6196 }
6197 }
6198 return to.concat(ar || Array.prototype.slice.call(from));
6199 }
6200
6201 function __await(v) {
6202 return this instanceof __await ? (this.v = v, this) : new __await(v);
6203 }
6204
6205 function __asyncGenerator(thisArg, _arguments, generator) {
6206 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6207 var g = generator.apply(thisArg, _arguments || []), i, q = [];
6208 return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
6209 function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
6210 function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
6211 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
6212 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
6213 function fulfill(value) { resume("next", value); }
6214 function reject(value) { resume("throw", value); }
6215 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
6216 }
6217
6218 function __asyncDelegator(o) {
6219 var i, p;
6220 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
6221 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
6222 }
6223
6224 function __asyncValues(o) {
6225 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6226 var m = o[Symbol.asyncIterator], i;
6227 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);
6228 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); }); }; }
6229 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
6230 }
6231
6232 function __makeTemplateObject(cooked, raw) {
6233 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
6234 return cooked;
6235 };
6236
6237 var __setModuleDefault = Object.create ? (function(o, v) {
6238 Object.defineProperty(o, "default", { enumerable: true, value: v });
6239 }) : function(o, v) {
6240 o["default"] = v;
6241 };
6242
6243 function __importStar(mod) {
6244 if (mod && mod.__esModule) return mod;
6245 var result = {};
6246 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
6247 __setModuleDefault(result, mod);
6248 return result;
6249 }
6250
6251 function __importDefault(mod) {
6252 return (mod && mod.__esModule) ? mod : { default: mod };
6253 }
6254
6255 function __classPrivateFieldGet(receiver, state, kind, f) {
6256 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
6257 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");
6258 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6259 }
6260
6261 function __classPrivateFieldSet(receiver, state, value, kind, f) {
6262 if (kind === "m") throw new TypeError("Private method is not writable");
6263 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
6264 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");
6265 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6266 }
6267
6268 function __classPrivateFieldIn(state, receiver) {
6269 if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
6270 return typeof state === "function" ? receiver === state : state.has(receiver);
6271 }
6272
6273 function __addDisposableResource(env, value, async) {
6274 if (value !== null && value !== void 0) {
6275 if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
6276 var dispose, inner;
6277 if (async) {
6278 if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
6279 dispose = value[Symbol.asyncDispose];
6280 }
6281 if (dispose === void 0) {
6282 if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
6283 dispose = value[Symbol.dispose];
6284 if (async) inner = dispose;
6285 }
6286 if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
6287 if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
6288 env.stack.push({ value: value, dispose: dispose, async: async });
6289 }
6290 else if (async) {
6291 env.stack.push({ async: true });
6292 }
6293 return value;
6294 }
6295
6296 var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
6297 var e = new Error(message);
6298 return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
6299 };
6300
6301 function __disposeResources(env) {
6302 function fail(e) {
6303 env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
6304 env.hasError = true;
6305 }
6306 function next() {
6307 while (env.stack.length) {
6308 var rec = env.stack.pop();
6309 try {
6310 var result = rec.dispose && rec.dispose.call(rec.value);
6311 if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
6312 }
6313 catch (e) {
6314 fail(e);
6315 }
6316 }
6317 if (env.hasError) throw env.error;
6318 }
6319 return next();
6320 }
6321
6322 /* harmony default export */ const tslib_es6 = ({
6323 __extends,
6324 __assign,
6325 __rest,
6326 __decorate,
6327 __param,
6328 __metadata,
6329 __awaiter,
6330 __generator,
6331 __createBinding,
6332 __exportStar,
6333 __values,
6334 __read,
6335 __spread,
6336 __spreadArrays,
6337 __spreadArray,
6338 __await,
6339 __asyncGenerator,
6340 __asyncDelegator,
6341 __asyncValues,
6342 __makeTemplateObject,
6343 __importStar,
6344 __importDefault,
6345 __classPrivateFieldGet,
6346 __classPrivateFieldSet,
6347 __classPrivateFieldIn,
6348 __addDisposableResource,
6349 __disposeResources,
6350 });
6351
6352 ;// CONCATENATED MODULE: ./node_modules/lower-case/dist.es2015/index.js
6353 /**
6354 * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
6355 */
6356 var SUPPORTED_LOCALE = {
6357 tr: {
6358 regexp: /\u0130|\u0049|\u0049\u0307/g,
6359 map: {
6360 İ: "\u0069",
6361 I: "\u0131",
6362 İ: "\u0069",
6363 },
6364 },
6365 az: {
6366 regexp: /\u0130/g,
6367 map: {
6368 İ: "\u0069",
6369 I: "\u0131",
6370 İ: "\u0069",
6371 },
6372 },
6373 lt: {
6374 regexp: /\u0049|\u004A|\u012E|\u00CC|\u00CD|\u0128/g,
6375 map: {
6376 I: "\u0069\u0307",
6377 J: "\u006A\u0307",
6378 Į: "\u012F\u0307",
6379 Ì: "\u0069\u0307\u0300",
6380 Í: "\u0069\u0307\u0301",
6381 Ĩ: "\u0069\u0307\u0303",
6382 },
6383 },
6384 };
6385 /**
6386 * Localized lower case.
6387 */
6388 function localeLowerCase(str, locale) {
6389 var lang = SUPPORTED_LOCALE[locale.toLowerCase()];
6390 if (lang)
6391 return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));
6392 return lowerCase(str);
6393 }
6394 /**
6395 * Lower case as a function.
6396 */
6397 function lowerCase(str) {
6398 return str.toLowerCase();
6399 }
6400
6401 ;// CONCATENATED MODULE: ./node_modules/no-case/dist.es2015/index.js
6402
6403 // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
6404 var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
6405 // Remove all non-word characters.
6406 var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
6407 /**
6408 * Normalize the string into something other libraries can manipulate easier.
6409 */
6410 function noCase(input, options) {
6411 if (options === void 0) { options = {}; }
6412 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;
6413 var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
6414 var start = 0;
6415 var end = result.length;
6416 // Trim the delimiter from around the output string.
6417 while (result.charAt(start) === "\0")
6418 start++;
6419 while (result.charAt(end - 1) === "\0")
6420 end--;
6421 // Transform each token independently.
6422 return result.slice(start, end).split("\0").map(transform).join(delimiter);
6423 }
6424 /**
6425 * Replace `re` in the input string with the replacement value.
6426 */
6427 function replace(input, re, value) {
6428 if (re instanceof RegExp)
6429 return input.replace(re, value);
6430 return re.reduce(function (input, re) { return input.replace(re, value); }, input);
6431 }
6432
6433 ;// CONCATENATED MODULE: ./node_modules/pascal-case/dist.es2015/index.js
6434
6435
6436 function pascalCaseTransform(input, index) {
6437 var firstChar = input.charAt(0);
6438 var lowerChars = input.substr(1).toLowerCase();
6439 if (index > 0 && firstChar >= "0" && firstChar <= "9") {
6440 return "_" + firstChar + lowerChars;
6441 }
6442 return "" + firstChar.toUpperCase() + lowerChars;
6443 }
6444 function dist_es2015_pascalCaseTransformMerge(input) {
6445 return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
6446 }
6447 function pascalCase(input, options) {
6448 if (options === void 0) { options = {}; }
6449 return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
6450 }
6451
6452 ;// CONCATENATED MODULE: ./node_modules/camel-case/dist.es2015/index.js
6453
6454
6455 function camelCaseTransform(input, index) {
6456 if (index === 0)
6457 return input.toLowerCase();
6458 return pascalCaseTransform(input, index);
6459 }
6460 function camelCaseTransformMerge(input, index) {
6461 if (index === 0)
6462 return input.toLowerCase();
6463 return pascalCaseTransformMerge(input);
6464 }
6465 function camelCase(input, options) {
6466 if (options === void 0) { options = {}; }
6467 return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
6468 }
6469
6470 ;// CONCATENATED MODULE: external ["wp","i18n"]
6471 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
6472 ;// CONCATENATED MODULE: ./node_modules/colord/index.mjs
6473 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()})};
6474
6475 ;// CONCATENATED MODULE: ./node_modules/colord/plugins/names.mjs
6476 /* 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"])}
6477
6478 ;// CONCATENATED MODULE: ./node_modules/colord/plugins/a11y.mjs
6479 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}}
6480
6481 ;// CONCATENATED MODULE: external ["wp","element"]
6482 const external_wp_element_namespaceObject = window["wp"]["element"];
6483 ;// CONCATENATED MODULE: external ["wp","dom"]
6484 const external_wp_dom_namespaceObject = window["wp"]["dom"];
6485 ;// CONCATENATED MODULE: external ["wp","richText"]
6486 const external_wp_richText_namespaceObject = window["wp"]["richText"];
6487 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/constants.js
6488 const BLOCK_ICON_DEFAULT = 'block-default';
6489
6490 /**
6491 * Array of valid keys in a block type settings deprecation object.
6492 *
6493 * @type {string[]}
6494 */
6495 const DEPRECATED_ENTRY_KEYS = ['attributes', 'supports', 'save', 'migrate', 'isEligible', 'apiVersion'];
6496 const __EXPERIMENTAL_STYLE_PROPERTY = {
6497 // Kept for back-compatibility purposes.
6498 '--wp--style--color--link': {
6499 value: ['color', 'link'],
6500 support: ['color', 'link']
6501 },
6502 aspectRatio: {
6503 value: ['dimensions', 'aspectRatio'],
6504 support: ['dimensions', 'aspectRatio'],
6505 useEngine: true
6506 },
6507 background: {
6508 value: ['color', 'gradient'],
6509 support: ['color', 'gradients'],
6510 useEngine: true
6511 },
6512 backgroundColor: {
6513 value: ['color', 'background'],
6514 support: ['color', 'background'],
6515 requiresOptOut: true,
6516 useEngine: true
6517 },
6518 backgroundImage: {
6519 value: ['background', 'backgroundImage'],
6520 support: ['background', 'backgroundImage'],
6521 useEngine: true
6522 },
6523 backgroundRepeat: {
6524 value: ['background', 'backgroundRepeat'],
6525 support: ['background', 'backgroundRepeat'],
6526 useEngine: true
6527 },
6528 backgroundSize: {
6529 value: ['background', 'backgroundSize'],
6530 support: ['background', 'backgroundSize'],
6531 useEngine: true
6532 },
6533 backgroundPosition: {
6534 value: ['background', 'backgroundPosition'],
6535 support: ['background', 'backgroundPosition'],
6536 useEngine: true
6537 },
6538 borderColor: {
6539 value: ['border', 'color'],
6540 support: ['__experimentalBorder', 'color'],
6541 useEngine: true
6542 },
6543 borderRadius: {
6544 value: ['border', 'radius'],
6545 support: ['__experimentalBorder', 'radius'],
6546 properties: {
6547 borderTopLeftRadius: 'topLeft',
6548 borderTopRightRadius: 'topRight',
6549 borderBottomLeftRadius: 'bottomLeft',
6550 borderBottomRightRadius: 'bottomRight'
6551 },
6552 useEngine: true
6553 },
6554 borderStyle: {
6555 value: ['border', 'style'],
6556 support: ['__experimentalBorder', 'style'],
6557 useEngine: true
6558 },
6559 borderWidth: {
6560 value: ['border', 'width'],
6561 support: ['__experimentalBorder', 'width'],
6562 useEngine: true
6563 },
6564 borderTopColor: {
6565 value: ['border', 'top', 'color'],
6566 support: ['__experimentalBorder', 'color'],
6567 useEngine: true
6568 },
6569 borderTopStyle: {
6570 value: ['border', 'top', 'style'],
6571 support: ['__experimentalBorder', 'style'],
6572 useEngine: true
6573 },
6574 borderTopWidth: {
6575 value: ['border', 'top', 'width'],
6576 support: ['__experimentalBorder', 'width'],
6577 useEngine: true
6578 },
6579 borderRightColor: {
6580 value: ['border', 'right', 'color'],
6581 support: ['__experimentalBorder', 'color'],
6582 useEngine: true
6583 },
6584 borderRightStyle: {
6585 value: ['border', 'right', 'style'],
6586 support: ['__experimentalBorder', 'style'],
6587 useEngine: true
6588 },
6589 borderRightWidth: {
6590 value: ['border', 'right', 'width'],
6591 support: ['__experimentalBorder', 'width'],
6592 useEngine: true
6593 },
6594 borderBottomColor: {
6595 value: ['border', 'bottom', 'color'],
6596 support: ['__experimentalBorder', 'color'],
6597 useEngine: true
6598 },
6599 borderBottomStyle: {
6600 value: ['border', 'bottom', 'style'],
6601 support: ['__experimentalBorder', 'style'],
6602 useEngine: true
6603 },
6604 borderBottomWidth: {
6605 value: ['border', 'bottom', 'width'],
6606 support: ['__experimentalBorder', 'width'],
6607 useEngine: true
6608 },
6609 borderLeftColor: {
6610 value: ['border', 'left', 'color'],
6611 support: ['__experimentalBorder', 'color'],
6612 useEngine: true
6613 },
6614 borderLeftStyle: {
6615 value: ['border', 'left', 'style'],
6616 support: ['__experimentalBorder', 'style'],
6617 useEngine: true
6618 },
6619 borderLeftWidth: {
6620 value: ['border', 'left', 'width'],
6621 support: ['__experimentalBorder', 'width'],
6622 useEngine: true
6623 },
6624 color: {
6625 value: ['color', 'text'],
6626 support: ['color', 'text'],
6627 requiresOptOut: true,
6628 useEngine: true
6629 },
6630 columnCount: {
6631 value: ['typography', 'textColumns'],
6632 support: ['typography', 'textColumns'],
6633 useEngine: true
6634 },
6635 filter: {
6636 value: ['filter', 'duotone'],
6637 support: ['filter', 'duotone']
6638 },
6639 linkColor: {
6640 value: ['elements', 'link', 'color', 'text'],
6641 support: ['color', 'link']
6642 },
6643 captionColor: {
6644 value: ['elements', 'caption', 'color', 'text'],
6645 support: ['color', 'caption']
6646 },
6647 buttonColor: {
6648 value: ['elements', 'button', 'color', 'text'],
6649 support: ['color', 'button']
6650 },
6651 buttonBackgroundColor: {
6652 value: ['elements', 'button', 'color', 'background'],
6653 support: ['color', 'button']
6654 },
6655 headingColor: {
6656 value: ['elements', 'heading', 'color', 'text'],
6657 support: ['color', 'heading']
6658 },
6659 headingBackgroundColor: {
6660 value: ['elements', 'heading', 'color', 'background'],
6661 support: ['color', 'heading']
6662 },
6663 fontFamily: {
6664 value: ['typography', 'fontFamily'],
6665 support: ['typography', '__experimentalFontFamily'],
6666 useEngine: true
6667 },
6668 fontSize: {
6669 value: ['typography', 'fontSize'],
6670 support: ['typography', 'fontSize'],
6671 useEngine: true
6672 },
6673 fontStyle: {
6674 value: ['typography', 'fontStyle'],
6675 support: ['typography', '__experimentalFontStyle'],
6676 useEngine: true
6677 },
6678 fontWeight: {
6679 value: ['typography', 'fontWeight'],
6680 support: ['typography', '__experimentalFontWeight'],
6681 useEngine: true
6682 },
6683 lineHeight: {
6684 value: ['typography', 'lineHeight'],
6685 support: ['typography', 'lineHeight'],
6686 useEngine: true
6687 },
6688 margin: {
6689 value: ['spacing', 'margin'],
6690 support: ['spacing', 'margin'],
6691 properties: {
6692 marginTop: 'top',
6693 marginRight: 'right',
6694 marginBottom: 'bottom',
6695 marginLeft: 'left'
6696 },
6697 useEngine: true
6698 },
6699 minHeight: {
6700 value: ['dimensions', 'minHeight'],
6701 support: ['dimensions', 'minHeight'],
6702 useEngine: true
6703 },
6704 padding: {
6705 value: ['spacing', 'padding'],
6706 support: ['spacing', 'padding'],
6707 properties: {
6708 paddingTop: 'top',
6709 paddingRight: 'right',
6710 paddingBottom: 'bottom',
6711 paddingLeft: 'left'
6712 },
6713 useEngine: true
6714 },
6715 textAlign: {
6716 value: ['typography', 'textAlign'],
6717 support: ['typography', 'textAlign'],
6718 useEngine: false
6719 },
6720 textDecoration: {
6721 value: ['typography', 'textDecoration'],
6722 support: ['typography', '__experimentalTextDecoration'],
6723 useEngine: true
6724 },
6725 textTransform: {
6726 value: ['typography', 'textTransform'],
6727 support: ['typography', '__experimentalTextTransform'],
6728 useEngine: true
6729 },
6730 letterSpacing: {
6731 value: ['typography', 'letterSpacing'],
6732 support: ['typography', '__experimentalLetterSpacing'],
6733 useEngine: true
6734 },
6735 writingMode: {
6736 value: ['typography', 'writingMode'],
6737 support: ['typography', '__experimentalWritingMode'],
6738 useEngine: true
6739 },
6740 '--wp--style--root--padding': {
6741 value: ['spacing', 'padding'],
6742 support: ['spacing', 'padding'],
6743 properties: {
6744 '--wp--style--root--padding-top': 'top',
6745 '--wp--style--root--padding-right': 'right',
6746 '--wp--style--root--padding-bottom': 'bottom',
6747 '--wp--style--root--padding-left': 'left'
6748 },
6749 rootOnly: true
6750 }
6751 };
6752 const __EXPERIMENTAL_ELEMENTS = {
6753 link: 'a:where(:not(.wp-element-button))',
6754 heading: 'h1, h2, h3, h4, h5, h6',
6755 h1: 'h1',
6756 h2: 'h2',
6757 h3: 'h3',
6758 h4: 'h4',
6759 h5: 'h5',
6760 h6: 'h6',
6761 button: '.wp-element-button, .wp-block-button__link',
6762 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',
6763 cite: 'cite'
6764 };
6765
6766 // These paths may have three origins, custom, theme, and default,
6767 // and are expected to override other origins with custom, theme,
6768 // and default priority.
6769 const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = {
6770 'color.duotone': true,
6771 'color.gradients': true,
6772 'color.palette': true,
6773 'dimensions.aspectRatios': true,
6774 'typography.fontSizes': true,
6775 'spacing.spacingSizes': true
6776 };
6777
6778 ;// CONCATENATED MODULE: external ["wp","warning"]
6779 const external_wp_warning_namespaceObject = window["wp"]["warning"];
6780 ;// CONCATENATED MODULE: external ["wp","privateApis"]
6781 const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
6782 ;// CONCATENATED MODULE: ./packages/blocks/build-module/lock-unlock.js
6783 /**
6784 * WordPress dependencies
6785 */
6786
6787 const {
6788 lock,
6789 unlock
6790 } = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/blocks');
6791
6792 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/registration.js
6793 /**
6794 * WordPress dependencies
6795 */
6796
6797
6798
6799
6800 /**
6801 * Internal dependencies
6802 */
6803 const i18nBlockSchema = {
6804 title: "block title",
6805 description: "block description",
6806 keywords: ["block keyword"],
6807 styles: [{
6808 label: "block style label"
6809 }],
6810 variations: [{
6811 title: "block variation title",
6812 description: "block variation description",
6813 keywords: ["block variation keyword"]
6814 }]
6815 };
6816
6817
6818
6819 /**
6820 * An icon type definition. One of a Dashicon slug, an element,
6821 * or a component.
6822 *
6823 * @typedef {(string|Element|Component)} WPIcon
6824 *
6825 * @see https://developer.wordpress.org/resource/dashicons/
6826 */
6827
6828 /**
6829 * Render behavior of a block type icon; one of a Dashicon slug, an element,
6830 * or a component.
6831 *
6832 * @typedef {WPIcon} WPBlockTypeIconRender
6833 */
6834
6835 /**
6836 * An object describing a normalized block type icon.
6837 *
6838 * @typedef {Object} WPBlockTypeIconDescriptor
6839 *
6840 * @property {WPBlockTypeIconRender} src Render behavior of the icon,
6841 * one of a Dashicon slug, an
6842 * element, or a component.
6843 * @property {string} background Optimal background hex string
6844 * color when displaying icon.
6845 * @property {string} foreground Optimal foreground hex string
6846 * color when displaying icon.
6847 * @property {string} shadowColor Optimal shadow hex string
6848 * color when displaying icon.
6849 */
6850
6851 /**
6852 * Value to use to render the icon for a block type in an editor interface,
6853 * either a Dashicon slug, an element, a component, or an object describing
6854 * the icon.
6855 *
6856 * @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
6857 */
6858
6859 /**
6860 * Named block variation scopes.
6861 *
6862 * @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
6863 */
6864
6865 /**
6866 * An object describing a variation defined for the block type.
6867 *
6868 * @typedef {Object} WPBlockVariation
6869 *
6870 * @property {string} name The unique and machine-readable name.
6871 * @property {string} title A human-readable variation title.
6872 * @property {string} [description] A detailed variation description.
6873 * @property {string} [category] Block type category classification,
6874 * used in search interfaces to arrange
6875 * block types by category.
6876 * @property {WPIcon} [icon] An icon helping to visualize the variation.
6877 * @property {boolean} [isDefault] Indicates whether the current variation is
6878 * the default one. Defaults to `false`.
6879 * @property {Object} [attributes] Values which override block attributes.
6880 * @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
6881 * @property {Object} [example] Example provides structured data for
6882 * the block preview. You can set to
6883 * `undefined` to disable the preview shown
6884 * for the block type.
6885 * @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
6886 * is applicable. When not provided, it
6887 * assumes all available scopes.
6888 * @property {string[]} [keywords] An array of terms (which can be translated)
6889 * that help users discover the variation
6890 * while searching.
6891 * @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
6892 * Function that accepts a block's attributes and the
6893 * variation's attributes and determines if a variation is active.
6894 * This function doesn't try to find a match dynamically based
6895 * on all block's attributes, as in many cases some attributes are irrelevant.
6896 * An example would be for `embed` block where we only care
6897 * about `providerNameSlug` attribute's value.
6898 * We can also use a `string[]` to tell which attributes
6899 * should be compared as a shorthand. Each attributes will
6900 * be matched and the variation will be active if all of them are matching.
6901 */
6902
6903 /**
6904 * Defined behavior of a block type.
6905 *
6906 * @typedef {Object} WPBlockType
6907 *
6908 * @property {string} name Block type's namespaced name.
6909 * @property {string} title Human-readable block type label.
6910 * @property {string} [description] A detailed block type description.
6911 * @property {string} [category] Block type category classification,
6912 * used in search interfaces to arrange
6913 * block types by category.
6914 * @property {WPBlockTypeIcon} [icon] Block type icon.
6915 * @property {string[]} [keywords] Additional keywords to produce block
6916 * type as result in search interfaces.
6917 * @property {Object} [attributes] Block type attributes.
6918 * @property {Component} [save] Optional component describing
6919 * serialized markup structure of a
6920 * block type.
6921 * @property {Component} edit Component rendering an element to
6922 * manipulate the attributes of a block
6923 * in the context of an editor.
6924 * @property {WPBlockVariation[]} [variations] The list of block variations.
6925 * @property {Object} [example] Example provides structured data for
6926 * the block preview. When not defined
6927 * then no preview is shown.
6928 */
6929
6930 function isObject(object) {
6931 return object !== null && typeof object === 'object';
6932 }
6933
6934 /**
6935 * Sets the server side block definition of blocks.
6936 *
6937 * Ignored from documentation due to being marked as unstable.
6938 *
6939 * @ignore
6940 *
6941 * @param {Object} definitions Server-side block definitions
6942 */
6943 // eslint-disable-next-line camelcase
6944 function unstable__bootstrapServerSideBlockDefinitions(definitions) {
6945 const {
6946 addBootstrappedBlockType
6947 } = unlock((0,external_wp_data_namespaceObject.dispatch)(store));
6948 for (const [name, blockType] of Object.entries(definitions)) {
6949 addBootstrappedBlockType(name, blockType);
6950 }
6951 }
6952
6953 /**
6954 * Gets block settings from metadata loaded from `block.json` file
6955 *
6956 * @param {Object} metadata Block metadata loaded from `block.json`.
6957 * @param {string} metadata.textdomain Textdomain to use with translations.
6958 *
6959 * @return {Object} Block settings.
6960 */
6961 function getBlockSettingsFromMetadata({
6962 textdomain,
6963 ...metadata
6964 }) {
6965 const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'selectors', 'supports', 'styles', 'example', 'variations', 'blockHooks', 'allowedBlocks'];
6966 const settings = Object.fromEntries(Object.entries(metadata).filter(([key]) => allowedFields.includes(key)));
6967 if (textdomain) {
6968 Object.keys(i18nBlockSchema).forEach(key => {
6969 if (!settings[key]) {
6970 return;
6971 }
6972 settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
6973 });
6974 }
6975 return settings;
6976 }
6977
6978 /**
6979 * Registers a new block provided a unique name and an object defining its
6980 * behavior. Once registered, the block is made available as an option to any
6981 * editor interface where blocks are implemented.
6982 *
6983 * For more in-depth information on registering a custom block see the
6984 * [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).
6985 *
6986 * @param {string|Object} blockNameOrMetadata Block type name or its metadata.
6987 * @param {Object} settings Block settings.
6988 *
6989 * @example
6990 * ```js
6991 * import { __ } from '@wordpress/i18n';
6992 * import { registerBlockType } from '@wordpress/blocks'
6993 *
6994 * registerBlockType( 'namespace/block-name', {
6995 * title: __( 'My First Block' ),
6996 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
6997 * save: () => <div>Hello from the saved content!</div>,
6998 * } );
6999 * ```
7000 *
7001 * @return {WPBlockType | undefined} The block, if it has been successfully registered;
7002 * otherwise `undefined`.
7003 */
7004 function registerBlockType(blockNameOrMetadata, settings) {
7005 const name = isObject(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
7006 if (typeof name !== 'string') {
7007 false ? 0 : void 0;
7008 return;
7009 }
7010 if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
7011 false ? 0 : void 0;
7012 return;
7013 }
7014 if ((0,external_wp_data_namespaceObject.select)(store).getBlockType(name)) {
7015 false ? 0 : void 0;
7016 return;
7017 }
7018 const {
7019 addBootstrappedBlockType,
7020 addUnprocessedBlockType
7021 } = unlock((0,external_wp_data_namespaceObject.dispatch)(store));
7022 if (isObject(blockNameOrMetadata)) {
7023 const metadata = getBlockSettingsFromMetadata(blockNameOrMetadata);
7024 addBootstrappedBlockType(name, metadata);
7025 }
7026 addUnprocessedBlockType(name, settings);
7027 return (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
7028 }
7029
7030 /**
7031 * Translates block settings provided with metadata using the i18n schema.
7032 *
7033 * @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
7034 * @param {string|string[]|Object[]} settingValue Value for the block setting.
7035 * @param {string} textdomain Textdomain to use with translations.
7036 *
7037 * @return {string|string[]|Object[]} Translated setting.
7038 */
7039 function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
7040 if (typeof i18nSchema === 'string' && typeof settingValue === 'string') {
7041 // eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
7042 return (0,external_wp_i18n_namespaceObject._x)(settingValue, i18nSchema, textdomain);
7043 }
7044 if (Array.isArray(i18nSchema) && i18nSchema.length && Array.isArray(settingValue)) {
7045 return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
7046 }
7047 if (isObject(i18nSchema) && Object.entries(i18nSchema).length && isObject(settingValue)) {
7048 return Object.keys(settingValue).reduce((accumulator, key) => {
7049 if (!i18nSchema[key]) {
7050 accumulator[key] = settingValue[key];
7051 return accumulator;
7052 }
7053 accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
7054 return accumulator;
7055 }, {});
7056 }
7057 return settingValue;
7058 }
7059
7060 /**
7061 * Registers a new block collection to group blocks in the same namespace in the inserter.
7062 *
7063 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
7064 * @param {Object} settings The block collection settings.
7065 * @param {string} settings.title The title to display in the block inserter.
7066 * @param {Object} [settings.icon] The icon to display in the block inserter.
7067 *
7068 * @example
7069 * ```js
7070 * import { __ } from '@wordpress/i18n';
7071 * import { registerBlockCollection, registerBlockType } from '@wordpress/blocks';
7072 *
7073 * // Register the collection.
7074 * registerBlockCollection( 'my-collection', {
7075 * title: __( 'Custom Collection' ),
7076 * } );
7077 *
7078 * // Register a block in the same namespace to add it to the collection.
7079 * registerBlockType( 'my-collection/block-name', {
7080 * title: __( 'My First Block' ),
7081 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
7082 * save: () => <div>'Hello from the saved content!</div>,
7083 * } );
7084 * ```
7085 */
7086 function registerBlockCollection(namespace, {
7087 title,
7088 icon
7089 }) {
7090 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockCollection(namespace, title, icon);
7091 }
7092
7093 /**
7094 * Unregisters a block collection
7095 *
7096 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
7097 *
7098 * @example
7099 * ```js
7100 * import { unregisterBlockCollection } from '@wordpress/blocks';
7101 *
7102 * unregisterBlockCollection( 'my-collection' );
7103 * ```
7104 */
7105 function unregisterBlockCollection(namespace) {
7106 dispatch(blocksStore).removeBlockCollection(namespace);
7107 }
7108
7109 /**
7110 * Unregisters a block.
7111 *
7112 * @param {string} name Block name.
7113 *
7114 * @example
7115 * ```js
7116 * import { __ } from '@wordpress/i18n';
7117 * import { unregisterBlockType } from '@wordpress/blocks';
7118 *
7119 * const ExampleComponent = () => {
7120 * return (
7121 * <Button
7122 * onClick={ () =>
7123 * unregisterBlockType( 'my-collection/block-name' )
7124 * }
7125 * >
7126 * { __( 'Unregister my custom block.' ) }
7127 * </Button>
7128 * );
7129 * };
7130 * ```
7131 *
7132 * @return {WPBlockType | undefined} The previous block value, if it has been successfully
7133 * unregistered; otherwise `undefined`.
7134 */
7135 function unregisterBlockType(name) {
7136 const oldBlock = (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
7137 if (!oldBlock) {
7138 false ? 0 : void 0;
7139 return;
7140 }
7141 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockTypes(name);
7142 return oldBlock;
7143 }
7144
7145 /**
7146 * Assigns name of block for handling non-block content.
7147 *
7148 * @param {string} blockName Block name.
7149 */
7150 function setFreeformContentHandlerName(blockName) {
7151 (0,external_wp_data_namespaceObject.dispatch)(store).setFreeformFallbackBlockName(blockName);
7152 }
7153
7154 /**
7155 * Retrieves name of block handling non-block content, or undefined if no
7156 * handler has been defined.
7157 *
7158 * @return {?string} Block name.
7159 */
7160 function getFreeformContentHandlerName() {
7161 return (0,external_wp_data_namespaceObject.select)(store).getFreeformFallbackBlockName();
7162 }
7163
7164 /**
7165 * Retrieves name of block used for handling grouping interactions.
7166 *
7167 * @return {?string} Block name.
7168 */
7169 function getGroupingBlockName() {
7170 return (0,external_wp_data_namespaceObject.select)(store).getGroupingBlockName();
7171 }
7172
7173 /**
7174 * Assigns name of block handling unregistered block types.
7175 *
7176 * @param {string} blockName Block name.
7177 */
7178 function setUnregisteredTypeHandlerName(blockName) {
7179 (0,external_wp_data_namespaceObject.dispatch)(store).setUnregisteredFallbackBlockName(blockName);
7180 }
7181
7182 /**
7183 * Retrieves name of block handling unregistered block types, or undefined if no
7184 * handler has been defined.
7185 *
7186 * @return {?string} Block name.
7187 */
7188 function getUnregisteredTypeHandlerName() {
7189 return (0,external_wp_data_namespaceObject.select)(store).getUnregisteredFallbackBlockName();
7190 }
7191
7192 /**
7193 * Assigns the default block name.
7194 *
7195 * @param {string} name Block name.
7196 *
7197 * @example
7198 * ```js
7199 * import { setDefaultBlockName } from '@wordpress/blocks';
7200 *
7201 * const ExampleComponent = () => {
7202 *
7203 * return (
7204 * <Button onClick={ () => setDefaultBlockName( 'core/heading' ) }>
7205 * { __( 'Set the default block to Heading' ) }
7206 * </Button>
7207 * );
7208 * };
7209 * ```
7210 */
7211 function setDefaultBlockName(name) {
7212 (0,external_wp_data_namespaceObject.dispatch)(store).setDefaultBlockName(name);
7213 }
7214
7215 /**
7216 * Assigns name of block for handling block grouping interactions.
7217 *
7218 * This function lets you select a different block to group other blocks in instead of the
7219 * default `core/group` block. This function must be used in a component or when the DOM is fully
7220 * loaded. See https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dom-ready/
7221 *
7222 * @param {string} name Block name.
7223 *
7224 * @example
7225 * ```js
7226 * import { setGroupingBlockName } from '@wordpress/blocks';
7227 *
7228 * const ExampleComponent = () => {
7229 *
7230 * return (
7231 * <Button onClick={ () => setGroupingBlockName( 'core/columns' ) }>
7232 * { __( 'Wrap in columns' ) }
7233 * </Button>
7234 * );
7235 * };
7236 * ```
7237 */
7238 function setGroupingBlockName(name) {
7239 (0,external_wp_data_namespaceObject.dispatch)(store).setGroupingBlockName(name);
7240 }
7241
7242 /**
7243 * Retrieves the default block name.
7244 *
7245 * @return {?string} Block name.
7246 */
7247 function getDefaultBlockName() {
7248 return (0,external_wp_data_namespaceObject.select)(store).getDefaultBlockName();
7249 }
7250
7251 /**
7252 * Returns a registered block type.
7253 *
7254 * @param {string} name Block name.
7255 *
7256 * @return {?Object} Block type.
7257 */
7258 function getBlockType(name) {
7259 return (0,external_wp_data_namespaceObject.select)(store)?.getBlockType(name);
7260 }
7261
7262 /**
7263 * Returns all registered blocks.
7264 *
7265 * @return {Array} Block settings.
7266 */
7267 function getBlockTypes() {
7268 return (0,external_wp_data_namespaceObject.select)(store).getBlockTypes();
7269 }
7270
7271 /**
7272 * Returns the block support value for a feature, if defined.
7273 *
7274 * @param {(string|Object)} nameOrType Block name or type object
7275 * @param {string} feature Feature to retrieve
7276 * @param {*} defaultSupports Default value to return if not
7277 * explicitly defined
7278 *
7279 * @return {?*} Block support value
7280 */
7281 function getBlockSupport(nameOrType, feature, defaultSupports) {
7282 return (0,external_wp_data_namespaceObject.select)(store).getBlockSupport(nameOrType, feature, defaultSupports);
7283 }
7284
7285 /**
7286 * Returns true if the block defines support for a feature, or false otherwise.
7287 *
7288 * @param {(string|Object)} nameOrType Block name or type object.
7289 * @param {string} feature Feature to test.
7290 * @param {boolean} defaultSupports Whether feature is supported by
7291 * default if not explicitly defined.
7292 *
7293 * @return {boolean} Whether block supports feature.
7294 */
7295 function hasBlockSupport(nameOrType, feature, defaultSupports) {
7296 return (0,external_wp_data_namespaceObject.select)(store).hasBlockSupport(nameOrType, feature, defaultSupports);
7297 }
7298
7299 /**
7300 * Determines whether or not the given block is a reusable block. This is a
7301 * special block type that is used to point to a global block stored via the
7302 * API.
7303 *
7304 * @param {Object} blockOrType Block or Block Type to test.
7305 *
7306 * @return {boolean} Whether the given block is a reusable block.
7307 */
7308 function isReusableBlock(blockOrType) {
7309 return blockOrType?.name === 'core/block';
7310 }
7311
7312 /**
7313 * Determines whether or not the given block is a template part. This is a
7314 * special block type that allows composing a page template out of reusable
7315 * design elements.
7316 *
7317 * @param {Object} blockOrType Block or Block Type to test.
7318 *
7319 * @return {boolean} Whether the given block is a template part.
7320 */
7321 function isTemplatePart(blockOrType) {
7322 return blockOrType?.name === 'core/template-part';
7323 }
7324
7325 /**
7326 * Returns an array with the child blocks of a given block.
7327 *
7328 * @param {string} blockName Name of block (example: “latest-posts”).
7329 *
7330 * @return {Array} Array of child block names.
7331 */
7332 const getChildBlockNames = blockName => {
7333 return (0,external_wp_data_namespaceObject.select)(store).getChildBlockNames(blockName);
7334 };
7335
7336 /**
7337 * Returns a boolean indicating if a block has child blocks or not.
7338 *
7339 * @param {string} blockName Name of block (example: “latest-posts”).
7340 *
7341 * @return {boolean} True if a block contains child blocks and false otherwise.
7342 */
7343 const hasChildBlocks = blockName => {
7344 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocks(blockName);
7345 };
7346
7347 /**
7348 * Returns a boolean indicating if a block has at least one child block with inserter support.
7349 *
7350 * @param {string} blockName Block type name.
7351 *
7352 * @return {boolean} True if a block contains at least one child blocks with inserter support
7353 * and false otherwise.
7354 */
7355 const hasChildBlocksWithInserterSupport = blockName => {
7356 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocksWithInserterSupport(blockName);
7357 };
7358
7359 /**
7360 * Registers a new block style for the given block types.
7361 *
7362 * For more information on connecting the styles with CSS
7363 * [the official documentation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/#styles).
7364 *
7365 * @param {string|Array} blockNames Name of blocks e.g. “core/latest-posts” or `["core/group", "core/columns"]`.
7366 * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
7367 *
7368 * @example
7369 * ```js
7370 * import { __ } from '@wordpress/i18n';
7371 * import { registerBlockStyle } from '@wordpress/blocks';
7372 * import { Button } from '@wordpress/components';
7373 *
7374 *
7375 * const ExampleComponent = () => {
7376 * return (
7377 * <Button
7378 * onClick={ () => {
7379 * registerBlockStyle( 'core/quote', {
7380 * name: 'fancy-quote',
7381 * label: __( 'Fancy Quote' ),
7382 * } );
7383 * } }
7384 * >
7385 * { __( 'Add a new block style for core/quote' ) }
7386 * </Button>
7387 * );
7388 * };
7389 * ```
7390 */
7391 const registerBlockStyle = (blockNames, styleVariation) => {
7392 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockStyles(blockNames, styleVariation);
7393 };
7394
7395 /**
7396 * Unregisters a block style for the given block.
7397 *
7398 * @param {string} blockName Name of block (example: “core/latest-posts”).
7399 * @param {string} styleVariationName Name of class applied to the block.
7400 *
7401 * @example
7402 * ```js
7403 * import { __ } from '@wordpress/i18n';
7404 * import { unregisterBlockStyle } from '@wordpress/blocks';
7405 * import { Button } from '@wordpress/components';
7406 *
7407 * const ExampleComponent = () => {
7408 * return (
7409 * <Button
7410 * onClick={ () => {
7411 * unregisterBlockStyle( 'core/quote', 'plain' );
7412 * } }
7413 * >
7414 * { __( 'Remove the "Plain" block style for core/quote' ) }
7415 * </Button>
7416 * );
7417 * };
7418 * ```
7419 */
7420 const unregisterBlockStyle = (blockName, styleVariationName) => {
7421 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockStyles(blockName, styleVariationName);
7422 };
7423
7424 /**
7425 * Returns an array with the variations of a given block type.
7426 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
7427 *
7428 * @ignore
7429 *
7430 * @param {string} blockName Name of block (example: “core/columns”).
7431 * @param {WPBlockVariationScope} [scope] Block variation scope name.
7432 *
7433 * @return {(WPBlockVariation[]|void)} Block variations.
7434 */
7435 const getBlockVariations = (blockName, scope) => {
7436 return (0,external_wp_data_namespaceObject.select)(store).getBlockVariations(blockName, scope);
7437 };
7438
7439 /**
7440 * Registers a new block variation for the given block type.
7441 *
7442 * For more information on block variations see
7443 * [the official documentation ](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/).
7444 *
7445 * @param {string} blockName Name of the block (example: “core/columns”).
7446 * @param {WPBlockVariation} variation Object describing a block variation.
7447 *
7448 * @example
7449 * ```js
7450 * import { __ } from '@wordpress/i18n';
7451 * import { registerBlockVariation } from '@wordpress/blocks';
7452 * import { Button } from '@wordpress/components';
7453 *
7454 * const ExampleComponent = () => {
7455 * return (
7456 * <Button
7457 * onClick={ () => {
7458 * registerBlockVariation( 'core/embed', {
7459 * name: 'custom',
7460 * title: __( 'My Custom Embed' ),
7461 * attributes: { providerNameSlug: 'custom' },
7462 * } );
7463 * } }
7464 * >
7465 * __( 'Add a custom variation for core/embed' ) }
7466 * </Button>
7467 * );
7468 * };
7469 * ```
7470 */
7471 const registerBlockVariation = (blockName, variation) => {
7472 if (typeof variation.name !== 'string') {
7473 false ? 0 : void 0;
7474 }
7475 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockVariations(blockName, variation);
7476 };
7477
7478 /**
7479 * Unregisters a block variation defined for the given block type.
7480 *
7481 * @param {string} blockName Name of the block (example: “core/columns”).
7482 * @param {string} variationName Name of the variation defined for the block.
7483 *
7484 * @example
7485 * ```js
7486 * import { __ } from '@wordpress/i18n';
7487 * import { unregisterBlockVariation } from '@wordpress/blocks';
7488 * import { Button } from '@wordpress/components';
7489 *
7490 * const ExampleComponent = () => {
7491 * return (
7492 * <Button
7493 * onClick={ () => {
7494 * unregisterBlockVariation( 'core/embed', 'youtube' );
7495 * } }
7496 * >
7497 * { __( 'Remove the YouTube variation from core/embed' ) }
7498 * </Button>
7499 * );
7500 * };
7501 * ```
7502 */
7503 const unregisterBlockVariation = (blockName, variationName) => {
7504 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockVariations(blockName, variationName);
7505 };
7506
7507 /**
7508 * Registers a new block bindings source with an object defining its
7509 * behavior. Once registered, the source is available to be connected
7510 * to the supported block attributes.
7511 *
7512 * @param {Object} source Properties of the source to be registered.
7513 * @param {string} source.name The unique and machine-readable name.
7514 * @param {string} [source.label] Human-readable label.
7515 * @param {Array} [source.usesContext] Array of context needed by the source only in the editor.
7516 * @param {Function} [source.getValues] Function to get the values from the source.
7517 * @param {Function} [source.setValues] Function to update multiple values connected to the source.
7518 * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined.
7519 * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value.
7520 *
7521 * @example
7522 * ```js
7523 * import { _x } from '@wordpress/i18n';
7524 * import { registerBlockBindingsSource } from '@wordpress/blocks'
7525 *
7526 * registerBlockBindingsSource( {
7527 * name: 'plugin/my-custom-source',
7528 * label: _x( 'My Custom Source', 'block bindings source' ),
7529 * getValues: () => getSourceValues(),
7530 * setValues: () => updateMyCustomValuesInBatch(),
7531 * getPlaceholder: () => 'Placeholder text when the value is undefined',
7532 * canUserEditValue: () => true,
7533 * } );
7534 * ```
7535 */
7536 const registerBlockBindingsSource = source => {
7537 const {
7538 name,
7539 label,
7540 usesContext,
7541 getValues,
7542 setValues,
7543 getPlaceholder,
7544 canUserEditValue
7545 } = source;
7546 const existingSource = unlock((0,external_wp_data_namespaceObject.select)(store)).getBlockBindingsSource(name);
7547
7548 /*
7549 * Check if the source has been already registered on the client.
7550 * If the `getValues` property is defined, it could be assumed the source is already registered.
7551 */
7552 if (existingSource?.getValues) {
7553 false ? 0 : void 0;
7554 return;
7555 }
7556
7557 // Check the `name` property is correct.
7558 if (!name) {
7559 false ? 0 : void 0;
7560 return;
7561 }
7562 if (typeof name !== 'string') {
7563 false ? 0 : void 0;
7564 return;
7565 }
7566 if (/[A-Z]+/.test(name)) {
7567 false ? 0 : void 0;
7568 return;
7569 }
7570 if (!/^[a-z0-9/-]+$/.test(name)) {
7571 false ? 0 : void 0;
7572 return;
7573 }
7574 if (!/^[a-z0-9-]+\/[a-z0-9-]+$/.test(name)) {
7575 false ? 0 : void 0;
7576 return;
7577 }
7578
7579 // Check the `label` property is correct.
7580 if (label && existingSource?.label) {
7581 false ? 0 : void 0;
7582 return;
7583 }
7584 if (!label && !existingSource?.label) {
7585 false ? 0 : void 0;
7586 return;
7587 }
7588 if (label && typeof label !== 'string') {
7589 false ? 0 : void 0;
7590 return;
7591 }
7592
7593 // Check the `usesContext` property is correct.
7594 if (usesContext && !Array.isArray(usesContext)) {
7595 false ? 0 : void 0;
7596 return;
7597 }
7598
7599 // Check the `getValues` property is correct.
7600 if (getValues && typeof getValues !== 'function') {
7601 false ? 0 : void 0;
7602 return;
7603 }
7604
7605 // Check the `setValues` property is correct.
7606 if (setValues && typeof setValues !== 'function') {
7607 false ? 0 : void 0;
7608 return;
7609 }
7610
7611 // Check the `getPlaceholder` property is correct.
7612 if (getPlaceholder && typeof getPlaceholder !== 'function') {
7613 false ? 0 : void 0;
7614 return;
7615 }
7616
7617 // Check the `getPlaceholder` property is correct.
7618 if (canUserEditValue && typeof canUserEditValue !== 'function') {
7619 false ? 0 : void 0;
7620 return;
7621 }
7622 return unlock((0,external_wp_data_namespaceObject.dispatch)(store)).addBlockBindingsSource(source);
7623 };
7624
7625 /**
7626 * Unregisters a block bindings source
7627 *
7628 * @param {string} name The name of the block bindings source to unregister.
7629 *
7630 * @example
7631 * ```js
7632 * import { unregisterBlockBindingsSource } from '@wordpress/blocks';
7633 *
7634 * unregisterBlockBindingsSource( 'plugin/my-custom-source' );
7635 * ```
7636 */
7637 function unregisterBlockBindingsSource(name) {
7638 const oldSource = getBlockBindingsSource(name);
7639 if (!oldSource) {
7640 false ? 0 : void 0;
7641 return;
7642 }
7643 unlock((0,external_wp_data_namespaceObject.dispatch)(store)).removeBlockBindingsSource(name);
7644 }
7645
7646 /**
7647 * Returns a registered block bindings source.
7648 *
7649 * @param {string} name Block bindings source name.
7650 *
7651 * @return {?Object} Block bindings source.
7652 */
7653 function getBlockBindingsSource(name) {
7654 return unlock((0,external_wp_data_namespaceObject.select)(store)).getBlockBindingsSource(name);
7655 }
7656
7657 /**
7658 * Returns all registered block bindings sources.
7659 *
7660 * @return {Array} Block bindings sources.
7661 */
7662 function getBlockBindingsSources() {
7663 return unlock((0,external_wp_data_namespaceObject.select)(store)).getAllBlockBindingsSources();
7664 }
7665
7666 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/utils.js
7667 /**
7668 * External dependencies
7669 */
7670
7671
7672
7673
7674 /**
7675 * WordPress dependencies
7676 */
7677
7678
7679
7680
7681
7682 /**
7683 * Internal dependencies
7684 */
7685
7686
7687 k([names, a11y]);
7688
7689 /**
7690 * Array of icon colors containing a color to be used if the icon color
7691 * was not explicitly set but the icon background color was.
7692 *
7693 * @type {Object}
7694 */
7695 const ICON_COLORS = ['#191e23', '#f8f9f9'];
7696
7697 /**
7698 * Determines whether the block's attributes are equal to the default attributes
7699 * which means the block is unmodified.
7700 *
7701 * @param {WPBlock} block Block Object
7702 *
7703 * @return {boolean} Whether the block is an unmodified block.
7704 */
7705 function isUnmodifiedBlock(block) {
7706 var _getBlockType$attribu;
7707 return Object.entries((_getBlockType$attribu = getBlockType(block.name)?.attributes) !== null && _getBlockType$attribu !== void 0 ? _getBlockType$attribu : {}).every(([key, definition]) => {
7708 const value = block.attributes[key];
7709
7710 // Every attribute that has a default must match the default.
7711 if (definition.hasOwnProperty('default')) {
7712 return value === definition.default;
7713 }
7714
7715 // The rich text type is a bit different from the rest because it
7716 // has an implicit default value of an empty RichTextData instance,
7717 // so check the length of the value.
7718 if (definition.type === 'rich-text') {
7719 return !value?.length;
7720 }
7721
7722 // Every attribute that doesn't have a default should be undefined.
7723 return value === undefined;
7724 });
7725 }
7726
7727 /**
7728 * Determines whether the block is a default block and its attributes are equal
7729 * to the default attributes which means the block is unmodified.
7730 *
7731 * @param {WPBlock} block Block Object
7732 *
7733 * @return {boolean} Whether the block is an unmodified default block.
7734 */
7735 function isUnmodifiedDefaultBlock(block) {
7736 return block.name === getDefaultBlockName() && isUnmodifiedBlock(block);
7737 }
7738
7739 /**
7740 * Function that checks if the parameter is a valid icon.
7741 *
7742 * @param {*} icon Parameter to be checked.
7743 *
7744 * @return {boolean} True if the parameter is a valid icon and false otherwise.
7745 */
7746
7747 function isValidIcon(icon) {
7748 return !!icon && (typeof icon === 'string' || (0,external_wp_element_namespaceObject.isValidElement)(icon) || typeof icon === 'function' || icon instanceof external_wp_element_namespaceObject.Component);
7749 }
7750
7751 /**
7752 * Function that receives an icon as set by the blocks during the registration
7753 * and returns a new icon object that is normalized so we can rely on just on possible icon structure
7754 * in the codebase.
7755 *
7756 * @param {WPBlockTypeIconRender} icon Render behavior of a block type icon;
7757 * one of a Dashicon slug, an element, or a
7758 * component.
7759 *
7760 * @return {WPBlockTypeIconDescriptor} Object describing the icon.
7761 */
7762 function normalizeIconObject(icon) {
7763 icon = icon || BLOCK_ICON_DEFAULT;
7764 if (isValidIcon(icon)) {
7765 return {
7766 src: icon
7767 };
7768 }
7769 if ('background' in icon) {
7770 const colordBgColor = w(icon.background);
7771 const getColorContrast = iconColor => colordBgColor.contrast(iconColor);
7772 const maxContrast = Math.max(...ICON_COLORS.map(getColorContrast));
7773 return {
7774 ...icon,
7775 foreground: icon.foreground ? icon.foreground : ICON_COLORS.find(iconColor => getColorContrast(iconColor) === maxContrast),
7776 shadowColor: colordBgColor.alpha(0.3).toRgbString()
7777 };
7778 }
7779 return icon;
7780 }
7781
7782 /**
7783 * Normalizes block type passed as param. When string is passed then
7784 * it converts it to the matching block type object.
7785 * It passes the original object otherwise.
7786 *
7787 * @param {string|Object} blockTypeOrName Block type or name.
7788 *
7789 * @return {?Object} Block type.
7790 */
7791 function normalizeBlockType(blockTypeOrName) {
7792 if (typeof blockTypeOrName === 'string') {
7793 return getBlockType(blockTypeOrName);
7794 }
7795 return blockTypeOrName;
7796 }
7797
7798 /**
7799 * Get the label for the block, usually this is either the block title,
7800 * or the value of the block's `label` function when that's specified.
7801 *
7802 * @param {Object} blockType The block type.
7803 * @param {Object} attributes The values of the block's attributes.
7804 * @param {Object} context The intended use for the label.
7805 *
7806 * @return {string} The block label.
7807 */
7808 function getBlockLabel(blockType, attributes, context = 'visual') {
7809 const {
7810 __experimentalLabel: getLabel,
7811 title
7812 } = blockType;
7813 const label = getLabel && getLabel(attributes, {
7814 context
7815 });
7816 if (!label) {
7817 return title;
7818 }
7819 if (label.toPlainText) {
7820 return label.toPlainText();
7821 }
7822
7823 // Strip any HTML (i.e. RichText formatting) before returning.
7824 return (0,external_wp_dom_namespaceObject.__unstableStripHTML)(label);
7825 }
7826
7827 /**
7828 * Get a label for the block for use by screenreaders, this is more descriptive
7829 * than the visual label and includes the block title and the value of the
7830 * `getLabel` function if it's specified.
7831 *
7832 * @param {?Object} blockType The block type.
7833 * @param {Object} attributes The values of the block's attributes.
7834 * @param {?number} position The position of the block in the block list.
7835 * @param {string} [direction='vertical'] The direction of the block layout.
7836 *
7837 * @return {string} The block label.
7838 */
7839 function getAccessibleBlockLabel(blockType, attributes, position, direction = 'vertical') {
7840 // `title` is already localized, `label` is a user-supplied value.
7841 const title = blockType?.title;
7842 const label = blockType ? getBlockLabel(blockType, attributes, 'accessibility') : '';
7843 const hasPosition = position !== undefined;
7844
7845 // getBlockLabel returns the block title as a fallback when there's no label,
7846 // if it did return the title, this function needs to avoid adding the
7847 // title twice within the accessible label. Use this `hasLabel` boolean to
7848 // handle that.
7849 const hasLabel = label && label !== title;
7850 if (hasPosition && direction === 'vertical') {
7851 if (hasLabel) {
7852 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */
7853 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d. %3$s'), title, position, label);
7854 }
7855 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. 1: The block title. 2: The block row number. */
7856 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d'), title, position);
7857 } else if (hasPosition && direction === 'horizontal') {
7858 if (hasLabel) {
7859 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */
7860 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d. %3$s'), title, position, label);
7861 }
7862 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. 1: The block title. 2: The block column number. */
7863 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d'), title, position);
7864 }
7865 if (hasLabel) {
7866 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. %1: The block title. %2: The block label. */
7867 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. %2$s'), title, label);
7868 }
7869 return (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: accessibility text. %s: The block title. */
7870 (0,external_wp_i18n_namespaceObject.__)('%s Block'), title);
7871 }
7872 function getDefault(attributeSchema) {
7873 if (attributeSchema.default !== undefined) {
7874 return attributeSchema.default;
7875 }
7876 if (attributeSchema.type === 'rich-text') {
7877 return new external_wp_richText_namespaceObject.RichTextData();
7878 }
7879 }
7880
7881 /**
7882 * Ensure attributes contains only values defined by block type, and merge
7883 * default values for missing attributes.
7884 *
7885 * @param {string} name The block's name.
7886 * @param {Object} attributes The block's attributes.
7887 * @return {Object} The sanitized attributes.
7888 */
7889 function __experimentalSanitizeBlockAttributes(name, attributes) {
7890 // Get the type definition associated with a registered block.
7891 const blockType = getBlockType(name);
7892 if (undefined === blockType) {
7893 throw new Error(`Block type '${name}' is not registered.`);
7894 }
7895 return Object.entries(blockType.attributes).reduce((accumulator, [key, schema]) => {
7896 const value = attributes[key];
7897 if (undefined !== value) {
7898 if (schema.type === 'rich-text') {
7899 if (value instanceof external_wp_richText_namespaceObject.RichTextData) {
7900 accumulator[key] = value;
7901 } else if (typeof value === 'string') {
7902 accumulator[key] = external_wp_richText_namespaceObject.RichTextData.fromHTMLString(value);
7903 }
7904 } else if (schema.type === 'string' && value instanceof external_wp_richText_namespaceObject.RichTextData) {
7905 accumulator[key] = value.toHTMLString();
7906 } else {
7907 accumulator[key] = value;
7908 }
7909 } else {
7910 const _default = getDefault(schema);
7911 if (undefined !== _default) {
7912 accumulator[key] = _default;
7913 }
7914 }
7915 if (['node', 'children'].indexOf(schema.source) !== -1) {
7916 // Ensure value passed is always an array, which we're expecting in
7917 // the RichText component to handle the deprecated value.
7918 if (typeof accumulator[key] === 'string') {
7919 accumulator[key] = [accumulator[key]];
7920 } else if (!Array.isArray(accumulator[key])) {
7921 accumulator[key] = [];
7922 }
7923 }
7924 return accumulator;
7925 }, {});
7926 }
7927
7928 /**
7929 * Filter block attributes by `role` and return their names.
7930 *
7931 * @param {string} name Block attribute's name.
7932 * @param {string} role The role of a block attribute.
7933 *
7934 * @return {string[]} The attribute names that have the provided role.
7935 */
7936 function __experimentalGetBlockAttributesNamesByRole(name, role) {
7937 const attributes = getBlockType(name)?.attributes;
7938 if (!attributes) {
7939 return [];
7940 }
7941 const attributesNames = Object.keys(attributes);
7942 if (!role) {
7943 return attributesNames;
7944 }
7945 return attributesNames.filter(attributeName => attributes[attributeName]?.__experimentalRole === role);
7946 }
7947
7948 /**
7949 * Return a new object with the specified keys omitted.
7950 *
7951 * @param {Object} object Original object.
7952 * @param {Array} keys Keys to be omitted.
7953 *
7954 * @return {Object} Object with omitted keys.
7955 */
7956 function omit(object, keys) {
7957 return Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key)));
7958 }
7959
7960 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/reducer.js
7961 /**
7962 * External dependencies
7963 */
7964
7965
7966 /**
7967 * WordPress dependencies
7968 */
7969
7970
7971
7972 /**
7973 * Internal dependencies
7974 */
7975
7976
7977 /**
7978 * @typedef {Object} WPBlockCategory
7979 *
7980 * @property {string} slug Unique category slug.
7981 * @property {string} title Category label, for display in user interface.
7982 */
7983
7984 /**
7985 * Default set of categories.
7986 *
7987 * @type {WPBlockCategory[]}
7988 */
7989 const DEFAULT_CATEGORIES = [{
7990 slug: 'text',
7991 title: (0,external_wp_i18n_namespaceObject.__)('Text')
7992 }, {
7993 slug: 'media',
7994 title: (0,external_wp_i18n_namespaceObject.__)('Media')
7995 }, {
7996 slug: 'design',
7997 title: (0,external_wp_i18n_namespaceObject.__)('Design')
7998 }, {
7999 slug: 'widgets',
8000 title: (0,external_wp_i18n_namespaceObject.__)('Widgets')
8001 }, {
8002 slug: 'theme',
8003 title: (0,external_wp_i18n_namespaceObject.__)('Theme')
8004 }, {
8005 slug: 'embed',
8006 title: (0,external_wp_i18n_namespaceObject.__)('Embeds')
8007 }, {
8008 slug: 'reusable',
8009 title: (0,external_wp_i18n_namespaceObject.__)('Reusable blocks')
8010 }];
8011
8012 // Key block types by their name.
8013 function keyBlockTypesByName(types) {
8014 return types.reduce((newBlockTypes, block) => ({
8015 ...newBlockTypes,
8016 [block.name]: block
8017 }), {});
8018 }
8019
8020 // Filter items to ensure they're unique by their name.
8021 function getUniqueItemsByName(items) {
8022 return items.reduce((acc, currentItem) => {
8023 if (!acc.some(item => item.name === currentItem.name)) {
8024 acc.push(currentItem);
8025 }
8026 return acc;
8027 }, []);
8028 }
8029 function bootstrappedBlockTypes(state = {}, action) {
8030 switch (action.type) {
8031 case 'ADD_BOOTSTRAPPED_BLOCK_TYPE':
8032 const {
8033 name,
8034 blockType
8035 } = action;
8036 const serverDefinition = state[name];
8037 let newDefinition;
8038 // Don't overwrite if already set. It covers the case when metadata
8039 // was initialized from the server.
8040 if (serverDefinition) {
8041 // The `blockHooks` prop is not yet included in the server provided
8042 // definitions and needs to be polyfilled. This can be removed when the
8043 // minimum supported WordPress is >= 6.4.
8044 if (serverDefinition.blockHooks === undefined && blockType.blockHooks) {
8045 newDefinition = {
8046 ...serverDefinition,
8047 ...newDefinition,
8048 blockHooks: blockType.blockHooks
8049 };
8050 }
8051
8052 // The `allowedBlocks` prop is not yet included in the server provided
8053 // definitions and needs to be polyfilled. This can be removed when the
8054 // minimum supported WordPress is >= 6.5.
8055 if (serverDefinition.allowedBlocks === undefined && blockType.allowedBlocks) {
8056 newDefinition = {
8057 ...serverDefinition,
8058 ...newDefinition,
8059 allowedBlocks: blockType.allowedBlocks
8060 };
8061 }
8062 } else {
8063 newDefinition = Object.fromEntries(Object.entries(blockType).filter(([, value]) => value !== null && value !== undefined).map(([key, value]) => [camelCase(key), value]));
8064 newDefinition.name = name;
8065 }
8066 if (newDefinition) {
8067 return {
8068 ...state,
8069 [name]: newDefinition
8070 };
8071 }
8072 return state;
8073 case 'REMOVE_BLOCK_TYPES':
8074 return omit(state, action.names);
8075 }
8076 return state;
8077 }
8078
8079 /**
8080 * Reducer managing the unprocessed block types in a form passed when registering the by block.
8081 * It's for internal use only. It allows recomputing the processed block types on-demand after block type filters
8082 * get added or removed.
8083 *
8084 * @param {Object} state Current state.
8085 * @param {Object} action Dispatched action.
8086 *
8087 * @return {Object} Updated state.
8088 */
8089 function unprocessedBlockTypes(state = {}, action) {
8090 switch (action.type) {
8091 case 'ADD_UNPROCESSED_BLOCK_TYPE':
8092 return {
8093 ...state,
8094 [action.name]: action.blockType
8095 };
8096 case 'REMOVE_BLOCK_TYPES':
8097 return omit(state, action.names);
8098 }
8099 return state;
8100 }
8101
8102 /**
8103 * Reducer managing the processed block types with all filters applied.
8104 * The state is derived from the `unprocessedBlockTypes` reducer.
8105 *
8106 * @param {Object} state Current state.
8107 * @param {Object} action Dispatched action.
8108 *
8109 * @return {Object} Updated state.
8110 */
8111 function blockTypes(state = {}, action) {
8112 switch (action.type) {
8113 case 'ADD_BLOCK_TYPES':
8114 return {
8115 ...state,
8116 ...keyBlockTypesByName(action.blockTypes)
8117 };
8118 case 'REMOVE_BLOCK_TYPES':
8119 return omit(state, action.names);
8120 }
8121 return state;
8122 }
8123
8124 /**
8125 * Reducer managing the block styles.
8126 *
8127 * @param {Object} state Current state.
8128 * @param {Object} action Dispatched action.
8129 *
8130 * @return {Object} Updated state.
8131 */
8132 function blockStyles(state = {}, action) {
8133 var _state$action$blockNa;
8134 switch (action.type) {
8135 case 'ADD_BLOCK_TYPES':
8136 return {
8137 ...state,
8138 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8139 var _blockType$styles, _state$blockType$name;
8140 return [name, getUniqueItemsByName([...((_blockType$styles = blockType.styles) !== null && _blockType$styles !== void 0 ? _blockType$styles : []).map(style => ({
8141 ...style,
8142 source: 'block'
8143 })), ...((_state$blockType$name = state[blockType.name]) !== null && _state$blockType$name !== void 0 ? _state$blockType$name : []).filter(({
8144 source
8145 }) => 'block' !== source)])];
8146 }))
8147 };
8148 case 'ADD_BLOCK_STYLES':
8149 const updatedStyles = {};
8150 action.blockNames.forEach(blockName => {
8151 var _state$blockName;
8152 updatedStyles[blockName] = getUniqueItemsByName([...((_state$blockName = state[blockName]) !== null && _state$blockName !== void 0 ? _state$blockName : []), ...action.styles]);
8153 });
8154 return {
8155 ...state,
8156 ...updatedStyles
8157 };
8158 case 'REMOVE_BLOCK_STYLES':
8159 return {
8160 ...state,
8161 [action.blockName]: ((_state$action$blockNa = state[action.blockName]) !== null && _state$action$blockNa !== void 0 ? _state$action$blockNa : []).filter(style => action.styleNames.indexOf(style.name) === -1)
8162 };
8163 }
8164 return state;
8165 }
8166
8167 /**
8168 * Reducer managing the block variations.
8169 *
8170 * @param {Object} state Current state.
8171 * @param {Object} action Dispatched action.
8172 *
8173 * @return {Object} Updated state.
8174 */
8175 function blockVariations(state = {}, action) {
8176 var _state$action$blockNa2, _state$action$blockNa3;
8177 switch (action.type) {
8178 case 'ADD_BLOCK_TYPES':
8179 return {
8180 ...state,
8181 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8182 var _blockType$variations, _state$blockType$name2;
8183 return [name, getUniqueItemsByName([...((_blockType$variations = blockType.variations) !== null && _blockType$variations !== void 0 ? _blockType$variations : []).map(variation => ({
8184 ...variation,
8185 source: 'block'
8186 })), ...((_state$blockType$name2 = state[blockType.name]) !== null && _state$blockType$name2 !== void 0 ? _state$blockType$name2 : []).filter(({
8187 source
8188 }) => 'block' !== source)])];
8189 }))
8190 };
8191 case 'ADD_BLOCK_VARIATIONS':
8192 return {
8193 ...state,
8194 [action.blockName]: getUniqueItemsByName([...((_state$action$blockNa2 = state[action.blockName]) !== null && _state$action$blockNa2 !== void 0 ? _state$action$blockNa2 : []), ...action.variations])
8195 };
8196 case 'REMOVE_BLOCK_VARIATIONS':
8197 return {
8198 ...state,
8199 [action.blockName]: ((_state$action$blockNa3 = state[action.blockName]) !== null && _state$action$blockNa3 !== void 0 ? _state$action$blockNa3 : []).filter(variation => action.variationNames.indexOf(variation.name) === -1)
8200 };
8201 }
8202 return state;
8203 }
8204
8205 /**
8206 * Higher-order Reducer creating a reducer keeping track of given block name.
8207 *
8208 * @param {string} setActionType Action type.
8209 *
8210 * @return {Function} Reducer.
8211 */
8212 function createBlockNameSetterReducer(setActionType) {
8213 return (state = null, action) => {
8214 switch (action.type) {
8215 case 'REMOVE_BLOCK_TYPES':
8216 if (action.names.indexOf(state) !== -1) {
8217 return null;
8218 }
8219 return state;
8220 case setActionType:
8221 return action.name || null;
8222 }
8223 return state;
8224 };
8225 }
8226 const defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
8227 const freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
8228 const unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
8229 const groupingBlockName = createBlockNameSetterReducer('SET_GROUPING_BLOCK_NAME');
8230
8231 /**
8232 * Reducer managing the categories
8233 *
8234 * @param {WPBlockCategory[]} state Current state.
8235 * @param {Object} action Dispatched action.
8236 *
8237 * @return {WPBlockCategory[]} Updated state.
8238 */
8239 function categories(state = DEFAULT_CATEGORIES, action) {
8240 switch (action.type) {
8241 case 'SET_CATEGORIES':
8242 return action.categories || [];
8243 case 'UPDATE_CATEGORY':
8244 {
8245 if (!action.category || !Object.keys(action.category).length) {
8246 return state;
8247 }
8248 const categoryToChange = state.find(({
8249 slug
8250 }) => slug === action.slug);
8251 if (categoryToChange) {
8252 return state.map(category => {
8253 if (category.slug === action.slug) {
8254 return {
8255 ...category,
8256 ...action.category
8257 };
8258 }
8259 return category;
8260 });
8261 }
8262 }
8263 }
8264 return state;
8265 }
8266 function collections(state = {}, action) {
8267 switch (action.type) {
8268 case 'ADD_BLOCK_COLLECTION':
8269 return {
8270 ...state,
8271 [action.namespace]: {
8272 title: action.title,
8273 icon: action.icon
8274 }
8275 };
8276 case 'REMOVE_BLOCK_COLLECTION':
8277 return omit(state, action.namespace);
8278 }
8279 return state;
8280 }
8281 function blockBindingsSources(state = {}, action) {
8282 switch (action.type) {
8283 case 'ADD_BLOCK_BINDINGS_SOURCE':
8284 // Merge usesContext with existing values, potentially defined in the server registration.
8285 let mergedUsesContext = [...(state[action.name]?.usesContext || []), ...(action.usesContext || [])];
8286 // Remove duplicates.
8287 mergedUsesContext = mergedUsesContext.length > 0 ? [...new Set(mergedUsesContext)] : undefined;
8288 return {
8289 ...state,
8290 [action.name]: {
8291 // Don't override the label if it's already set.
8292 label: state[action.name]?.label || action.label,
8293 usesContext: mergedUsesContext,
8294 getValues: action.getValues,
8295 setValues: action.setValues,
8296 getPlaceholder: action.getPlaceholder,
8297 canUserEditValue: action.canUserEditValue
8298 }
8299 };
8300 case 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE':
8301 return {
8302 ...state,
8303 [action.name]: {
8304 label: action.label,
8305 usesContext: action.usesContext
8306 }
8307 };
8308 case 'REMOVE_BLOCK_BINDINGS_SOURCE':
8309 return omit(state, action.name);
8310 }
8311 return state;
8312 }
8313 /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
8314 bootstrappedBlockTypes,
8315 unprocessedBlockTypes,
8316 blockTypes,
8317 blockStyles,
8318 blockVariations,
8319 defaultBlockName,
8320 freeformFallbackBlockName,
8321 unregisteredFallbackBlockName,
8322 groupingBlockName,
8323 categories,
8324 collections,
8325 blockBindingsSources
8326 }));
8327
8328 // EXTERNAL MODULE: ./node_modules/remove-accents/index.js
8329 var remove_accents = __webpack_require__(4793);
8330 var remove_accents_default = /*#__PURE__*/__webpack_require__.n(remove_accents);
8331 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/utils.js
8332 /**
8333 * Helper util to return a value from a certain path of the object.
8334 * Path is specified as either:
8335 * - a string of properties, separated by dots, for example: "x.y".
8336 * - an array of properties, for example `[ 'x', 'y' ]`.
8337 * You can also specify a default value in case the result is nullish.
8338 *
8339 * @param {Object} object Input object.
8340 * @param {string|Array} path Path to the object property.
8341 * @param {*} defaultValue Default value if the value at the specified path is nullish.
8342 * @return {*} Value of the object property at the specified path.
8343 */
8344 const getValueFromObjectPath = (object, path, defaultValue) => {
8345 var _value;
8346 const normalizedPath = Array.isArray(path) ? path : path.split('.');
8347 let value = object;
8348 normalizedPath.forEach(fieldName => {
8349 value = value?.[fieldName];
8350 });
8351 return (_value = value) !== null && _value !== void 0 ? _value : defaultValue;
8352 };
8353 function utils_isObject(candidate) {
8354 return typeof candidate === 'object' && candidate.constructor === Object && candidate !== null;
8355 }
8356
8357 /**
8358 * Determine whether a set of object properties matches a given object.
8359 *
8360 * Given an object of block attributes and an object of variation attributes,
8361 * this function checks recursively whether all the variation attributes are
8362 * present in the block attributes object.
8363 *
8364 * @param {Object} blockAttributes The object to inspect.
8365 * @param {Object} variationAttributes The object of property values to match.
8366 * @return {boolean} Whether the block attributes match the variation attributes.
8367 */
8368 function matchesAttributes(blockAttributes, variationAttributes) {
8369 if (utils_isObject(blockAttributes) && utils_isObject(variationAttributes)) {
8370 return Object.entries(variationAttributes).every(([key, value]) => matchesAttributes(blockAttributes?.[key], value));
8371 }
8372 return blockAttributes === variationAttributes;
8373 }
8374
8375 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/selectors.js
8376 /**
8377 * External dependencies
8378 */
8379
8380
8381 /**
8382 * WordPress dependencies
8383 */
8384
8385
8386
8387 /**
8388 * Internal dependencies
8389 */
8390
8391
8392 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
8393 /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
8394 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
8395
8396 /**
8397 * Given a block name or block type object, returns the corresponding
8398 * normalized block type object.
8399 *
8400 * @param {Object} state Blocks state.
8401 * @param {(string|Object)} nameOrType Block name or type object
8402 *
8403 * @return {Object} Block type object.
8404 */
8405 const getNormalizedBlockType = (state, nameOrType) => 'string' === typeof nameOrType ? selectors_getBlockType(state, nameOrType) : nameOrType;
8406
8407 /**
8408 * Returns all the available block types.
8409 *
8410 * @param {Object} state Data state.
8411 *
8412 * @example
8413 * ```js
8414 * import { store as blocksStore } from '@wordpress/blocks';
8415 * import { useSelect } from '@wordpress/data';
8416 *
8417 * const ExampleComponent = () => {
8418 * const blockTypes = useSelect(
8419 * ( select ) => select( blocksStore ).getBlockTypes(),
8420 * []
8421 * );
8422 *
8423 * return (
8424 * <ul>
8425 * { blockTypes.map( ( block ) => (
8426 * <li key={ block.name }>{ block.title }</li>
8427 * ) ) }
8428 * </ul>
8429 * );
8430 * };
8431 * ```
8432 *
8433 * @return {Array} Block Types.
8434 */
8435 const selectors_getBlockTypes = (0,external_wp_data_namespaceObject.createSelector)(state => Object.values(state.blockTypes), state => [state.blockTypes]);
8436
8437 /**
8438 * Returns a block type by name.
8439 *
8440 * @param {Object} state Data state.
8441 * @param {string} name Block type name.
8442 *
8443 * @example
8444 * ```js
8445 * import { store as blocksStore } from '@wordpress/blocks';
8446 * import { useSelect } from '@wordpress/data';
8447 *
8448 * const ExampleComponent = () => {
8449 * const paragraphBlock = useSelect( ( select ) =>
8450 * ( select ) => select( blocksStore ).getBlockType( 'core/paragraph' ),
8451 * []
8452 * );
8453 *
8454 * return (
8455 * <ul>
8456 * { paragraphBlock &&
8457 * Object.entries( paragraphBlock.supports ).map(
8458 * ( blockSupportsEntry ) => {
8459 * const [ propertyName, value ] = blockSupportsEntry;
8460 * return (
8461 * <li
8462 * key={ propertyName }
8463 * >{ `${ propertyName } : ${ value }` }</li>
8464 * );
8465 * }
8466 * ) }
8467 * </ul>
8468 * );
8469 * };
8470 * ```
8471 *
8472 * @return {Object?} Block Type.
8473 */
8474 function selectors_getBlockType(state, name) {
8475 return state.blockTypes[name];
8476 }
8477
8478 /**
8479 * Returns block styles by block name.
8480 *
8481 * @param {Object} state Data state.
8482 * @param {string} name Block type name.
8483 *
8484 * @example
8485 * ```js
8486 * import { store as blocksStore } from '@wordpress/blocks';
8487 * import { useSelect } from '@wordpress/data';
8488 *
8489 * const ExampleComponent = () => {
8490 * const buttonBlockStyles = useSelect( ( select ) =>
8491 * select( blocksStore ).getBlockStyles( 'core/button' ),
8492 * []
8493 * );
8494 *
8495 * return (
8496 * <ul>
8497 * { buttonBlockStyles &&
8498 * buttonBlockStyles.map( ( style ) => (
8499 * <li key={ style.name }>{ style.label }</li>
8500 * ) ) }
8501 * </ul>
8502 * );
8503 * };
8504 * ```
8505 *
8506 * @return {Array?} Block Styles.
8507 */
8508 function getBlockStyles(state, name) {
8509 return state.blockStyles[name];
8510 }
8511
8512 /**
8513 * Returns block variations by block name.
8514 *
8515 * @param {Object} state Data state.
8516 * @param {string} blockName Block type name.
8517 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8518 *
8519 * @example
8520 * ```js
8521 * import { store as blocksStore } from '@wordpress/blocks';
8522 * import { useSelect } from '@wordpress/data';
8523 *
8524 * const ExampleComponent = () => {
8525 * const socialLinkVariations = useSelect( ( select ) =>
8526 * select( blocksStore ).getBlockVariations( 'core/social-link' ),
8527 * []
8528 * );
8529 *
8530 * return (
8531 * <ul>
8532 * { socialLinkVariations &&
8533 * socialLinkVariations.map( ( variation ) => (
8534 * <li key={ variation.name }>{ variation.title }</li>
8535 * ) ) }
8536 * </ul>
8537 * );
8538 * };
8539 * ```
8540 *
8541 * @return {(WPBlockVariation[]|void)} Block variations.
8542 */
8543 const selectors_getBlockVariations = (0,external_wp_data_namespaceObject.createSelector)((state, blockName, scope) => {
8544 const variations = state.blockVariations[blockName];
8545 if (!variations || !scope) {
8546 return variations;
8547 }
8548 return variations.filter(variation => {
8549 // For backward compatibility reasons, variation's scope defaults to
8550 // `block` and `inserter` when not set.
8551 return (variation.scope || ['block', 'inserter']).includes(scope);
8552 });
8553 }, (state, blockName) => [state.blockVariations[blockName]]);
8554
8555 /**
8556 * Returns the active block variation for a given block based on its attributes.
8557 * Variations are determined by their `isActive` property.
8558 * Which is either an array of block attribute keys or a function.
8559 *
8560 * In case of an array of block attribute keys, the `attributes` are compared
8561 * to the variation's attributes using strict equality check.
8562 *
8563 * In case of function type, the function should accept a block's attributes
8564 * and the variation's attributes and determines if a variation is active.
8565 * A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
8566 *
8567 * @param {Object} state Data state.
8568 * @param {string} blockName Name of block (example: “core/columns”).
8569 * @param {Object} attributes Block attributes used to determine active variation.
8570 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8571 *
8572 * @example
8573 * ```js
8574 * import { __ } from '@wordpress/i18n';
8575 * import { store as blocksStore } from '@wordpress/blocks';
8576 * import { store as blockEditorStore } from '@wordpress/block-editor';
8577 * import { useSelect } from '@wordpress/data';
8578 *
8579 * const ExampleComponent = () => {
8580 * // This example assumes that a core/embed block is the first block in the Block Editor.
8581 * const activeBlockVariation = useSelect( ( select ) => {
8582 * // Retrieve the list of blocks.
8583 * const [ firstBlock ] = select( blockEditorStore ).getBlocks()
8584 *
8585 * // Return the active block variation for the first block.
8586 * return select( blocksStore ).getActiveBlockVariation(
8587 * firstBlock.name,
8588 * firstBlock.attributes
8589 * );
8590 * }, [] );
8591 *
8592 * return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
8593 * <p>{ __( 'Spotify variation' ) }</p>
8594 * ) : (
8595 * <p>{ __( 'Other variation' ) }</p>
8596 * );
8597 * };
8598 * ```
8599 *
8600 * @return {(WPBlockVariation|undefined)} Active block variation.
8601 */
8602 function getActiveBlockVariation(state, blockName, attributes, scope) {
8603 const variations = selectors_getBlockVariations(state, blockName, scope);
8604 if (!variations) {
8605 return variations;
8606 }
8607 const blockType = selectors_getBlockType(state, blockName);
8608 const attributeKeys = Object.keys(blockType?.attributes || {});
8609 let match;
8610 let maxMatchedAttributes = 0;
8611 for (const variation of variations) {
8612 if (Array.isArray(variation.isActive)) {
8613 const definedAttributes = variation.isActive.filter(attribute => {
8614 // We support nested attribute paths, e.g. `layout.type`.
8615 // In this case, we need to check if the part before the
8616 // first dot is a known attribute.
8617 const topLevelAttribute = attribute.split('.')[0];
8618 return attributeKeys.includes(topLevelAttribute);
8619 });
8620 const definedAttributesLength = definedAttributes.length;
8621 if (definedAttributesLength === 0) {
8622 continue;
8623 }
8624 const isMatch = definedAttributes.every(attribute => {
8625 const variationAttributeValue = getValueFromObjectPath(variation.attributes, attribute);
8626 if (variationAttributeValue === undefined) {
8627 return false;
8628 }
8629 let blockAttributeValue = getValueFromObjectPath(attributes, attribute);
8630 if (blockAttributeValue instanceof external_wp_richText_namespaceObject.RichTextData) {
8631 blockAttributeValue = blockAttributeValue.toHTMLString();
8632 }
8633 return matchesAttributes(blockAttributeValue, variationAttributeValue);
8634 });
8635 if (isMatch && definedAttributesLength > maxMatchedAttributes) {
8636 match = variation;
8637 maxMatchedAttributes = definedAttributesLength;
8638 }
8639 } else if (variation.isActive?.(attributes, variation.attributes)) {
8640 // If isActive is a function, we cannot know how many attributes it matches.
8641 // This means that we cannot compare the specificity of our matches,
8642 // and simply return the best match we have found.
8643 return match || variation;
8644 }
8645 }
8646 return match;
8647 }
8648
8649 /**
8650 * Returns the default block variation for the given block type.
8651 * When there are multiple variations annotated as the default one,
8652 * the last added item is picked. This simplifies registering overrides.
8653 * When there is no default variation set, it returns the first item.
8654 *
8655 * @param {Object} state Data state.
8656 * @param {string} blockName Block type name.
8657 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8658 *
8659 * @example
8660 * ```js
8661 * import { __, sprintf } from '@wordpress/i18n';
8662 * import { store as blocksStore } from '@wordpress/blocks';
8663 * import { useSelect } from '@wordpress/data';
8664 *
8665 * const ExampleComponent = () => {
8666 * const defaultEmbedBlockVariation = useSelect( ( select ) =>
8667 * select( blocksStore ).getDefaultBlockVariation( 'core/embed' ),
8668 * []
8669 * );
8670 *
8671 * return (
8672 * defaultEmbedBlockVariation && (
8673 * <p>
8674 * { sprintf(
8675 * __( 'core/embed default variation: %s' ),
8676 * defaultEmbedBlockVariation.title
8677 * ) }
8678 * </p>
8679 * )
8680 * );
8681 * };
8682 * ```
8683 *
8684 * @return {?WPBlockVariation} The default block variation.
8685 */
8686 function getDefaultBlockVariation(state, blockName, scope) {
8687 const variations = selectors_getBlockVariations(state, blockName, scope);
8688 const defaultVariation = [...variations].reverse().find(({
8689 isDefault
8690 }) => !!isDefault);
8691 return defaultVariation || variations[0];
8692 }
8693
8694 /**
8695 * Returns all the available block categories.
8696 *
8697 * @param {Object} state Data state.
8698 *
8699 * @example
8700 * ```js
8701 * import { store as blocksStore } from '@wordpress/blocks';
8702 * import { useSelect, } from '@wordpress/data';
8703 *
8704 * const ExampleComponent = () => {
8705 * const blockCategories = useSelect( ( select ) =>
8706 * select( blocksStore ).getCategories(),
8707 * []
8708 * );
8709 *
8710 * return (
8711 * <ul>
8712 * { blockCategories.map( ( category ) => (
8713 * <li key={ category.slug }>{ category.title }</li>
8714 * ) ) }
8715 * </ul>
8716 * );
8717 * };
8718 * ```
8719 *
8720 * @return {WPBlockCategory[]} Categories list.
8721 */
8722 function getCategories(state) {
8723 return state.categories;
8724 }
8725
8726 /**
8727 * Returns all the available collections.
8728 *
8729 * @param {Object} state Data state.
8730 *
8731 * @example
8732 * ```js
8733 * import { store as blocksStore } from '@wordpress/blocks';
8734 * import { useSelect } from '@wordpress/data';
8735 *
8736 * const ExampleComponent = () => {
8737 * const blockCollections = useSelect( ( select ) =>
8738 * select( blocksStore ).getCollections(),
8739 * []
8740 * );
8741 *
8742 * return (
8743 * <ul>
8744 * { Object.values( blockCollections ).length > 0 &&
8745 * Object.values( blockCollections ).map( ( collection ) => (
8746 * <li key={ collection.title }>{ collection.title }</li>
8747 * ) ) }
8748 * </ul>
8749 * );
8750 * };
8751 * ```
8752 *
8753 * @return {Object} Collections list.
8754 */
8755 function getCollections(state) {
8756 return state.collections;
8757 }
8758
8759 /**
8760 * Returns the name of the default block name.
8761 *
8762 * @param {Object} state Data state.
8763 *
8764 * @example
8765 * ```js
8766 * import { __, sprintf } from '@wordpress/i18n';
8767 * import { store as blocksStore } from '@wordpress/blocks';
8768 * import { useSelect } from '@wordpress/data';
8769 *
8770 * const ExampleComponent = () => {
8771 * const defaultBlockName = useSelect( ( select ) =>
8772 * select( blocksStore ).getDefaultBlockName(),
8773 * []
8774 * );
8775 *
8776 * return (
8777 * defaultBlockName && (
8778 * <p>
8779 * { sprintf( __( 'Default block name: %s' ), defaultBlockName ) }
8780 * </p>
8781 * )
8782 * );
8783 * };
8784 * ```
8785 *
8786 * @return {string?} Default block name.
8787 */
8788 function selectors_getDefaultBlockName(state) {
8789 return state.defaultBlockName;
8790 }
8791
8792 /**
8793 * Returns the name of the block for handling non-block content.
8794 *
8795 * @param {Object} state Data state.
8796 *
8797 * @example
8798 * ```js
8799 * import { __, sprintf } from '@wordpress/i18n';
8800 * import { store as blocksStore } from '@wordpress/blocks';
8801 * import { useSelect } from '@wordpress/data';
8802 *
8803 * const ExampleComponent = () => {
8804 * const freeformFallbackBlockName = useSelect( ( select ) =>
8805 * select( blocksStore ).getFreeformFallbackBlockName(),
8806 * []
8807 * );
8808 *
8809 * return (
8810 * freeformFallbackBlockName && (
8811 * <p>
8812 * { sprintf( __(
8813 * 'Freeform fallback block name: %s' ),
8814 * freeformFallbackBlockName
8815 * ) }
8816 * </p>
8817 * )
8818 * );
8819 * };
8820 * ```
8821 *
8822 * @return {string?} Name of the block for handling non-block content.
8823 */
8824 function getFreeformFallbackBlockName(state) {
8825 return state.freeformFallbackBlockName;
8826 }
8827
8828 /**
8829 * Returns the name of the block for handling unregistered blocks.
8830 *
8831 * @param {Object} state Data state.
8832 *
8833 * @example
8834 * ```js
8835 * import { __, sprintf } from '@wordpress/i18n';
8836 * import { store as blocksStore } from '@wordpress/blocks';
8837 * import { useSelect } from '@wordpress/data';
8838 *
8839 * const ExampleComponent = () => {
8840 * const unregisteredFallbackBlockName = useSelect( ( select ) =>
8841 * select( blocksStore ).getUnregisteredFallbackBlockName(),
8842 * []
8843 * );
8844 *
8845 * return (
8846 * unregisteredFallbackBlockName && (
8847 * <p>
8848 * { sprintf( __(
8849 * 'Unregistered fallback block name: %s' ),
8850 * unregisteredFallbackBlockName
8851 * ) }
8852 * </p>
8853 * )
8854 * );
8855 * };
8856 * ```
8857 *
8858 * @return {string?} Name of the block for handling unregistered blocks.
8859 */
8860 function getUnregisteredFallbackBlockName(state) {
8861 return state.unregisteredFallbackBlockName;
8862 }
8863
8864 /**
8865 * Returns the name of the block for handling the grouping of blocks.
8866 *
8867 * @param {Object} state Data state.
8868 *
8869 * @example
8870 * ```js
8871 * import { __, sprintf } from '@wordpress/i18n';
8872 * import { store as blocksStore } from '@wordpress/blocks';
8873 * import { useSelect } from '@wordpress/data';
8874 *
8875 * const ExampleComponent = () => {
8876 * const groupingBlockName = useSelect( ( select ) =>
8877 * select( blocksStore ).getGroupingBlockName(),
8878 * []
8879 * );
8880 *
8881 * return (
8882 * groupingBlockName && (
8883 * <p>
8884 * { sprintf(
8885 * __( 'Default grouping block name: %s' ),
8886 * groupingBlockName
8887 * ) }
8888 * </p>
8889 * )
8890 * );
8891 * };
8892 * ```
8893 *
8894 * @return {string?} Name of the block for handling the grouping of blocks.
8895 */
8896 function selectors_getGroupingBlockName(state) {
8897 return state.groupingBlockName;
8898 }
8899
8900 /**
8901 * Returns an array with the child blocks of a given block.
8902 *
8903 * @param {Object} state Data state.
8904 * @param {string} blockName Block type name.
8905 *
8906 * @example
8907 * ```js
8908 * import { store as blocksStore } from '@wordpress/blocks';
8909 * import { useSelect } from '@wordpress/data';
8910 *
8911 * const ExampleComponent = () => {
8912 * const childBlockNames = useSelect( ( select ) =>
8913 * select( blocksStore ).getChildBlockNames( 'core/navigation' ),
8914 * []
8915 * );
8916 *
8917 * return (
8918 * <ul>
8919 * { childBlockNames &&
8920 * childBlockNames.map( ( child ) => (
8921 * <li key={ child }>{ child }</li>
8922 * ) ) }
8923 * </ul>
8924 * );
8925 * };
8926 * ```
8927 *
8928 * @return {Array} Array of child block names.
8929 */
8930 const selectors_getChildBlockNames = (0,external_wp_data_namespaceObject.createSelector)((state, blockName) => {
8931 return selectors_getBlockTypes(state).filter(blockType => {
8932 return blockType.parent?.includes(blockName);
8933 }).map(({
8934 name
8935 }) => name);
8936 }, state => [state.blockTypes]);
8937
8938 /**
8939 * Returns the block support value for a feature, if defined.
8940 *
8941 * @param {Object} state Data state.
8942 * @param {(string|Object)} nameOrType Block name or type object
8943 * @param {Array|string} feature Feature to retrieve
8944 * @param {*} defaultSupports Default value to return if not
8945 * explicitly defined
8946 *
8947 * @example
8948 * ```js
8949 * import { __, sprintf } from '@wordpress/i18n';
8950 * import { store as blocksStore } from '@wordpress/blocks';
8951 * import { useSelect } from '@wordpress/data';
8952 *
8953 * const ExampleComponent = () => {
8954 * const paragraphBlockSupportValue = useSelect( ( select ) =>
8955 * select( blocksStore ).getBlockSupport( 'core/paragraph', 'anchor' ),
8956 * []
8957 * );
8958 *
8959 * return (
8960 * <p>
8961 * { sprintf(
8962 * __( 'core/paragraph supports.anchor value: %s' ),
8963 * paragraphBlockSupportValue
8964 * ) }
8965 * </p>
8966 * );
8967 * };
8968 * ```
8969 *
8970 * @return {?*} Block support value
8971 */
8972 const selectors_getBlockSupport = (state, nameOrType, feature, defaultSupports) => {
8973 const blockType = getNormalizedBlockType(state, nameOrType);
8974 if (!blockType?.supports) {
8975 return defaultSupports;
8976 }
8977 return getValueFromObjectPath(blockType.supports, feature, defaultSupports);
8978 };
8979
8980 /**
8981 * Returns true if the block defines support for a feature, or false otherwise.
8982 *
8983 * @param {Object} state Data state.
8984 * @param {(string|Object)} nameOrType Block name or type object.
8985 * @param {string} feature Feature to test.
8986 * @param {boolean} defaultSupports Whether feature is supported by
8987 * default if not explicitly defined.
8988 *
8989 * @example
8990 * ```js
8991 * import { __, sprintf } from '@wordpress/i18n';
8992 * import { store as blocksStore } from '@wordpress/blocks';
8993 * import { useSelect } from '@wordpress/data';
8994 *
8995 * const ExampleComponent = () => {
8996 * const paragraphBlockSupportClassName = useSelect( ( select ) =>
8997 * select( blocksStore ).hasBlockSupport( 'core/paragraph', 'className' ),
8998 * []
8999 * );
9000 *
9001 * return (
9002 * <p>
9003 * { sprintf(
9004 * __( 'core/paragraph supports custom class name?: %s' ),
9005 * paragraphBlockSupportClassName
9006 * ) }
9007 * /p>
9008 * );
9009 * };
9010 * ```
9011 *
9012 * @return {boolean} Whether block supports feature.
9013 */
9014 function selectors_hasBlockSupport(state, nameOrType, feature, defaultSupports) {
9015 return !!selectors_getBlockSupport(state, nameOrType, feature, defaultSupports);
9016 }
9017
9018 /**
9019 * Normalizes a search term string: removes accents, converts to lowercase, removes extra whitespace.
9020 *
9021 * @param {string|null|undefined} term Search term to normalize.
9022 * @return {string} Normalized search term.
9023 */
9024 function getNormalizedSearchTerm(term) {
9025 return remove_accents_default()(term !== null && term !== void 0 ? term : '').toLowerCase().trim();
9026 }
9027
9028 /**
9029 * Returns true if the block type by the given name or object value matches a
9030 * search term, or false otherwise.
9031 *
9032 * @param {Object} state Blocks state.
9033 * @param {(string|Object)} nameOrType Block name or type object.
9034 * @param {string} searchTerm Search term by which to filter.
9035 *
9036 * @example
9037 * ```js
9038 * import { __, sprintf } from '@wordpress/i18n';
9039 * import { store as blocksStore } from '@wordpress/blocks';
9040 * import { useSelect } from '@wordpress/data';
9041 *
9042 * const ExampleComponent = () => {
9043 * const termFound = useSelect(
9044 * ( select ) =>
9045 * select( blocksStore ).isMatchingSearchTerm(
9046 * 'core/navigation',
9047 * 'theme'
9048 * ),
9049 * []
9050 * );
9051 *
9052 * return (
9053 * <p>
9054 * { sprintf(
9055 * __(
9056 * 'Search term was found in the title, keywords, category or description in block.json: %s'
9057 * ),
9058 * termFound
9059 * ) }
9060 * </p>
9061 * );
9062 * };
9063 * ```
9064 *
9065 * @return {Object[]} Whether block type matches search term.
9066 */
9067 function isMatchingSearchTerm(state, nameOrType, searchTerm = '') {
9068 const blockType = getNormalizedBlockType(state, nameOrType);
9069 const normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
9070 const isSearchMatch = candidate => getNormalizedSearchTerm(candidate).includes(normalizedSearchTerm);
9071 return isSearchMatch(blockType.title) || blockType.keywords?.some(isSearchMatch) || isSearchMatch(blockType.category) || typeof blockType.description === 'string' && isSearchMatch(blockType.description);
9072 }
9073
9074 /**
9075 * Returns a boolean indicating if a block has child blocks or not.
9076 *
9077 * @param {Object} state Data state.
9078 * @param {string} blockName Block type name.
9079 *
9080 * @example
9081 * ```js
9082 * import { __, sprintf } from '@wordpress/i18n';
9083 * import { store as blocksStore } from '@wordpress/blocks';
9084 * import { useSelect } from '@wordpress/data';
9085 *
9086 * const ExampleComponent = () => {
9087 * const navigationBlockHasChildBlocks = useSelect( ( select ) =>
9088 * select( blocksStore ).hasChildBlocks( 'core/navigation' ),
9089 * []
9090 * );
9091 *
9092 * return (
9093 * <p>
9094 * { sprintf(
9095 * __( 'core/navigation has child blocks: %s' ),
9096 * navigationBlockHasChildBlocks
9097 * ) }
9098 * </p>
9099 * );
9100 * };
9101 * ```
9102 *
9103 * @return {boolean} True if a block contains child blocks and false otherwise.
9104 */
9105 const selectors_hasChildBlocks = (state, blockName) => {
9106 return selectors_getChildBlockNames(state, blockName).length > 0;
9107 };
9108
9109 /**
9110 * Returns a boolean indicating if a block has at least one child block with inserter support.
9111 *
9112 * @param {Object} state Data state.
9113 * @param {string} blockName Block type name.
9114 *
9115 * @example
9116 * ```js
9117 * import { __, sprintf } from '@wordpress/i18n';
9118 * import { store as blocksStore } from '@wordpress/blocks';
9119 * import { useSelect } from '@wordpress/data';
9120 *
9121 * const ExampleComponent = () => {
9122 * const navigationBlockHasChildBlocksWithInserterSupport = useSelect( ( select ) =>
9123 * select( blocksStore ).hasChildBlocksWithInserterSupport(
9124 * 'core/navigation'
9125 * ),
9126 * []
9127 * );
9128 *
9129 * return (
9130 * <p>
9131 * { sprintf(
9132 * __( 'core/navigation has child blocks with inserter support: %s' ),
9133 * navigationBlockHasChildBlocksWithInserterSupport
9134 * ) }
9135 * </p>
9136 * );
9137 * };
9138 * ```
9139 *
9140 * @return {boolean} True if a block contains at least one child blocks with inserter support
9141 * and false otherwise.
9142 */
9143 const selectors_hasChildBlocksWithInserterSupport = (state, blockName) => {
9144 return selectors_getChildBlockNames(state, blockName).some(childBlockName => {
9145 return selectors_hasBlockSupport(state, childBlockName, 'inserter', true);
9146 });
9147 };
9148
9149 /**
9150 * DO-NOT-USE in production.
9151 * This selector is created for internal/experimental only usage and may be
9152 * removed anytime without any warning, causing breakage on any plugin or theme invoking it.
9153 */
9154 const __experimentalHasContentRoleAttribute = (0,external_wp_data_namespaceObject.createSelector)((state, blockTypeName) => {
9155 const blockType = selectors_getBlockType(state, blockTypeName);
9156 if (!blockType) {
9157 return false;
9158 }
9159 return Object.entries(blockType.attributes).some(([, {
9160 __experimentalRole
9161 }]) => __experimentalRole === 'content');
9162 }, (state, blockTypeName) => [state.blockTypes[blockTypeName]?.attributes]);
9163
9164 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/private-selectors.js
9165 /**
9166 * WordPress dependencies
9167 */
9168
9169
9170 /**
9171 * Internal dependencies
9172 */
9173
9174
9175
9176 const ROOT_BLOCK_SUPPORTS = ['background', 'backgroundColor', 'color', 'linkColor', 'captionColor', 'buttonColor', 'headingColor', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'lineHeight', 'padding', 'contentSize', 'wideSize', 'blockGap', 'textDecoration', 'textTransform', 'letterSpacing'];
9177
9178 /**
9179 * Filters the list of supported styles for a given element.
9180 *
9181 * @param {string[]} blockSupports list of supported styles.
9182 * @param {string|undefined} name block name.
9183 * @param {string|undefined} element element name.
9184 *
9185 * @return {string[]} filtered list of supported styles.
9186 */
9187 function filterElementBlockSupports(blockSupports, name, element) {
9188 return blockSupports.filter(support => {
9189 if (support === 'fontSize' && element === 'heading') {
9190 return false;
9191 }
9192
9193 // This is only available for links
9194 if (support === 'textDecoration' && !name && element !== 'link') {
9195 return false;
9196 }
9197
9198 // This is only available for heading, button, caption and text
9199 if (support === 'textTransform' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
9200 return false;
9201 }
9202
9203 // This is only available for heading, button, caption and text
9204 if (support === 'letterSpacing' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
9205 return false;
9206 }
9207
9208 // Text columns is only available for blocks.
9209 if (support === 'textColumns' && !name) {
9210 return false;
9211 }
9212 return true;
9213 });
9214 }
9215
9216 /**
9217 * Returns the list of supported styles for a given block name and element.
9218 */
9219 const getSupportedStyles = (0,external_wp_data_namespaceObject.createSelector)((state, name, element) => {
9220 if (!name) {
9221 return filterElementBlockSupports(ROOT_BLOCK_SUPPORTS, name, element);
9222 }
9223 const blockType = selectors_getBlockType(state, name);
9224 if (!blockType) {
9225 return [];
9226 }
9227 const supportKeys = [];
9228
9229 // Check for blockGap support.
9230 // Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
9231 if (blockType?.supports?.spacing?.blockGap) {
9232 supportKeys.push('blockGap');
9233 }
9234
9235 // check for shadow support
9236 if (blockType?.supports?.shadow) {
9237 supportKeys.push('shadow');
9238 }
9239 Object.keys(__EXPERIMENTAL_STYLE_PROPERTY).forEach(styleName => {
9240 if (!__EXPERIMENTAL_STYLE_PROPERTY[styleName].support) {
9241 return;
9242 }
9243
9244 // Opting out means that, for certain support keys like background color,
9245 // blocks have to explicitly set the support value false. If the key is
9246 // unset, we still enable it.
9247 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].requiresOptOut) {
9248 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].support[0] in blockType.supports && getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support) !== false) {
9249 supportKeys.push(styleName);
9250 return;
9251 }
9252 }
9253 if (getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support, false)) {
9254 supportKeys.push(styleName);
9255 }
9256 });
9257 return filterElementBlockSupports(supportKeys, name, element);
9258 }, (state, name) => [state.blockTypes[name]]);
9259
9260 /**
9261 * Returns the bootstrapped block type metadata for a give block name.
9262 *
9263 * @param {Object} state Data state.
9264 * @param {string} name Block name.
9265 *
9266 * @return {Object} Bootstrapped block type metadata for a block.
9267 */
9268 function getBootstrappedBlockType(state, name) {
9269 return state.bootstrappedBlockTypes[name];
9270 }
9271
9272 /**
9273 * Returns all the unprocessed (before applying the `registerBlockType` filter)
9274 * block type settings as passed during block registration.
9275 *
9276 * @param {Object} state Data state.
9277 *
9278 * @return {Array} Unprocessed block type settings for all blocks.
9279 */
9280 function getUnprocessedBlockTypes(state) {
9281 return state.unprocessedBlockTypes;
9282 }
9283
9284 /**
9285 * Returns all the block bindings sources registered.
9286 *
9287 * @param {Object} state Data state.
9288 *
9289 * @return {Object} All the registered sources and their properties.
9290 */
9291 function getAllBlockBindingsSources(state) {
9292 return state.blockBindingsSources;
9293 }
9294
9295 /**
9296 * Returns a specific block bindings source.
9297 *
9298 * @param {Object} state Data state.
9299 * @param {string} sourceName Name of the source to get.
9300 *
9301 * @return {Object} The specific block binding source and its properties.
9302 */
9303 function private_selectors_getBlockBindingsSource(state, sourceName) {
9304 return state.blockBindingsSources[sourceName];
9305 }
9306
9307 ;// CONCATENATED MODULE: external ["wp","deprecated"]
9308 const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
9309 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
9310 ;// CONCATENATED MODULE: ./node_modules/is-plain-object/dist/is-plain-object.mjs
9311 /*!
9312 * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
9313 *
9314 * Copyright (c) 2014-2017, Jon Schlinkert.
9315 * Released under the MIT License.
9316 */
9317
9318 function is_plain_object_isObject(o) {
9319 return Object.prototype.toString.call(o) === '[object Object]';
9320 }
9321
9322 function isPlainObject(o) {
9323 var ctor,prot;
9324
9325 if (is_plain_object_isObject(o) === false) return false;
9326
9327 // If has modified constructor
9328 ctor = o.constructor;
9329 if (ctor === undefined) return true;
9330
9331 // If has modified prototype
9332 prot = ctor.prototype;
9333 if (is_plain_object_isObject(prot) === false) return false;
9334
9335 // If constructor does not have an Object-specific method
9336 if (prot.hasOwnProperty('isPrototypeOf') === false) {
9337 return false;
9338 }
9339
9340 // Most likely a plain Object
9341 return true;
9342 }
9343
9344
9345
9346 // EXTERNAL MODULE: ./packages/blocks/node_modules/react-is/index.js
9347 var react_is = __webpack_require__(8243);
9348 ;// CONCATENATED MODULE: external ["wp","hooks"]
9349 const external_wp_hooks_namespaceObject = window["wp"]["hooks"];
9350 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/process-block-type.js
9351 /**
9352 * External dependencies
9353 */
9354
9355
9356
9357 /**
9358 * WordPress dependencies
9359 */
9360
9361
9362
9363
9364 /**
9365 * Internal dependencies
9366 */
9367
9368
9369
9370 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9371
9372 /**
9373 * Mapping of legacy category slugs to their latest normal values, used to
9374 * accommodate updates of the default set of block categories.
9375 *
9376 * @type {Record<string,string>}
9377 */
9378 const LEGACY_CATEGORY_MAPPING = {
9379 common: 'text',
9380 formatting: 'text',
9381 layout: 'design'
9382 };
9383
9384 /**
9385 * Merge block variations bootstrapped from the server and client.
9386 *
9387 * When a variation is registered in both places, its properties are merged.
9388 *
9389 * @param {Array} bootstrappedVariations - A block type variations from the server.
9390 * @param {Array} clientVariations - A block type variations from the client.
9391 * @return {Array} The merged array of block variations.
9392 */
9393 function mergeBlockVariations(bootstrappedVariations = [], clientVariations = []) {
9394 const result = [...bootstrappedVariations];
9395 clientVariations.forEach(clientVariation => {
9396 const index = result.findIndex(bootstrappedVariation => bootstrappedVariation.name === clientVariation.name);
9397 if (index !== -1) {
9398 result[index] = {
9399 ...result[index],
9400 ...clientVariation
9401 };
9402 } else {
9403 result.push(clientVariation);
9404 }
9405 });
9406 return result;
9407 }
9408
9409 /**
9410 * Takes the unprocessed block type settings, merges them with block type metadata
9411 * and applies all the existing filters for the registered block type.
9412 * Next, it validates all the settings and performs additional processing to the block type definition.
9413 *
9414 * @param {string} name Block name.
9415 * @param {WPBlockType} blockSettings Unprocessed block type settings.
9416 *
9417 * @return {WPBlockType | undefined} The block, if it has been processed and can be registered; otherwise `undefined`.
9418 */
9419 const processBlockType = (name, blockSettings) => ({
9420 select
9421 }) => {
9422 const bootstrappedBlockType = select.getBootstrappedBlockType(name);
9423 const blockType = {
9424 name,
9425 icon: BLOCK_ICON_DEFAULT,
9426 keywords: [],
9427 attributes: {},
9428 providesContext: {},
9429 usesContext: [],
9430 selectors: {},
9431 supports: {},
9432 styles: [],
9433 blockHooks: {},
9434 save: () => null,
9435 ...bootstrappedBlockType,
9436 ...blockSettings,
9437 // blockType.variations can be defined as a filePath.
9438 variations: mergeBlockVariations(Array.isArray(bootstrappedBlockType?.variations) ? bootstrappedBlockType.variations : [], Array.isArray(blockSettings?.variations) ? blockSettings.variations : [])
9439 };
9440 const settings = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', blockType, name, null);
9441 if (settings.description && typeof settings.description !== 'string') {
9442 external_wp_deprecated_default()('Declaring non-string block descriptions', {
9443 since: '6.2'
9444 });
9445 }
9446 if (settings.deprecated) {
9447 settings.deprecated = settings.deprecated.map(deprecation => Object.fromEntries(Object.entries(
9448 // Only keep valid deprecation keys.
9449 (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType',
9450 // Merge deprecation keys with pre-filter settings
9451 // so that filters that depend on specific keys being
9452 // present don't fail.
9453 {
9454 // Omit deprecation keys here so that deprecations
9455 // can opt out of specific keys like "supports".
9456 ...omit(blockType, DEPRECATED_ENTRY_KEYS),
9457 ...deprecation
9458 }, blockType.name, deprecation)).filter(([key]) => DEPRECATED_ENTRY_KEYS.includes(key))));
9459 }
9460 if (!isPlainObject(settings)) {
9461 false ? 0 : void 0;
9462 return;
9463 }
9464 if (typeof settings.save !== 'function') {
9465 false ? 0 : void 0;
9466 return;
9467 }
9468 if ('edit' in settings && !(0,react_is.isValidElementType)(settings.edit)) {
9469 false ? 0 : void 0;
9470 return;
9471 }
9472
9473 // Canonicalize legacy categories to equivalent fallback.
9474 if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) {
9475 settings.category = LEGACY_CATEGORY_MAPPING[settings.category];
9476 }
9477 if ('category' in settings && !select.getCategories().some(({
9478 slug
9479 }) => slug === settings.category)) {
9480 false ? 0 : void 0;
9481 delete settings.category;
9482 }
9483 if (!('title' in settings) || settings.title === '') {
9484 false ? 0 : void 0;
9485 return;
9486 }
9487 if (typeof settings.title !== 'string') {
9488 false ? 0 : void 0;
9489 return;
9490 }
9491 settings.icon = normalizeIconObject(settings.icon);
9492 if (!isValidIcon(settings.icon.src)) {
9493 false ? 0 : void 0;
9494 return;
9495 }
9496 return settings;
9497 };
9498
9499 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/actions.js
9500 /**
9501 * WordPress dependencies
9502 */
9503
9504
9505 /**
9506 * Internal dependencies
9507 */
9508
9509
9510 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
9511 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9512 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
9513
9514 /**
9515 * Returns an action object used in signalling that block types have been added.
9516 * Ignored from documentation as the recommended usage for this action through registerBlockType from @wordpress/blocks.
9517 *
9518 * @ignore
9519 *
9520 * @param {WPBlockType|WPBlockType[]} blockTypes Object or array of objects representing blocks to added.
9521 *
9522 *
9523 * @return {Object} Action object.
9524 */
9525 function addBlockTypes(blockTypes) {
9526 return {
9527 type: 'ADD_BLOCK_TYPES',
9528 blockTypes: Array.isArray(blockTypes) ? blockTypes : [blockTypes]
9529 };
9530 }
9531
9532 /**
9533 * Signals that all block types should be computed again.
9534 * It uses stored unprocessed block types and all the most recent list of registered filters.
9535 *
9536 * It addresses the issue where third party block filters get registered after third party blocks. A sample sequence:
9537 * 1. Filter A.
9538 * 2. Block B.
9539 * 3. Block C.
9540 * 4. Filter D.
9541 * 5. Filter E.
9542 * 6. Block F.
9543 * 7. Filter G.
9544 * In this scenario some filters would not get applied for all blocks because they are registered too late.
9545 */
9546 function reapplyBlockTypeFilters() {
9547 return ({
9548 dispatch,
9549 select
9550 }) => {
9551 const processedBlockTypes = [];
9552 for (const [name, settings] of Object.entries(select.getUnprocessedBlockTypes())) {
9553 const result = dispatch(processBlockType(name, settings));
9554 if (result) {
9555 processedBlockTypes.push(result);
9556 }
9557 }
9558 if (!processedBlockTypes.length) {
9559 return;
9560 }
9561 dispatch.addBlockTypes(processedBlockTypes);
9562 };
9563 }
9564 function __experimentalReapplyBlockFilters() {
9565 external_wp_deprecated_default()('wp.data.dispatch( "core/blocks" ).__experimentalReapplyBlockFilters', {
9566 since: '6.4',
9567 alternative: 'reapplyBlockFilters'
9568 });
9569 return reapplyBlockTypeFilters();
9570 }
9571
9572 /**
9573 * Returns an action object used to remove a registered block type.
9574 * Ignored from documentation as the recommended usage for this action through unregisterBlockType from @wordpress/blocks.
9575 *
9576 * @ignore
9577 *
9578 * @param {string|string[]} names Block name or array of block names to be removed.
9579 *
9580 *
9581 * @return {Object} Action object.
9582 */
9583 function removeBlockTypes(names) {
9584 return {
9585 type: 'REMOVE_BLOCK_TYPES',
9586 names: Array.isArray(names) ? names : [names]
9587 };
9588 }
9589
9590 /**
9591 * Returns an action object used in signalling that new block styles have been added.
9592 * Ignored from documentation as the recommended usage for this action through registerBlockStyle from @wordpress/blocks.
9593 *
9594 * @param {string|Array} blockNames Block names to register new styles for.
9595 * @param {Array|Object} styles Block style object or array of block style objects.
9596 *
9597 * @ignore
9598 *
9599 * @return {Object} Action object.
9600 */
9601 function addBlockStyles(blockNames, styles) {
9602 return {
9603 type: 'ADD_BLOCK_STYLES',
9604 styles: Array.isArray(styles) ? styles : [styles],
9605 blockNames: Array.isArray(blockNames) ? blockNames : [blockNames]
9606 };
9607 }
9608
9609 /**
9610 * Returns an action object used in signalling that block styles have been removed.
9611 * Ignored from documentation as the recommended usage for this action through unregisterBlockStyle from @wordpress/blocks.
9612 *
9613 * @ignore
9614 *
9615 * @param {string} blockName Block name.
9616 * @param {Array|string} styleNames Block style names or array of block style names.
9617 *
9618 * @return {Object} Action object.
9619 */
9620 function removeBlockStyles(blockName, styleNames) {
9621 return {
9622 type: 'REMOVE_BLOCK_STYLES',
9623 styleNames: Array.isArray(styleNames) ? styleNames : [styleNames],
9624 blockName
9625 };
9626 }
9627
9628 /**
9629 * Returns an action object used in signalling that new block variations have been added.
9630 * Ignored from documentation as the recommended usage for this action through registerBlockVariation from @wordpress/blocks.
9631 *
9632 * @ignore
9633 *
9634 * @param {string} blockName Block name.
9635 * @param {WPBlockVariation|WPBlockVariation[]} variations Block variations.
9636 *
9637 * @return {Object} Action object.
9638 */
9639 function addBlockVariations(blockName, variations) {
9640 return {
9641 type: 'ADD_BLOCK_VARIATIONS',
9642 variations: Array.isArray(variations) ? variations : [variations],
9643 blockName
9644 };
9645 }
9646
9647 /**
9648 * Returns an action object used in signalling that block variations have been removed.
9649 * Ignored from documentation as the recommended usage for this action through unregisterBlockVariation from @wordpress/blocks.
9650 *
9651 * @ignore
9652 *
9653 * @param {string} blockName Block name.
9654 * @param {string|string[]} variationNames Block variation names.
9655 *
9656 * @return {Object} Action object.
9657 */
9658 function removeBlockVariations(blockName, variationNames) {
9659 return {
9660 type: 'REMOVE_BLOCK_VARIATIONS',
9661 variationNames: Array.isArray(variationNames) ? variationNames : [variationNames],
9662 blockName
9663 };
9664 }
9665
9666 /**
9667 * Returns an action object used to set the default block name.
9668 * Ignored from documentation as the recommended usage for this action through setDefaultBlockName from @wordpress/blocks.
9669 *
9670 * @ignore
9671 *
9672 * @param {string} name Block name.
9673 *
9674 * @return {Object} Action object.
9675 */
9676 function actions_setDefaultBlockName(name) {
9677 return {
9678 type: 'SET_DEFAULT_BLOCK_NAME',
9679 name
9680 };
9681 }
9682
9683 /**
9684 * Returns an action object used to set the name of the block used as a fallback
9685 * for non-block content.
9686 * Ignored from documentation as the recommended usage for this action through setFreeformContentHandlerName from @wordpress/blocks.
9687 *
9688 * @ignore
9689 *
9690 * @param {string} name Block name.
9691 *
9692 * @return {Object} Action object.
9693 */
9694 function setFreeformFallbackBlockName(name) {
9695 return {
9696 type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
9697 name
9698 };
9699 }
9700
9701 /**
9702 * Returns an action object used to set the name of the block used as a fallback
9703 * for unregistered blocks.
9704 * Ignored from documentation as the recommended usage for this action through setUnregisteredTypeHandlerName from @wordpress/blocks.
9705 *
9706 * @ignore
9707 *
9708 * @param {string} name Block name.
9709 *
9710 * @return {Object} Action object.
9711 */
9712 function setUnregisteredFallbackBlockName(name) {
9713 return {
9714 type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
9715 name
9716 };
9717 }
9718
9719 /**
9720 * Returns an action object used to set the name of the block used
9721 * when grouping other blocks
9722 * eg: in "Group/Ungroup" interactions
9723 * Ignored from documentation as the recommended usage for this action through setGroupingBlockName from @wordpress/blocks.
9724 *
9725 * @ignore
9726 *
9727 * @param {string} name Block name.
9728 *
9729 * @return {Object} Action object.
9730 */
9731 function actions_setGroupingBlockName(name) {
9732 return {
9733 type: 'SET_GROUPING_BLOCK_NAME',
9734 name
9735 };
9736 }
9737
9738 /**
9739 * Returns an action object used to set block categories.
9740 * Ignored from documentation as the recommended usage for this action through setCategories from @wordpress/blocks.
9741 *
9742 * @ignore
9743 *
9744 * @param {WPBlockCategory[]} categories Block categories.
9745 *
9746 * @return {Object} Action object.
9747 */
9748 function setCategories(categories) {
9749 return {
9750 type: 'SET_CATEGORIES',
9751 categories
9752 };
9753 }
9754
9755 /**
9756 * Returns an action object used to update a category.
9757 * Ignored from documentation as the recommended usage for this action through updateCategory from @wordpress/blocks.
9758 *
9759 * @ignore
9760 *
9761 * @param {string} slug Block category slug.
9762 * @param {Object} category Object containing the category properties that should be updated.
9763 *
9764 * @return {Object} Action object.
9765 */
9766 function updateCategory(slug, category) {
9767 return {
9768 type: 'UPDATE_CATEGORY',
9769 slug,
9770 category
9771 };
9772 }
9773
9774 /**
9775 * Returns an action object used to add block collections
9776 * Ignored from documentation as the recommended usage for this action through registerBlockCollection from @wordpress/blocks.
9777 *
9778 * @ignore
9779 *
9780 * @param {string} namespace The namespace of the blocks to put in the collection
9781 * @param {string} title The title to display in the block inserter
9782 * @param {Object} icon (optional) The icon to display in the block inserter
9783 *
9784 * @return {Object} Action object.
9785 */
9786 function addBlockCollection(namespace, title, icon) {
9787 return {
9788 type: 'ADD_BLOCK_COLLECTION',
9789 namespace,
9790 title,
9791 icon
9792 };
9793 }
9794
9795 /**
9796 * Returns an action object used to remove block collections
9797 * Ignored from documentation as the recommended usage for this action through unregisterBlockCollection from @wordpress/blocks.
9798 *
9799 * @ignore
9800 *
9801 * @param {string} namespace The namespace of the blocks to put in the collection
9802 *
9803 * @return {Object} Action object.
9804 */
9805 function removeBlockCollection(namespace) {
9806 return {
9807 type: 'REMOVE_BLOCK_COLLECTION',
9808 namespace
9809 };
9810 }
9811
9812 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/private-actions.js
9813 /**
9814 * Internal dependencies
9815 */
9816
9817
9818 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9819
9820 /**
9821 * Add bootstrapped block type metadata to the store. These metadata usually come from
9822 * the `block.json` file and are either statically boostrapped from the server, or
9823 * passed as the `metadata` parameter to the `registerBlockType` function.
9824 *
9825 * @param {string} name Block name.
9826 * @param {WPBlockType} blockType Block type metadata.
9827 */
9828 function addBootstrappedBlockType(name, blockType) {
9829 return {
9830 type: 'ADD_BOOTSTRAPPED_BLOCK_TYPE',
9831 name,
9832 blockType
9833 };
9834 }
9835
9836 /**
9837 * Add unprocessed block type settings to the store. These data are passed as the
9838 * `settings` parameter to the client-side `registerBlockType` function.
9839 *
9840 * @param {string} name Block name.
9841 * @param {WPBlockType} blockType Unprocessed block type settings.
9842 */
9843 function addUnprocessedBlockType(name, blockType) {
9844 return ({
9845 dispatch
9846 }) => {
9847 dispatch({
9848 type: 'ADD_UNPROCESSED_BLOCK_TYPE',
9849 name,
9850 blockType
9851 });
9852 const processedBlockType = dispatch(processBlockType(name, blockType));
9853 if (!processedBlockType) {
9854 return;
9855 }
9856 dispatch.addBlockTypes(processedBlockType);
9857 };
9858 }
9859
9860 /**
9861 * Adds new block bindings source.
9862 *
9863 * @param {string} source Name of the source to register.
9864 */
9865 function addBlockBindingsSource(source) {
9866 return {
9867 type: 'ADD_BLOCK_BINDINGS_SOURCE',
9868 name: source.name,
9869 label: source.label,
9870 usesContext: source.usesContext,
9871 getValues: source.getValues,
9872 setValues: source.setValues,
9873 getPlaceholder: source.getPlaceholder,
9874 canUserEditValue: source.canUserEditValue
9875 };
9876 }
9877
9878 /**
9879 * Removes existing block bindings source.
9880 *
9881 * @param {string} name Name of the source to remove.
9882 */
9883 function removeBlockBindingsSource(name) {
9884 return {
9885 type: 'REMOVE_BLOCK_BINDINGS_SOURCE',
9886 name
9887 };
9888 }
9889
9890 /**
9891 * Add bootstrapped block bindings sources, usually initialized from the server.
9892 *
9893 * @param {string} source Name of the source to bootstrap.
9894 */
9895 function addBootstrappedBlockBindingsSource(source) {
9896 return {
9897 type: 'ADD_BOOTSTRAPPED_BLOCK_BINDINGS_SOURCE',
9898 name: source.name,
9899 label: source.label,
9900 usesContext: source.usesContext
9901 };
9902 }
9903
9904 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/constants.js
9905 const STORE_NAME = 'core/blocks';
9906
9907 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/index.js
9908 /**
9909 * WordPress dependencies
9910 */
9911
9912
9913 /**
9914 * Internal dependencies
9915 */
9916
9917
9918
9919
9920
9921
9922
9923
9924 /**
9925 * Store definition for the blocks namespace.
9926 *
9927 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
9928 *
9929 * @type {Object}
9930 */
9931 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
9932 reducer: reducer,
9933 selectors: selectors_namespaceObject,
9934 actions: actions_namespaceObject
9935 });
9936 (0,external_wp_data_namespaceObject.register)(store);
9937 unlock(store).registerPrivateSelectors(private_selectors_namespaceObject);
9938 unlock(store).registerPrivateActions(private_actions_namespaceObject);
9939
9940 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/uuid/dist/esm-browser/rng.js
9941 // Unique ID creation requires a high quality random # generator. In the browser we therefore
9942 // require the crypto API and do not support built-in fallback to lower quality random number
9943 // generators (like Math.random()).
9944 var getRandomValues;
9945 var rnds8 = new Uint8Array(16);
9946 function rng() {
9947 // lazy load so that environments that need to polyfill have a chance to do so
9948 if (!getRandomValues) {
9949 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
9950 // find the complete implementation of crypto (msCrypto) on IE11.
9951 getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
9952
9953 if (!getRandomValues) {
9954 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
9955 }
9956 }
9957
9958 return getRandomValues(rnds8);
9959 }
9960 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/uuid/dist/esm-browser/regex.js
9961 /* 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);
9962 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/uuid/dist/esm-browser/validate.js
9963
9964
9965 function validate(uuid) {
9966 return typeof uuid === 'string' && regex.test(uuid);
9967 }
9968
9969 /* harmony default export */ const esm_browser_validate = (validate);
9970 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/uuid/dist/esm-browser/stringify.js
9971
9972 /**
9973 * Convert array of 16 byte values to UUID string format of the form:
9974 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
9975 */
9976
9977 var byteToHex = [];
9978
9979 for (var stringify_i = 0; stringify_i < 256; ++stringify_i) {
9980 byteToHex.push((stringify_i + 0x100).toString(16).substr(1));
9981 }
9982
9983 function stringify(arr) {
9984 var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
9985 // Note: Be careful editing this code! It's been tuned for performance
9986 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
9987 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
9988 // of the following:
9989 // - One or more input array values don't map to a hex octet (leading to
9990 // "undefined" in the uuid)
9991 // - Invalid input values for the RFC `version` or `variant` fields
9992
9993 if (!esm_browser_validate(uuid)) {
9994 throw TypeError('Stringified UUID is invalid');
9995 }
9996
9997 return uuid;
9998 }
9999
10000 /* harmony default export */ const esm_browser_stringify = (stringify);
10001 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/uuid/dist/esm-browser/v4.js
10002
10003
10004
10005 function v4(options, buf, offset) {
10006 options = options || {};
10007 var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
10008
10009 rnds[6] = rnds[6] & 0x0f | 0x40;
10010 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
10011
10012 if (buf) {
10013 offset = offset || 0;
10014
10015 for (var i = 0; i < 16; ++i) {
10016 buf[offset + i] = rnds[i];
10017 }
10018
10019 return buf;
10020 }
10021
10022 return esm_browser_stringify(rnds);
10023 }
10024
10025 /* harmony default export */ const esm_browser_v4 = (v4);
10026 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/factory.js
10027 /**
10028 * External dependencies
10029 */
10030
10031
10032 /**
10033 * WordPress dependencies
10034 */
10035
10036
10037 /**
10038 * Internal dependencies
10039 */
10040
10041
10042
10043 /**
10044 * Returns a block object given its type and attributes.
10045 *
10046 * @param {string} name Block name.
10047 * @param {Object} attributes Block attributes.
10048 * @param {?Array} innerBlocks Nested blocks.
10049 *
10050 * @return {Object} Block object.
10051 */
10052 function createBlock(name, attributes = {}, innerBlocks = []) {
10053 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, attributes);
10054 const clientId = esm_browser_v4();
10055
10056 // Blocks are stored with a unique ID, the assigned type name, the block
10057 // attributes, and their inner blocks.
10058 return {
10059 clientId,
10060 name,
10061 isValid: true,
10062 attributes: sanitizedAttributes,
10063 innerBlocks
10064 };
10065 }
10066
10067 /**
10068 * Given an array of InnerBlocks templates or Block Objects,
10069 * returns an array of created Blocks from them.
10070 * It handles the case of having InnerBlocks as Blocks by
10071 * converting them to the proper format to continue recursively.
10072 *
10073 * @param {Array} innerBlocksOrTemplate Nested blocks or InnerBlocks templates.
10074 *
10075 * @return {Object[]} Array of Block objects.
10076 */
10077 function createBlocksFromInnerBlocksTemplate(innerBlocksOrTemplate = []) {
10078 return innerBlocksOrTemplate.map(innerBlock => {
10079 const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [innerBlock.name, innerBlock.attributes, innerBlock.innerBlocks];
10080 const [name, attributes, innerBlocks = []] = innerBlockTemplate;
10081 return createBlock(name, attributes, createBlocksFromInnerBlocksTemplate(innerBlocks));
10082 });
10083 }
10084
10085 /**
10086 * Given a block object, returns a copy of the block object while sanitizing its attributes,
10087 * optionally merging new attributes and/or replacing its inner blocks.
10088 *
10089 * @param {Object} block Block instance.
10090 * @param {Object} mergeAttributes Block attributes.
10091 * @param {?Array} newInnerBlocks Nested blocks.
10092 *
10093 * @return {Object} A cloned block.
10094 */
10095 function __experimentalCloneSanitizedBlock(block, mergeAttributes = {}, newInnerBlocks) {
10096 const clientId = esm_browser_v4();
10097 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(block.name, {
10098 ...block.attributes,
10099 ...mergeAttributes
10100 });
10101 return {
10102 ...block,
10103 clientId,
10104 attributes: sanitizedAttributes,
10105 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => __experimentalCloneSanitizedBlock(innerBlock))
10106 };
10107 }
10108
10109 /**
10110 * Given a block object, returns a copy of the block object,
10111 * optionally merging new attributes and/or replacing its inner blocks.
10112 *
10113 * @param {Object} block Block instance.
10114 * @param {Object} mergeAttributes Block attributes.
10115 * @param {?Array} newInnerBlocks Nested blocks.
10116 *
10117 * @return {Object} A cloned block.
10118 */
10119 function cloneBlock(block, mergeAttributes = {}, newInnerBlocks) {
10120 const clientId = esm_browser_v4();
10121 return {
10122 ...block,
10123 clientId,
10124 attributes: {
10125 ...block.attributes,
10126 ...mergeAttributes
10127 },
10128 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => cloneBlock(innerBlock))
10129 };
10130 }
10131
10132 /**
10133 * Returns a boolean indicating whether a transform is possible based on
10134 * various bits of context.
10135 *
10136 * @param {Object} transform The transform object to validate.
10137 * @param {string} direction Is this a 'from' or 'to' transform.
10138 * @param {Array} blocks The blocks to transform from.
10139 *
10140 * @return {boolean} Is the transform possible?
10141 */
10142 const isPossibleTransformForSource = (transform, direction, blocks) => {
10143 if (!blocks.length) {
10144 return false;
10145 }
10146
10147 // If multiple blocks are selected, only multi block transforms
10148 // or wildcard transforms are allowed.
10149 const isMultiBlock = blocks.length > 1;
10150 const firstBlockName = blocks[0].name;
10151 const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
10152 if (!isValidForMultiBlocks) {
10153 return false;
10154 }
10155
10156 // Check non-wildcard transforms to ensure that transform is valid
10157 // for a block selection of multiple blocks of different types.
10158 if (!isWildcardBlockTransform(transform) && !blocks.every(block => block.name === firstBlockName)) {
10159 return false;
10160 }
10161
10162 // Only consider 'block' type transforms as valid.
10163 const isBlockType = transform.type === 'block';
10164 if (!isBlockType) {
10165 return false;
10166 }
10167
10168 // Check if the transform's block name matches the source block (or is a wildcard)
10169 // only if this is a transform 'from'.
10170 const sourceBlock = blocks[0];
10171 const hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
10172 if (!hasMatchingName) {
10173 return false;
10174 }
10175
10176 // Don't allow single Grouping blocks to be transformed into
10177 // a Grouping block.
10178 if (!isMultiBlock && direction === 'from' && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
10179 return false;
10180 }
10181
10182 // If the transform has a `isMatch` function specified, check that it returns true.
10183 if (!maybeCheckTransformIsMatch(transform, blocks)) {
10184 return false;
10185 }
10186 return true;
10187 };
10188
10189 /**
10190 * Returns block types that the 'blocks' can be transformed into, based on
10191 * 'from' transforms on other blocks.
10192 *
10193 * @param {Array} blocks The blocks to transform from.
10194 *
10195 * @return {Array} Block types that the blocks can be transformed into.
10196 */
10197 const getBlockTypesForPossibleFromTransforms = blocks => {
10198 if (!blocks.length) {
10199 return [];
10200 }
10201 const allBlockTypes = getBlockTypes();
10202
10203 // filter all blocks to find those with a 'from' transform.
10204 const blockTypesWithPossibleFromTransforms = allBlockTypes.filter(blockType => {
10205 const fromTransforms = getBlockTransforms('from', blockType.name);
10206 return !!findTransform(fromTransforms, transform => {
10207 return isPossibleTransformForSource(transform, 'from', blocks);
10208 });
10209 });
10210 return blockTypesWithPossibleFromTransforms;
10211 };
10212
10213 /**
10214 * Returns block types that the 'blocks' can be transformed into, based on
10215 * the source block's own 'to' transforms.
10216 *
10217 * @param {Array} blocks The blocks to transform from.
10218 *
10219 * @return {Array} Block types that the source can be transformed into.
10220 */
10221 const getBlockTypesForPossibleToTransforms = blocks => {
10222 if (!blocks.length) {
10223 return [];
10224 }
10225 const sourceBlock = blocks[0];
10226 const blockType = getBlockType(sourceBlock.name);
10227 const transformsTo = blockType ? getBlockTransforms('to', blockType.name) : [];
10228
10229 // filter all 'to' transforms to find those that are possible.
10230 const possibleTransforms = transformsTo.filter(transform => {
10231 return transform && isPossibleTransformForSource(transform, 'to', blocks);
10232 });
10233
10234 // Build a list of block names using the possible 'to' transforms.
10235 const blockNames = possibleTransforms.map(transformation => transformation.blocks).flat();
10236
10237 // Map block names to block types.
10238 return blockNames.map(getBlockType);
10239 };
10240
10241 /**
10242 * Determines whether transform is a "block" type
10243 * and if so whether it is a "wildcard" transform
10244 * ie: targets "any" block type
10245 *
10246 * @param {Object} t the Block transform object
10247 *
10248 * @return {boolean} whether transform is a wildcard transform
10249 */
10250 const isWildcardBlockTransform = t => t && t.type === 'block' && Array.isArray(t.blocks) && t.blocks.includes('*');
10251
10252 /**
10253 * Determines whether the given Block is the core Block which
10254 * acts as a container Block for other Blocks as part of the
10255 * Grouping mechanics
10256 *
10257 * @param {string} name the name of the Block to test against
10258 *
10259 * @return {boolean} whether or not the Block is the container Block type
10260 */
10261 const isContainerGroupBlock = name => name === getGroupingBlockName();
10262
10263 /**
10264 * Returns an array of block types that the set of blocks received as argument
10265 * can be transformed into.
10266 *
10267 * @param {Array} blocks Blocks array.
10268 *
10269 * @return {Array} Block types that the blocks argument can be transformed to.
10270 */
10271 function getPossibleBlockTransformations(blocks) {
10272 if (!blocks.length) {
10273 return [];
10274 }
10275 const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
10276 const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
10277 return [...new Set([...blockTypesForFromTransforms, ...blockTypesForToTransforms])];
10278 }
10279
10280 /**
10281 * Given an array of transforms, returns the highest-priority transform where
10282 * the predicate function returns a truthy value. A higher-priority transform
10283 * is one with a lower priority value (i.e. first in priority order). Returns
10284 * null if the transforms set is empty or the predicate function returns a
10285 * falsey value for all entries.
10286 *
10287 * @param {Object[]} transforms Transforms to search.
10288 * @param {Function} predicate Function returning true on matching transform.
10289 *
10290 * @return {?Object} Highest-priority transform candidate.
10291 */
10292 function findTransform(transforms, predicate) {
10293 // The hooks library already has built-in mechanisms for managing priority
10294 // queue, so leverage via locally-defined instance.
10295 const hooks = (0,external_wp_hooks_namespaceObject.createHooks)();
10296 for (let i = 0; i < transforms.length; i++) {
10297 const candidate = transforms[i];
10298 if (predicate(candidate)) {
10299 hooks.addFilter('transform', 'transform/' + i.toString(), result => result ? result : candidate, candidate.priority);
10300 }
10301 }
10302
10303 // Filter name is arbitrarily chosen but consistent with above aggregation.
10304 return hooks.applyFilters('transform', null);
10305 }
10306
10307 /**
10308 * Returns normal block transforms for a given transform direction, optionally
10309 * for a specific block by name, or an empty array if there are no transforms.
10310 * If no block name is provided, returns transforms for all blocks. A normal
10311 * transform object includes `blockName` as a property.
10312 *
10313 * @param {string} direction Transform direction ("to", "from").
10314 * @param {string|Object} blockTypeOrName Block type or name.
10315 *
10316 * @return {Array} Block transforms for direction.
10317 */
10318 function getBlockTransforms(direction, blockTypeOrName) {
10319 // When retrieving transforms for all block types, recurse into self.
10320 if (blockTypeOrName === undefined) {
10321 return getBlockTypes().map(({
10322 name
10323 }) => getBlockTransforms(direction, name)).flat();
10324 }
10325
10326 // Validate that block type exists and has array of direction.
10327 const blockType = normalizeBlockType(blockTypeOrName);
10328 const {
10329 name: blockName,
10330 transforms
10331 } = blockType || {};
10332 if (!transforms || !Array.isArray(transforms[direction])) {
10333 return [];
10334 }
10335 const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
10336 const filteredTransforms = usingMobileTransformations ? transforms[direction].filter(t => {
10337 if (t.type === 'raw') {
10338 return true;
10339 }
10340 if (t.type === 'prefix') {
10341 return true;
10342 }
10343 if (!t.blocks || !t.blocks.length) {
10344 return false;
10345 }
10346 if (isWildcardBlockTransform(t)) {
10347 return true;
10348 }
10349 return t.blocks.every(transformBlockName => transforms.supportedMobileTransforms.includes(transformBlockName));
10350 }) : transforms[direction];
10351
10352 // Map transforms to normal form.
10353 return filteredTransforms.map(transform => ({
10354 ...transform,
10355 blockName,
10356 usingMobileTransformations
10357 }));
10358 }
10359
10360 /**
10361 * Checks that a given transforms isMatch method passes for given source blocks.
10362 *
10363 * @param {Object} transform A transform object.
10364 * @param {Array} blocks Blocks array.
10365 *
10366 * @return {boolean} True if given blocks are a match for the transform.
10367 */
10368 function maybeCheckTransformIsMatch(transform, blocks) {
10369 if (typeof transform.isMatch !== 'function') {
10370 return true;
10371 }
10372 const sourceBlock = blocks[0];
10373 const attributes = transform.isMultiBlock ? blocks.map(block => block.attributes) : sourceBlock.attributes;
10374 const block = transform.isMultiBlock ? blocks : sourceBlock;
10375 return transform.isMatch(attributes, block);
10376 }
10377
10378 /**
10379 * Switch one or more blocks into one or more blocks of the new block type.
10380 *
10381 * @param {Array|Object} blocks Blocks array or block object.
10382 * @param {string} name Block name.
10383 *
10384 * @return {?Array} Array of blocks or null.
10385 */
10386 function switchToBlockType(blocks, name) {
10387 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
10388 const isMultiBlock = blocksArray.length > 1;
10389 const firstBlock = blocksArray[0];
10390 const sourceName = firstBlock.name;
10391
10392 // Find the right transformation by giving priority to the "to"
10393 // transformation.
10394 const transformationsFrom = getBlockTransforms('from', name);
10395 const transformationsTo = getBlockTransforms('to', sourceName);
10396 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));
10397
10398 // Stop if there is no valid transformation.
10399 if (!transformation) {
10400 return null;
10401 }
10402 let transformationResults;
10403 if (transformation.isMultiBlock) {
10404 if ('__experimentalConvert' in transformation) {
10405 transformationResults = transformation.__experimentalConvert(blocksArray);
10406 } else {
10407 transformationResults = transformation.transform(blocksArray.map(currentBlock => currentBlock.attributes), blocksArray.map(currentBlock => currentBlock.innerBlocks));
10408 }
10409 } else if ('__experimentalConvert' in transformation) {
10410 transformationResults = transformation.__experimentalConvert(firstBlock);
10411 } else {
10412 transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
10413 }
10414
10415 // Ensure that the transformation function returned an object or an array
10416 // of objects.
10417 if (transformationResults === null || typeof transformationResults !== 'object') {
10418 return null;
10419 }
10420
10421 // If the transformation function returned a single object, we want to work
10422 // with an array instead.
10423 transformationResults = Array.isArray(transformationResults) ? transformationResults : [transformationResults];
10424
10425 // Ensure that every block object returned by the transformation has a
10426 // valid block type.
10427 if (transformationResults.some(result => !getBlockType(result.name))) {
10428 return null;
10429 }
10430 const hasSwitchedBlock = transformationResults.some(result => result.name === name);
10431
10432 // Ensure that at least one block object returned by the transformation has
10433 // the expected "destination" block type.
10434 if (!hasSwitchedBlock) {
10435 return null;
10436 }
10437 const ret = transformationResults.map((result, index, results) => {
10438 /**
10439 * Filters an individual transform result from block transformation.
10440 * All of the original blocks are passed, since transformations are
10441 * many-to-many, not one-to-one.
10442 *
10443 * @param {Object} transformedBlock The transformed block.
10444 * @param {Object[]} blocks Original blocks transformed.
10445 * @param {Object[]} index Index of the transformed block on the array of results.
10446 * @param {Object[]} results An array all the blocks that resulted from the transformation.
10447 */
10448 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.switchToBlockType.transformedBlock', result, blocks, index, results);
10449 });
10450 return ret;
10451 }
10452
10453 /**
10454 * Create a block object from the example API.
10455 *
10456 * @param {string} name
10457 * @param {Object} example
10458 *
10459 * @return {Object} block.
10460 */
10461 const getBlockFromExample = (name, example) => {
10462 try {
10463 var _example$innerBlocks;
10464 return createBlock(name, example.attributes, ((_example$innerBlocks = example.innerBlocks) !== null && _example$innerBlocks !== void 0 ? _example$innerBlocks : []).map(innerBlock => getBlockFromExample(innerBlock.name, innerBlock)));
10465 } catch {
10466 return createBlock('core/missing', {
10467 originalName: name,
10468 originalContent: '',
10469 originalUndelimitedContent: ''
10470 });
10471 }
10472 };
10473
10474 ;// CONCATENATED MODULE: external ["wp","blockSerializationDefaultParser"]
10475 const external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
10476 ;// CONCATENATED MODULE: external ["wp","autop"]
10477 const external_wp_autop_namespaceObject = window["wp"]["autop"];
10478 ;// CONCATENATED MODULE: external ["wp","isShallowEqual"]
10479 const external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"];
10480 var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject);
10481 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/serialize-raw-block.js
10482 /**
10483 * Internal dependencies
10484 */
10485
10486
10487 /**
10488 * @typedef {Object} Options Serialization options.
10489 * @property {boolean} [isCommentDelimited=true] Whether to output HTML comments around blocks.
10490 */
10491
10492 /** @typedef {import("./").WPRawBlock} WPRawBlock */
10493
10494 /**
10495 * Serializes a block node into the native HTML-comment-powered block format.
10496 * CAVEAT: This function is intended for re-serializing blocks as parsed by
10497 * valid parsers and skips any validation steps. This is NOT a generic
10498 * serialization function for in-memory blocks. For most purposes, see the
10499 * following functions available in the `@wordpress/blocks` package:
10500 *
10501 * @see serializeBlock
10502 * @see serialize
10503 *
10504 * For more on the format of block nodes as returned by valid parsers:
10505 *
10506 * @see `@wordpress/block-serialization-default-parser` package
10507 * @see `@wordpress/block-serialization-spec-parser` package
10508 *
10509 * @param {WPRawBlock} rawBlock A block node as returned by a valid parser.
10510 * @param {Options} [options={}] Serialization options.
10511 *
10512 * @return {string} An HTML string representing a block.
10513 */
10514 function serializeRawBlock(rawBlock, options = {}) {
10515 const {
10516 isCommentDelimited = true
10517 } = options;
10518 const {
10519 blockName,
10520 attrs = {},
10521 innerBlocks = [],
10522 innerContent = []
10523 } = rawBlock;
10524 let childIndex = 0;
10525 const content = innerContent.map(item =>
10526 // `null` denotes a nested block, otherwise we have an HTML fragment.
10527 item !== null ? item : serializeRawBlock(innerBlocks[childIndex++], options)).join('\n').replace(/\n+/g, '\n').trim();
10528 return isCommentDelimited ? getCommentDelimitedContent(blockName, attrs, content) : content;
10529 }
10530
10531 ;// CONCATENATED MODULE: external "ReactJSXRuntime"
10532 const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
10533 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/serializer.js
10534 /**
10535 * WordPress dependencies
10536 */
10537
10538
10539
10540
10541
10542 /**
10543 * Internal dependencies
10544 */
10545
10546
10547
10548
10549 /** @typedef {import('./parser').WPBlock} WPBlock */
10550
10551 /**
10552 * @typedef {Object} WPBlockSerializationOptions Serialization Options.
10553 *
10554 * @property {boolean} isInnerBlocks Whether we are serializing inner blocks.
10555 */
10556
10557 /**
10558 * Returns the block's default classname from its name.
10559 *
10560 * @param {string} blockName The block name.
10561 *
10562 * @return {string} The block's default class.
10563 */
10564
10565 function getBlockDefaultClassName(blockName) {
10566 // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
10567 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10568 const className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10569 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockDefaultClassName', className, blockName);
10570 }
10571
10572 /**
10573 * Returns the block's default menu item classname from its name.
10574 *
10575 * @param {string} blockName The block name.
10576 *
10577 * @return {string} The block's default menu item class.
10578 */
10579 function getBlockMenuDefaultClassName(blockName) {
10580 // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
10581 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10582 const className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10583 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockMenuDefaultClassName', className, blockName);
10584 }
10585 const blockPropsProvider = {};
10586 const innerBlocksPropsProvider = {};
10587
10588 /**
10589 * Call within a save function to get the props for the block wrapper.
10590 *
10591 * @param {Object} props Optional. Props to pass to the element.
10592 */
10593 function getBlockProps(props = {}) {
10594 const {
10595 blockType,
10596 attributes
10597 } = blockPropsProvider;
10598 return getBlockProps.skipFilters ? props : (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', {
10599 ...props
10600 }, blockType, attributes);
10601 }
10602
10603 /**
10604 * Call within a save function to get the props for the inner blocks wrapper.
10605 *
10606 * @param {Object} props Optional. Props to pass to the element.
10607 */
10608 function getInnerBlocksProps(props = {}) {
10609 const {
10610 innerBlocks
10611 } = innerBlocksPropsProvider;
10612 // Allow a different component to be passed to getSaveElement to handle
10613 // inner blocks, bypassing the default serialisation.
10614 if (!Array.isArray(innerBlocks)) {
10615 return {
10616 ...props,
10617 children: innerBlocks
10618 };
10619 }
10620 // Value is an array of blocks, so defer to block serializer.
10621 const html = serialize(innerBlocks, {
10622 isInnerBlocks: true
10623 });
10624 // Use special-cased raw HTML tag to avoid default escaping.
10625 const children = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_element_namespaceObject.RawHTML, {
10626 children: html
10627 });
10628 return {
10629 ...props,
10630 children
10631 };
10632 }
10633
10634 /**
10635 * Given a block type containing a save render implementation and attributes, returns the
10636 * enhanced element to be saved or string when raw HTML expected.
10637 *
10638 * @param {string|Object} blockTypeOrName Block type or name.
10639 * @param {Object} attributes Block attributes.
10640 * @param {?Array} innerBlocks Nested blocks.
10641 *
10642 * @return {Object|string} Save element or raw HTML string.
10643 */
10644 function getSaveElement(blockTypeOrName, attributes, innerBlocks = []) {
10645 const blockType = normalizeBlockType(blockTypeOrName);
10646 if (!blockType?.save) {
10647 return null;
10648 }
10649 let {
10650 save
10651 } = blockType;
10652
10653 // Component classes are unsupported for save since serialization must
10654 // occur synchronously. For improved interoperability with higher-order
10655 // components which often return component class, emulate basic support.
10656 if (save.prototype instanceof external_wp_element_namespaceObject.Component) {
10657 const instance = new save({
10658 attributes
10659 });
10660 save = instance.render.bind(instance);
10661 }
10662 blockPropsProvider.blockType = blockType;
10663 blockPropsProvider.attributes = attributes;
10664 innerBlocksPropsProvider.innerBlocks = innerBlocks;
10665 let element = save({
10666 attributes,
10667 innerBlocks
10668 });
10669 if (element !== null && typeof element === 'object' && (0,external_wp_hooks_namespaceObject.hasFilter)('blocks.getSaveContent.extraProps') && !(blockType.apiVersion > 1)) {
10670 /**
10671 * Filters the props applied to the block save result element.
10672 *
10673 * @param {Object} props Props applied to save element.
10674 * @param {WPBlock} blockType Block type definition.
10675 * @param {Object} attributes Block attributes.
10676 */
10677 const props = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', {
10678 ...element.props
10679 }, blockType, attributes);
10680 if (!external_wp_isShallowEqual_default()(props, element.props)) {
10681 element = (0,external_wp_element_namespaceObject.cloneElement)(element, props);
10682 }
10683 }
10684
10685 /**
10686 * Filters the save result of a block during serialization.
10687 *
10688 * @param {Element} element Block save result.
10689 * @param {WPBlock} blockType Block type definition.
10690 * @param {Object} attributes Block attributes.
10691 */
10692 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveElement', element, blockType, attributes);
10693 }
10694
10695 /**
10696 * Given a block type containing a save render implementation and attributes, returns the
10697 * static markup to be saved.
10698 *
10699 * @param {string|Object} blockTypeOrName Block type or name.
10700 * @param {Object} attributes Block attributes.
10701 * @param {?Array} innerBlocks Nested blocks.
10702 *
10703 * @return {string} Save content.
10704 */
10705 function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
10706 const blockType = normalizeBlockType(blockTypeOrName);
10707 return (0,external_wp_element_namespaceObject.renderToString)(getSaveElement(blockType, attributes, innerBlocks));
10708 }
10709
10710 /**
10711 * Returns attributes which are to be saved and serialized into the block
10712 * comment delimiter.
10713 *
10714 * When a block exists in memory it contains as its attributes both those
10715 * parsed the block comment delimiter _and_ those which matched from the
10716 * contents of the block.
10717 *
10718 * This function returns only those attributes which are needed to persist and
10719 * which cannot be matched from the block content.
10720 *
10721 * @param {Object<string,*>} blockType Block type.
10722 * @param {Object<string,*>} attributes Attributes from in-memory block data.
10723 *
10724 * @return {Object<string,*>} Subset of attributes for comment serialization.
10725 */
10726 function getCommentAttributes(blockType, attributes) {
10727 var _blockType$attributes;
10728 return Object.entries((_blockType$attributes = blockType.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}).reduce((accumulator, [key, attributeSchema]) => {
10729 const value = attributes[key];
10730 // Ignore undefined values.
10731 if (undefined === value) {
10732 return accumulator;
10733 }
10734
10735 // Ignore all attributes but the ones with an "undefined" source
10736 // "undefined" source refers to attributes saved in the block comment.
10737 if (attributeSchema.source !== undefined) {
10738 return accumulator;
10739 }
10740
10741 // Ignore all local attributes
10742 if (attributeSchema.__experimentalRole === 'local') {
10743 return accumulator;
10744 }
10745
10746 // Ignore default value.
10747 if ('default' in attributeSchema && JSON.stringify(attributeSchema.default) === JSON.stringify(value)) {
10748 return accumulator;
10749 }
10750
10751 // Otherwise, include in comment set.
10752 accumulator[key] = value;
10753 return accumulator;
10754 }, {});
10755 }
10756
10757 /**
10758 * Given an attributes object, returns a string in the serialized attributes
10759 * format prepared for post content.
10760 *
10761 * @param {Object} attributes Attributes object.
10762 *
10763 * @return {string} Serialized attributes.
10764 */
10765 function serializeAttributes(attributes) {
10766 return JSON.stringify(attributes)
10767 // Don't break HTML comments.
10768 .replace(/--/g, '\\u002d\\u002d')
10769
10770 // Don't break non-standard-compliant tools.
10771 .replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026')
10772
10773 // Bypass server stripslashes behavior which would unescape stringify's
10774 // escaping of quotation mark.
10775 //
10776 // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
10777 .replace(/\\"/g, '\\u0022');
10778 }
10779
10780 /**
10781 * Given a block object, returns the Block's Inner HTML markup.
10782 *
10783 * @param {Object} block Block instance.
10784 *
10785 * @return {string} HTML.
10786 */
10787 function getBlockInnerHTML(block) {
10788 // If block was parsed as invalid or encounters an error while generating
10789 // save content, use original content instead to avoid content loss. If a
10790 // block contains nested content, exempt it from this condition because we
10791 // otherwise have no access to its original content and content loss would
10792 // still occur.
10793 let saveContent = block.originalContent;
10794 if (block.isValid || block.innerBlocks.length) {
10795 try {
10796 saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
10797 } catch (error) {}
10798 }
10799 return saveContent;
10800 }
10801
10802 /**
10803 * Returns the content of a block, including comment delimiters.
10804 *
10805 * @param {string} rawBlockName Block name.
10806 * @param {Object} attributes Block attributes.
10807 * @param {string} content Block save content.
10808 *
10809 * @return {string} Comment-delimited block content.
10810 */
10811 function getCommentDelimitedContent(rawBlockName, attributes, content) {
10812 const serializedAttributes = attributes && Object.entries(attributes).length ? serializeAttributes(attributes) + ' ' : '';
10813
10814 // Strip core blocks of their namespace prefix.
10815 const blockName = rawBlockName?.startsWith('core/') ? rawBlockName.slice(5) : rawBlockName;
10816
10817 // @todo make the `wp:` prefix potentially configurable.
10818
10819 if (!content) {
10820 return `<!-- wp:${blockName} ${serializedAttributes}/-->`;
10821 }
10822 return `<!-- wp:${blockName} ${serializedAttributes}-->\n` + content + `\n<!-- /wp:${blockName} -->`;
10823 }
10824
10825 /**
10826 * Returns the content of a block, including comment delimiters, determining
10827 * serialized attributes and content form from the current state of the block.
10828 *
10829 * @param {WPBlock} block Block instance.
10830 * @param {WPBlockSerializationOptions} options Serialization options.
10831 *
10832 * @return {string} Serialized block.
10833 */
10834 function serializeBlock(block, {
10835 isInnerBlocks = false
10836 } = {}) {
10837 if (!block.isValid && block.__unstableBlockSource) {
10838 return serializeRawBlock(block.__unstableBlockSource);
10839 }
10840 const blockName = block.name;
10841 const saveContent = getBlockInnerHTML(block);
10842 if (blockName === getUnregisteredTypeHandlerName() || !isInnerBlocks && blockName === getFreeformContentHandlerName()) {
10843 return saveContent;
10844 }
10845 const blockType = getBlockType(blockName);
10846 if (!blockType) {
10847 return saveContent;
10848 }
10849 const saveAttributes = getCommentAttributes(blockType, block.attributes);
10850 return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
10851 }
10852 function __unstableSerializeAndClean(blocks) {
10853 // A single unmodified default block is assumed to
10854 // be equivalent to an empty post.
10855 if (blocks.length === 1 && isUnmodifiedDefaultBlock(blocks[0])) {
10856 blocks = [];
10857 }
10858 let content = serialize(blocks);
10859
10860 // For compatibility, treat a post consisting of a
10861 // single freeform block as legacy content and apply
10862 // pre-block-editor removep'd content formatting.
10863 if (blocks.length === 1 && blocks[0].name === getFreeformContentHandlerName() && blocks[0].name === 'core/freeform') {
10864 content = (0,external_wp_autop_namespaceObject.removep)(content);
10865 }
10866 return content;
10867 }
10868
10869 /**
10870 * Takes a block or set of blocks and returns the serialized post content.
10871 *
10872 * @param {Array} blocks Block(s) to serialize.
10873 * @param {WPBlockSerializationOptions} options Serialization options.
10874 *
10875 * @return {string} The post content.
10876 */
10877 function serialize(blocks, options) {
10878 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
10879 return blocksArray.map(block => serializeBlock(block, options)).join('\n\n');
10880 }
10881
10882 ;// CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/index.js
10883 /**
10884 * generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
10885 * do not edit
10886 */
10887 var namedCharRefs = {
10888 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"
10889 };
10890
10891 var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
10892 var CHARCODE = /^#([0-9]+)$/;
10893 var NAMED = /^([A-Za-z0-9]+)$/;
10894 var EntityParser = /** @class */ (function () {
10895 function EntityParser(named) {
10896 this.named = named;
10897 }
10898 EntityParser.prototype.parse = function (entity) {
10899 if (!entity) {
10900 return;
10901 }
10902 var matches = entity.match(HEXCHARCODE);
10903 if (matches) {
10904 return String.fromCharCode(parseInt(matches[1], 16));
10905 }
10906 matches = entity.match(CHARCODE);
10907 if (matches) {
10908 return String.fromCharCode(parseInt(matches[1], 10));
10909 }
10910 matches = entity.match(NAMED);
10911 if (matches) {
10912 return this.named[matches[1]];
10913 }
10914 };
10915 return EntityParser;
10916 }());
10917
10918 var WSP = /[\t\n\f ]/;
10919 var ALPHA = /[A-Za-z]/;
10920 var CRLF = /\r\n?/g;
10921 function isSpace(char) {
10922 return WSP.test(char);
10923 }
10924 function isAlpha(char) {
10925 return ALPHA.test(char);
10926 }
10927 function preprocessInput(input) {
10928 return input.replace(CRLF, '\n');
10929 }
10930
10931 var EventedTokenizer = /** @class */ (function () {
10932 function EventedTokenizer(delegate, entityParser) {
10933 this.delegate = delegate;
10934 this.entityParser = entityParser;
10935 this.state = "beforeData" /* beforeData */;
10936 this.line = -1;
10937 this.column = -1;
10938 this.input = '';
10939 this.index = -1;
10940 this.tagNameBuffer = '';
10941 this.states = {
10942 beforeData: function () {
10943 var char = this.peek();
10944 if (char === '<') {
10945 this.transitionTo("tagOpen" /* tagOpen */);
10946 this.markTagStart();
10947 this.consume();
10948 }
10949 else {
10950 if (char === '\n') {
10951 var tag = this.tagNameBuffer.toLowerCase();
10952 if (tag === 'pre' || tag === 'textarea') {
10953 this.consume();
10954 }
10955 }
10956 this.transitionTo("data" /* data */);
10957 this.delegate.beginData();
10958 }
10959 },
10960 data: function () {
10961 var char = this.peek();
10962 if (char === '<') {
10963 this.delegate.finishData();
10964 this.transitionTo("tagOpen" /* tagOpen */);
10965 this.markTagStart();
10966 this.consume();
10967 }
10968 else if (char === '&') {
10969 this.consume();
10970 this.delegate.appendToData(this.consumeCharRef() || '&');
10971 }
10972 else {
10973 this.consume();
10974 this.delegate.appendToData(char);
10975 }
10976 },
10977 tagOpen: function () {
10978 var char = this.consume();
10979 if (char === '!') {
10980 this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
10981 }
10982 else if (char === '/') {
10983 this.transitionTo("endTagOpen" /* endTagOpen */);
10984 }
10985 else if (char === '@' || char === ':' || isAlpha(char)) {
10986 this.transitionTo("tagName" /* tagName */);
10987 this.tagNameBuffer = '';
10988 this.delegate.beginStartTag();
10989 this.appendToTagName(char);
10990 }
10991 },
10992 markupDeclarationOpen: function () {
10993 var char = this.consume();
10994 if (char === '-' && this.input.charAt(this.index) === '-') {
10995 this.consume();
10996 this.transitionTo("commentStart" /* commentStart */);
10997 this.delegate.beginComment();
10998 }
10999 },
11000 commentStart: function () {
11001 var char = this.consume();
11002 if (char === '-') {
11003 this.transitionTo("commentStartDash" /* commentStartDash */);
11004 }
11005 else if (char === '>') {
11006 this.delegate.finishComment();
11007 this.transitionTo("beforeData" /* beforeData */);
11008 }
11009 else {
11010 this.delegate.appendToCommentData(char);
11011 this.transitionTo("comment" /* comment */);
11012 }
11013 },
11014 commentStartDash: function () {
11015 var char = this.consume();
11016 if (char === '-') {
11017 this.transitionTo("commentEnd" /* commentEnd */);
11018 }
11019 else if (char === '>') {
11020 this.delegate.finishComment();
11021 this.transitionTo("beforeData" /* beforeData */);
11022 }
11023 else {
11024 this.delegate.appendToCommentData('-');
11025 this.transitionTo("comment" /* comment */);
11026 }
11027 },
11028 comment: function () {
11029 var char = this.consume();
11030 if (char === '-') {
11031 this.transitionTo("commentEndDash" /* commentEndDash */);
11032 }
11033 else {
11034 this.delegate.appendToCommentData(char);
11035 }
11036 },
11037 commentEndDash: function () {
11038 var char = this.consume();
11039 if (char === '-') {
11040 this.transitionTo("commentEnd" /* commentEnd */);
11041 }
11042 else {
11043 this.delegate.appendToCommentData('-' + char);
11044 this.transitionTo("comment" /* comment */);
11045 }
11046 },
11047 commentEnd: function () {
11048 var char = this.consume();
11049 if (char === '>') {
11050 this.delegate.finishComment();
11051 this.transitionTo("beforeData" /* beforeData */);
11052 }
11053 else {
11054 this.delegate.appendToCommentData('--' + char);
11055 this.transitionTo("comment" /* comment */);
11056 }
11057 },
11058 tagName: function () {
11059 var char = this.consume();
11060 if (isSpace(char)) {
11061 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11062 }
11063 else if (char === '/') {
11064 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11065 }
11066 else if (char === '>') {
11067 this.delegate.finishTag();
11068 this.transitionTo("beforeData" /* beforeData */);
11069 }
11070 else {
11071 this.appendToTagName(char);
11072 }
11073 },
11074 beforeAttributeName: function () {
11075 var char = this.peek();
11076 if (isSpace(char)) {
11077 this.consume();
11078 return;
11079 }
11080 else if (char === '/') {
11081 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11082 this.consume();
11083 }
11084 else if (char === '>') {
11085 this.consume();
11086 this.delegate.finishTag();
11087 this.transitionTo("beforeData" /* beforeData */);
11088 }
11089 else if (char === '=') {
11090 this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
11091 this.transitionTo("attributeName" /* attributeName */);
11092 this.delegate.beginAttribute();
11093 this.consume();
11094 this.delegate.appendToAttributeName(char);
11095 }
11096 else {
11097 this.transitionTo("attributeName" /* attributeName */);
11098 this.delegate.beginAttribute();
11099 }
11100 },
11101 attributeName: function () {
11102 var char = this.peek();
11103 if (isSpace(char)) {
11104 this.transitionTo("afterAttributeName" /* afterAttributeName */);
11105 this.consume();
11106 }
11107 else if (char === '/') {
11108 this.delegate.beginAttributeValue(false);
11109 this.delegate.finishAttributeValue();
11110 this.consume();
11111 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11112 }
11113 else if (char === '=') {
11114 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
11115 this.consume();
11116 }
11117 else if (char === '>') {
11118 this.delegate.beginAttributeValue(false);
11119 this.delegate.finishAttributeValue();
11120 this.consume();
11121 this.delegate.finishTag();
11122 this.transitionTo("beforeData" /* beforeData */);
11123 }
11124 else if (char === '"' || char === "'" || char === '<') {
11125 this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
11126 this.consume();
11127 this.delegate.appendToAttributeName(char);
11128 }
11129 else {
11130 this.consume();
11131 this.delegate.appendToAttributeName(char);
11132 }
11133 },
11134 afterAttributeName: function () {
11135 var char = this.peek();
11136 if (isSpace(char)) {
11137 this.consume();
11138 return;
11139 }
11140 else if (char === '/') {
11141 this.delegate.beginAttributeValue(false);
11142 this.delegate.finishAttributeValue();
11143 this.consume();
11144 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11145 }
11146 else if (char === '=') {
11147 this.consume();
11148 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
11149 }
11150 else if (char === '>') {
11151 this.delegate.beginAttributeValue(false);
11152 this.delegate.finishAttributeValue();
11153 this.consume();
11154 this.delegate.finishTag();
11155 this.transitionTo("beforeData" /* beforeData */);
11156 }
11157 else {
11158 this.delegate.beginAttributeValue(false);
11159 this.delegate.finishAttributeValue();
11160 this.transitionTo("attributeName" /* attributeName */);
11161 this.delegate.beginAttribute();
11162 this.consume();
11163 this.delegate.appendToAttributeName(char);
11164 }
11165 },
11166 beforeAttributeValue: function () {
11167 var char = this.peek();
11168 if (isSpace(char)) {
11169 this.consume();
11170 }
11171 else if (char === '"') {
11172 this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
11173 this.delegate.beginAttributeValue(true);
11174 this.consume();
11175 }
11176 else if (char === "'") {
11177 this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
11178 this.delegate.beginAttributeValue(true);
11179 this.consume();
11180 }
11181 else if (char === '>') {
11182 this.delegate.beginAttributeValue(false);
11183 this.delegate.finishAttributeValue();
11184 this.consume();
11185 this.delegate.finishTag();
11186 this.transitionTo("beforeData" /* beforeData */);
11187 }
11188 else {
11189 this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
11190 this.delegate.beginAttributeValue(false);
11191 this.consume();
11192 this.delegate.appendToAttributeValue(char);
11193 }
11194 },
11195 attributeValueDoubleQuoted: function () {
11196 var char = this.consume();
11197 if (char === '"') {
11198 this.delegate.finishAttributeValue();
11199 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
11200 }
11201 else if (char === '&') {
11202 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11203 }
11204 else {
11205 this.delegate.appendToAttributeValue(char);
11206 }
11207 },
11208 attributeValueSingleQuoted: function () {
11209 var char = this.consume();
11210 if (char === "'") {
11211 this.delegate.finishAttributeValue();
11212 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
11213 }
11214 else if (char === '&') {
11215 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11216 }
11217 else {
11218 this.delegate.appendToAttributeValue(char);
11219 }
11220 },
11221 attributeValueUnquoted: function () {
11222 var char = this.peek();
11223 if (isSpace(char)) {
11224 this.delegate.finishAttributeValue();
11225 this.consume();
11226 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11227 }
11228 else if (char === '/') {
11229 this.delegate.finishAttributeValue();
11230 this.consume();
11231 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11232 }
11233 else if (char === '&') {
11234 this.consume();
11235 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11236 }
11237 else if (char === '>') {
11238 this.delegate.finishAttributeValue();
11239 this.consume();
11240 this.delegate.finishTag();
11241 this.transitionTo("beforeData" /* beforeData */);
11242 }
11243 else {
11244 this.consume();
11245 this.delegate.appendToAttributeValue(char);
11246 }
11247 },
11248 afterAttributeValueQuoted: function () {
11249 var char = this.peek();
11250 if (isSpace(char)) {
11251 this.consume();
11252 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11253 }
11254 else if (char === '/') {
11255 this.consume();
11256 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11257 }
11258 else if (char === '>') {
11259 this.consume();
11260 this.delegate.finishTag();
11261 this.transitionTo("beforeData" /* beforeData */);
11262 }
11263 else {
11264 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11265 }
11266 },
11267 selfClosingStartTag: function () {
11268 var char = this.peek();
11269 if (char === '>') {
11270 this.consume();
11271 this.delegate.markTagAsSelfClosing();
11272 this.delegate.finishTag();
11273 this.transitionTo("beforeData" /* beforeData */);
11274 }
11275 else {
11276 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11277 }
11278 },
11279 endTagOpen: function () {
11280 var char = this.consume();
11281 if (char === '@' || char === ':' || isAlpha(char)) {
11282 this.transitionTo("tagName" /* tagName */);
11283 this.tagNameBuffer = '';
11284 this.delegate.beginEndTag();
11285 this.appendToTagName(char);
11286 }
11287 }
11288 };
11289 this.reset();
11290 }
11291 EventedTokenizer.prototype.reset = function () {
11292 this.transitionTo("beforeData" /* beforeData */);
11293 this.input = '';
11294 this.index = 0;
11295 this.line = 1;
11296 this.column = 0;
11297 this.delegate.reset();
11298 };
11299 EventedTokenizer.prototype.transitionTo = function (state) {
11300 this.state = state;
11301 };
11302 EventedTokenizer.prototype.tokenize = function (input) {
11303 this.reset();
11304 this.tokenizePart(input);
11305 this.tokenizeEOF();
11306 };
11307 EventedTokenizer.prototype.tokenizePart = function (input) {
11308 this.input += preprocessInput(input);
11309 while (this.index < this.input.length) {
11310 var handler = this.states[this.state];
11311 if (handler !== undefined) {
11312 handler.call(this);
11313 }
11314 else {
11315 throw new Error("unhandled state " + this.state);
11316 }
11317 }
11318 };
11319 EventedTokenizer.prototype.tokenizeEOF = function () {
11320 this.flushData();
11321 };
11322 EventedTokenizer.prototype.flushData = function () {
11323 if (this.state === 'data') {
11324 this.delegate.finishData();
11325 this.transitionTo("beforeData" /* beforeData */);
11326 }
11327 };
11328 EventedTokenizer.prototype.peek = function () {
11329 return this.input.charAt(this.index);
11330 };
11331 EventedTokenizer.prototype.consume = function () {
11332 var char = this.peek();
11333 this.index++;
11334 if (char === '\n') {
11335 this.line++;
11336 this.column = 0;
11337 }
11338 else {
11339 this.column++;
11340 }
11341 return char;
11342 };
11343 EventedTokenizer.prototype.consumeCharRef = function () {
11344 var endIndex = this.input.indexOf(';', this.index);
11345 if (endIndex === -1) {
11346 return;
11347 }
11348 var entity = this.input.slice(this.index, endIndex);
11349 var chars = this.entityParser.parse(entity);
11350 if (chars) {
11351 var count = entity.length;
11352 // consume the entity chars
11353 while (count) {
11354 this.consume();
11355 count--;
11356 }
11357 // consume the `;`
11358 this.consume();
11359 return chars;
11360 }
11361 };
11362 EventedTokenizer.prototype.markTagStart = function () {
11363 this.delegate.tagOpen();
11364 };
11365 EventedTokenizer.prototype.appendToTagName = function (char) {
11366 this.tagNameBuffer += char;
11367 this.delegate.appendToTagName(char);
11368 };
11369 return EventedTokenizer;
11370 }());
11371
11372 var Tokenizer = /** @class */ (function () {
11373 function Tokenizer(entityParser, options) {
11374 if (options === void 0) { options = {}; }
11375 this.options = options;
11376 this.token = null;
11377 this.startLine = 1;
11378 this.startColumn = 0;
11379 this.tokens = [];
11380 this.tokenizer = new EventedTokenizer(this, entityParser);
11381 this._currentAttribute = undefined;
11382 }
11383 Tokenizer.prototype.tokenize = function (input) {
11384 this.tokens = [];
11385 this.tokenizer.tokenize(input);
11386 return this.tokens;
11387 };
11388 Tokenizer.prototype.tokenizePart = function (input) {
11389 this.tokens = [];
11390 this.tokenizer.tokenizePart(input);
11391 return this.tokens;
11392 };
11393 Tokenizer.prototype.tokenizeEOF = function () {
11394 this.tokens = [];
11395 this.tokenizer.tokenizeEOF();
11396 return this.tokens[0];
11397 };
11398 Tokenizer.prototype.reset = function () {
11399 this.token = null;
11400 this.startLine = 1;
11401 this.startColumn = 0;
11402 };
11403 Tokenizer.prototype.current = function () {
11404 var token = this.token;
11405 if (token === null) {
11406 throw new Error('token was unexpectedly null');
11407 }
11408 if (arguments.length === 0) {
11409 return token;
11410 }
11411 for (var i = 0; i < arguments.length; i++) {
11412 if (token.type === arguments[i]) {
11413 return token;
11414 }
11415 }
11416 throw new Error("token type was unexpectedly " + token.type);
11417 };
11418 Tokenizer.prototype.push = function (token) {
11419 this.token = token;
11420 this.tokens.push(token);
11421 };
11422 Tokenizer.prototype.currentAttribute = function () {
11423 return this._currentAttribute;
11424 };
11425 Tokenizer.prototype.addLocInfo = function () {
11426 if (this.options.loc) {
11427 this.current().loc = {
11428 start: {
11429 line: this.startLine,
11430 column: this.startColumn
11431 },
11432 end: {
11433 line: this.tokenizer.line,
11434 column: this.tokenizer.column
11435 }
11436 };
11437 }
11438 this.startLine = this.tokenizer.line;
11439 this.startColumn = this.tokenizer.column;
11440 };
11441 // Data
11442 Tokenizer.prototype.beginData = function () {
11443 this.push({
11444 type: "Chars" /* Chars */,
11445 chars: ''
11446 });
11447 };
11448 Tokenizer.prototype.appendToData = function (char) {
11449 this.current("Chars" /* Chars */).chars += char;
11450 };
11451 Tokenizer.prototype.finishData = function () {
11452 this.addLocInfo();
11453 };
11454 // Comment
11455 Tokenizer.prototype.beginComment = function () {
11456 this.push({
11457 type: "Comment" /* Comment */,
11458 chars: ''
11459 });
11460 };
11461 Tokenizer.prototype.appendToCommentData = function (char) {
11462 this.current("Comment" /* Comment */).chars += char;
11463 };
11464 Tokenizer.prototype.finishComment = function () {
11465 this.addLocInfo();
11466 };
11467 // Tags - basic
11468 Tokenizer.prototype.tagOpen = function () { };
11469 Tokenizer.prototype.beginStartTag = function () {
11470 this.push({
11471 type: "StartTag" /* StartTag */,
11472 tagName: '',
11473 attributes: [],
11474 selfClosing: false
11475 });
11476 };
11477 Tokenizer.prototype.beginEndTag = function () {
11478 this.push({
11479 type: "EndTag" /* EndTag */,
11480 tagName: ''
11481 });
11482 };
11483 Tokenizer.prototype.finishTag = function () {
11484 this.addLocInfo();
11485 };
11486 Tokenizer.prototype.markTagAsSelfClosing = function () {
11487 this.current("StartTag" /* StartTag */).selfClosing = true;
11488 };
11489 // Tags - name
11490 Tokenizer.prototype.appendToTagName = function (char) {
11491 this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
11492 };
11493 // Tags - attributes
11494 Tokenizer.prototype.beginAttribute = function () {
11495 this._currentAttribute = ['', '', false];
11496 };
11497 Tokenizer.prototype.appendToAttributeName = function (char) {
11498 this.currentAttribute()[0] += char;
11499 };
11500 Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
11501 this.currentAttribute()[2] = isQuoted;
11502 };
11503 Tokenizer.prototype.appendToAttributeValue = function (char) {
11504 this.currentAttribute()[1] += char;
11505 };
11506 Tokenizer.prototype.finishAttributeValue = function () {
11507 this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
11508 };
11509 Tokenizer.prototype.reportSyntaxError = function (message) {
11510 this.current().syntaxError = message;
11511 };
11512 return Tokenizer;
11513 }());
11514
11515 function tokenize(input, options) {
11516 var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);
11517 return tokenizer.tokenize(input);
11518 }
11519
11520
11521
11522 // EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js
11523 var es6 = __webpack_require__(5619);
11524 var es6_default = /*#__PURE__*/__webpack_require__.n(es6);
11525 ;// CONCATENATED MODULE: external ["wp","htmlEntities"]
11526 const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
11527 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/logger.js
11528 /**
11529 * @typedef LoggerItem
11530 * @property {Function} log Which logger recorded the message
11531 * @property {Array<any>} args White arguments were supplied to the logger
11532 */
11533
11534 function createLogger() {
11535 /**
11536 * Creates a log handler with block validation prefix.
11537 *
11538 * @param {Function} logger Original logger function.
11539 *
11540 * @return {Function} Augmented logger function.
11541 */
11542 function createLogHandler(logger) {
11543 let log = (message, ...args) => logger('Block validation: ' + message, ...args);
11544
11545 // In test environments, pre-process string substitutions to improve
11546 // readability of error messages. We'd prefer to avoid pulling in this
11547 // dependency in runtime environments, and it can be dropped by a combo
11548 // of Webpack env substitution + UglifyJS dead code elimination.
11549 if (false) {}
11550 return log;
11551 }
11552 return {
11553 // eslint-disable-next-line no-console
11554 error: createLogHandler(console.error),
11555 // eslint-disable-next-line no-console
11556 warning: createLogHandler(console.warn),
11557 getItems() {
11558 return [];
11559 }
11560 };
11561 }
11562 function createQueuedLogger() {
11563 /**
11564 * The list of enqueued log actions to print.
11565 *
11566 * @type {Array<LoggerItem>}
11567 */
11568 const queue = [];
11569 const logger = createLogger();
11570 return {
11571 error(...args) {
11572 queue.push({
11573 log: logger.error,
11574 args
11575 });
11576 },
11577 warning(...args) {
11578 queue.push({
11579 log: logger.warning,
11580 args
11581 });
11582 },
11583 getItems() {
11584 return queue;
11585 }
11586 };
11587 }
11588
11589 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/index.js
11590 /**
11591 * External dependencies
11592 */
11593
11594
11595
11596 /**
11597 * WordPress dependencies
11598 */
11599
11600
11601
11602 /**
11603 * Internal dependencies
11604 */
11605
11606
11607
11608
11609
11610 /** @typedef {import('../parser').WPBlock} WPBlock */
11611 /** @typedef {import('../registration').WPBlockType} WPBlockType */
11612 /** @typedef {import('./logger').LoggerItem} LoggerItem */
11613
11614 const identity = x => x;
11615
11616 /**
11617 * Globally matches any consecutive whitespace
11618 *
11619 * @type {RegExp}
11620 */
11621 const REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
11622
11623 /**
11624 * Matches a string containing only whitespace
11625 *
11626 * @type {RegExp}
11627 */
11628 const REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
11629
11630 /**
11631 * Matches a CSS URL type value
11632 *
11633 * @type {RegExp}
11634 */
11635 const REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
11636
11637 /**
11638 * Boolean attributes are attributes whose presence as being assigned is
11639 * meaningful, even if only empty.
11640 *
11641 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
11642 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11643 *
11644 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11645 * .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
11646 * .reduce( ( result, tr ) => Object.assign( result, {
11647 * [ tr.firstChild.textContent.trim() ]: true
11648 * } ), {} ) ).sort();
11649 *
11650 * @type {Array}
11651 */
11652 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'];
11653
11654 /**
11655 * Enumerated attributes are attributes which must be of a specific value form.
11656 * Like boolean attributes, these are meaningful if specified, even if not of a
11657 * valid enumerated value.
11658 *
11659 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
11660 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11661 *
11662 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11663 * .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
11664 * .reduce( ( result, tr ) => Object.assign( result, {
11665 * [ tr.firstChild.textContent.trim() ]: true
11666 * } ), {} ) ).sort();
11667 *
11668 * @type {Array}
11669 */
11670 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'];
11671
11672 /**
11673 * Meaningful attributes are those who cannot be safely ignored when omitted in
11674 * one HTML markup string and not another.
11675 *
11676 * @type {Array}
11677 */
11678 const MEANINGFUL_ATTRIBUTES = [...BOOLEAN_ATTRIBUTES, ...ENUMERATED_ATTRIBUTES];
11679
11680 /**
11681 * Array of functions which receive a text string on which to apply normalizing
11682 * behavior for consideration in text token equivalence, carefully ordered from
11683 * least-to-most expensive operations.
11684 *
11685 * @type {Array}
11686 */
11687 const TEXT_NORMALIZATIONS = [identity, getTextWithCollapsedWhitespace];
11688
11689 /**
11690 * Regular expression matching a named character reference. In lieu of bundling
11691 * a full set of references, the pattern covers the minimal necessary to test
11692 * positively against the full set.
11693 *
11694 * "The ampersand must be followed by one of the names given in the named
11695 * character references section, using the same case."
11696 *
11697 * Tested aginst "12.5 Named character references":
11698 *
11699 * ```
11700 * const references = Array.from( document.querySelectorAll(
11701 * '#named-character-references-table tr[id^=entity-] td:first-child'
11702 * ) ).map( ( code ) => code.textContent )
11703 * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
11704 * ```
11705 *
11706 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11707 * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
11708 *
11709 * @type {RegExp}
11710 */
11711 const REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
11712
11713 /**
11714 * Regular expression matching a decimal character reference.
11715 *
11716 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
11717 * followed by one or more ASCII digits, representing a base-ten integer"
11718 *
11719 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11720 *
11721 * @type {RegExp}
11722 */
11723 const REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
11724
11725 /**
11726 * Regular expression matching a hexadecimal character reference.
11727 *
11728 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
11729 * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
11730 * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
11731 * one or more ASCII hex digits, representing a hexadecimal integer"
11732 *
11733 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11734 *
11735 * @type {RegExp}
11736 */
11737 const REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
11738
11739 /**
11740 * Returns true if the given string is a valid character reference segment, or
11741 * false otherwise. The text should be stripped of `&` and `;` demarcations.
11742 *
11743 * @param {string} text Text to test.
11744 *
11745 * @return {boolean} Whether text is valid character reference.
11746 */
11747 function isValidCharacterReference(text) {
11748 return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
11749 }
11750
11751 /**
11752 * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
11753 * implementation of `decodeEntities` from `html-entities`, in order to avoid
11754 * bundling a massive named character reference.
11755 *
11756 * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts
11757 */
11758 class DecodeEntityParser {
11759 /**
11760 * Returns a substitute string for an entity string sequence between `&`
11761 * and `;`, or undefined if no substitution should occur.
11762 *
11763 * @param {string} entity Entity fragment discovered in HTML.
11764 *
11765 * @return {string | undefined} Entity substitute value.
11766 */
11767 parse(entity) {
11768 if (isValidCharacterReference(entity)) {
11769 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)('&' + entity + ';');
11770 }
11771 }
11772 }
11773
11774 /**
11775 * Given a specified string, returns an array of strings split by consecutive
11776 * whitespace, ignoring leading or trailing whitespace.
11777 *
11778 * @param {string} text Original text.
11779 *
11780 * @return {string[]} Text pieces split on whitespace.
11781 */
11782 function getTextPiecesSplitOnWhitespace(text) {
11783 return text.trim().split(REGEXP_WHITESPACE);
11784 }
11785
11786 /**
11787 * Given a specified string, returns a new trimmed string where all consecutive
11788 * whitespace is collapsed to a single space.
11789 *
11790 * @param {string} text Original text.
11791 *
11792 * @return {string} Trimmed text with consecutive whitespace collapsed.
11793 */
11794 function getTextWithCollapsedWhitespace(text) {
11795 // This is an overly simplified whitespace comparison. The specification is
11796 // more prescriptive of whitespace behavior in inline and block contexts.
11797 //
11798 // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
11799 return getTextPiecesSplitOnWhitespace(text).join(' ');
11800 }
11801
11802 /**
11803 * Returns attribute pairs of the given StartTag token, including only pairs
11804 * where the value is non-empty or the attribute is a boolean attribute, an
11805 * enumerated attribute, or a custom data- attribute.
11806 *
11807 * @see MEANINGFUL_ATTRIBUTES
11808 *
11809 * @param {Object} token StartTag token.
11810 *
11811 * @return {Array[]} Attribute pairs.
11812 */
11813 function getMeaningfulAttributePairs(token) {
11814 return token.attributes.filter(pair => {
11815 const [key, value] = pair;
11816 return value || key.indexOf('data-') === 0 || MEANINGFUL_ATTRIBUTES.includes(key);
11817 });
11818 }
11819
11820 /**
11821 * Returns true if two text tokens (with `chars` property) are equivalent, or
11822 * false otherwise.
11823 *
11824 * @param {Object} actual Actual token.
11825 * @param {Object} expected Expected token.
11826 * @param {Object} logger Validation logger object.
11827 *
11828 * @return {boolean} Whether two text tokens are equivalent.
11829 */
11830 function isEquivalentTextTokens(actual, expected, logger = createLogger()) {
11831 // This function is intentionally written as syntactically "ugly" as a hot
11832 // path optimization. Text is progressively normalized in order from least-
11833 // to-most operationally expensive, until the earliest point at which text
11834 // can be confidently inferred as being equal.
11835 let actualChars = actual.chars;
11836 let expectedChars = expected.chars;
11837 for (let i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
11838 const normalize = TEXT_NORMALIZATIONS[i];
11839 actualChars = normalize(actualChars);
11840 expectedChars = normalize(expectedChars);
11841 if (actualChars === expectedChars) {
11842 return true;
11843 }
11844 }
11845 logger.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
11846 return false;
11847 }
11848
11849 /**
11850 * Given a CSS length value, returns a normalized CSS length value for strict equality
11851 * comparison.
11852 *
11853 * @param {string} value CSS length value.
11854 *
11855 * @return {string} Normalized CSS length value.
11856 */
11857 function getNormalizedLength(value) {
11858 if (0 === parseFloat(value)) {
11859 return '0';
11860 }
11861 // Normalize strings with floats to always include a leading zero.
11862 if (value.indexOf('.') === 0) {
11863 return '0' + value;
11864 }
11865 return value;
11866 }
11867
11868 /**
11869 * Given a style value, returns a normalized style value for strict equality
11870 * comparison.
11871 *
11872 * @param {string} value Style value.
11873 *
11874 * @return {string} Normalized style value.
11875 */
11876 function getNormalizedStyleValue(value) {
11877 const textPieces = getTextPiecesSplitOnWhitespace(value);
11878 const normalizedPieces = textPieces.map(getNormalizedLength);
11879 const result = normalizedPieces.join(' ');
11880 return result
11881 // Normalize URL type to omit whitespace or quotes.
11882 .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
11883 }
11884
11885 /**
11886 * Given a style attribute string, returns an object of style properties.
11887 *
11888 * @param {string} text Style attribute.
11889 *
11890 * @return {Object} Style properties.
11891 */
11892 function getStyleProperties(text) {
11893 const pairs = text
11894 // Trim ending semicolon (avoid including in split)
11895 .replace(/;?\s*$/, '')
11896 // Split on property assignment.
11897 .split(';')
11898 // For each property assignment...
11899 .map(style => {
11900 // ...split further into key-value pairs.
11901 const [key, ...valueParts] = style.split(':');
11902 const value = valueParts.join(':');
11903 return [key.trim(), getNormalizedStyleValue(value.trim())];
11904 });
11905 return Object.fromEntries(pairs);
11906 }
11907
11908 /**
11909 * Attribute-specific equality handlers
11910 *
11911 * @type {Object}
11912 */
11913 const isEqualAttributesOfName = {
11914 class: (actual, expected) => {
11915 // Class matches if members are the same, even if out of order or
11916 // superfluous whitespace between.
11917 const [actualPieces, expectedPieces] = [actual, expected].map(getTextPiecesSplitOnWhitespace);
11918 const actualDiff = actualPieces.filter(c => !expectedPieces.includes(c));
11919 const expectedDiff = expectedPieces.filter(c => !actualPieces.includes(c));
11920 return actualDiff.length === 0 && expectedDiff.length === 0;
11921 },
11922 style: (actual, expected) => {
11923 return es6_default()(...[actual, expected].map(getStyleProperties));
11924 },
11925 // For each boolean attribute, mere presence of attribute in both is enough
11926 // to assume equivalence.
11927 ...Object.fromEntries(BOOLEAN_ATTRIBUTES.map(attribute => [attribute, () => true]))
11928 };
11929
11930 /**
11931 * Given two sets of attribute tuples, returns true if the attribute sets are
11932 * equivalent.
11933 *
11934 * @param {Array[]} actual Actual attributes tuples.
11935 * @param {Array[]} expected Expected attributes tuples.
11936 * @param {Object} logger Validation logger object.
11937 *
11938 * @return {boolean} Whether attributes are equivalent.
11939 */
11940 function isEqualTagAttributePairs(actual, expected, logger = createLogger()) {
11941 // Attributes is tokenized as tuples. Their lengths should match. This also
11942 // avoids us needing to check both attributes sets, since if A has any keys
11943 // which do not exist in B, we know the sets to be different.
11944 if (actual.length !== expected.length) {
11945 logger.warning('Expected attributes %o, instead saw %o.', expected, actual);
11946 return false;
11947 }
11948
11949 // Attributes are not guaranteed to occur in the same order. For validating
11950 // actual attributes, first convert the set of expected attribute values to
11951 // an object, for lookup by key.
11952 const expectedAttributes = {};
11953 for (let i = 0; i < expected.length; i++) {
11954 expectedAttributes[expected[i][0].toLowerCase()] = expected[i][1];
11955 }
11956 for (let i = 0; i < actual.length; i++) {
11957 const [name, actualValue] = actual[i];
11958 const nameLower = name.toLowerCase();
11959
11960 // As noted above, if missing member in B, assume different.
11961 if (!expectedAttributes.hasOwnProperty(nameLower)) {
11962 logger.warning('Encountered unexpected attribute `%s`.', name);
11963 return false;
11964 }
11965 const expectedValue = expectedAttributes[nameLower];
11966 const isEqualAttributes = isEqualAttributesOfName[nameLower];
11967 if (isEqualAttributes) {
11968 // Defer custom attribute equality handling.
11969 if (!isEqualAttributes(actualValue, expectedValue)) {
11970 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11971 return false;
11972 }
11973 } else if (actualValue !== expectedValue) {
11974 // Otherwise strict inequality should bail.
11975 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11976 return false;
11977 }
11978 }
11979 return true;
11980 }
11981
11982 /**
11983 * Token-type-specific equality handlers
11984 *
11985 * @type {Object}
11986 */
11987 const isEqualTokensOfType = {
11988 StartTag: (actual, expected, logger = createLogger()) => {
11989 if (actual.tagName !== expected.tagName &&
11990 // Optimization: Use short-circuit evaluation to defer case-
11991 // insensitive check on the assumption that the majority case will
11992 // have exactly equal tag names.
11993 actual.tagName.toLowerCase() !== expected.tagName.toLowerCase()) {
11994 logger.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
11995 return false;
11996 }
11997 return isEqualTagAttributePairs(...[actual, expected].map(getMeaningfulAttributePairs), logger);
11998 },
11999 Chars: isEquivalentTextTokens,
12000 Comment: isEquivalentTextTokens
12001 };
12002
12003 /**
12004 * Given an array of tokens, returns the first token which is not purely
12005 * whitespace.
12006 *
12007 * Mutates the tokens array.
12008 *
12009 * @param {Object[]} tokens Set of tokens to search.
12010 *
12011 * @return {Object | undefined} Next non-whitespace token.
12012 */
12013 function getNextNonWhitespaceToken(tokens) {
12014 let token;
12015 while (token = tokens.shift()) {
12016 if (token.type !== 'Chars') {
12017 return token;
12018 }
12019 if (!REGEXP_ONLY_WHITESPACE.test(token.chars)) {
12020 return token;
12021 }
12022 }
12023 }
12024
12025 /**
12026 * Tokenize an HTML string, gracefully handling any errors thrown during
12027 * underlying tokenization.
12028 *
12029 * @param {string} html HTML string to tokenize.
12030 * @param {Object} logger Validation logger object.
12031 *
12032 * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error
12033 */
12034 function getHTMLTokens(html, logger = createLogger()) {
12035 try {
12036 return new Tokenizer(new DecodeEntityParser()).tokenize(html);
12037 } catch (e) {
12038 logger.warning('Malformed HTML detected: %s', html);
12039 }
12040 return null;
12041 }
12042
12043 /**
12044 * Returns true if the next HTML token closes the current token.
12045 *
12046 * @param {Object} currentToken Current token to compare with.
12047 * @param {Object|undefined} nextToken Next token to compare against.
12048 *
12049 * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise
12050 */
12051 function isClosedByToken(currentToken, nextToken) {
12052 // Ensure this is a self closed token.
12053 if (!currentToken.selfClosing) {
12054 return false;
12055 }
12056
12057 // Check token names and determine if nextToken is the closing tag for currentToken.
12058 if (nextToken && nextToken.tagName === currentToken.tagName && nextToken.type === 'EndTag') {
12059 return true;
12060 }
12061 return false;
12062 }
12063
12064 /**
12065 * Returns true if the given HTML strings are effectively equivalent, or
12066 * false otherwise. Invalid HTML is not considered equivalent, even if the
12067 * strings directly match.
12068 *
12069 * @param {string} actual Actual HTML string.
12070 * @param {string} expected Expected HTML string.
12071 * @param {Object} logger Validation logger object.
12072 *
12073 * @return {boolean} Whether HTML strings are equivalent.
12074 */
12075 function isEquivalentHTML(actual, expected, logger = createLogger()) {
12076 // Short-circuit if markup is identical.
12077 if (actual === expected) {
12078 return true;
12079 }
12080
12081 // Tokenize input content and reserialized save content.
12082 const [actualTokens, expectedTokens] = [actual, expected].map(html => getHTMLTokens(html, logger));
12083
12084 // If either is malformed then stop comparing - the strings are not equivalent.
12085 if (!actualTokens || !expectedTokens) {
12086 return false;
12087 }
12088 let actualToken, expectedToken;
12089 while (actualToken = getNextNonWhitespaceToken(actualTokens)) {
12090 expectedToken = getNextNonWhitespaceToken(expectedTokens);
12091
12092 // Inequal if exhausted all expected tokens.
12093 if (!expectedToken) {
12094 logger.warning('Expected end of content, instead saw %o.', actualToken);
12095 return false;
12096 }
12097
12098 // Inequal if next non-whitespace token of each set are not same type.
12099 if (actualToken.type !== expectedToken.type) {
12100 logger.warning('Expected token of type `%s` (%o), instead saw `%s` (%o).', expectedToken.type, expectedToken, actualToken.type, actualToken);
12101 return false;
12102 }
12103
12104 // Defer custom token type equality handling, otherwise continue and
12105 // assume as equal.
12106 const isEqualTokens = isEqualTokensOfType[actualToken.type];
12107 if (isEqualTokens && !isEqualTokens(actualToken, expectedToken, logger)) {
12108 return false;
12109 }
12110
12111 // Peek at the next tokens (actual and expected) to see if they close
12112 // a self-closing tag.
12113 if (isClosedByToken(actualToken, expectedTokens[0])) {
12114 // Consume the next expected token that closes the current actual
12115 // self-closing token.
12116 getNextNonWhitespaceToken(expectedTokens);
12117 } else if (isClosedByToken(expectedToken, actualTokens[0])) {
12118 // Consume the next actual token that closes the current expected
12119 // self-closing token.
12120 getNextNonWhitespaceToken(actualTokens);
12121 }
12122 }
12123 if (expectedToken = getNextNonWhitespaceToken(expectedTokens)) {
12124 // If any non-whitespace tokens remain in expected token set, this
12125 // indicates inequality.
12126 logger.warning('Expected %o, instead saw end of content.', expectedToken);
12127 return false;
12128 }
12129 return true;
12130 }
12131
12132 /**
12133 * Returns an object with `isValid` property set to `true` if the parsed block
12134 * is valid given the input content. A block is considered valid if, when serialized
12135 * with assumed attributes, the content matches the original value. If block is
12136 * invalid, this function returns all validations issues as well.
12137 *
12138 * @param {string|Object} blockTypeOrName Block type.
12139 * @param {Object} attributes Parsed block attributes.
12140 * @param {string} originalBlockContent Original block content.
12141 * @param {Object} logger Validation logger object.
12142 *
12143 * @return {Object} Whether block is valid and contains validation messages.
12144 */
12145
12146 /**
12147 * Returns an object with `isValid` property set to `true` if the parsed block
12148 * is valid given the input content. A block is considered valid if, when serialized
12149 * with assumed attributes, the content matches the original value. If block is
12150 * invalid, this function returns all validations issues as well.
12151 *
12152 * @param {WPBlock} block block object.
12153 * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.
12154 *
12155 * @return {[boolean,Array<LoggerItem>]} validation results.
12156 */
12157 function validateBlock(block, blockTypeOrName = block.name) {
12158 const isFallbackBlock = block.name === getFreeformContentHandlerName() || block.name === getUnregisteredTypeHandlerName();
12159
12160 // Shortcut to avoid costly validation.
12161 if (isFallbackBlock) {
12162 return [true, []];
12163 }
12164 const logger = createQueuedLogger();
12165 const blockType = normalizeBlockType(blockTypeOrName);
12166 let generatedBlockContent;
12167 try {
12168 generatedBlockContent = getSaveContent(blockType, block.attributes);
12169 } catch (error) {
12170 logger.error('Block validation failed because an error occurred while generating block content:\n\n%s', error.toString());
12171 return [false, logger.getItems()];
12172 }
12173 const isValid = isEquivalentHTML(block.originalContent, generatedBlockContent, logger);
12174 if (!isValid) {
12175 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);
12176 }
12177 return [isValid, logger.getItems()];
12178 }
12179
12180 /**
12181 * Returns true if the parsed block is valid given the input content. A block
12182 * is considered valid if, when serialized with assumed attributes, the content
12183 * matches the original value.
12184 *
12185 * Logs to console in development environments when invalid.
12186 *
12187 * @deprecated Use validateBlock instead to avoid data loss.
12188 *
12189 * @param {string|Object} blockTypeOrName Block type.
12190 * @param {Object} attributes Parsed block attributes.
12191 * @param {string} originalBlockContent Original block content.
12192 *
12193 * @return {boolean} Whether block is valid.
12194 */
12195 function isValidBlockContent(blockTypeOrName, attributes, originalBlockContent) {
12196 external_wp_deprecated_default()('isValidBlockContent introduces opportunity for data loss', {
12197 since: '12.6',
12198 plugin: 'Gutenberg',
12199 alternative: 'validateBlock'
12200 });
12201 const blockType = normalizeBlockType(blockTypeOrName);
12202 const block = {
12203 name: blockType.name,
12204 attributes,
12205 innerBlocks: [],
12206 originalContent: originalBlockContent
12207 };
12208 const [isValid] = validateBlock(block, blockType);
12209 return isValid;
12210 }
12211
12212 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/convert-legacy-block.js
12213 /**
12214 * Convert legacy blocks to their canonical form. This function is used
12215 * both in the parser level for previous content and to convert such blocks
12216 * used in Custom Post Types templates.
12217 *
12218 * @param {string} name The block's name
12219 * @param {Object} attributes The block's attributes
12220 *
12221 * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found
12222 */
12223 function convertLegacyBlockNameAndAttributes(name, attributes) {
12224 const newAttributes = {
12225 ...attributes
12226 };
12227 // Convert 'core/cover-image' block in existing content to 'core/cover'.
12228 if ('core/cover-image' === name) {
12229 name = 'core/cover';
12230 }
12231
12232 // Convert 'core/text' blocks in existing content to 'core/paragraph'.
12233 if ('core/text' === name || 'core/cover-text' === name) {
12234 name = 'core/paragraph';
12235 }
12236
12237 // Convert derivative blocks such as 'core/social-link-wordpress' to the
12238 // canonical form 'core/social-link'.
12239 if (name && name.indexOf('core/social-link-') === 0) {
12240 // Capture `social-link-wordpress` into `{"service":"wordpress"}`
12241 newAttributes.service = name.substring(17);
12242 name = 'core/social-link';
12243 }
12244
12245 // Convert derivative blocks such as 'core-embed/instagram' to the
12246 // canonical form 'core/embed'.
12247 if (name && name.indexOf('core-embed/') === 0) {
12248 // Capture `core-embed/instagram` into `{"providerNameSlug":"instagram"}`
12249 const providerSlug = name.substring(11);
12250 const deprecated = {
12251 speaker: 'speaker-deck',
12252 polldaddy: 'crowdsignal'
12253 };
12254 newAttributes.providerNameSlug = providerSlug in deprecated ? deprecated[providerSlug] : providerSlug;
12255 // This is needed as the `responsive` attribute was passed
12256 // in a different way before the refactoring to block variations.
12257 if (!['amazon-kindle', 'wordpress'].includes(providerSlug)) {
12258 newAttributes.responsive = true;
12259 }
12260 name = 'core/embed';
12261 }
12262
12263 // Convert Post Comment blocks in existing content to Comment blocks.
12264 // TODO: Remove these checks when WordPress 6.0 is released.
12265 if (name === 'core/post-comment-author') {
12266 name = 'core/comment-author-name';
12267 }
12268 if (name === 'core/post-comment-content') {
12269 name = 'core/comment-content';
12270 }
12271 if (name === 'core/post-comment-date') {
12272 name = 'core/comment-date';
12273 }
12274 if (name === 'core/comments-query-loop') {
12275 name = 'core/comments';
12276 const {
12277 className = ''
12278 } = newAttributes;
12279 if (!className.includes('wp-block-comments-query-loop')) {
12280 newAttributes.className = ['wp-block-comments-query-loop', className].join(' ');
12281 }
12282 // Note that we also had to add a deprecation to the block in order
12283 // for the ID change to work.
12284 }
12285 if (name === 'core/post-comments') {
12286 name = 'core/comments';
12287 newAttributes.legacy = true;
12288 }
12289
12290 // Column count was stored as a string from WP 6.3-6.6. Convert it to a number.
12291 if (attributes.layout?.type === 'grid' && typeof attributes.layout?.columnCount === 'string') {
12292 newAttributes.layout = {
12293 ...newAttributes.layout,
12294 columnCount: parseInt(attributes.layout.columnCount, 10)
12295 };
12296 }
12297
12298 // Column span and row span were stored as strings in WP 6.6. Convert them to numbers.
12299 if (typeof attributes.style?.layout?.columnSpan === 'string') {
12300 const columnSpanNumber = parseInt(attributes.style.layout.columnSpan, 10);
12301 newAttributes.style = {
12302 ...newAttributes.style,
12303 layout: {
12304 ...newAttributes.style.layout,
12305 columnSpan: isNaN(columnSpanNumber) ? undefined : columnSpanNumber
12306 }
12307 };
12308 }
12309 if (typeof attributes.style?.layout?.rowSpan === 'string') {
12310 const rowSpanNumber = parseInt(attributes.style.layout.rowSpan, 10);
12311 newAttributes.style = {
12312 ...newAttributes.style,
12313 layout: {
12314 ...newAttributes.style.layout,
12315 rowSpan: isNaN(rowSpanNumber) ? undefined : rowSpanNumber
12316 }
12317 };
12318 }
12319
12320 // The following code is only relevant for the Gutenberg plugin.
12321 // It's a stand-alone if statement for dead-code elimination.
12322 if (true) {
12323 // Convert pattern overrides added during experimental phase.
12324 // Only four blocks were supported initially.
12325 // These checks can be removed in WordPress 6.6.
12326 if (newAttributes.metadata?.bindings && (name === 'core/paragraph' || name === 'core/heading' || name === 'core/image' || name === 'core/button') && newAttributes.metadata.bindings.__default?.source !== 'core/pattern-overrides') {
12327 const bindings = ['content', 'url', 'title', 'id', 'alt', 'text', 'linkTarget'];
12328 // Delete any existing individual bindings and add a default binding.
12329 // It was only possible to add all the default attributes through the UI,
12330 // So as soon as we find an attribute, we can assume all default attributes are overridable.
12331 let hasPatternOverrides = false;
12332 bindings.forEach(binding => {
12333 if (newAttributes.metadata.bindings[binding]?.source === 'core/pattern-overrides') {
12334 hasPatternOverrides = true;
12335 newAttributes.metadata = {
12336 ...newAttributes.metadata,
12337 bindings: {
12338 ...newAttributes.metadata.bindings
12339 }
12340 };
12341 delete newAttributes.metadata.bindings[binding];
12342 }
12343 });
12344 if (hasPatternOverrides) {
12345 newAttributes.metadata.bindings.__default = {
12346 source: 'core/pattern-overrides'
12347 };
12348 }
12349 }
12350 }
12351 return [name, newAttributes];
12352 }
12353
12354 ;// CONCATENATED MODULE: ./node_modules/hpq/es/get-path.js
12355 /**
12356 * Given object and string of dot-delimited path segments, returns value at
12357 * path or undefined if path cannot be resolved.
12358 *
12359 * @param {Object} object Lookup object
12360 * @param {string} path Path to resolve
12361 * @return {?*} Resolved value
12362 */
12363 function getPath(object, path) {
12364 var segments = path.split('.');
12365 var segment;
12366
12367 while (segment = segments.shift()) {
12368 if (!(segment in object)) {
12369 return;
12370 }
12371
12372 object = object[segment];
12373 }
12374
12375 return object;
12376 }
12377 ;// CONCATENATED MODULE: ./node_modules/hpq/es/index.js
12378 /**
12379 * Internal dependencies
12380 */
12381
12382 /**
12383 * Function returning a DOM document created by `createHTMLDocument`. The same
12384 * document is returned between invocations.
12385 *
12386 * @return {Document} DOM document.
12387 */
12388
12389 var getDocument = function () {
12390 var doc;
12391 return function () {
12392 if (!doc) {
12393 doc = document.implementation.createHTMLDocument('');
12394 }
12395
12396 return doc;
12397 };
12398 }();
12399 /**
12400 * Given a markup string or DOM element, creates an object aligning with the
12401 * shape of the matchers object, or the value returned by the matcher.
12402 *
12403 * @param {(string|Element)} source Source content
12404 * @param {(Object|Function)} matchers Matcher function or object of matchers
12405 * @return {(Object|*)} Matched value(s), shaped by object
12406 */
12407
12408
12409 function parse(source, matchers) {
12410 if (!matchers) {
12411 return;
12412 } // Coerce to element
12413
12414
12415 if ('string' === typeof source) {
12416 var doc = getDocument();
12417 doc.body.innerHTML = source;
12418 source = doc.body;
12419 } // Return singular value
12420
12421
12422 if ('function' === typeof matchers) {
12423 return matchers(source);
12424 } // Bail if we can't handle matchers
12425
12426
12427 if (Object !== matchers.constructor) {
12428 return;
12429 } // Shape result by matcher object
12430
12431
12432 return Object.keys(matchers).reduce(function (memo, key) {
12433 memo[key] = parse(source, matchers[key]);
12434 return memo;
12435 }, {});
12436 }
12437 /**
12438 * Generates a function which matches node of type selector, returning an
12439 * attribute by property if the attribute exists. If no selector is passed,
12440 * returns property of the query element.
12441 *
12442 * @param {?string} selector Optional selector
12443 * @param {string} name Property name
12444 * @return {*} Property value
12445 */
12446
12447 function prop(selector, name) {
12448 if (1 === arguments.length) {
12449 name = selector;
12450 selector = undefined;
12451 }
12452
12453 return function (node) {
12454 var match = node;
12455
12456 if (selector) {
12457 match = node.querySelector(selector);
12458 }
12459
12460 if (match) {
12461 return getPath(match, name);
12462 }
12463 };
12464 }
12465 /**
12466 * Generates a function which matches node of type selector, returning an
12467 * attribute by name if the attribute exists. If no selector is passed,
12468 * returns attribute of the query element.
12469 *
12470 * @param {?string} selector Optional selector
12471 * @param {string} name Attribute name
12472 * @return {?string} Attribute value
12473 */
12474
12475 function attr(selector, name) {
12476 if (1 === arguments.length) {
12477 name = selector;
12478 selector = undefined;
12479 }
12480
12481 return function (node) {
12482 var attributes = prop(selector, 'attributes')(node);
12483
12484 if (attributes && attributes.hasOwnProperty(name)) {
12485 return attributes[name].value;
12486 }
12487 };
12488 }
12489 /**
12490 * Convenience for `prop( selector, 'innerHTML' )`.
12491 *
12492 * @see prop()
12493 *
12494 * @param {?string} selector Optional selector
12495 * @return {string} Inner HTML
12496 */
12497
12498 function html(selector) {
12499 return prop(selector, 'innerHTML');
12500 }
12501 /**
12502 * Convenience for `prop( selector, 'textContent' )`.
12503 *
12504 * @see prop()
12505 *
12506 * @param {?string} selector Optional selector
12507 * @return {string} Text content
12508 */
12509
12510 function es_text(selector) {
12511 return prop(selector, 'textContent');
12512 }
12513 /**
12514 * Creates a new matching context by first finding elements matching selector
12515 * using querySelectorAll before then running another `parse` on `matchers`
12516 * scoped to the matched elements.
12517 *
12518 * @see parse()
12519 *
12520 * @param {string} selector Selector to match
12521 * @param {(Object|Function)} matchers Matcher function or object of matchers
12522 * @return {Array.<*,Object>} Array of matched value(s)
12523 */
12524
12525 function query(selector, matchers) {
12526 return function (node) {
12527 var matches = node.querySelectorAll(selector);
12528 return [].map.call(matches, function (match) {
12529 return parse(match, matchers);
12530 });
12531 };
12532 }
12533 ;// CONCATENATED MODULE: ./node_modules/memize/dist/index.js
12534 /**
12535 * Memize options object.
12536 *
12537 * @typedef MemizeOptions
12538 *
12539 * @property {number} [maxSize] Maximum size of the cache.
12540 */
12541
12542 /**
12543 * Internal cache entry.
12544 *
12545 * @typedef MemizeCacheNode
12546 *
12547 * @property {?MemizeCacheNode|undefined} [prev] Previous node.
12548 * @property {?MemizeCacheNode|undefined} [next] Next node.
12549 * @property {Array<*>} args Function arguments for cache
12550 * entry.
12551 * @property {*} val Function result.
12552 */
12553
12554 /**
12555 * Properties of the enhanced function for controlling cache.
12556 *
12557 * @typedef MemizeMemoizedFunction
12558 *
12559 * @property {()=>void} clear Clear the cache.
12560 */
12561
12562 /**
12563 * Accepts a function to be memoized, and returns a new memoized function, with
12564 * optional options.
12565 *
12566 * @template {(...args: any[]) => any} F
12567 *
12568 * @param {F} fn Function to memoize.
12569 * @param {MemizeOptions} [options] Options object.
12570 *
12571 * @return {((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction} Memoized function.
12572 */
12573 function memize(fn, options) {
12574 var size = 0;
12575
12576 /** @type {?MemizeCacheNode|undefined} */
12577 var head;
12578
12579 /** @type {?MemizeCacheNode|undefined} */
12580 var tail;
12581
12582 options = options || {};
12583
12584 function memoized(/* ...args */) {
12585 var node = head,
12586 len = arguments.length,
12587 args,
12588 i;
12589
12590 searchCache: while (node) {
12591 // Perform a shallow equality test to confirm that whether the node
12592 // under test is a candidate for the arguments passed. Two arrays
12593 // are shallowly equal if their length matches and each entry is
12594 // strictly equal between the two sets. Avoid abstracting to a
12595 // function which could incur an arguments leaking deoptimization.
12596
12597 // Check whether node arguments match arguments length
12598 if (node.args.length !== arguments.length) {
12599 node = node.next;
12600 continue;
12601 }
12602
12603 // Check whether node arguments match arguments values
12604 for (i = 0; i < len; i++) {
12605 if (node.args[i] !== arguments[i]) {
12606 node = node.next;
12607 continue searchCache;
12608 }
12609 }
12610
12611 // At this point we can assume we've found a match
12612
12613 // Surface matched node to head if not already
12614 if (node !== head) {
12615 // As tail, shift to previous. Must only shift if not also
12616 // head, since if both head and tail, there is no previous.
12617 if (node === tail) {
12618 tail = node.prev;
12619 }
12620
12621 // Adjust siblings to point to each other. If node was tail,
12622 // this also handles new tail's empty `next` assignment.
12623 /** @type {MemizeCacheNode} */ (node.prev).next = node.next;
12624 if (node.next) {
12625 node.next.prev = node.prev;
12626 }
12627
12628 node.next = head;
12629 node.prev = null;
12630 /** @type {MemizeCacheNode} */ (head).prev = node;
12631 head = node;
12632 }
12633
12634 // Return immediately
12635 return node.val;
12636 }
12637
12638 // No cached value found. Continue to insertion phase:
12639
12640 // Create a copy of arguments (avoid leaking deoptimization)
12641 args = new Array(len);
12642 for (i = 0; i < len; i++) {
12643 args[i] = arguments[i];
12644 }
12645
12646 node = {
12647 args: args,
12648
12649 // Generate the result from original function
12650 val: fn.apply(null, args),
12651 };
12652
12653 // Don't need to check whether node is already head, since it would
12654 // have been returned above already if it was
12655
12656 // Shift existing head down list
12657 if (head) {
12658 head.prev = node;
12659 node.next = head;
12660 } else {
12661 // If no head, follows that there's no tail (at initial or reset)
12662 tail = node;
12663 }
12664
12665 // Trim tail if we're reached max size and are pending cache insertion
12666 if (size === /** @type {MemizeOptions} */ (options).maxSize) {
12667 tail = /** @type {MemizeCacheNode} */ (tail).prev;
12668 /** @type {MemizeCacheNode} */ (tail).next = null;
12669 } else {
12670 size++;
12671 }
12672
12673 head = node;
12674
12675 return node.val;
12676 }
12677
12678 memoized.clear = function () {
12679 head = null;
12680 tail = null;
12681 size = 0;
12682 };
12683
12684 // Ignore reason: There's not a clear solution to create an intersection of
12685 // the function with additional properties, where the goal is to retain the
12686 // function signature of the incoming argument and add control properties
12687 // on the return value.
12688
12689 // @ts-ignore
12690 return memoized;
12691 }
12692
12693
12694
12695 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/matchers.js
12696 /**
12697 * External dependencies
12698 */
12699
12700
12701 /**
12702 * WordPress dependencies
12703 */
12704
12705
12706 /**
12707 * Internal dependencies
12708 */
12709
12710
12711 function matchers_html(selector, multilineTag) {
12712 return domNode => {
12713 let match = domNode;
12714 if (selector) {
12715 match = domNode.querySelector(selector);
12716 }
12717 if (!match) {
12718 return '';
12719 }
12720 if (multilineTag) {
12721 let value = '';
12722 const length = match.children.length;
12723 for (let index = 0; index < length; index++) {
12724 const child = match.children[index];
12725 if (child.nodeName.toLowerCase() !== multilineTag) {
12726 continue;
12727 }
12728 value += child.outerHTML;
12729 }
12730 return value;
12731 }
12732 return match.innerHTML;
12733 };
12734 }
12735 const richText = (selector, preserveWhiteSpace) => el => {
12736 const target = selector ? el.querySelector(selector) : el;
12737 return target ? external_wp_richText_namespaceObject.RichTextData.fromHTMLElement(target, {
12738 preserveWhiteSpace
12739 }) : external_wp_richText_namespaceObject.RichTextData.empty();
12740 };
12741
12742 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/node.js
12743 /**
12744 * WordPress dependencies
12745 */
12746
12747
12748 /**
12749 * Internal dependencies
12750 */
12751
12752
12753 /**
12754 * A representation of a single node within a block's rich text value. If
12755 * representing a text node, the value is simply a string of the node value.
12756 * As representing an element node, it is an object of:
12757 *
12758 * 1. `type` (string): Tag name.
12759 * 2. `props` (object): Attributes and children array of WPBlockNode.
12760 *
12761 * @typedef {string|Object} WPBlockNode
12762 */
12763
12764 /**
12765 * Given a single node and a node type (e.g. `'br'`), returns true if the node
12766 * corresponds to that type, false otherwise.
12767 *
12768 * @param {WPBlockNode} node Block node to test
12769 * @param {string} type Node to type to test against.
12770 *
12771 * @return {boolean} Whether node is of intended type.
12772 */
12773 function isNodeOfType(node, type) {
12774 external_wp_deprecated_default()('wp.blocks.node.isNodeOfType', {
12775 since: '6.1',
12776 version: '6.3',
12777 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12778 });
12779 return node && node.type === type;
12780 }
12781
12782 /**
12783 * Given an object implementing the NamedNodeMap interface, returns a plain
12784 * object equivalent value of name, value key-value pairs.
12785 *
12786 * @see https://dom.spec.whatwg.org/#interface-namednodemap
12787 *
12788 * @param {NamedNodeMap} nodeMap NamedNodeMap to convert to object.
12789 *
12790 * @return {Object} Object equivalent value of NamedNodeMap.
12791 */
12792 function getNamedNodeMapAsObject(nodeMap) {
12793 const result = {};
12794 for (let i = 0; i < nodeMap.length; i++) {
12795 const {
12796 name,
12797 value
12798 } = nodeMap[i];
12799 result[name] = value;
12800 }
12801 return result;
12802 }
12803
12804 /**
12805 * Given a DOM Element or Text node, returns an equivalent block node. Throws
12806 * if passed any node type other than element or text.
12807 *
12808 * @throws {TypeError} If non-element/text node is passed.
12809 *
12810 * @param {Node} domNode DOM node to convert.
12811 *
12812 * @return {WPBlockNode} Block node equivalent to DOM node.
12813 */
12814 function fromDOM(domNode) {
12815 external_wp_deprecated_default()('wp.blocks.node.fromDOM', {
12816 since: '6.1',
12817 version: '6.3',
12818 alternative: 'wp.richText.create',
12819 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12820 });
12821 if (domNode.nodeType === domNode.TEXT_NODE) {
12822 return domNode.nodeValue;
12823 }
12824 if (domNode.nodeType !== domNode.ELEMENT_NODE) {
12825 throw new TypeError('A block node can only be created from a node of type text or ' + 'element.');
12826 }
12827 return {
12828 type: domNode.nodeName.toLowerCase(),
12829 props: {
12830 ...getNamedNodeMapAsObject(domNode.attributes),
12831 children: children_fromDOM(domNode.childNodes)
12832 }
12833 };
12834 }
12835
12836 /**
12837 * Given a block node, returns its HTML string representation.
12838 *
12839 * @param {WPBlockNode} node Block node to convert to string.
12840 *
12841 * @return {string} String HTML representation of block node.
12842 */
12843 function toHTML(node) {
12844 external_wp_deprecated_default()('wp.blocks.node.toHTML', {
12845 since: '6.1',
12846 version: '6.3',
12847 alternative: 'wp.richText.toHTMLString',
12848 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12849 });
12850 return children_toHTML([node]);
12851 }
12852
12853 /**
12854 * Given a selector, returns an hpq matcher generating a WPBlockNode value
12855 * matching the selector result.
12856 *
12857 * @param {string} selector DOM selector.
12858 *
12859 * @return {Function} hpq matcher.
12860 */
12861 function matcher(selector) {
12862 external_wp_deprecated_default()('wp.blocks.node.matcher', {
12863 since: '6.1',
12864 version: '6.3',
12865 alternative: 'html source',
12866 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12867 });
12868 return domNode => {
12869 let match = domNode;
12870 if (selector) {
12871 match = domNode.querySelector(selector);
12872 }
12873 try {
12874 return fromDOM(match);
12875 } catch (error) {
12876 return null;
12877 }
12878 };
12879 }
12880
12881 /**
12882 * Object of utility functions used in managing block attribute values of
12883 * source `node`.
12884 *
12885 * @see https://github.com/WordPress/gutenberg/pull/10439
12886 *
12887 * @deprecated since 4.0. The `node` source should not be used, and can be
12888 * replaced by the `html` source.
12889 *
12890 * @private
12891 */
12892 /* harmony default export */ const node = ({
12893 isNodeOfType,
12894 fromDOM,
12895 toHTML,
12896 matcher
12897 });
12898
12899 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/children.js
12900 /**
12901 * WordPress dependencies
12902 */
12903
12904
12905
12906 /**
12907 * Internal dependencies
12908 */
12909
12910
12911 /**
12912 * A representation of a block's rich text value.
12913 *
12914 * @typedef {WPBlockNode[]} WPBlockChildren
12915 */
12916
12917 /**
12918 * Given block children, returns a serialize-capable WordPress element.
12919 *
12920 * @param {WPBlockChildren} children Block children object to convert.
12921 *
12922 * @return {Element} A serialize-capable element.
12923 */
12924 function getSerializeCapableElement(children) {
12925 // The fact that block children are compatible with the element serializer is
12926 // merely an implementation detail that currently serves to be true, but
12927 // should not be mistaken as being a guarantee on the external API. The
12928 // public API only offers guarantees to work with strings (toHTML) and DOM
12929 // elements (fromDOM), and should provide utilities to manipulate the value
12930 // rather than expect consumers to inspect or construct its shape (concat).
12931 return children;
12932 }
12933
12934 /**
12935 * Given block children, returns an array of block nodes.
12936 *
12937 * @param {WPBlockChildren} children Block children object to convert.
12938 *
12939 * @return {Array<WPBlockNode>} An array of individual block nodes.
12940 */
12941 function getChildrenArray(children) {
12942 external_wp_deprecated_default()('wp.blocks.children.getChildrenArray', {
12943 since: '6.1',
12944 version: '6.3',
12945 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12946 });
12947
12948 // The fact that block children are compatible with the element serializer
12949 // is merely an implementation detail that currently serves to be true, but
12950 // should not be mistaken as being a guarantee on the external API.
12951 return children;
12952 }
12953
12954 /**
12955 * Given two or more block nodes, returns a new block node representing a
12956 * concatenation of its values.
12957 *
12958 * @param {...WPBlockChildren} blockNodes Block nodes to concatenate.
12959 *
12960 * @return {WPBlockChildren} Concatenated block node.
12961 */
12962 function concat(...blockNodes) {
12963 external_wp_deprecated_default()('wp.blocks.children.concat', {
12964 since: '6.1',
12965 version: '6.3',
12966 alternative: 'wp.richText.concat',
12967 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12968 });
12969 const result = [];
12970 for (let i = 0; i < blockNodes.length; i++) {
12971 const blockNode = Array.isArray(blockNodes[i]) ? blockNodes[i] : [blockNodes[i]];
12972 for (let j = 0; j < blockNode.length; j++) {
12973 const child = blockNode[j];
12974 const canConcatToPreviousString = typeof child === 'string' && typeof result[result.length - 1] === 'string';
12975 if (canConcatToPreviousString) {
12976 result[result.length - 1] += child;
12977 } else {
12978 result.push(child);
12979 }
12980 }
12981 }
12982 return result;
12983 }
12984
12985 /**
12986 * Given an iterable set of DOM nodes, returns equivalent block children.
12987 * Ignores any non-element/text nodes included in set.
12988 *
12989 * @param {Iterable.<Node>} domNodes Iterable set of DOM nodes to convert.
12990 *
12991 * @return {WPBlockChildren} Block children equivalent to DOM nodes.
12992 */
12993 function children_fromDOM(domNodes) {
12994 external_wp_deprecated_default()('wp.blocks.children.fromDOM', {
12995 since: '6.1',
12996 version: '6.3',
12997 alternative: 'wp.richText.create',
12998 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12999 });
13000 const result = [];
13001 for (let i = 0; i < domNodes.length; i++) {
13002 try {
13003 result.push(fromDOM(domNodes[i]));
13004 } catch (error) {
13005 // Simply ignore if DOM node could not be converted.
13006 }
13007 }
13008 return result;
13009 }
13010
13011 /**
13012 * Given a block node, returns its HTML string representation.
13013 *
13014 * @param {WPBlockChildren} children Block node(s) to convert to string.
13015 *
13016 * @return {string} String HTML representation of block node.
13017 */
13018 function children_toHTML(children) {
13019 external_wp_deprecated_default()('wp.blocks.children.toHTML', {
13020 since: '6.1',
13021 version: '6.3',
13022 alternative: 'wp.richText.toHTMLString',
13023 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13024 });
13025 const element = getSerializeCapableElement(children);
13026 return (0,external_wp_element_namespaceObject.renderToString)(element);
13027 }
13028
13029 /**
13030 * Given a selector, returns an hpq matcher generating a WPBlockChildren value
13031 * matching the selector result.
13032 *
13033 * @param {string} selector DOM selector.
13034 *
13035 * @return {Function} hpq matcher.
13036 */
13037 function children_matcher(selector) {
13038 external_wp_deprecated_default()('wp.blocks.children.matcher', {
13039 since: '6.1',
13040 version: '6.3',
13041 alternative: 'html source',
13042 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13043 });
13044 return domNode => {
13045 let match = domNode;
13046 if (selector) {
13047 match = domNode.querySelector(selector);
13048 }
13049 if (match) {
13050 return children_fromDOM(match.childNodes);
13051 }
13052 return [];
13053 };
13054 }
13055
13056 /**
13057 * Object of utility functions used in managing block attribute values of
13058 * source `children`.
13059 *
13060 * @see https://github.com/WordPress/gutenberg/pull/10439
13061 *
13062 * @deprecated since 4.0. The `children` source should not be used, and can be
13063 * replaced by the `html` source.
13064 *
13065 * @private
13066 */
13067 /* harmony default export */ const children = ({
13068 concat,
13069 getChildrenArray,
13070 fromDOM: children_fromDOM,
13071 toHTML: children_toHTML,
13072 matcher: children_matcher
13073 });
13074
13075 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/get-block-attributes.js
13076 /**
13077 * External dependencies
13078 */
13079
13080
13081
13082 /**
13083 * WordPress dependencies
13084 */
13085
13086
13087
13088 /**
13089 * Internal dependencies
13090 */
13091
13092
13093
13094 /**
13095 * Higher-order hpq matcher which enhances an attribute matcher to return true
13096 * or false depending on whether the original matcher returns undefined. This
13097 * is useful for boolean attributes (e.g. disabled) whose attribute values may
13098 * be technically falsey (empty string), though their mere presence should be
13099 * enough to infer as true.
13100 *
13101 * @param {Function} matcher Original hpq matcher.
13102 *
13103 * @return {Function} Enhanced hpq matcher.
13104 */
13105 const toBooleanAttributeMatcher = matcher => value => matcher(value) !== undefined;
13106
13107 /**
13108 * Returns true if value is of the given JSON schema type, or false otherwise.
13109 *
13110 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
13111 *
13112 * @param {*} value Value to test.
13113 * @param {string} type Type to test.
13114 *
13115 * @return {boolean} Whether value is of type.
13116 */
13117 function isOfType(value, type) {
13118 switch (type) {
13119 case 'rich-text':
13120 return value instanceof external_wp_richText_namespaceObject.RichTextData;
13121 case 'string':
13122 return typeof value === 'string';
13123 case 'boolean':
13124 return typeof value === 'boolean';
13125 case 'object':
13126 return !!value && value.constructor === Object;
13127 case 'null':
13128 return value === null;
13129 case 'array':
13130 return Array.isArray(value);
13131 case 'integer':
13132 case 'number':
13133 return typeof value === 'number';
13134 }
13135 return true;
13136 }
13137
13138 /**
13139 * Returns true if value is of an array of given JSON schema types, or false
13140 * otherwise.
13141 *
13142 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
13143 *
13144 * @param {*} value Value to test.
13145 * @param {string[]} types Types to test.
13146 *
13147 * @return {boolean} Whether value is of types.
13148 */
13149 function isOfTypes(value, types) {
13150 return types.some(type => isOfType(value, type));
13151 }
13152
13153 /**
13154 * Given an attribute key, an attribute's schema, a block's raw content and the
13155 * commentAttributes returns the attribute value depending on its source
13156 * definition of the given attribute key.
13157 *
13158 * @param {string} attributeKey Attribute key.
13159 * @param {Object} attributeSchema Attribute's schema.
13160 * @param {Node} innerDOM Parsed DOM of block's inner HTML.
13161 * @param {Object} commentAttributes Block's comment attributes.
13162 * @param {string} innerHTML Raw HTML from block node's innerHTML property.
13163 *
13164 * @return {*} Attribute value.
13165 */
13166 function getBlockAttribute(attributeKey, attributeSchema, innerDOM, commentAttributes, innerHTML) {
13167 let value;
13168 switch (attributeSchema.source) {
13169 // An undefined source means that it's an attribute serialized to the
13170 // block's "comment".
13171 case undefined:
13172 value = commentAttributes ? commentAttributes[attributeKey] : undefined;
13173 break;
13174 // raw source means that it's the original raw block content.
13175 case 'raw':
13176 value = innerHTML;
13177 break;
13178 case 'attribute':
13179 case 'property':
13180 case 'html':
13181 case 'text':
13182 case 'rich-text':
13183 case 'children':
13184 case 'node':
13185 case 'query':
13186 case 'tag':
13187 value = parseWithAttributeSchema(innerDOM, attributeSchema);
13188 break;
13189 }
13190 if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) {
13191 // Reject the value if it is not valid. Reverting to the undefined
13192 // value ensures the default is respected, if applicable.
13193 value = undefined;
13194 }
13195 if (value === undefined) {
13196 value = getDefault(attributeSchema);
13197 }
13198 return value;
13199 }
13200
13201 /**
13202 * Returns true if value is valid per the given block attribute schema type
13203 * definition, or false otherwise.
13204 *
13205 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1
13206 *
13207 * @param {*} value Value to test.
13208 * @param {?(Array<string>|string)} type Block attribute schema type.
13209 *
13210 * @return {boolean} Whether value is valid.
13211 */
13212 function isValidByType(value, type) {
13213 return type === undefined || isOfTypes(value, Array.isArray(type) ? type : [type]);
13214 }
13215
13216 /**
13217 * Returns true if value is valid per the given block attribute schema enum
13218 * definition, or false otherwise.
13219 *
13220 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2
13221 *
13222 * @param {*} value Value to test.
13223 * @param {?Array} enumSet Block attribute schema enum.
13224 *
13225 * @return {boolean} Whether value is valid.
13226 */
13227 function isValidByEnum(value, enumSet) {
13228 return !Array.isArray(enumSet) || enumSet.includes(value);
13229 }
13230
13231 /**
13232 * Returns an hpq matcher given a source object.
13233 *
13234 * @param {Object} sourceConfig Attribute Source object.
13235 *
13236 * @return {Function} A hpq Matcher.
13237 */
13238 const matcherFromSource = memize(sourceConfig => {
13239 switch (sourceConfig.source) {
13240 case 'attribute':
13241 {
13242 let matcher = attr(sourceConfig.selector, sourceConfig.attribute);
13243 if (sourceConfig.type === 'boolean') {
13244 matcher = toBooleanAttributeMatcher(matcher);
13245 }
13246 return matcher;
13247 }
13248 case 'html':
13249 return matchers_html(sourceConfig.selector, sourceConfig.multiline);
13250 case 'text':
13251 return es_text(sourceConfig.selector);
13252 case 'rich-text':
13253 return richText(sourceConfig.selector, sourceConfig.__unstablePreserveWhiteSpace);
13254 case 'children':
13255 return children_matcher(sourceConfig.selector);
13256 case 'node':
13257 return matcher(sourceConfig.selector);
13258 case 'query':
13259 const subMatchers = Object.fromEntries(Object.entries(sourceConfig.query).map(([key, subSourceConfig]) => [key, matcherFromSource(subSourceConfig)]));
13260 return query(sourceConfig.selector, subMatchers);
13261 case 'tag':
13262 {
13263 const matcher = prop(sourceConfig.selector, 'nodeName');
13264 return domNode => matcher(domNode)?.toLowerCase();
13265 }
13266 default:
13267 // eslint-disable-next-line no-console
13268 console.error(`Unknown source type "${sourceConfig.source}"`);
13269 }
13270 });
13271
13272 /**
13273 * Parse a HTML string into DOM tree.
13274 *
13275 * @param {string|Node} innerHTML HTML string or already parsed DOM node.
13276 *
13277 * @return {Node} Parsed DOM node.
13278 */
13279 function parseHtml(innerHTML) {
13280 return parse(innerHTML, h => h);
13281 }
13282
13283 /**
13284 * Given a block's raw content and an attribute's schema returns the attribute's
13285 * value depending on its source.
13286 *
13287 * @param {string|Node} innerHTML Block's raw content.
13288 * @param {Object} attributeSchema Attribute's schema.
13289 *
13290 * @return {*} Attribute value.
13291 */
13292 function parseWithAttributeSchema(innerHTML, attributeSchema) {
13293 return matcherFromSource(attributeSchema)(parseHtml(innerHTML));
13294 }
13295
13296 /**
13297 * Returns the block attributes of a registered block node given its type.
13298 *
13299 * @param {string|Object} blockTypeOrName Block type or name.
13300 * @param {string|Node} innerHTML Raw block content.
13301 * @param {?Object} attributes Known block attributes (from delimiters).
13302 *
13303 * @return {Object} All block attributes.
13304 */
13305 function getBlockAttributes(blockTypeOrName, innerHTML, attributes = {}) {
13306 var _blockType$attributes;
13307 const doc = parseHtml(innerHTML);
13308 const blockType = normalizeBlockType(blockTypeOrName);
13309 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)]));
13310 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockAttributes', blockAttributes, blockType, innerHTML, attributes);
13311 }
13312
13313 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/fix-custom-classname.js
13314 /**
13315 * Internal dependencies
13316 */
13317
13318
13319
13320 const CLASS_ATTR_SCHEMA = {
13321 type: 'string',
13322 source: 'attribute',
13323 selector: '[data-custom-class-name] > *',
13324 attribute: 'class'
13325 };
13326
13327 /**
13328 * Given an HTML string, returns an array of class names assigned to the root
13329 * element in the markup.
13330 *
13331 * @param {string} innerHTML Markup string from which to extract classes.
13332 *
13333 * @return {string[]} Array of class names assigned to the root element.
13334 */
13335 function getHTMLRootElementClasses(innerHTML) {
13336 const parsed = parseWithAttributeSchema(`<div data-custom-class-name>${innerHTML}</div>`, CLASS_ATTR_SCHEMA);
13337 return parsed ? parsed.trim().split(/\s+/) : [];
13338 }
13339
13340 /**
13341 * Given a parsed set of block attributes, if the block supports custom class
13342 * names and an unknown class (per the block's serialization behavior) is
13343 * found, the unknown classes are treated as custom classes. This prevents the
13344 * block from being considered as invalid.
13345 *
13346 * @param {Object} blockAttributes Original block attributes.
13347 * @param {Object} blockType Block type settings.
13348 * @param {string} innerHTML Original block markup.
13349 *
13350 * @return {Object} Filtered block attributes.
13351 */
13352 function fixCustomClassname(blockAttributes, blockType, innerHTML) {
13353 if (!hasBlockSupport(blockType, 'customClassName', true)) {
13354 return blockAttributes;
13355 }
13356 const modifiedBlockAttributes = {
13357 ...blockAttributes
13358 };
13359 // To determine difference, serialize block given the known set of
13360 // attributes, with the exception of `className`. This will determine
13361 // the default set of classes. From there, any difference in innerHTML
13362 // can be considered as custom classes.
13363 const {
13364 className: omittedClassName,
13365 ...attributesSansClassName
13366 } = modifiedBlockAttributes;
13367 const serialized = getSaveContent(blockType, attributesSansClassName);
13368 const defaultClasses = getHTMLRootElementClasses(serialized);
13369 const actualClasses = getHTMLRootElementClasses(innerHTML);
13370 const customClasses = actualClasses.filter(className => !defaultClasses.includes(className));
13371 if (customClasses.length) {
13372 modifiedBlockAttributes.className = customClasses.join(' ');
13373 } else if (serialized) {
13374 delete modifiedBlockAttributes.className;
13375 }
13376 return modifiedBlockAttributes;
13377 }
13378
13379 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-built-in-validation-fixes.js
13380 /**
13381 * Internal dependencies
13382 */
13383
13384
13385 /**
13386 * Attempts to fix block invalidation by applying build-in validation fixes
13387 * like moving all extra classNames to the className attribute.
13388 *
13389 * @param {WPBlock} block block object.
13390 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13391 * can be inferred from the block name,
13392 * but it's here for performance reasons.
13393 *
13394 * @return {WPBlock} Fixed block object
13395 */
13396 function applyBuiltInValidationFixes(block, blockType) {
13397 const updatedBlockAttributes = fixCustomClassname(block.attributes, blockType, block.originalContent);
13398 return {
13399 ...block,
13400 attributes: updatedBlockAttributes
13401 };
13402 }
13403
13404 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-block-deprecated-versions.js
13405 /**
13406 * Internal dependencies
13407 */
13408
13409
13410
13411
13412
13413
13414 /**
13415 * Function that takes no arguments and always returns false.
13416 *
13417 * @return {boolean} Always returns false.
13418 */
13419 function stubFalse() {
13420 return false;
13421 }
13422
13423 /**
13424 * Given a block object, returns a new copy of the block with any applicable
13425 * deprecated migrations applied, or the original block if it was both valid
13426 * and no eligible migrations exist.
13427 *
13428 * @param {import(".").WPBlock} block Parsed and invalid block object.
13429 * @param {import(".").WPRawBlock} rawBlock Raw block object.
13430 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13431 * can be inferred from the block name,
13432 * but it's here for performance reasons.
13433 *
13434 * @return {import(".").WPBlock} Migrated block object.
13435 */
13436 function applyBlockDeprecatedVersions(block, rawBlock, blockType) {
13437 const parsedAttributes = rawBlock.attrs;
13438 const {
13439 deprecated: deprecatedDefinitions
13440 } = blockType;
13441 // Bail early if there are no registered deprecations to be handled.
13442 if (!deprecatedDefinitions || !deprecatedDefinitions.length) {
13443 return block;
13444 }
13445
13446 // By design, blocks lack any sort of version tracking. Instead, to process
13447 // outdated content the system operates a queue out of all the defined
13448 // attribute shapes and tries each definition until the input produces a
13449 // valid result. This mechanism seeks to avoid polluting the user-space with
13450 // machine-specific code. An invalid block is thus a block that could not be
13451 // matched successfully with any of the registered deprecation definitions.
13452 for (let i = 0; i < deprecatedDefinitions.length; i++) {
13453 // A block can opt into a migration even if the block is valid by
13454 // defining `isEligible` on its deprecation. If the block is both valid
13455 // and does not opt to migrate, skip.
13456 const {
13457 isEligible = stubFalse
13458 } = deprecatedDefinitions[i];
13459 if (block.isValid && !isEligible(parsedAttributes, block.innerBlocks, {
13460 blockNode: rawBlock,
13461 block
13462 })) {
13463 continue;
13464 }
13465
13466 // Block type properties which could impact either serialization or
13467 // parsing are not considered in the deprecated block type by default,
13468 // and must be explicitly provided.
13469 const deprecatedBlockType = Object.assign(omit(blockType, DEPRECATED_ENTRY_KEYS), deprecatedDefinitions[i]);
13470 let migratedBlock = {
13471 ...block,
13472 attributes: getBlockAttributes(deprecatedBlockType, block.originalContent, parsedAttributes)
13473 };
13474
13475 // Ignore the deprecation if it produces a block which is not valid.
13476 let [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
13477
13478 // If the migrated block is not valid initially, try the built-in fixes.
13479 if (!isValid) {
13480 migratedBlock = applyBuiltInValidationFixes(migratedBlock, deprecatedBlockType);
13481 [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
13482 }
13483
13484 // An invalid block does not imply incorrect HTML but the fact block
13485 // source information could be lost on re-serialization.
13486 if (!isValid) {
13487 continue;
13488 }
13489 let migratedInnerBlocks = migratedBlock.innerBlocks;
13490 let migratedAttributes = migratedBlock.attributes;
13491
13492 // A block may provide custom behavior to assign new attributes and/or
13493 // inner blocks.
13494 const {
13495 migrate
13496 } = deprecatedBlockType;
13497 if (migrate) {
13498 let migrated = migrate(migratedAttributes, block.innerBlocks);
13499 if (!Array.isArray(migrated)) {
13500 migrated = [migrated];
13501 }
13502 [migratedAttributes = parsedAttributes, migratedInnerBlocks = block.innerBlocks] = migrated;
13503 }
13504 block = {
13505 ...block,
13506 attributes: migratedAttributes,
13507 innerBlocks: migratedInnerBlocks,
13508 isValid: true,
13509 validationIssues: []
13510 };
13511 }
13512 return block;
13513 }
13514
13515 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/index.js
13516 /**
13517 * WordPress dependencies
13518 */
13519
13520
13521
13522 /**
13523 * Internal dependencies
13524 */
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535 /**
13536 * The raw structure of a block includes its attributes, inner
13537 * blocks, and inner HTML. It is important to distinguish inner blocks from
13538 * the HTML content of the block as only the latter is relevant for block
13539 * validation and edit operations.
13540 *
13541 * @typedef WPRawBlock
13542 *
13543 * @property {string=} blockName Block name
13544 * @property {Object=} attrs Block raw or comment attributes.
13545 * @property {string} innerHTML HTML content of the block.
13546 * @property {(string|null)[]} innerContent Content without inner blocks.
13547 * @property {WPRawBlock[]} innerBlocks Inner Blocks.
13548 */
13549
13550 /**
13551 * Fully parsed block object.
13552 *
13553 * @typedef WPBlock
13554 *
13555 * @property {string} name Block name
13556 * @property {Object} attributes Block raw or comment attributes.
13557 * @property {WPBlock[]} innerBlocks Inner Blocks.
13558 * @property {string} originalContent Original content of the block before validation fixes.
13559 * @property {boolean} isValid Whether the block is valid.
13560 * @property {Object[]} validationIssues Validation issues.
13561 * @property {WPRawBlock} [__unstableBlockSource] Un-processed original copy of block if created through parser.
13562 */
13563
13564 /**
13565 * @typedef {Object} ParseOptions
13566 * @property {boolean?} __unstableSkipMigrationLogs If a block is migrated from a deprecated version, skip logging the migration details.
13567 * @property {boolean?} __unstableSkipAutop Whether to skip autop when processing freeform content.
13568 */
13569
13570 /**
13571 * Convert legacy blocks to their canonical form. This function is used
13572 * both in the parser level for previous content and to convert such blocks
13573 * used in Custom Post Types templates.
13574 *
13575 * @param {WPRawBlock} rawBlock
13576 *
13577 * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found
13578 */
13579 function convertLegacyBlocks(rawBlock) {
13580 const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(rawBlock.blockName, rawBlock.attrs);
13581 return {
13582 ...rawBlock,
13583 blockName: correctName,
13584 attrs: correctedAttributes
13585 };
13586 }
13587
13588 /**
13589 * Normalize the raw block by applying the fallback block name if none given,
13590 * sanitize the parsed HTML...
13591 *
13592 * @param {WPRawBlock} rawBlock The raw block object.
13593 * @param {ParseOptions?} options Extra options for handling block parsing.
13594 *
13595 * @return {WPRawBlock} The normalized block object.
13596 */
13597 function normalizeRawBlock(rawBlock, options) {
13598 const fallbackBlockName = getFreeformContentHandlerName();
13599
13600 // If the grammar parsing don't produce any block name, use the freeform block.
13601 const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
13602 const rawAttributes = rawBlock.attrs || {};
13603 const rawInnerBlocks = rawBlock.innerBlocks || [];
13604 let rawInnerHTML = rawBlock.innerHTML.trim();
13605
13606 // Fallback content may be upgraded from classic content expecting implicit
13607 // automatic paragraphs, so preserve them. Assumes wpautop is idempotent,
13608 // meaning there are no negative consequences to repeated autop calls.
13609 if (rawBlockName === fallbackBlockName && rawBlockName === 'core/freeform' && !options?.__unstableSkipAutop) {
13610 rawInnerHTML = (0,external_wp_autop_namespaceObject.autop)(rawInnerHTML).trim();
13611 }
13612 return {
13613 ...rawBlock,
13614 blockName: rawBlockName,
13615 attrs: rawAttributes,
13616 innerHTML: rawInnerHTML,
13617 innerBlocks: rawInnerBlocks
13618 };
13619 }
13620
13621 /**
13622 * Uses the "unregistered blockType" to create a block object.
13623 *
13624 * @param {WPRawBlock} rawBlock block.
13625 *
13626 * @return {WPRawBlock} The unregistered block object.
13627 */
13628 function createMissingBlockType(rawBlock) {
13629 const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName();
13630
13631 // Preserve undelimited content for use by the unregistered type
13632 // handler. A block node's `innerHTML` isn't enough, as that field only
13633 // carries the block's own HTML and not its nested blocks.
13634 const originalUndelimitedContent = serializeRawBlock(rawBlock, {
13635 isCommentDelimited: false
13636 });
13637
13638 // Preserve full block content for use by the unregistered type
13639 // handler, block boundaries included.
13640 const originalContent = serializeRawBlock(rawBlock, {
13641 isCommentDelimited: true
13642 });
13643 return {
13644 blockName: unregisteredFallbackBlock,
13645 attrs: {
13646 originalName: rawBlock.blockName,
13647 originalContent,
13648 originalUndelimitedContent
13649 },
13650 innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
13651 innerBlocks: rawBlock.innerBlocks,
13652 innerContent: rawBlock.innerContent
13653 };
13654 }
13655
13656 /**
13657 * Validates a block and wraps with validation meta.
13658 *
13659 * The name here is regrettable but `validateBlock` is already taken.
13660 *
13661 * @param {WPBlock} unvalidatedBlock
13662 * @param {import('../registration').WPBlockType} blockType
13663 * @return {WPBlock} validated block, with auto-fixes if initially invalid
13664 */
13665 function applyBlockValidation(unvalidatedBlock, blockType) {
13666 // Attempt to validate the block.
13667 const [isValid] = validateBlock(unvalidatedBlock, blockType);
13668 if (isValid) {
13669 return {
13670 ...unvalidatedBlock,
13671 isValid,
13672 validationIssues: []
13673 };
13674 }
13675
13676 // If the block is invalid, attempt some built-in fixes
13677 // like custom classNames handling.
13678 const fixedBlock = applyBuiltInValidationFixes(unvalidatedBlock, blockType);
13679 // Attempt to validate the block once again after the built-in fixes.
13680 const [isFixedValid, validationIssues] = validateBlock(fixedBlock, blockType);
13681 return {
13682 ...fixedBlock,
13683 isValid: isFixedValid,
13684 validationIssues
13685 };
13686 }
13687
13688 /**
13689 * Given a raw block returned by grammar parsing, returns a fully parsed block.
13690 *
13691 * @param {WPRawBlock} rawBlock The raw block object.
13692 * @param {ParseOptions} options Extra options for handling block parsing.
13693 *
13694 * @return {WPBlock | undefined} Fully parsed block.
13695 */
13696 function parseRawBlock(rawBlock, options) {
13697 let normalizedBlock = normalizeRawBlock(rawBlock, options);
13698
13699 // During the lifecycle of the project, we renamed some old blocks
13700 // and transformed others to new blocks. To avoid breaking existing content,
13701 // we added this function to properly parse the old content.
13702 normalizedBlock = convertLegacyBlocks(normalizedBlock);
13703
13704 // Try finding the type for known block name.
13705 let blockType = getBlockType(normalizedBlock.blockName);
13706
13707 // If not blockType is found for the specified name, fallback to the "unregistedBlockType".
13708 if (!blockType) {
13709 normalizedBlock = createMissingBlockType(normalizedBlock);
13710 blockType = getBlockType(normalizedBlock.blockName);
13711 }
13712
13713 // If it's an empty freeform block or there's no blockType (no missing block handler)
13714 // Then, just ignore the block.
13715 // It might be a good idea to throw a warning here.
13716 // TODO: I'm unsure about the unregisteredFallbackBlock check,
13717 // it might ignore some dynamic unregistered third party blocks wrongly.
13718 const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
13719 if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
13720 return;
13721 }
13722
13723 // Parse inner blocks recursively.
13724 const parsedInnerBlocks = normalizedBlock.innerBlocks.map(innerBlock => parseRawBlock(innerBlock, options))
13725 // See https://github.com/WordPress/gutenberg/pull/17164.
13726 .filter(innerBlock => !!innerBlock);
13727
13728 // Get the fully parsed block.
13729 const parsedBlock = createBlock(normalizedBlock.blockName, getBlockAttributes(blockType, normalizedBlock.innerHTML, normalizedBlock.attrs), parsedInnerBlocks);
13730 parsedBlock.originalContent = normalizedBlock.innerHTML;
13731 const validatedBlock = applyBlockValidation(parsedBlock, blockType);
13732 const {
13733 validationIssues
13734 } = validatedBlock;
13735
13736 // Run the block deprecation and migrations.
13737 // This is performed on both invalid and valid blocks because
13738 // migration using the `migrate` functions should run even
13739 // if the output is deemed valid.
13740 const updatedBlock = applyBlockDeprecatedVersions(validatedBlock, normalizedBlock, blockType);
13741 if (!updatedBlock.isValid) {
13742 // Preserve the original unprocessed version of the block
13743 // that we received (no fixes, no deprecations) so that
13744 // we can save it as close to exactly the same way as
13745 // we loaded it. This is important to avoid corruption
13746 // and data loss caused by block implementations trying
13747 // to process data that isn't fully recognized.
13748 updatedBlock.__unstableBlockSource = rawBlock;
13749 }
13750 if (!validatedBlock.isValid && updatedBlock.isValid && !options?.__unstableSkipMigrationLogs) {
13751 /* eslint-disable no-console */
13752 console.groupCollapsed('Updated Block: %s', blockType.name);
13753 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);
13754 console.groupEnd();
13755 /* eslint-enable no-console */
13756 } else if (!validatedBlock.isValid && !updatedBlock.isValid) {
13757 validationIssues.forEach(({
13758 log,
13759 args
13760 }) => log(...args));
13761 }
13762 return updatedBlock;
13763 }
13764
13765 /**
13766 * Utilizes an optimized token-driven parser based on the Gutenberg grammar spec
13767 * defined through a parsing expression grammar to take advantage of the regular
13768 * cadence provided by block delimiters -- composed syntactically through HTML
13769 * comments -- which, given a general HTML document as an input, returns a block
13770 * list array representation.
13771 *
13772 * This is a recursive-descent parser that scans linearly once through the input
13773 * document. Instead of directly recursing it utilizes a trampoline mechanism to
13774 * prevent stack overflow. This initial pass is mainly interested in separating
13775 * and isolating the blocks serialized in the document and manifestly not in the
13776 * content within the blocks.
13777 *
13778 * @see
13779 * https://developer.wordpress.org/block-editor/packages/packages-block-serialization-default-parser/
13780 *
13781 * @param {string} content The post content.
13782 * @param {ParseOptions} options Extra options for handling block parsing.
13783 *
13784 * @return {Array} Block list.
13785 */
13786 function parser_parse(content, options) {
13787 return (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(content).reduce((accumulator, rawBlock) => {
13788 const block = parseRawBlock(rawBlock, options);
13789 if (block) {
13790 accumulator.push(block);
13791 }
13792 return accumulator;
13793 }, []);
13794 }
13795
13796 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/get-raw-transforms.js
13797 /**
13798 * Internal dependencies
13799 */
13800
13801 function getRawTransforms() {
13802 return getBlockTransforms('from').filter(({
13803 type
13804 }) => type === 'raw').map(transform => {
13805 return transform.isMatch ? transform : {
13806 ...transform,
13807 isMatch: node => transform.selector && node.matches(transform.selector)
13808 };
13809 });
13810 }
13811
13812 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-to-blocks.js
13813 /**
13814 * WordPress dependencies
13815 */
13816
13817
13818 /**
13819 * Internal dependencies
13820 */
13821
13822
13823
13824
13825
13826 /**
13827 * Converts HTML directly to blocks. Looks for a matching transform for each
13828 * top-level tag. The HTML should be filtered to not have any text between
13829 * top-level tags and formatted in a way that blocks can handle the HTML.
13830 *
13831 * @param {string} html HTML to convert.
13832 * @param {Function} handler The handler calling htmlToBlocks: either rawHandler
13833 * or pasteHandler.
13834 *
13835 * @return {Array} An array of blocks.
13836 */
13837 function htmlToBlocks(html, handler) {
13838 const doc = document.implementation.createHTMLDocument('');
13839 doc.body.innerHTML = html;
13840 return Array.from(doc.body.children).flatMap(node => {
13841 const rawTransform = findTransform(getRawTransforms(), ({
13842 isMatch
13843 }) => isMatch(node));
13844 if (!rawTransform) {
13845 // Until the HTML block is supported in the native version, we'll parse it
13846 // instead of creating the block to generate it as an unsupported block.
13847 if (external_wp_element_namespaceObject.Platform.isNative) {
13848 return parser_parse(`<!-- wp:html -->${node.outerHTML}<!-- /wp:html -->`);
13849 }
13850 return createBlock(
13851 // Should not be hardcoded.
13852 'core/html', getBlockAttributes('core/html', node.outerHTML));
13853 }
13854 const {
13855 transform,
13856 blockName
13857 } = rawTransform;
13858 if (transform) {
13859 const block = transform(node, handler);
13860 if (node.hasAttribute('class')) {
13861 block.attributes.className = node.getAttribute('class');
13862 }
13863 return block;
13864 }
13865 return createBlock(blockName, getBlockAttributes(blockName, node.outerHTML));
13866 });
13867 }
13868
13869 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/normalise-blocks.js
13870 /**
13871 * WordPress dependencies
13872 */
13873
13874 function normaliseBlocks(HTML, options = {}) {
13875 const decuDoc = document.implementation.createHTMLDocument('');
13876 const accuDoc = document.implementation.createHTMLDocument('');
13877 const decu = decuDoc.body;
13878 const accu = accuDoc.body;
13879 decu.innerHTML = HTML;
13880 while (decu.firstChild) {
13881 const node = decu.firstChild;
13882
13883 // Text nodes: wrap in a paragraph, or append to previous.
13884 if (node.nodeType === node.TEXT_NODE) {
13885 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
13886 decu.removeChild(node);
13887 } else {
13888 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13889 accu.appendChild(accuDoc.createElement('P'));
13890 }
13891 accu.lastChild.appendChild(node);
13892 }
13893 // Element nodes.
13894 } else if (node.nodeType === node.ELEMENT_NODE) {
13895 // BR nodes: create a new paragraph on double, or append to previous.
13896 if (node.nodeName === 'BR') {
13897 if (node.nextSibling && node.nextSibling.nodeName === 'BR') {
13898 accu.appendChild(accuDoc.createElement('P'));
13899 decu.removeChild(node.nextSibling);
13900 }
13901
13902 // Don't append to an empty paragraph.
13903 if (accu.lastChild && accu.lastChild.nodeName === 'P' && accu.lastChild.hasChildNodes()) {
13904 accu.lastChild.appendChild(node);
13905 } else {
13906 decu.removeChild(node);
13907 }
13908 } else if (node.nodeName === 'P') {
13909 // Only append non-empty paragraph nodes.
13910 if ((0,external_wp_dom_namespaceObject.isEmpty)(node) && !options.raw) {
13911 decu.removeChild(node);
13912 } else {
13913 accu.appendChild(node);
13914 }
13915 } else if ((0,external_wp_dom_namespaceObject.isPhrasingContent)(node)) {
13916 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13917 accu.appendChild(accuDoc.createElement('P'));
13918 }
13919 accu.lastChild.appendChild(node);
13920 } else {
13921 accu.appendChild(node);
13922 }
13923 } else {
13924 decu.removeChild(node);
13925 }
13926 }
13927 return accu.innerHTML;
13928 }
13929
13930 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/special-comment-converter.js
13931 /**
13932 * WordPress dependencies
13933 */
13934
13935
13936 /**
13937 * Looks for `<!--nextpage-->` and `<!--more-->` comments and
13938 * replaces them with a custom element representing a future block.
13939 *
13940 * The custom element is a way to bypass the rest of the `raw-handling`
13941 * transforms, which would eliminate other kinds of node with which to carry
13942 * `<!--more-->`'s data: nodes with `data` attributes, empty paragraphs, etc.
13943 *
13944 * The custom element is then expected to be recognized by any registered
13945 * block's `raw` transform.
13946 *
13947 * @param {Node} node The node to be processed.
13948 * @param {Document} doc The document of the node.
13949 * @return {void}
13950 */
13951 function specialCommentConverter(node, doc) {
13952 if (node.nodeType !== node.COMMENT_NODE) {
13953 return;
13954 }
13955 if (node.nodeValue !== 'nextpage' && node.nodeValue.indexOf('more') !== 0) {
13956 return;
13957 }
13958 const block = special_comment_converter_createBlock(node, doc);
13959
13960 // If our `<!--more-->` comment is in the middle of a paragraph, we should
13961 // split the paragraph in two and insert the more block in between. If it's
13962 // inside an empty paragraph, we should still move it out of the paragraph
13963 // and remove the paragraph. If there's no paragraph, fall back to simply
13964 // replacing the comment.
13965 if (!node.parentNode || node.parentNode.nodeName !== 'P') {
13966 (0,external_wp_dom_namespaceObject.replace)(node, block);
13967 } else {
13968 const childNodes = Array.from(node.parentNode.childNodes);
13969 const nodeIndex = childNodes.indexOf(node);
13970 const wrapperNode = node.parentNode.parentNode || doc.body;
13971 const paragraphBuilder = (acc, child) => {
13972 if (!acc) {
13973 acc = doc.createElement('p');
13974 }
13975 acc.appendChild(child);
13976 return acc;
13977 };
13978
13979 // Split the original parent node and insert our more block
13980 [childNodes.slice(0, nodeIndex).reduce(paragraphBuilder, null), block, childNodes.slice(nodeIndex + 1).reduce(paragraphBuilder, null)].forEach(element => element && wrapperNode.insertBefore(element, node.parentNode));
13981
13982 // Remove the old parent paragraph
13983 (0,external_wp_dom_namespaceObject.remove)(node.parentNode);
13984 }
13985 }
13986 function special_comment_converter_createBlock(commentNode, doc) {
13987 if (commentNode.nodeValue === 'nextpage') {
13988 return createNextpage(doc);
13989 }
13990
13991 // Grab any custom text in the comment.
13992 const customText = commentNode.nodeValue.slice(4).trim();
13993
13994 /*
13995 * When a `<!--more-->` comment is found, we need to look for any
13996 * `<!--noteaser-->` sibling, but it may not be a direct sibling
13997 * (whitespace typically lies in between)
13998 */
13999 let sibling = commentNode;
14000 let noTeaser = false;
14001 while (sibling = sibling.nextSibling) {
14002 if (sibling.nodeType === sibling.COMMENT_NODE && sibling.nodeValue === 'noteaser') {
14003 noTeaser = true;
14004 (0,external_wp_dom_namespaceObject.remove)(sibling);
14005 break;
14006 }
14007 }
14008 return createMore(customText, noTeaser, doc);
14009 }
14010 function createMore(customText, noTeaser, doc) {
14011 const node = doc.createElement('wp-block');
14012 node.dataset.block = 'core/more';
14013 if (customText) {
14014 node.dataset.customText = customText;
14015 }
14016 if (noTeaser) {
14017 // "Boolean" data attribute.
14018 node.dataset.noTeaser = '';
14019 }
14020 return node;
14021 }
14022 function createNextpage(doc) {
14023 const node = doc.createElement('wp-block');
14024 node.dataset.block = 'core/nextpage';
14025 return node;
14026 }
14027
14028 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/list-reducer.js
14029 /**
14030 * WordPress dependencies
14031 */
14032
14033 function isList(node) {
14034 return node.nodeName === 'OL' || node.nodeName === 'UL';
14035 }
14036 function shallowTextContent(element) {
14037 return Array.from(element.childNodes).map(({
14038 nodeValue = ''
14039 }) => nodeValue).join('');
14040 }
14041 function listReducer(node) {
14042 if (!isList(node)) {
14043 return;
14044 }
14045 const list = node;
14046 const prevElement = node.previousElementSibling;
14047
14048 // Merge with previous list if:
14049 // * There is a previous list of the same type.
14050 // * There is only one list item.
14051 if (prevElement && prevElement.nodeName === node.nodeName && list.children.length === 1) {
14052 // Move all child nodes, including any text nodes, if any.
14053 while (list.firstChild) {
14054 prevElement.appendChild(list.firstChild);
14055 }
14056 list.parentNode.removeChild(list);
14057 }
14058 const parentElement = node.parentNode;
14059
14060 // Nested list with empty parent item.
14061 if (parentElement && parentElement.nodeName === 'LI' && parentElement.children.length === 1 && !/\S/.test(shallowTextContent(parentElement))) {
14062 const parentListItem = parentElement;
14063 const prevListItem = parentListItem.previousElementSibling;
14064 const parentList = parentListItem.parentNode;
14065 if (prevListItem) {
14066 prevListItem.appendChild(list);
14067 parentList.removeChild(parentListItem);
14068 }
14069 }
14070
14071 // Invalid: OL/UL > OL/UL.
14072 if (parentElement && isList(parentElement)) {
14073 const prevListItem = node.previousElementSibling;
14074 if (prevListItem) {
14075 prevListItem.appendChild(node);
14076 } else {
14077 (0,external_wp_dom_namespaceObject.unwrap)(node);
14078 }
14079 }
14080 }
14081
14082 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/blockquote-normaliser.js
14083 /**
14084 * Internal dependencies
14085 */
14086
14087 function blockquoteNormaliser(options) {
14088 return node => {
14089 if (node.nodeName !== 'BLOCKQUOTE') {
14090 return;
14091 }
14092 node.innerHTML = normaliseBlocks(node.innerHTML, options);
14093 };
14094 }
14095
14096 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/figure-content-reducer.js
14097 /**
14098 * WordPress dependencies
14099 */
14100
14101
14102 /**
14103 * Whether or not the given node is figure content.
14104 *
14105 * @param {Node} node The node to check.
14106 * @param {Object} schema The schema to use.
14107 *
14108 * @return {boolean} True if figure content, false if not.
14109 */
14110 function isFigureContent(node, schema) {
14111 var _schema$figure$childr;
14112 const tag = node.nodeName.toLowerCase();
14113
14114 // We are looking for tags that can be a child of the figure tag, excluding
14115 // `figcaption` and any phrasing content.
14116 if (tag === 'figcaption' || (0,external_wp_dom_namespaceObject.isTextContent)(node)) {
14117 return false;
14118 }
14119 return tag in ((_schema$figure$childr = schema?.figure?.children) !== null && _schema$figure$childr !== void 0 ? _schema$figure$childr : {});
14120 }
14121
14122 /**
14123 * Whether or not the given node can have an anchor.
14124 *
14125 * @param {Node} node The node to check.
14126 * @param {Object} schema The schema to use.
14127 *
14128 * @return {boolean} True if it can, false if not.
14129 */
14130 function canHaveAnchor(node, schema) {
14131 var _schema$figure$childr2;
14132 const tag = node.nodeName.toLowerCase();
14133 return tag in ((_schema$figure$childr2 = schema?.figure?.children?.a?.children) !== null && _schema$figure$childr2 !== void 0 ? _schema$figure$childr2 : {});
14134 }
14135
14136 /**
14137 * Wraps the given element in a figure element.
14138 *
14139 * @param {Element} element The element to wrap.
14140 * @param {Element} beforeElement The element before which to place the figure.
14141 */
14142 function wrapFigureContent(element, beforeElement = element) {
14143 const figure = element.ownerDocument.createElement('figure');
14144 beforeElement.parentNode.insertBefore(figure, beforeElement);
14145 figure.appendChild(element);
14146 }
14147
14148 /**
14149 * This filter takes figure content out of paragraphs, wraps it in a figure
14150 * element, and moves any anchors with it if needed.
14151 *
14152 * @param {Node} node The node to filter.
14153 * @param {Document} doc The document of the node.
14154 * @param {Object} schema The schema to use.
14155 *
14156 * @return {void}
14157 */
14158 function figureContentReducer(node, doc, schema) {
14159 if (!isFigureContent(node, schema)) {
14160 return;
14161 }
14162 let nodeToInsert = node;
14163 const parentNode = node.parentNode;
14164
14165 // If the figure content can have an anchor and its parent is an anchor with
14166 // only the figure content, take the anchor out instead of just the content.
14167 if (canHaveAnchor(node, schema) && parentNode.nodeName === 'A' && parentNode.childNodes.length === 1) {
14168 nodeToInsert = node.parentNode;
14169 }
14170 const wrapper = nodeToInsert.closest('p,div');
14171
14172 // If wrapped in a paragraph or div, only extract if it's aligned or if
14173 // there is no text content.
14174 // Otherwise, if directly at the root, wrap in a figure element.
14175 if (wrapper) {
14176 // In jsdom-jscore, 'node.classList' can be undefined.
14177 // In this case, default to extract as it offers a better UI experience on mobile.
14178 if (!node.classList) {
14179 wrapFigureContent(nodeToInsert, wrapper);
14180 } else if (node.classList.contains('alignright') || node.classList.contains('alignleft') || node.classList.contains('aligncenter') || !wrapper.textContent.trim()) {
14181 wrapFigureContent(nodeToInsert, wrapper);
14182 }
14183 } else if (nodeToInsert.parentNode.nodeName === 'BODY') {
14184 wrapFigureContent(nodeToInsert);
14185 }
14186 }
14187
14188 ;// CONCATENATED MODULE: external ["wp","shortcode"]
14189 const external_wp_shortcode_namespaceObject = window["wp"]["shortcode"];
14190 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/shortcode-converter.js
14191 /**
14192 * WordPress dependencies
14193 */
14194
14195
14196 /**
14197 * Internal dependencies
14198 */
14199
14200
14201
14202
14203 const castArray = maybeArray => Array.isArray(maybeArray) ? maybeArray : [maybeArray];
14204 const beforeLineRegexp = /(\n|<p>)\s*$/;
14205 const afterLineRegexp = /^\s*(\n|<\/p>)/;
14206 function segmentHTMLToShortcodeBlock(HTML, lastIndex = 0, excludedBlockNames = []) {
14207 // Get all matches.
14208 const transformsFrom = getBlockTransforms('from');
14209 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)));
14210 if (!transformation) {
14211 return [HTML];
14212 }
14213 const transformTags = castArray(transformation.tag);
14214 const transformTag = transformTags.find(tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML));
14215 let match;
14216 const previousIndex = lastIndex;
14217 if (match = (0,external_wp_shortcode_namespaceObject.next)(transformTag, HTML, lastIndex)) {
14218 lastIndex = match.index + match.content.length;
14219 const beforeHTML = HTML.substr(0, match.index);
14220 const afterHTML = HTML.substr(lastIndex);
14221
14222 // If the shortcode content does not contain HTML and the shortcode is
14223 // not on a new line (or in paragraph from Markdown converter),
14224 // consider the shortcode as inline text, and thus skip conversion for
14225 // this segment.
14226 if (!match.shortcode.content?.includes('<') && !(beforeLineRegexp.test(beforeHTML) && afterLineRegexp.test(afterHTML))) {
14227 return segmentHTMLToShortcodeBlock(HTML, lastIndex);
14228 }
14229
14230 // If a transformation's `isMatch` predicate fails for the inbound
14231 // shortcode, try again by excluding the current block type.
14232 //
14233 // This is the only call to `segmentHTMLToShortcodeBlock` that should
14234 // ever carry over `excludedBlockNames`. Other calls in the module
14235 // should skip that argument as a way to reset the exclusion state, so
14236 // that one `isMatch` fail in an HTML fragment doesn't prevent any
14237 // valid matches in subsequent fragments.
14238 if (transformation.isMatch && !transformation.isMatch(match.shortcode.attrs)) {
14239 return segmentHTMLToShortcodeBlock(HTML, previousIndex, [...excludedBlockNames, transformation.blockName]);
14240 }
14241 let blocks = [];
14242 if (typeof transformation.transform === 'function') {
14243 // Passing all of `match` as second argument is intentionally broad
14244 // but shouldn't be too relied upon.
14245 //
14246 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14247 blocks = [].concat(transformation.transform(match.shortcode.attrs, match));
14248
14249 // Applying the built-in fixes can enhance the attributes with missing content like "className".
14250 blocks = blocks.map(block => {
14251 block.originalContent = match.shortcode.content;
14252 return applyBuiltInValidationFixes(block, getBlockType(block.name));
14253 });
14254 } else {
14255 const attributes = Object.fromEntries(Object.entries(transformation.attributes).filter(([, schema]) => schema.shortcode)
14256 // Passing all of `match` as second argument is intentionally broad
14257 // but shouldn't be too relied upon.
14258 //
14259 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14260 .map(([key, schema]) => [key, schema.shortcode(match.shortcode.attrs, match)]));
14261 const blockType = getBlockType(transformation.blockName);
14262 if (!blockType) {
14263 return [HTML];
14264 }
14265 const transformationBlockType = {
14266 ...blockType,
14267 attributes: transformation.attributes
14268 };
14269 let block = createBlock(transformation.blockName, getBlockAttributes(transformationBlockType, match.shortcode.content, attributes));
14270
14271 // Applying the built-in fixes can enhance the attributes with missing content like "className".
14272 block.originalContent = match.shortcode.content;
14273 block = applyBuiltInValidationFixes(block, transformationBlockType);
14274 blocks = [block];
14275 }
14276 return [...segmentHTMLToShortcodeBlock(beforeHTML.replace(beforeLineRegexp, '')), ...blocks, ...segmentHTMLToShortcodeBlock(afterHTML.replace(afterLineRegexp, ''))];
14277 }
14278 return [HTML];
14279 }
14280 /* harmony default export */ const shortcode_converter = (segmentHTMLToShortcodeBlock);
14281
14282 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/utils.js
14283 /**
14284 * WordPress dependencies
14285 */
14286
14287
14288 /**
14289 * Internal dependencies
14290 */
14291
14292
14293 function getBlockContentSchemaFromTransforms(transforms, context) {
14294 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14295 const schemaArgs = {
14296 phrasingContentSchema,
14297 isPaste: context === 'paste'
14298 };
14299 const schemas = transforms.map(({
14300 isMatch,
14301 blockName,
14302 schema
14303 }) => {
14304 const hasAnchorSupport = hasBlockSupport(blockName, 'anchor');
14305 schema = typeof schema === 'function' ? schema(schemaArgs) : schema;
14306
14307 // If the block does not has anchor support and the transform does not
14308 // provides an isMatch we can return the schema right away.
14309 if (!hasAnchorSupport && !isMatch) {
14310 return schema;
14311 }
14312 if (!schema) {
14313 return {};
14314 }
14315 return Object.fromEntries(Object.entries(schema).map(([key, value]) => {
14316 let attributes = value.attributes || [];
14317 // If the block supports the "anchor" functionality, it needs to keep its ID attribute.
14318 if (hasAnchorSupport) {
14319 attributes = [...attributes, 'id'];
14320 }
14321 return [key, {
14322 ...value,
14323 attributes,
14324 isMatch: isMatch ? isMatch : undefined
14325 }];
14326 }));
14327 });
14328 function mergeTagNameSchemaProperties(objValue, srcValue, key) {
14329 switch (key) {
14330 case 'children':
14331 {
14332 if (objValue === '*' || srcValue === '*') {
14333 return '*';
14334 }
14335 return {
14336 ...objValue,
14337 ...srcValue
14338 };
14339 }
14340 case 'attributes':
14341 case 'require':
14342 {
14343 return [...(objValue || []), ...(srcValue || [])];
14344 }
14345 case 'isMatch':
14346 {
14347 // If one of the values being merge is undefined (matches everything),
14348 // the result of the merge will be undefined.
14349 if (!objValue || !srcValue) {
14350 return undefined;
14351 }
14352 // When merging two isMatch functions, the result is a new function
14353 // that returns if one of the source functions returns true.
14354 return (...args) => {
14355 return objValue(...args) || srcValue(...args);
14356 };
14357 }
14358 }
14359 }
14360
14361 // A tagName schema is an object with children, attributes, require, and
14362 // isMatch properties.
14363 function mergeTagNameSchemas(a, b) {
14364 for (const key in b) {
14365 a[key] = a[key] ? mergeTagNameSchemaProperties(a[key], b[key], key) : {
14366 ...b[key]
14367 };
14368 }
14369 return a;
14370 }
14371
14372 // A schema is an object with tagName schemas by tag name.
14373 function mergeSchemas(a, b) {
14374 for (const key in b) {
14375 a[key] = a[key] ? mergeTagNameSchemas(a[key], b[key]) : {
14376 ...b[key]
14377 };
14378 }
14379 return a;
14380 }
14381 return schemas.reduce(mergeSchemas, {});
14382 }
14383
14384 /**
14385 * Gets the block content schema, which is extracted and merged from all
14386 * registered blocks with raw transfroms.
14387 *
14388 * @param {string} context Set to "paste" when in paste context, where the
14389 * schema is more strict.
14390 *
14391 * @return {Object} A complete block content schema.
14392 */
14393 function getBlockContentSchema(context) {
14394 return getBlockContentSchemaFromTransforms(getRawTransforms(), context);
14395 }
14396
14397 /**
14398 * Checks whether HTML can be considered plain text. That is, it does not contain
14399 * any elements that are not line breaks.
14400 *
14401 * @param {string} HTML The HTML to check.
14402 *
14403 * @return {boolean} Whether the HTML can be considered plain text.
14404 */
14405 function isPlain(HTML) {
14406 return !/<(?!br[ />])/i.test(HTML);
14407 }
14408
14409 /**
14410 * Given node filters, deeply filters and mutates a NodeList.
14411 *
14412 * @param {NodeList} nodeList The nodeList to filter.
14413 * @param {Array} filters An array of functions that can mutate with the provided node.
14414 * @param {Document} doc The document of the nodeList.
14415 * @param {Object} schema The schema to use.
14416 */
14417 function deepFilterNodeList(nodeList, filters, doc, schema) {
14418 Array.from(nodeList).forEach(node => {
14419 deepFilterNodeList(node.childNodes, filters, doc, schema);
14420 filters.forEach(item => {
14421 // Make sure the node is still attached to the document.
14422 if (!doc.contains(node)) {
14423 return;
14424 }
14425 item(node, doc, schema);
14426 });
14427 });
14428 }
14429
14430 /**
14431 * Given node filters, deeply filters HTML tags.
14432 * Filters from the deepest nodes to the top.
14433 *
14434 * @param {string} HTML The HTML to filter.
14435 * @param {Array} filters An array of functions that can mutate with the provided node.
14436 * @param {Object} schema The schema to use.
14437 *
14438 * @return {string} The filtered HTML.
14439 */
14440 function deepFilterHTML(HTML, filters = [], schema) {
14441 const doc = document.implementation.createHTMLDocument('');
14442 doc.body.innerHTML = HTML;
14443 deepFilterNodeList(doc.body.childNodes, filters, doc, schema);
14444 return doc.body.innerHTML;
14445 }
14446
14447 /**
14448 * Gets a sibling within text-level context.
14449 *
14450 * @param {Element} node The subject node.
14451 * @param {string} which "next" or "previous".
14452 */
14453 function getSibling(node, which) {
14454 const sibling = node[`${which}Sibling`];
14455 if (sibling && (0,external_wp_dom_namespaceObject.isPhrasingContent)(sibling)) {
14456 return sibling;
14457 }
14458 const {
14459 parentNode
14460 } = node;
14461 if (!parentNode || !(0,external_wp_dom_namespaceObject.isPhrasingContent)(parentNode)) {
14462 return;
14463 }
14464 return getSibling(parentNode, which);
14465 }
14466
14467 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/index.js
14468 /**
14469 * WordPress dependencies
14470 */
14471
14472
14473
14474 /**
14475 * Internal dependencies
14476 */
14477
14478
14479
14480
14481
14482
14483
14484
14485
14486
14487 function deprecatedGetPhrasingContentSchema(context) {
14488 external_wp_deprecated_default()('wp.blocks.getPhrasingContentSchema', {
14489 since: '5.6',
14490 alternative: 'wp.dom.getPhrasingContentSchema'
14491 });
14492 return (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14493 }
14494
14495 /**
14496 * Converts an HTML string to known blocks.
14497 *
14498 * @param {Object} $1
14499 * @param {string} $1.HTML The HTML to convert.
14500 *
14501 * @return {Array} A list of blocks.
14502 */
14503 function rawHandler({
14504 HTML = ''
14505 }) {
14506 // If we detect block delimiters, parse entirely as blocks.
14507 if (HTML.indexOf('<!-- wp:') !== -1) {
14508 const parseResult = parser_parse(HTML);
14509 const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform';
14510 if (!isSingleFreeFormBlock) {
14511 return parseResult;
14512 }
14513 }
14514
14515 // An array of HTML strings and block objects. The blocks replace matched
14516 // shortcodes.
14517 const pieces = shortcode_converter(HTML);
14518 const blockContentSchema = getBlockContentSchema();
14519 return pieces.map(piece => {
14520 // Already a block from shortcode.
14521 if (typeof piece !== 'string') {
14522 return piece;
14523 }
14524
14525 // These filters are essential for some blocks to be able to transform
14526 // from raw HTML. These filters move around some content or add
14527 // additional tags, they do not remove any content.
14528 const filters = [
14529 // Needed to adjust invalid lists.
14530 listReducer,
14531 // Needed to create more and nextpage blocks.
14532 specialCommentConverter,
14533 // Needed to create media blocks.
14534 figureContentReducer,
14535 // Needed to create the quote block, which cannot handle text
14536 // without wrapper paragraphs.
14537 blockquoteNormaliser({
14538 raw: true
14539 })];
14540 piece = deepFilterHTML(piece, filters, blockContentSchema);
14541 piece = normaliseBlocks(piece, {
14542 raw: true
14543 });
14544 return htmlToBlocks(piece, rawHandler);
14545 }).flat().filter(Boolean);
14546 }
14547
14548 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/comment-remover.js
14549 /**
14550 * WordPress dependencies
14551 */
14552
14553
14554 /**
14555 * Looks for comments, and removes them.
14556 *
14557 * @param {Node} node The node to be processed.
14558 * @return {void}
14559 */
14560 function commentRemover(node) {
14561 if (node.nodeType === node.COMMENT_NODE) {
14562 (0,external_wp_dom_namespaceObject.remove)(node);
14563 }
14564 }
14565
14566 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/is-inline-content.js
14567 /**
14568 * WordPress dependencies
14569 */
14570
14571
14572 /**
14573 * Checks if the given node should be considered inline content, optionally
14574 * depending on a context tag.
14575 *
14576 * @param {Node} node Node name.
14577 * @param {string} contextTag Tag name.
14578 *
14579 * @return {boolean} True if the node is inline content, false if nohe.
14580 */
14581 function isInline(node, contextTag) {
14582 if ((0,external_wp_dom_namespaceObject.isTextContent)(node)) {
14583 return true;
14584 }
14585 if (!contextTag) {
14586 return false;
14587 }
14588 const tag = node.nodeName.toLowerCase();
14589 const inlineAllowedTagGroups = [['ul', 'li', 'ol'], ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']];
14590 return inlineAllowedTagGroups.some(tagGroup => [tag, contextTag].filter(t => !tagGroup.includes(t)).length === 0);
14591 }
14592 function deepCheck(nodes, contextTag) {
14593 return nodes.every(node => isInline(node, contextTag) && deepCheck(Array.from(node.children), contextTag));
14594 }
14595 function isDoubleBR(node) {
14596 return node.nodeName === 'BR' && node.previousSibling && node.previousSibling.nodeName === 'BR';
14597 }
14598 function isInlineContent(HTML, contextTag) {
14599 const doc = document.implementation.createHTMLDocument('');
14600 doc.body.innerHTML = HTML;
14601 const nodes = Array.from(doc.body.children);
14602 return !nodes.some(isDoubleBR) && deepCheck(nodes, contextTag);
14603 }
14604
14605 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/phrasing-content-reducer.js
14606 /**
14607 * WordPress dependencies
14608 */
14609
14610 function phrasingContentReducer(node, doc) {
14611 // In jsdom-jscore, 'node.style' can be null.
14612 // TODO: Explore fixing this by patching jsdom-jscore.
14613 if (node.nodeName === 'SPAN' && node.style) {
14614 const {
14615 fontWeight,
14616 fontStyle,
14617 textDecorationLine,
14618 textDecoration,
14619 verticalAlign
14620 } = node.style;
14621 if (fontWeight === 'bold' || fontWeight === '700') {
14622 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('strong'), node);
14623 }
14624 if (fontStyle === 'italic') {
14625 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('em'), node);
14626 }
14627
14628 // Some DOM implementations (Safari, JSDom) don't support
14629 // style.textDecorationLine, so we check style.textDecoration as a
14630 // fallback.
14631 if (textDecorationLine === 'line-through' || textDecoration.includes('line-through')) {
14632 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('s'), node);
14633 }
14634 if (verticalAlign === 'super') {
14635 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sup'), node);
14636 } else if (verticalAlign === 'sub') {
14637 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sub'), node);
14638 }
14639 } else if (node.nodeName === 'B') {
14640 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'strong');
14641 } else if (node.nodeName === 'I') {
14642 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'em');
14643 } else if (node.nodeName === 'A') {
14644 // In jsdom-jscore, 'node.target' can be null.
14645 // TODO: Explore fixing this by patching jsdom-jscore.
14646 if (node.target && node.target.toLowerCase() === '_blank') {
14647 node.rel = 'noreferrer noopener';
14648 } else {
14649 node.removeAttribute('target');
14650 node.removeAttribute('rel');
14651 }
14652
14653 // Saves anchor elements name attribute as id
14654 if (node.name && !node.id) {
14655 node.id = node.name;
14656 }
14657
14658 // Keeps id only if there is an internal link pointing to it
14659 if (node.id && !node.ownerDocument.querySelector(`[href="#${node.id}"]`)) {
14660 node.removeAttribute('id');
14661 }
14662 }
14663 }
14664
14665 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/head-remover.js
14666 function headRemover(node) {
14667 if (node.nodeName !== 'SCRIPT' && node.nodeName !== 'NOSCRIPT' && node.nodeName !== 'TEMPLATE' && node.nodeName !== 'STYLE') {
14668 return;
14669 }
14670 node.parentNode.removeChild(node);
14671 }
14672
14673 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/ms-list-ignore.js
14674 /**
14675 * Looks for comments, and removes them.
14676 *
14677 * @param {Node} node The node to be processed.
14678 * @return {void}
14679 */
14680 function msListIgnore(node) {
14681 if (node.nodeType !== node.ELEMENT_NODE) {
14682 return;
14683 }
14684 const style = node.getAttribute('style');
14685 if (!style || !style.includes('mso-list')) {
14686 return;
14687 }
14688 const rules = style.split(';').reduce((acc, rule) => {
14689 const [key, value] = rule.split(':');
14690 if (key && value) {
14691 acc[key.trim().toLowerCase()] = value.trim().toLowerCase();
14692 }
14693 return acc;
14694 }, {});
14695 if (rules['mso-list'] === 'ignore') {
14696 node.remove();
14697 }
14698 }
14699
14700 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/ms-list-converter.js
14701 /**
14702 * Internal dependencies
14703 */
14704
14705
14706 function ms_list_converter_isList(node) {
14707 return node.nodeName === 'OL' || node.nodeName === 'UL';
14708 }
14709 function msListConverter(node, doc) {
14710 if (node.nodeName !== 'P') {
14711 return;
14712 }
14713 const style = node.getAttribute('style');
14714 if (!style || !style.includes('mso-list')) {
14715 return;
14716 }
14717 const prevNode = node.previousElementSibling;
14718
14719 // Add new list if no previous.
14720 if (!prevNode || !ms_list_converter_isList(prevNode)) {
14721 // See https://html.spec.whatwg.org/multipage/grouping-content.html#attr-ol-type.
14722 const type = node.textContent.trim().slice(0, 1);
14723 const isNumeric = /[1iIaA]/.test(type);
14724 const newListNode = doc.createElement(isNumeric ? 'ol' : 'ul');
14725 if (isNumeric) {
14726 newListNode.setAttribute('type', type);
14727 }
14728 node.parentNode.insertBefore(newListNode, node);
14729 }
14730 const listNode = node.previousElementSibling;
14731 const listType = listNode.nodeName;
14732 const listItem = doc.createElement('li');
14733 let receivingNode = listNode;
14734
14735 // Add content.
14736 listItem.innerHTML = deepFilterHTML(node.innerHTML, [msListIgnore]);
14737 const matches = /mso-list\s*:[^;]+level([0-9]+)/i.exec(style);
14738 let level = matches ? parseInt(matches[1], 10) - 1 || 0 : 0;
14739
14740 // Change pointer depending on indentation level.
14741 while (level--) {
14742 receivingNode = receivingNode.lastChild || receivingNode;
14743
14744 // If it's a list, move pointer to the last item.
14745 if (ms_list_converter_isList(receivingNode)) {
14746 receivingNode = receivingNode.lastChild || receivingNode;
14747 }
14748 }
14749
14750 // Make sure we append to a list.
14751 if (!ms_list_converter_isList(receivingNode)) {
14752 receivingNode = receivingNode.appendChild(doc.createElement(listType));
14753 }
14754
14755 // Append the list item to the list.
14756 receivingNode.appendChild(listItem);
14757
14758 // Remove the wrapper paragraph.
14759 node.parentNode.removeChild(node);
14760 }
14761
14762 ;// CONCATENATED MODULE: external ["wp","blob"]
14763 const external_wp_blob_namespaceObject = window["wp"]["blob"];
14764 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/image-corrector.js
14765 /**
14766 * WordPress dependencies
14767 */
14768
14769 function imageCorrector(node) {
14770 if (node.nodeName !== 'IMG') {
14771 return;
14772 }
14773 if (node.src.indexOf('file:') === 0) {
14774 node.src = '';
14775 }
14776
14777 // This piece cannot be tested outside a browser env.
14778 if (node.src.indexOf('data:') === 0) {
14779 const [properties, data] = node.src.split(',');
14780 const [type] = properties.slice(5).split(';');
14781 if (!data || !type) {
14782 node.src = '';
14783 return;
14784 }
14785 let decoded;
14786
14787 // Can throw DOMException!
14788 try {
14789 decoded = atob(data);
14790 } catch (e) {
14791 node.src = '';
14792 return;
14793 }
14794 const uint8Array = new Uint8Array(decoded.length);
14795 for (let i = 0; i < uint8Array.length; i++) {
14796 uint8Array[i] = decoded.charCodeAt(i);
14797 }
14798 const name = type.replace('/', '.');
14799 const file = new window.File([uint8Array], name, {
14800 type
14801 });
14802 node.src = (0,external_wp_blob_namespaceObject.createBlobURL)(file);
14803 }
14804
14805 // Remove trackers and hardly visible images.
14806 if (node.height === 1 || node.width === 1) {
14807 node.parentNode.removeChild(node);
14808 }
14809 }
14810
14811 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/div-normaliser.js
14812 /**
14813 * Internal dependencies
14814 */
14815
14816 function divNormaliser(node) {
14817 if (node.nodeName !== 'DIV') {
14818 return;
14819 }
14820 node.innerHTML = normaliseBlocks(node.innerHTML);
14821 }
14822
14823 // EXTERNAL MODULE: ./node_modules/showdown/dist/showdown.js
14824 var showdown = __webpack_require__(7308);
14825 var showdown_default = /*#__PURE__*/__webpack_require__.n(showdown);
14826 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/markdown-converter.js
14827 /**
14828 * External dependencies
14829 */
14830
14831
14832 // Reuse the same showdown converter.
14833 const converter = new (showdown_default()).Converter({
14834 noHeaderId: true,
14835 tables: true,
14836 literalMidWordUnderscores: true,
14837 omitExtraWLInCodeBlocks: true,
14838 simpleLineBreaks: true,
14839 strikethrough: true
14840 });
14841
14842 /**
14843 * Corrects the Slack Markdown variant of the code block.
14844 * If uncorrected, it will be converted to inline code.
14845 *
14846 * @see https://get.slack.help/hc/en-us/articles/202288908-how-can-i-add-formatting-to-my-messages-#code-blocks
14847 *
14848 * @param {string} text The potential Markdown text to correct.
14849 *
14850 * @return {string} The corrected Markdown.
14851 */
14852 function slackMarkdownVariantCorrector(text) {
14853 return text.replace(/((?:^|\n)```)([^\n`]+)(```(?:$|\n))/, (match, p1, p2, p3) => `${p1}\n${p2}\n${p3}`);
14854 }
14855 function bulletsToAsterisks(text) {
14856 return text.replace(/(^|\n)•( +)/g, '$1*$2');
14857 }
14858
14859 /**
14860 * Converts a piece of text into HTML based on any Markdown present.
14861 * Also decodes any encoded HTML.
14862 *
14863 * @param {string} text The plain text to convert.
14864 *
14865 * @return {string} HTML.
14866 */
14867 function markdownConverter(text) {
14868 return converter.makeHtml(slackMarkdownVariantCorrector(bulletsToAsterisks(text)));
14869 }
14870
14871 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/iframe-remover.js
14872 /**
14873 * Removes iframes.
14874 *
14875 * @param {Node} node The node to check.
14876 *
14877 * @return {void}
14878 */
14879 function iframeRemover(node) {
14880 if (node.nodeName === 'IFRAME') {
14881 const text = node.ownerDocument.createTextNode(node.src);
14882 node.parentNode.replaceChild(text, node);
14883 }
14884 }
14885
14886 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/google-docs-uid-remover.js
14887 /**
14888 * WordPress dependencies
14889 */
14890
14891 function googleDocsUIdRemover(node) {
14892 if (!node.id || node.id.indexOf('docs-internal-guid-') !== 0) {
14893 return;
14894 }
14895
14896 // Google Docs sometimes wraps the content in a B tag. We don't want to keep
14897 // this.
14898 if (node.tagName === 'B') {
14899 (0,external_wp_dom_namespaceObject.unwrap)(node);
14900 } else {
14901 node.removeAttribute('id');
14902 }
14903 }
14904
14905 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-formatting-remover.js
14906 /**
14907 * Internal dependencies
14908 */
14909
14910 function isFormattingSpace(character) {
14911 return character === ' ' || character === '\r' || character === '\n' || character === '\t';
14912 }
14913
14914 /**
14915 * Removes spacing that formats HTML.
14916 *
14917 * @see https://www.w3.org/TR/css-text-3/#white-space-processing
14918 *
14919 * @param {Node} node The node to be processed.
14920 * @return {void}
14921 */
14922 function htmlFormattingRemover(node) {
14923 if (node.nodeType !== node.TEXT_NODE) {
14924 return;
14925 }
14926
14927 // Ignore pre content. Note that this does not use Element#closest due to
14928 // a combination of (a) node may not be Element and (b) node.parentElement
14929 // does not have full support in all browsers (Internet Exporer).
14930 //
14931 // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility
14932
14933 /** @type {Node?} */
14934 let parent = node;
14935 while (parent = parent.parentNode) {
14936 if (parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE') {
14937 return;
14938 }
14939 }
14940
14941 // First, replace any sequence of HTML formatting space with a single space.
14942 let newData = node.data.replace(/[ \r\n\t]+/g, ' ');
14943
14944 // Remove the leading space if the text element is at the start of a block,
14945 // is preceded by a line break element, or has a space in the previous
14946 // node.
14947 if (newData[0] === ' ') {
14948 const previousSibling = getSibling(node, 'previous');
14949 if (!previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice(-1) === ' ') {
14950 newData = newData.slice(1);
14951 }
14952 }
14953
14954 // Remove the trailing space if the text element is at the end of a block,
14955 // is succeded by a line break element, or has a space in the next text
14956 // node.
14957 if (newData[newData.length - 1] === ' ') {
14958 const nextSibling = getSibling(node, 'next');
14959 if (!nextSibling || nextSibling.nodeName === 'BR' || nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace(nextSibling.textContent[0])) {
14960 newData = newData.slice(0, -1);
14961 }
14962 }
14963
14964 // If there's no data left, remove the node, so `previousSibling` stays
14965 // accurate. Otherwise, update the node data.
14966 if (!newData) {
14967 node.parentNode.removeChild(node);
14968 } else {
14969 node.data = newData;
14970 }
14971 }
14972
14973 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/br-remover.js
14974 /**
14975 * Internal dependencies
14976 */
14977
14978
14979 /**
14980 * Removes trailing br elements from text-level content.
14981 *
14982 * @param {Element} node Node to check.
14983 */
14984 function brRemover(node) {
14985 if (node.nodeName !== 'BR') {
14986 return;
14987 }
14988 if (getSibling(node, 'next')) {
14989 return;
14990 }
14991 node.parentNode.removeChild(node);
14992 }
14993
14994 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/empty-paragraph-remover.js
14995 /**
14996 * Removes empty paragraph elements.
14997 *
14998 * @param {Element} node Node to check.
14999 */
15000 function emptyParagraphRemover(node) {
15001 if (node.nodeName !== 'P') {
15002 return;
15003 }
15004 if (node.hasChildNodes()) {
15005 return;
15006 }
15007 node.parentNode.removeChild(node);
15008 }
15009
15010 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/slack-paragraph-corrector.js
15011 /**
15012 * Replaces Slack paragraph markup with a double line break (later converted to
15013 * a proper paragraph).
15014 *
15015 * @param {Element} node Node to check.
15016 */
15017 function slackParagraphCorrector(node) {
15018 if (node.nodeName !== 'SPAN') {
15019 return;
15020 }
15021 if (node.getAttribute('data-stringify-type') !== 'paragraph-break') {
15022 return;
15023 }
15024 const {
15025 parentNode
15026 } = node;
15027 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
15028 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
15029 parentNode.removeChild(node);
15030 }
15031
15032 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/paste-handler.js
15033 /**
15034 * WordPress dependencies
15035 */
15036
15037
15038 /**
15039 * Internal dependencies
15040 */
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067 const log = (...args) => window?.console?.log?.(...args);
15068
15069 /**
15070 * Filters HTML to only contain phrasing content.
15071 *
15072 * @param {string} HTML The HTML to filter.
15073 *
15074 * @return {string} HTML only containing phrasing content.
15075 */
15076 function filterInlineHTML(HTML) {
15077 HTML = deepFilterHTML(HTML, [headRemover, googleDocsUIdRemover, msListIgnore, phrasingContentReducer, commentRemover]);
15078 HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
15079 inline: true
15080 });
15081 HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
15082
15083 // Allows us to ask for this information when we get a report.
15084 log('Processed inline HTML:\n\n', HTML);
15085 return HTML;
15086 }
15087
15088 /**
15089 * Converts an HTML string to known blocks. Strips everything else.
15090 *
15091 * @param {Object} options
15092 * @param {string} [options.HTML] The HTML to convert.
15093 * @param {string} [options.plainText] Plain text version.
15094 * @param {string} [options.mode] Handle content as blocks or inline content.
15095 * * 'AUTO': Decide based on the content passed.
15096 * * 'INLINE': Always handle as inline content, and return string.
15097 * * 'BLOCKS': Always handle as blocks, and return array of blocks.
15098 * @param {Array} [options.tagName] The tag into which content will be inserted.
15099 *
15100 * @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
15101 */
15102 function pasteHandler({
15103 HTML = '',
15104 plainText = '',
15105 mode = 'AUTO',
15106 tagName
15107 }) {
15108 // First of all, strip any meta tags.
15109 HTML = HTML.replace(/<meta[^>]+>/g, '');
15110 // Strip Windows markers.
15111 HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
15112 HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, '');
15113
15114 // If we detect block delimiters in HTML, parse entirely as blocks.
15115 if (mode !== 'INLINE') {
15116 // Check plain text if there is no HTML.
15117 const content = HTML ? HTML : plainText;
15118 if (content.indexOf('<!-- wp:') !== -1) {
15119 const parseResult = parser_parse(content);
15120 const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform';
15121 if (!isSingleFreeFormBlock) {
15122 return parseResult;
15123 }
15124 }
15125 }
15126
15127 // Normalize unicode to use composed characters.
15128 // Not normalizing the content will only affect older browsers and won't
15129 // entirely break the app.
15130 // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
15131 // See: https://core.trac.wordpress.org/ticket/30130
15132 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
15133 if (String.prototype.normalize) {
15134 HTML = HTML.normalize();
15135 }
15136
15137 // Must be run before checking if it's inline content.
15138 HTML = deepFilterHTML(HTML, [slackParagraphCorrector]);
15139
15140 // Consider plain text if:
15141 // * There is a plain text version.
15142 // * There is no HTML version, or it has no formatting.
15143 const isPlainText = plainText && (!HTML || isPlain(HTML));
15144
15145 // Parse Markdown (and encoded HTML) if it's considered plain text.
15146 if (isPlainText) {
15147 HTML = plainText;
15148
15149 // The markdown converter (Showdown) trims whitespace.
15150 if (!/^\s+$/.test(plainText)) {
15151 HTML = markdownConverter(HTML);
15152 }
15153 }
15154
15155 // An array of HTML strings and block objects. The blocks replace matched
15156 // shortcodes.
15157 const pieces = shortcode_converter(HTML);
15158
15159 // The call to shortcodeConverter will always return more than one element
15160 // if shortcodes are matched. The reason is when shortcodes are matched
15161 // empty HTML strings are included.
15162 const hasShortcodes = pieces.length > 1;
15163 if (isPlainText && !hasShortcodes) {
15164 // Switch to inline mode if:
15165 // * The current mode is AUTO.
15166 // * The original plain text had no line breaks.
15167 // * The original plain text was not an HTML paragraph.
15168 // * The converted text is just a paragraph.
15169 if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
15170 mode = 'INLINE';
15171 }
15172 }
15173 if (mode === 'INLINE') {
15174 return filterInlineHTML(HTML);
15175 }
15176 if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
15177 return filterInlineHTML(HTML);
15178 }
15179 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
15180 const blockContentSchema = getBlockContentSchema('paste');
15181 const blocks = pieces.map(piece => {
15182 // Already a block from shortcode.
15183 if (typeof piece !== 'string') {
15184 return piece;
15185 }
15186 const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser(), divNormaliser];
15187 const schema = {
15188 ...blockContentSchema,
15189 // Keep top-level phrasing content, normalised by `normaliseBlocks`.
15190 ...phrasingContentSchema
15191 };
15192 piece = deepFilterHTML(piece, filters, blockContentSchema);
15193 piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
15194 piece = normaliseBlocks(piece);
15195 piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema);
15196
15197 // Allows us to ask for this information when we get a report.
15198 log('Processed HTML piece:\n\n', piece);
15199 return htmlToBlocks(piece, pasteHandler);
15200 }).flat().filter(Boolean);
15201
15202 // If we're allowed to return inline content, and there is only one
15203 // inlineable block, and the original plain text content does not have any
15204 // line breaks, then treat it as inline paste.
15205 if (mode === 'AUTO' && blocks.length === 1 && hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
15206 const trimRegex = /^[\n]+|[\n]+$/g;
15207 // Don't catch line breaks at the start or end.
15208 const trimmedPlainText = plainText.replace(trimRegex, '');
15209 if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
15210 return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema).replace(trimRegex, '');
15211 }
15212 }
15213 return blocks;
15214 }
15215
15216 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/categories.js
15217 /**
15218 * WordPress dependencies
15219 */
15220
15221
15222 /**
15223 * Internal dependencies
15224 */
15225
15226
15227 /** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
15228
15229 /**
15230 * Returns all the block categories.
15231 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
15232 *
15233 * @ignore
15234 *
15235 * @return {WPBlockCategory[]} Block categories.
15236 */
15237 function categories_getCategories() {
15238 return (0,external_wp_data_namespaceObject.select)(store).getCategories();
15239 }
15240
15241 /**
15242 * Sets the block categories.
15243 *
15244 * @param {WPBlockCategory[]} categories Block categories.
15245 *
15246 * @example
15247 * ```js
15248 * import { __ } from '@wordpress/i18n';
15249 * import { store as blocksStore, setCategories } from '@wordpress/blocks';
15250 * import { useSelect } from '@wordpress/data';
15251 * import { Button } from '@wordpress/components';
15252 *
15253 * const ExampleComponent = () => {
15254 * // Retrieve the list of current categories.
15255 * const blockCategories = useSelect(
15256 * ( select ) => select( blocksStore ).getCategories(),
15257 * []
15258 * );
15259 *
15260 * return (
15261 * <Button
15262 * onClick={ () => {
15263 * // Add a custom category to the existing list.
15264 * setCategories( [
15265 * ...blockCategories,
15266 * { title: 'Custom Category', slug: 'custom-category' },
15267 * ] );
15268 * } }
15269 * >
15270 * { __( 'Add a new custom block category' ) }
15271 * </Button>
15272 * );
15273 * };
15274 * ```
15275 */
15276 function categories_setCategories(categories) {
15277 (0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
15278 }
15279
15280 /**
15281 * Updates a category.
15282 *
15283 * @param {string} slug Block category slug.
15284 * @param {WPBlockCategory} category Object containing the category properties
15285 * that should be updated.
15286 *
15287 * @example
15288 * ```js
15289 * import { __ } from '@wordpress/i18n';
15290 * import { updateCategory } from '@wordpress/blocks';
15291 * import { Button } from '@wordpress/components';
15292 *
15293 * const ExampleComponent = () => {
15294 * return (
15295 * <Button
15296 * onClick={ () => {
15297 * updateCategory( 'text', { title: __( 'Written Word' ) } );
15298 * } }
15299 * >
15300 * { __( 'Update Text category title' ) }
15301 * </Button>
15302 * ) ;
15303 * };
15304 * ```
15305 */
15306 function categories_updateCategory(slug, category) {
15307 (0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
15308 }
15309
15310 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/templates.js
15311 /**
15312 * WordPress dependencies
15313 */
15314
15315
15316 /**
15317 * Internal dependencies
15318 */
15319
15320
15321
15322
15323 /**
15324 * Checks whether a list of blocks matches a template by comparing the block names.
15325 *
15326 * @param {Array} blocks Block list.
15327 * @param {Array} template Block template.
15328 *
15329 * @return {boolean} Whether the list of blocks matches a templates.
15330 */
15331 function doBlocksMatchTemplate(blocks = [], template = []) {
15332 return blocks.length === template.length && template.every(([name,, innerBlocksTemplate], index) => {
15333 const block = blocks[index];
15334 return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
15335 });
15336 }
15337 const isHTMLAttribute = attributeDefinition => attributeDefinition?.source === 'html';
15338 const isQueryAttribute = attributeDefinition => attributeDefinition?.source === 'query';
15339 function normalizeAttributes(schema, values) {
15340 if (!values) {
15341 return {};
15342 }
15343 return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, normalizeAttribute(schema[key], value)]));
15344 }
15345 function normalizeAttribute(definition, value) {
15346 if (isHTMLAttribute(definition) && Array.isArray(value)) {
15347 // Introduce a deprecated call at this point
15348 // When we're confident that "children" format should be removed from the templates.
15349
15350 return (0,external_wp_element_namespaceObject.renderToString)(value);
15351 }
15352 if (isQueryAttribute(definition) && value) {
15353 return value.map(subValues => {
15354 return normalizeAttributes(definition.query, subValues);
15355 });
15356 }
15357 return value;
15358 }
15359
15360 /**
15361 * Synchronize a block list with a block template.
15362 *
15363 * Synchronizing a block list with a block template means that we loop over the blocks
15364 * keep the block as is if it matches the block at the same position in the template
15365 * (If it has the same name) and if doesn't match, we create a new block based on the template.
15366 * Extra blocks not present in the template are removed.
15367 *
15368 * @param {Array} blocks Block list.
15369 * @param {Array} template Block template.
15370 *
15371 * @return {Array} Updated Block list.
15372 */
15373 function synchronizeBlocksWithTemplate(blocks = [], template) {
15374 // If no template is provided, return blocks unmodified.
15375 if (!template) {
15376 return blocks;
15377 }
15378 return template.map(([name, attributes, innerBlocksTemplate], index) => {
15379 var _blockType$attributes;
15380 const block = blocks[index];
15381 if (block && block.name === name) {
15382 const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
15383 return {
15384 ...block,
15385 innerBlocks
15386 };
15387 }
15388
15389 // To support old templates that were using the "children" format
15390 // for the attributes using "html" strings now, we normalize the template attributes
15391 // before creating the blocks.
15392
15393 const blockType = getBlockType(name);
15394 const normalizedAttributes = normalizeAttributes((_blockType$attributes = blockType?.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}, attributes);
15395 let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes);
15396
15397 // If a Block is undefined at this point, use the core/missing block as
15398 // a placeholder for a better user experience.
15399 if (undefined === getBlockType(blockName)) {
15400 blockAttributes = {
15401 originalName: name,
15402 originalContent: '',
15403 originalUndelimitedContent: ''
15404 };
15405 blockName = 'core/missing';
15406 }
15407 return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
15408 });
15409 }
15410
15411 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/index.js
15412 /**
15413 * Internal dependencies
15414 */
15415
15416
15417
15418 // The blocktype is the most important concept within the block API. It defines
15419 // all aspects of the block configuration and its interfaces, including `edit`
15420 // and `save`. The transforms specification allows converting one blocktype to
15421 // another through formulas defined by either the source or the destination.
15422 // Switching a blocktype is to be considered a one-way operation implying a
15423 // transformation in the opposite way has to be handled explicitly.
15424
15425
15426 // The block tree is composed of a collection of block nodes. Blocks contained
15427 // within other blocks are called inner blocks. An important design
15428 // consideration is that inner blocks are -- conceptually -- not part of the
15429 // territory established by the parent block that contains them.
15430 //
15431 // This has multiple practical implications: when parsing, we can safely dispose
15432 // of any block boundary found within a block from the innerHTML property when
15433 // transfering to state. Not doing so would have a compounding effect on memory
15434 // and uncertainty over the source of truth. This can be illustrated in how,
15435 // given a tree of `n` nested blocks, the entry node would have to contain the
15436 // actual content of each block while each subsequent block node in the state
15437 // tree would replicate the entire chain `n-1`, meaning the extreme end node
15438 // would have been replicated `n` times as the tree is traversed and would
15439 // generate uncertainty as to which one is to hold the current value of the
15440 // block. For composition, it also means inner blocks can effectively be child
15441 // components whose mechanisms can be shielded from the `edit` implementation
15442 // and just passed along.
15443
15444
15445
15446
15447 // While block transformations account for a specific surface of the API, there
15448 // are also raw transformations which handle arbitrary sources not made out of
15449 // blocks but producing block basaed on various heursitics. This includes
15450 // pasting rich text or HTML data.
15451
15452
15453 // The process of serialization aims to deflate the internal memory of the block
15454 // editor and its state representation back into an HTML valid string. This
15455 // process restores the document integrity and inserts invisible delimiters
15456 // around each block with HTML comment boundaries which can contain any extra
15457 // attributes needed to operate with the block later on.
15458
15459
15460 // Validation is the process of comparing a block source with its output before
15461 // there is any user input or interaction with a block. When this operation
15462 // fails -- for whatever reason -- the block is to be considered invalid. As
15463 // part of validating a block the system will attempt to run the source against
15464 // any provided deprecation definitions.
15465 //
15466 // Worth emphasizing that validation is not a case of whether the markup is
15467 // merely HTML spec-compliant but about how the editor knows to create such
15468 // markup and that its inability to create an identical result can be a strong
15469 // indicator of potential data loss (the invalidation is then a protective
15470 // measure).
15471 //
15472 // The invalidation process can also be deconstructed in phases: 1) validate the
15473 // block exists; 2) validate the source matches the output; 3) validate the
15474 // source matches deprecated outputs; 4) work through the significance of
15475 // differences. These are stacked in a way that favors performance and optimizes
15476 // for the majority of cases. That is to say, the evaluation logic can become
15477 // more sophisticated the further down it goes in the process as the cost is
15478 // accounted for. The first logic checks have to be extremely efficient since
15479 // they will be run for all valid and invalid blocks alike. However, once a
15480 // block is detected as invalid -- failing the three first steps -- it is
15481 // adequate to spend more time determining validity before throwing a conflict.
15482
15483
15484
15485 // Blocks are inherently indifferent about where the data they operate with ends
15486 // up being saved. For example, all blocks can have a static and dynamic aspect
15487 // to them depending on the needs. The static nature of a block is the `save()`
15488 // definition that is meant to be serialized into HTML and which can be left
15489 // void. Any block can also register a `render_callback` on the server, which
15490 // makes its output dynamic either in part or in its totality.
15491 //
15492 // Child blocks are defined as a relationship that builds on top of the inner
15493 // blocks mechanism. A child block is a block node of a particular type that can
15494 // only exist within the inner block boundaries of a specific parent type. This
15495 // allows block authors to compose specific blocks that are not meant to be used
15496 // outside of a specified parent block context. Thus, child blocks extend the
15497 // concept of inner blocks to support a more direct relationship between sets of
15498 // blocks. The addition of parent–child would be a subset of the inner block
15499 // functionality under the premise that certain blocks only make sense as
15500 // children of another block.
15501
15502
15503
15504 // Templates are, in a general sense, a basic collection of block nodes with any
15505 // given set of predefined attributes that are supplied as the initial state of
15506 // an inner blocks group. These nodes can, in turn, contain any number of nested
15507 // blocks within their definition. Templates allow both to specify a default
15508 // state for an editor session or a default set of blocks for any inner block
15509 // implementation within a specific block.
15510
15511
15512
15513
15514 const privateApis = {};
15515 lock(privateApis, {
15516 registerBlockBindingsSource: registerBlockBindingsSource,
15517 unregisterBlockBindingsSource: unregisterBlockBindingsSource,
15518 getBlockBindingsSource: getBlockBindingsSource,
15519 getBlockBindingsSources: getBlockBindingsSources
15520 });
15521
15522 ;// CONCATENATED MODULE: ./packages/blocks/build-module/deprecated.js
15523 /**
15524 * WordPress dependencies
15525 */
15526
15527
15528 /**
15529 * A Higher Order Component used to inject BlockContent using context to the
15530 * wrapped component.
15531 *
15532 * @deprecated
15533 *
15534 * @param {Component} OriginalComponent The component to enhance.
15535 * @return {Component} The same component.
15536 */
15537 function withBlockContentContext(OriginalComponent) {
15538 external_wp_deprecated_default()('wp.blocks.withBlockContentContext', {
15539 since: '6.1'
15540 });
15541 return OriginalComponent;
15542 }
15543
15544 ;// CONCATENATED MODULE: ./packages/blocks/build-module/index.js
15545 // A "block" is the abstract term used to describe units of markup that,
15546 // when composed together, form the content or layout of a page.
15547 // The API for blocks is exposed via `wp.blocks`.
15548 //
15549 // Supported blocks are registered by calling `registerBlockType`. Once registered,
15550 // the block is made available as an option to the editor interface.
15551 //
15552 // Blocks are inferred from the HTML source of a post through a parsing mechanism
15553 // and then stored as objects in state, from which it is then rendered for editing.
15554
15555
15556
15557
15558
15559 })();
15560
15561 (window.wp = window.wp || {}).blocks = __webpack_exports__;
15562 /******/ })()
15563 ;