PluginProbe
Gutenberg / 19.6.0
Gutenberg v19.6.0
24.1.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 All 404 releases
gutenberg / build / blocks / index.js

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

15,708 lines 539.0 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 /***/ 7734:
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 /***/ 9681:
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 /***/ 1030:
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 /***/ 5970:
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 /***/ 4398:
5741 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
5742
5743 "use strict";
5744
5745
5746 if (true) {
5747 module.exports = __webpack_require__(5970);
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 getBlockAttributesNamesByRole: () => (/* reexport */ getBlockAttributesNamesByRole),
5849 getBlockBindingsSource: () => (/* reexport */ getBlockBindingsSource),
5850 getBlockBindingsSources: () => (/* reexport */ getBlockBindingsSources),
5851 getBlockContent: () => (/* reexport */ getBlockInnerHTML),
5852 getBlockDefaultClassName: () => (/* reexport */ getBlockDefaultClassName),
5853 getBlockFromExample: () => (/* reexport */ getBlockFromExample),
5854 getBlockMenuDefaultClassName: () => (/* reexport */ getBlockMenuDefaultClassName),
5855 getBlockSupport: () => (/* reexport */ getBlockSupport),
5856 getBlockTransforms: () => (/* reexport */ getBlockTransforms),
5857 getBlockType: () => (/* reexport */ getBlockType),
5858 getBlockTypes: () => (/* reexport */ getBlockTypes),
5859 getBlockVariations: () => (/* reexport */ getBlockVariations),
5860 getCategories: () => (/* reexport */ categories_getCategories),
5861 getChildBlockNames: () => (/* reexport */ getChildBlockNames),
5862 getDefaultBlockName: () => (/* reexport */ getDefaultBlockName),
5863 getFreeformContentHandlerName: () => (/* reexport */ getFreeformContentHandlerName),
5864 getGroupingBlockName: () => (/* reexport */ getGroupingBlockName),
5865 getPhrasingContentSchema: () => (/* reexport */ deprecatedGetPhrasingContentSchema),
5866 getPossibleBlockTransformations: () => (/* reexport */ getPossibleBlockTransformations),
5867 getSaveContent: () => (/* reexport */ getSaveContent),
5868 getSaveElement: () => (/* reexport */ getSaveElement),
5869 getUnregisteredTypeHandlerName: () => (/* reexport */ getUnregisteredTypeHandlerName),
5870 hasBlockSupport: () => (/* reexport */ hasBlockSupport),
5871 hasChildBlocks: () => (/* reexport */ hasChildBlocks),
5872 hasChildBlocksWithInserterSupport: () => (/* reexport */ hasChildBlocksWithInserterSupport),
5873 isReusableBlock: () => (/* reexport */ isReusableBlock),
5874 isTemplatePart: () => (/* reexport */ isTemplatePart),
5875 isUnmodifiedBlock: () => (/* reexport */ isUnmodifiedBlock),
5876 isUnmodifiedDefaultBlock: () => (/* reexport */ isUnmodifiedDefaultBlock),
5877 isValidBlockContent: () => (/* reexport */ isValidBlockContent),
5878 isValidIcon: () => (/* reexport */ isValidIcon),
5879 node: () => (/* reexport */ node),
5880 normalizeIconObject: () => (/* reexport */ normalizeIconObject),
5881 parse: () => (/* reexport */ parser_parse),
5882 parseWithAttributeSchema: () => (/* reexport */ parseWithAttributeSchema),
5883 pasteHandler: () => (/* reexport */ pasteHandler),
5884 privateApis: () => (/* reexport */ privateApis),
5885 rawHandler: () => (/* reexport */ rawHandler),
5886 registerBlockBindingsSource: () => (/* reexport */ registerBlockBindingsSource),
5887 registerBlockCollection: () => (/* reexport */ registerBlockCollection),
5888 registerBlockStyle: () => (/* reexport */ registerBlockStyle),
5889 registerBlockType: () => (/* reexport */ registerBlockType),
5890 registerBlockVariation: () => (/* reexport */ registerBlockVariation),
5891 serialize: () => (/* reexport */ serialize),
5892 serializeRawBlock: () => (/* reexport */ serializeRawBlock),
5893 setCategories: () => (/* reexport */ categories_setCategories),
5894 setDefaultBlockName: () => (/* reexport */ setDefaultBlockName),
5895 setFreeformContentHandlerName: () => (/* reexport */ setFreeformContentHandlerName),
5896 setGroupingBlockName: () => (/* reexport */ setGroupingBlockName),
5897 setUnregisteredTypeHandlerName: () => (/* reexport */ setUnregisteredTypeHandlerName),
5898 store: () => (/* reexport */ store),
5899 switchToBlockType: () => (/* reexport */ switchToBlockType),
5900 synchronizeBlocksWithTemplate: () => (/* reexport */ synchronizeBlocksWithTemplate),
5901 unregisterBlockBindingsSource: () => (/* reexport */ unregisterBlockBindingsSource),
5902 unregisterBlockStyle: () => (/* reexport */ unregisterBlockStyle),
5903 unregisterBlockType: () => (/* reexport */ unregisterBlockType),
5904 unregisterBlockVariation: () => (/* reexport */ unregisterBlockVariation),
5905 unstable__bootstrapServerSideBlockDefinitions: () => (/* reexport */ unstable__bootstrapServerSideBlockDefinitions),
5906 updateCategory: () => (/* reexport */ categories_updateCategory),
5907 validateBlock: () => (/* reexport */ validateBlock),
5908 withBlockContentContext: () => (/* reexport */ withBlockContentContext)
5909 });
5910
5911 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/private-selectors.js
5912 var private_selectors_namespaceObject = {};
5913 __webpack_require__.r(private_selectors_namespaceObject);
5914 __webpack_require__.d(private_selectors_namespaceObject, {
5915 getAllBlockBindingsSources: () => (getAllBlockBindingsSources),
5916 getBlockBindingsSource: () => (private_selectors_getBlockBindingsSource),
5917 getBootstrappedBlockType: () => (getBootstrappedBlockType),
5918 getSupportedStyles: () => (getSupportedStyles),
5919 getUnprocessedBlockTypes: () => (getUnprocessedBlockTypes),
5920 hasContentRoleAttribute: () => (hasContentRoleAttribute)
5921 });
5922
5923 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/selectors.js
5924 var selectors_namespaceObject = {};
5925 __webpack_require__.r(selectors_namespaceObject);
5926 __webpack_require__.d(selectors_namespaceObject, {
5927 __experimentalHasContentRoleAttribute: () => (__experimentalHasContentRoleAttribute),
5928 getActiveBlockVariation: () => (getActiveBlockVariation),
5929 getBlockStyles: () => (getBlockStyles),
5930 getBlockSupport: () => (selectors_getBlockSupport),
5931 getBlockType: () => (selectors_getBlockType),
5932 getBlockTypes: () => (selectors_getBlockTypes),
5933 getBlockVariations: () => (selectors_getBlockVariations),
5934 getCategories: () => (getCategories),
5935 getChildBlockNames: () => (selectors_getChildBlockNames),
5936 getCollections: () => (getCollections),
5937 getDefaultBlockName: () => (selectors_getDefaultBlockName),
5938 getDefaultBlockVariation: () => (getDefaultBlockVariation),
5939 getFreeformFallbackBlockName: () => (getFreeformFallbackBlockName),
5940 getGroupingBlockName: () => (selectors_getGroupingBlockName),
5941 getUnregisteredFallbackBlockName: () => (getUnregisteredFallbackBlockName),
5942 hasBlockSupport: () => (selectors_hasBlockSupport),
5943 hasChildBlocks: () => (selectors_hasChildBlocks),
5944 hasChildBlocksWithInserterSupport: () => (selectors_hasChildBlocksWithInserterSupport),
5945 isMatchingSearchTerm: () => (isMatchingSearchTerm)
5946 });
5947
5948 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/actions.js
5949 var actions_namespaceObject = {};
5950 __webpack_require__.r(actions_namespaceObject);
5951 __webpack_require__.d(actions_namespaceObject, {
5952 __experimentalReapplyBlockFilters: () => (__experimentalReapplyBlockFilters),
5953 addBlockCollection: () => (addBlockCollection),
5954 addBlockStyles: () => (addBlockStyles),
5955 addBlockTypes: () => (addBlockTypes),
5956 addBlockVariations: () => (addBlockVariations),
5957 reapplyBlockTypeFilters: () => (reapplyBlockTypeFilters),
5958 removeBlockCollection: () => (removeBlockCollection),
5959 removeBlockStyles: () => (removeBlockStyles),
5960 removeBlockTypes: () => (removeBlockTypes),
5961 removeBlockVariations: () => (removeBlockVariations),
5962 setCategories: () => (setCategories),
5963 setDefaultBlockName: () => (actions_setDefaultBlockName),
5964 setFreeformFallbackBlockName: () => (setFreeformFallbackBlockName),
5965 setGroupingBlockName: () => (actions_setGroupingBlockName),
5966 setUnregisteredFallbackBlockName: () => (setUnregisteredFallbackBlockName),
5967 updateCategory: () => (updateCategory)
5968 });
5969
5970 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/private-actions.js
5971 var private_actions_namespaceObject = {};
5972 __webpack_require__.r(private_actions_namespaceObject);
5973 __webpack_require__.d(private_actions_namespaceObject, {
5974 addBlockBindingsSource: () => (addBlockBindingsSource),
5975 addBootstrappedBlockType: () => (addBootstrappedBlockType),
5976 addUnprocessedBlockType: () => (addUnprocessedBlockType),
5977 removeBlockBindingsSource: () => (removeBlockBindingsSource)
5978 });
5979
5980 ;// external ["wp","data"]
5981 const external_wp_data_namespaceObject = window["wp"]["data"];
5982 ;// ./node_modules/tslib/tslib.es6.mjs
5983 /******************************************************************************
5984 Copyright (c) Microsoft Corporation.
5985
5986 Permission to use, copy, modify, and/or distribute this software for any
5987 purpose with or without fee is hereby granted.
5988
5989 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
5990 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
5991 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
5992 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
5993 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
5994 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5995 PERFORMANCE OF THIS SOFTWARE.
5996 ***************************************************************************** */
5997 /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
5998
5999 var extendStatics = function(d, b) {
6000 extendStatics = Object.setPrototypeOf ||
6001 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6002 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6003 return extendStatics(d, b);
6004 };
6005
6006 function __extends(d, b) {
6007 if (typeof b !== "function" && b !== null)
6008 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
6009 extendStatics(d, b);
6010 function __() { this.constructor = d; }
6011 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6012 }
6013
6014 var __assign = function() {
6015 __assign = Object.assign || function __assign(t) {
6016 for (var s, i = 1, n = arguments.length; i < n; i++) {
6017 s = arguments[i];
6018 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
6019 }
6020 return t;
6021 }
6022 return __assign.apply(this, arguments);
6023 }
6024
6025 function __rest(s, e) {
6026 var t = {};
6027 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6028 t[p] = s[p];
6029 if (s != null && typeof Object.getOwnPropertySymbols === "function")
6030 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
6031 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
6032 t[p[i]] = s[p[i]];
6033 }
6034 return t;
6035 }
6036
6037 function __decorate(decorators, target, key, desc) {
6038 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6039 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6040 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;
6041 return c > 3 && r && Object.defineProperty(target, key, r), r;
6042 }
6043
6044 function __param(paramIndex, decorator) {
6045 return function (target, key) { decorator(target, key, paramIndex); }
6046 }
6047
6048 function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
6049 function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
6050 var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
6051 var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6052 var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6053 var _, done = false;
6054 for (var i = decorators.length - 1; i >= 0; i--) {
6055 var context = {};
6056 for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
6057 for (var p in contextIn.access) context.access[p] = contextIn.access[p];
6058 context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
6059 var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
6060 if (kind === "accessor") {
6061 if (result === void 0) continue;
6062 if (result === null || typeof result !== "object") throw new TypeError("Object expected");
6063 if (_ = accept(result.get)) descriptor.get = _;
6064 if (_ = accept(result.set)) descriptor.set = _;
6065 if (_ = accept(result.init)) initializers.unshift(_);
6066 }
6067 else if (_ = accept(result)) {
6068 if (kind === "field") initializers.unshift(_);
6069 else descriptor[key] = _;
6070 }
6071 }
6072 if (target) Object.defineProperty(target, contextIn.name, descriptor);
6073 done = true;
6074 };
6075
6076 function __runInitializers(thisArg, initializers, value) {
6077 var useValue = arguments.length > 2;
6078 for (var i = 0; i < initializers.length; i++) {
6079 value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6080 }
6081 return useValue ? value : void 0;
6082 };
6083
6084 function __propKey(x) {
6085 return typeof x === "symbol" ? x : "".concat(x);
6086 };
6087
6088 function __setFunctionName(f, name, prefix) {
6089 if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
6090 return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
6091 };
6092
6093 function __metadata(metadataKey, metadataValue) {
6094 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
6095 }
6096
6097 function __awaiter(thisArg, _arguments, P, generator) {
6098 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6099 return new (P || (P = Promise))(function (resolve, reject) {
6100 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6101 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6102 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
6103 step((generator = generator.apply(thisArg, _arguments || [])).next());
6104 });
6105 }
6106
6107 function __generator(thisArg, body) {
6108 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
6109 return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
6110 function verb(n) { return function (v) { return step([n, v]); }; }
6111 function step(op) {
6112 if (f) throw new TypeError("Generator is already executing.");
6113 while (g && (g = 0, op[0] && (_ = 0)), _) try {
6114 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;
6115 if (y = 0, t) op = [op[0] & 2, t.value];
6116 switch (op[0]) {
6117 case 0: case 1: t = op; break;
6118 case 4: _.label++; return { value: op[1], done: false };
6119 case 5: _.label++; y = op[1]; op = [0]; continue;
6120 case 7: op = _.ops.pop(); _.trys.pop(); continue;
6121 default:
6122 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
6123 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
6124 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
6125 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
6126 if (t[2]) _.ops.pop();
6127 _.trys.pop(); continue;
6128 }
6129 op = body.call(thisArg, _);
6130 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
6131 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
6132 }
6133 }
6134
6135 var __createBinding = Object.create ? (function(o, m, k, k2) {
6136 if (k2 === undefined) k2 = k;
6137 var desc = Object.getOwnPropertyDescriptor(m, k);
6138 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6139 desc = { enumerable: true, get: function() { return m[k]; } };
6140 }
6141 Object.defineProperty(o, k2, desc);
6142 }) : (function(o, m, k, k2) {
6143 if (k2 === undefined) k2 = k;
6144 o[k2] = m[k];
6145 });
6146
6147 function __exportStar(m, o) {
6148 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
6149 }
6150
6151 function __values(o) {
6152 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
6153 if (m) return m.call(o);
6154 if (o && typeof o.length === "number") return {
6155 next: function () {
6156 if (o && i >= o.length) o = void 0;
6157 return { value: o && o[i++], done: !o };
6158 }
6159 };
6160 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
6161 }
6162
6163 function __read(o, n) {
6164 var m = typeof Symbol === "function" && o[Symbol.iterator];
6165 if (!m) return o;
6166 var i = m.call(o), r, ar = [], e;
6167 try {
6168 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
6169 }
6170 catch (error) { e = { error: error }; }
6171 finally {
6172 try {
6173 if (r && !r.done && (m = i["return"])) m.call(i);
6174 }
6175 finally { if (e) throw e.error; }
6176 }
6177 return ar;
6178 }
6179
6180 /** @deprecated */
6181 function __spread() {
6182 for (var ar = [], i = 0; i < arguments.length; i++)
6183 ar = ar.concat(__read(arguments[i]));
6184 return ar;
6185 }
6186
6187 /** @deprecated */
6188 function __spreadArrays() {
6189 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
6190 for (var r = Array(s), k = 0, i = 0; i < il; i++)
6191 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
6192 r[k] = a[j];
6193 return r;
6194 }
6195
6196 function __spreadArray(to, from, pack) {
6197 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
6198 if (ar || !(i in from)) {
6199 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6200 ar[i] = from[i];
6201 }
6202 }
6203 return to.concat(ar || Array.prototype.slice.call(from));
6204 }
6205
6206 function __await(v) {
6207 return this instanceof __await ? (this.v = v, this) : new __await(v);
6208 }
6209
6210 function __asyncGenerator(thisArg, _arguments, generator) {
6211 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6212 var g = generator.apply(thisArg, _arguments || []), i, q = [];
6213 return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
6214 function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
6215 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]); } }
6216 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
6217 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
6218 function fulfill(value) { resume("next", value); }
6219 function reject(value) { resume("throw", value); }
6220 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
6221 }
6222
6223 function __asyncDelegator(o) {
6224 var i, p;
6225 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
6226 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; }
6227 }
6228
6229 function __asyncValues(o) {
6230 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
6231 var m = o[Symbol.asyncIterator], i;
6232 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);
6233 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); }); }; }
6234 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
6235 }
6236
6237 function __makeTemplateObject(cooked, raw) {
6238 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
6239 return cooked;
6240 };
6241
6242 var __setModuleDefault = Object.create ? (function(o, v) {
6243 Object.defineProperty(o, "default", { enumerable: true, value: v });
6244 }) : function(o, v) {
6245 o["default"] = v;
6246 };
6247
6248 function __importStar(mod) {
6249 if (mod && mod.__esModule) return mod;
6250 var result = {};
6251 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
6252 __setModuleDefault(result, mod);
6253 return result;
6254 }
6255
6256 function __importDefault(mod) {
6257 return (mod && mod.__esModule) ? mod : { default: mod };
6258 }
6259
6260 function __classPrivateFieldGet(receiver, state, kind, f) {
6261 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
6262 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");
6263 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6264 }
6265
6266 function __classPrivateFieldSet(receiver, state, value, kind, f) {
6267 if (kind === "m") throw new TypeError("Private method is not writable");
6268 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
6269 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");
6270 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6271 }
6272
6273 function __classPrivateFieldIn(state, receiver) {
6274 if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
6275 return typeof state === "function" ? receiver === state : state.has(receiver);
6276 }
6277
6278 function __addDisposableResource(env, value, async) {
6279 if (value !== null && value !== void 0) {
6280 if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
6281 var dispose, inner;
6282 if (async) {
6283 if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
6284 dispose = value[Symbol.asyncDispose];
6285 }
6286 if (dispose === void 0) {
6287 if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
6288 dispose = value[Symbol.dispose];
6289 if (async) inner = dispose;
6290 }
6291 if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
6292 if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
6293 env.stack.push({ value: value, dispose: dispose, async: async });
6294 }
6295 else if (async) {
6296 env.stack.push({ async: true });
6297 }
6298 return value;
6299 }
6300
6301 var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
6302 var e = new Error(message);
6303 return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
6304 };
6305
6306 function __disposeResources(env) {
6307 function fail(e) {
6308 env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
6309 env.hasError = true;
6310 }
6311 var r, s = 0;
6312 function next() {
6313 while (r = env.stack.pop()) {
6314 try {
6315 if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
6316 if (r.dispose) {
6317 var result = r.dispose.call(r.value);
6318 if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
6319 }
6320 else s |= 1;
6321 }
6322 catch (e) {
6323 fail(e);
6324 }
6325 }
6326 if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
6327 if (env.hasError) throw env.error;
6328 }
6329 return next();
6330 }
6331
6332 function __rewriteRelativeImportExtension(path, preserveJsx) {
6333 if (typeof path === "string" && /^\.\.?\//.test(path)) {
6334 return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
6335 return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
6336 });
6337 }
6338 return path;
6339 }
6340
6341 /* harmony default export */ const tslib_es6 = ({
6342 __extends,
6343 __assign,
6344 __rest,
6345 __decorate,
6346 __param,
6347 __esDecorate,
6348 __runInitializers,
6349 __propKey,
6350 __setFunctionName,
6351 __metadata,
6352 __awaiter,
6353 __generator,
6354 __createBinding,
6355 __exportStar,
6356 __values,
6357 __read,
6358 __spread,
6359 __spreadArrays,
6360 __spreadArray,
6361 __await,
6362 __asyncGenerator,
6363 __asyncDelegator,
6364 __asyncValues,
6365 __makeTemplateObject,
6366 __importStar,
6367 __importDefault,
6368 __classPrivateFieldGet,
6369 __classPrivateFieldSet,
6370 __classPrivateFieldIn,
6371 __addDisposableResource,
6372 __disposeResources,
6373 __rewriteRelativeImportExtension,
6374 });
6375
6376 ;// ./node_modules/lower-case/dist.es2015/index.js
6377 /**
6378 * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
6379 */
6380 var SUPPORTED_LOCALE = {
6381 tr: {
6382 regexp: /\u0130|\u0049|\u0049\u0307/g,
6383 map: {
6384 İ: "\u0069",
6385 I: "\u0131",
6386 İ: "\u0069",
6387 },
6388 },
6389 az: {
6390 regexp: /\u0130/g,
6391 map: {
6392 İ: "\u0069",
6393 I: "\u0131",
6394 İ: "\u0069",
6395 },
6396 },
6397 lt: {
6398 regexp: /\u0049|\u004A|\u012E|\u00CC|\u00CD|\u0128/g,
6399 map: {
6400 I: "\u0069\u0307",
6401 J: "\u006A\u0307",
6402 Į: "\u012F\u0307",
6403 Ì: "\u0069\u0307\u0300",
6404 Í: "\u0069\u0307\u0301",
6405 Ĩ: "\u0069\u0307\u0303",
6406 },
6407 },
6408 };
6409 /**
6410 * Localized lower case.
6411 */
6412 function localeLowerCase(str, locale) {
6413 var lang = SUPPORTED_LOCALE[locale.toLowerCase()];
6414 if (lang)
6415 return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));
6416 return lowerCase(str);
6417 }
6418 /**
6419 * Lower case as a function.
6420 */
6421 function lowerCase(str) {
6422 return str.toLowerCase();
6423 }
6424
6425 ;// ./node_modules/no-case/dist.es2015/index.js
6426
6427 // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
6428 var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
6429 // Remove all non-word characters.
6430 var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
6431 /**
6432 * Normalize the string into something other libraries can manipulate easier.
6433 */
6434 function noCase(input, options) {
6435 if (options === void 0) { options = {}; }
6436 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;
6437 var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
6438 var start = 0;
6439 var end = result.length;
6440 // Trim the delimiter from around the output string.
6441 while (result.charAt(start) === "\0")
6442 start++;
6443 while (result.charAt(end - 1) === "\0")
6444 end--;
6445 // Transform each token independently.
6446 return result.slice(start, end).split("\0").map(transform).join(delimiter);
6447 }
6448 /**
6449 * Replace `re` in the input string with the replacement value.
6450 */
6451 function replace(input, re, value) {
6452 if (re instanceof RegExp)
6453 return input.replace(re, value);
6454 return re.reduce(function (input, re) { return input.replace(re, value); }, input);
6455 }
6456
6457 ;// ./node_modules/pascal-case/dist.es2015/index.js
6458
6459
6460 function pascalCaseTransform(input, index) {
6461 var firstChar = input.charAt(0);
6462 var lowerChars = input.substr(1).toLowerCase();
6463 if (index > 0 && firstChar >= "0" && firstChar <= "9") {
6464 return "_" + firstChar + lowerChars;
6465 }
6466 return "" + firstChar.toUpperCase() + lowerChars;
6467 }
6468 function dist_es2015_pascalCaseTransformMerge(input) {
6469 return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
6470 }
6471 function pascalCase(input, options) {
6472 if (options === void 0) { options = {}; }
6473 return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
6474 }
6475
6476 ;// ./node_modules/camel-case/dist.es2015/index.js
6477
6478
6479 function camelCaseTransform(input, index) {
6480 if (index === 0)
6481 return input.toLowerCase();
6482 return pascalCaseTransform(input, index);
6483 }
6484 function camelCaseTransformMerge(input, index) {
6485 if (index === 0)
6486 return input.toLowerCase();
6487 return pascalCaseTransformMerge(input);
6488 }
6489 function camelCase(input, options) {
6490 if (options === void 0) { options = {}; }
6491 return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
6492 }
6493
6494 ;// external ["wp","i18n"]
6495 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
6496 ;// ./node_modules/colord/index.mjs
6497 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()})};
6498
6499 ;// ./node_modules/colord/plugins/names.mjs
6500 /* 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"])}
6501
6502 ;// ./node_modules/colord/plugins/a11y.mjs
6503 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}}
6504
6505 ;// external ["wp","element"]
6506 const external_wp_element_namespaceObject = window["wp"]["element"];
6507 ;// external ["wp","dom"]
6508 const external_wp_dom_namespaceObject = window["wp"]["dom"];
6509 ;// external ["wp","richText"]
6510 const external_wp_richText_namespaceObject = window["wp"]["richText"];
6511 ;// external ["wp","deprecated"]
6512 const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
6513 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
6514 ;// ./packages/blocks/build-module/api/constants.js
6515 const BLOCK_ICON_DEFAULT = 'block-default';
6516
6517 /**
6518 * Array of valid keys in a block type settings deprecation object.
6519 *
6520 * @type {string[]}
6521 */
6522 const DEPRECATED_ENTRY_KEYS = ['attributes', 'supports', 'save', 'migrate', 'isEligible', 'apiVersion'];
6523 const __EXPERIMENTAL_STYLE_PROPERTY = {
6524 // Kept for back-compatibility purposes.
6525 '--wp--style--color--link': {
6526 value: ['color', 'link'],
6527 support: ['color', 'link']
6528 },
6529 aspectRatio: {
6530 value: ['dimensions', 'aspectRatio'],
6531 support: ['dimensions', 'aspectRatio'],
6532 useEngine: true
6533 },
6534 background: {
6535 value: ['color', 'gradient'],
6536 support: ['color', 'gradients'],
6537 useEngine: true
6538 },
6539 backgroundColor: {
6540 value: ['color', 'background'],
6541 support: ['color', 'background'],
6542 requiresOptOut: true,
6543 useEngine: true
6544 },
6545 backgroundImage: {
6546 value: ['background', 'backgroundImage'],
6547 support: ['background', 'backgroundImage'],
6548 useEngine: true
6549 },
6550 backgroundRepeat: {
6551 value: ['background', 'backgroundRepeat'],
6552 support: ['background', 'backgroundRepeat'],
6553 useEngine: true
6554 },
6555 backgroundSize: {
6556 value: ['background', 'backgroundSize'],
6557 support: ['background', 'backgroundSize'],
6558 useEngine: true
6559 },
6560 backgroundPosition: {
6561 value: ['background', 'backgroundPosition'],
6562 support: ['background', 'backgroundPosition'],
6563 useEngine: true
6564 },
6565 borderColor: {
6566 value: ['border', 'color'],
6567 support: ['__experimentalBorder', 'color'],
6568 useEngine: true
6569 },
6570 borderRadius: {
6571 value: ['border', 'radius'],
6572 support: ['__experimentalBorder', 'radius'],
6573 properties: {
6574 borderTopLeftRadius: 'topLeft',
6575 borderTopRightRadius: 'topRight',
6576 borderBottomLeftRadius: 'bottomLeft',
6577 borderBottomRightRadius: 'bottomRight'
6578 },
6579 useEngine: true
6580 },
6581 borderStyle: {
6582 value: ['border', 'style'],
6583 support: ['__experimentalBorder', 'style'],
6584 useEngine: true
6585 },
6586 borderWidth: {
6587 value: ['border', 'width'],
6588 support: ['__experimentalBorder', 'width'],
6589 useEngine: true
6590 },
6591 borderTopColor: {
6592 value: ['border', 'top', 'color'],
6593 support: ['__experimentalBorder', 'color'],
6594 useEngine: true
6595 },
6596 borderTopStyle: {
6597 value: ['border', 'top', 'style'],
6598 support: ['__experimentalBorder', 'style'],
6599 useEngine: true
6600 },
6601 borderTopWidth: {
6602 value: ['border', 'top', 'width'],
6603 support: ['__experimentalBorder', 'width'],
6604 useEngine: true
6605 },
6606 borderRightColor: {
6607 value: ['border', 'right', 'color'],
6608 support: ['__experimentalBorder', 'color'],
6609 useEngine: true
6610 },
6611 borderRightStyle: {
6612 value: ['border', 'right', 'style'],
6613 support: ['__experimentalBorder', 'style'],
6614 useEngine: true
6615 },
6616 borderRightWidth: {
6617 value: ['border', 'right', 'width'],
6618 support: ['__experimentalBorder', 'width'],
6619 useEngine: true
6620 },
6621 borderBottomColor: {
6622 value: ['border', 'bottom', 'color'],
6623 support: ['__experimentalBorder', 'color'],
6624 useEngine: true
6625 },
6626 borderBottomStyle: {
6627 value: ['border', 'bottom', 'style'],
6628 support: ['__experimentalBorder', 'style'],
6629 useEngine: true
6630 },
6631 borderBottomWidth: {
6632 value: ['border', 'bottom', 'width'],
6633 support: ['__experimentalBorder', 'width'],
6634 useEngine: true
6635 },
6636 borderLeftColor: {
6637 value: ['border', 'left', 'color'],
6638 support: ['__experimentalBorder', 'color'],
6639 useEngine: true
6640 },
6641 borderLeftStyle: {
6642 value: ['border', 'left', 'style'],
6643 support: ['__experimentalBorder', 'style'],
6644 useEngine: true
6645 },
6646 borderLeftWidth: {
6647 value: ['border', 'left', 'width'],
6648 support: ['__experimentalBorder', 'width'],
6649 useEngine: true
6650 },
6651 color: {
6652 value: ['color', 'text'],
6653 support: ['color', 'text'],
6654 requiresOptOut: true,
6655 useEngine: true
6656 },
6657 columnCount: {
6658 value: ['typography', 'textColumns'],
6659 support: ['typography', 'textColumns'],
6660 useEngine: true
6661 },
6662 filter: {
6663 value: ['filter', 'duotone'],
6664 support: ['filter', 'duotone']
6665 },
6666 linkColor: {
6667 value: ['elements', 'link', 'color', 'text'],
6668 support: ['color', 'link']
6669 },
6670 captionColor: {
6671 value: ['elements', 'caption', 'color', 'text'],
6672 support: ['color', 'caption']
6673 },
6674 buttonColor: {
6675 value: ['elements', 'button', 'color', 'text'],
6676 support: ['color', 'button']
6677 },
6678 buttonBackgroundColor: {
6679 value: ['elements', 'button', 'color', 'background'],
6680 support: ['color', 'button']
6681 },
6682 headingColor: {
6683 value: ['elements', 'heading', 'color', 'text'],
6684 support: ['color', 'heading']
6685 },
6686 headingBackgroundColor: {
6687 value: ['elements', 'heading', 'color', 'background'],
6688 support: ['color', 'heading']
6689 },
6690 fontFamily: {
6691 value: ['typography', 'fontFamily'],
6692 support: ['typography', '__experimentalFontFamily'],
6693 useEngine: true
6694 },
6695 fontSize: {
6696 value: ['typography', 'fontSize'],
6697 support: ['typography', 'fontSize'],
6698 useEngine: true
6699 },
6700 fontStyle: {
6701 value: ['typography', 'fontStyle'],
6702 support: ['typography', '__experimentalFontStyle'],
6703 useEngine: true
6704 },
6705 fontWeight: {
6706 value: ['typography', 'fontWeight'],
6707 support: ['typography', '__experimentalFontWeight'],
6708 useEngine: true
6709 },
6710 lineHeight: {
6711 value: ['typography', 'lineHeight'],
6712 support: ['typography', 'lineHeight'],
6713 useEngine: true
6714 },
6715 margin: {
6716 value: ['spacing', 'margin'],
6717 support: ['spacing', 'margin'],
6718 properties: {
6719 marginTop: 'top',
6720 marginRight: 'right',
6721 marginBottom: 'bottom',
6722 marginLeft: 'left'
6723 },
6724 useEngine: true
6725 },
6726 minHeight: {
6727 value: ['dimensions', 'minHeight'],
6728 support: ['dimensions', 'minHeight'],
6729 useEngine: true
6730 },
6731 padding: {
6732 value: ['spacing', 'padding'],
6733 support: ['spacing', 'padding'],
6734 properties: {
6735 paddingTop: 'top',
6736 paddingRight: 'right',
6737 paddingBottom: 'bottom',
6738 paddingLeft: 'left'
6739 },
6740 useEngine: true
6741 },
6742 textAlign: {
6743 value: ['typography', 'textAlign'],
6744 support: ['typography', 'textAlign'],
6745 useEngine: false
6746 },
6747 textDecoration: {
6748 value: ['typography', 'textDecoration'],
6749 support: ['typography', '__experimentalTextDecoration'],
6750 useEngine: true
6751 },
6752 textTransform: {
6753 value: ['typography', 'textTransform'],
6754 support: ['typography', '__experimentalTextTransform'],
6755 useEngine: true
6756 },
6757 letterSpacing: {
6758 value: ['typography', 'letterSpacing'],
6759 support: ['typography', '__experimentalLetterSpacing'],
6760 useEngine: true
6761 },
6762 writingMode: {
6763 value: ['typography', 'writingMode'],
6764 support: ['typography', '__experimentalWritingMode'],
6765 useEngine: true
6766 },
6767 '--wp--style--root--padding': {
6768 value: ['spacing', 'padding'],
6769 support: ['spacing', 'padding'],
6770 properties: {
6771 '--wp--style--root--padding-top': 'top',
6772 '--wp--style--root--padding-right': 'right',
6773 '--wp--style--root--padding-bottom': 'bottom',
6774 '--wp--style--root--padding-left': 'left'
6775 },
6776 rootOnly: true
6777 }
6778 };
6779 const __EXPERIMENTAL_ELEMENTS = {
6780 link: 'a:where(:not(.wp-element-button))',
6781 heading: 'h1, h2, h3, h4, h5, h6',
6782 h1: 'h1',
6783 h2: 'h2',
6784 h3: 'h3',
6785 h4: 'h4',
6786 h5: 'h5',
6787 h6: 'h6',
6788 button: '.wp-element-button, .wp-block-button__link',
6789 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',
6790 cite: 'cite'
6791 };
6792
6793 // These paths may have three origins, custom, theme, and default,
6794 // and are expected to override other origins with custom, theme,
6795 // and default priority.
6796 const __EXPERIMENTAL_PATHS_WITH_OVERRIDE = {
6797 'color.duotone': true,
6798 'color.gradients': true,
6799 'color.palette': true,
6800 'dimensions.aspectRatios': true,
6801 'typography.fontSizes': true,
6802 'spacing.spacingSizes': true
6803 };
6804
6805 ;// external ["wp","warning"]
6806 const external_wp_warning_namespaceObject = window["wp"]["warning"];
6807 ;// external ["wp","privateApis"]
6808 const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
6809 ;// ./packages/blocks/build-module/lock-unlock.js
6810 /**
6811 * WordPress dependencies
6812 */
6813
6814 const {
6815 lock,
6816 unlock
6817 } = (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');
6818
6819 ;// ./packages/blocks/build-module/api/registration.js
6820 /**
6821 * WordPress dependencies
6822 */
6823
6824
6825
6826
6827 /**
6828 * Internal dependencies
6829 */
6830 const i18nBlockSchema = {
6831 title: "block title",
6832 description: "block description",
6833 keywords: ["block keyword"],
6834 styles: [{
6835 label: "block style label"
6836 }],
6837 variations: [{
6838 title: "block variation title",
6839 description: "block variation description",
6840 keywords: ["block variation keyword"]
6841 }]
6842 };
6843
6844
6845
6846 /**
6847 * An icon type definition. One of a Dashicon slug, an element,
6848 * or a component.
6849 *
6850 * @typedef {(string|Element|Component)} WPIcon
6851 *
6852 * @see https://developer.wordpress.org/resource/dashicons/
6853 */
6854
6855 /**
6856 * Render behavior of a block type icon; one of a Dashicon slug, an element,
6857 * or a component.
6858 *
6859 * @typedef {WPIcon} WPBlockTypeIconRender
6860 */
6861
6862 /**
6863 * An object describing a normalized block type icon.
6864 *
6865 * @typedef {Object} WPBlockTypeIconDescriptor
6866 *
6867 * @property {WPBlockTypeIconRender} src Render behavior of the icon,
6868 * one of a Dashicon slug, an
6869 * element, or a component.
6870 * @property {string} background Optimal background hex string
6871 * color when displaying icon.
6872 * @property {string} foreground Optimal foreground hex string
6873 * color when displaying icon.
6874 * @property {string} shadowColor Optimal shadow hex string
6875 * color when displaying icon.
6876 */
6877
6878 /**
6879 * Value to use to render the icon for a block type in an editor interface,
6880 * either a Dashicon slug, an element, a component, or an object describing
6881 * the icon.
6882 *
6883 * @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
6884 */
6885
6886 /**
6887 * Named block variation scopes.
6888 *
6889 * @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
6890 */
6891
6892 /**
6893 * An object describing a variation defined for the block type.
6894 *
6895 * @typedef {Object} WPBlockVariation
6896 *
6897 * @property {string} name The unique and machine-readable name.
6898 * @property {string} title A human-readable variation title.
6899 * @property {string} [description] A detailed variation description.
6900 * @property {string} [category] Block type category classification,
6901 * used in search interfaces to arrange
6902 * block types by category.
6903 * @property {WPIcon} [icon] An icon helping to visualize the variation.
6904 * @property {boolean} [isDefault] Indicates whether the current variation is
6905 * the default one. Defaults to `false`.
6906 * @property {Object} [attributes] Values which override block attributes.
6907 * @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
6908 * @property {Object} [example] Example provides structured data for
6909 * the block preview. You can set to
6910 * `undefined` to disable the preview shown
6911 * for the block type.
6912 * @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
6913 * is applicable. When not provided, it
6914 * assumes all available scopes.
6915 * @property {string[]} [keywords] An array of terms (which can be translated)
6916 * that help users discover the variation
6917 * while searching.
6918 * @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
6919 * Function that accepts a block's attributes and the
6920 * variation's attributes and determines if a variation is active.
6921 * This function doesn't try to find a match dynamically based
6922 * on all block's attributes, as in many cases some attributes are irrelevant.
6923 * An example would be for `embed` block where we only care
6924 * about `providerNameSlug` attribute's value.
6925 * We can also use a `string[]` to tell which attributes
6926 * should be compared as a shorthand. Each attributes will
6927 * be matched and the variation will be active if all of them are matching.
6928 */
6929
6930 /**
6931 * Defined behavior of a block type.
6932 *
6933 * @typedef {Object} WPBlockType
6934 *
6935 * @property {string} name Block type's namespaced name.
6936 * @property {string} title Human-readable block type label.
6937 * @property {string} [description] A detailed block type description.
6938 * @property {string} [category] Block type category classification,
6939 * used in search interfaces to arrange
6940 * block types by category.
6941 * @property {WPBlockTypeIcon} [icon] Block type icon.
6942 * @property {string[]} [keywords] Additional keywords to produce block
6943 * type as result in search interfaces.
6944 * @property {Object} [attributes] Block type attributes.
6945 * @property {Component} [save] Optional component describing
6946 * serialized markup structure of a
6947 * block type.
6948 * @property {Component} edit Component rendering an element to
6949 * manipulate the attributes of a block
6950 * in the context of an editor.
6951 * @property {WPBlockVariation[]} [variations] The list of block variations.
6952 * @property {Object} [example] Example provides structured data for
6953 * the block preview. When not defined
6954 * then no preview is shown.
6955 */
6956
6957 function isObject(object) {
6958 return object !== null && typeof object === 'object';
6959 }
6960
6961 /**
6962 * Sets the server side block definition of blocks.
6963 *
6964 * Ignored from documentation due to being marked as unstable.
6965 *
6966 * @ignore
6967 *
6968 * @param {Object} definitions Server-side block definitions
6969 */
6970 // eslint-disable-next-line camelcase
6971 function unstable__bootstrapServerSideBlockDefinitions(definitions) {
6972 const {
6973 addBootstrappedBlockType
6974 } = unlock((0,external_wp_data_namespaceObject.dispatch)(store));
6975 for (const [name, blockType] of Object.entries(definitions)) {
6976 addBootstrappedBlockType(name, blockType);
6977 }
6978 }
6979
6980 /**
6981 * Gets block settings from metadata loaded from `block.json` file
6982 *
6983 * @param {Object} metadata Block metadata loaded from `block.json`.
6984 * @param {string} metadata.textdomain Textdomain to use with translations.
6985 *
6986 * @return {Object} Block settings.
6987 */
6988 function getBlockSettingsFromMetadata({
6989 textdomain,
6990 ...metadata
6991 }) {
6992 const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'selectors', 'supports', 'styles', 'example', 'variations', 'blockHooks', 'allowedBlocks'];
6993 const settings = Object.fromEntries(Object.entries(metadata).filter(([key]) => allowedFields.includes(key)));
6994 if (textdomain) {
6995 Object.keys(i18nBlockSchema).forEach(key => {
6996 if (!settings[key]) {
6997 return;
6998 }
6999 settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
7000 });
7001 }
7002 return settings;
7003 }
7004
7005 /**
7006 * Registers a new block provided a unique name and an object defining its
7007 * behavior. Once registered, the block is made available as an option to any
7008 * editor interface where blocks are implemented.
7009 *
7010 * For more in-depth information on registering a custom block see the
7011 * [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).
7012 *
7013 * @param {string|Object} blockNameOrMetadata Block type name or its metadata.
7014 * @param {Object} settings Block settings.
7015 *
7016 * @example
7017 * ```js
7018 * import { __ } from '@wordpress/i18n';
7019 * import { registerBlockType } from '@wordpress/blocks'
7020 *
7021 * registerBlockType( 'namespace/block-name', {
7022 * title: __( 'My First Block' ),
7023 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
7024 * save: () => <div>Hello from the saved content!</div>,
7025 * } );
7026 * ```
7027 *
7028 * @return {WPBlockType | undefined} The block, if it has been successfully registered;
7029 * otherwise `undefined`.
7030 */
7031 function registerBlockType(blockNameOrMetadata, settings) {
7032 const name = isObject(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
7033 if (typeof name !== 'string') {
7034 false ? 0 : void 0;
7035 return;
7036 }
7037 if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
7038 false ? 0 : void 0;
7039 return;
7040 }
7041 if ((0,external_wp_data_namespaceObject.select)(store).getBlockType(name)) {
7042 false ? 0 : void 0;
7043 return;
7044 }
7045 const {
7046 addBootstrappedBlockType,
7047 addUnprocessedBlockType
7048 } = unlock((0,external_wp_data_namespaceObject.dispatch)(store));
7049 if (isObject(blockNameOrMetadata)) {
7050 const metadata = getBlockSettingsFromMetadata(blockNameOrMetadata);
7051 addBootstrappedBlockType(name, metadata);
7052 }
7053 addUnprocessedBlockType(name, settings);
7054 return (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
7055 }
7056
7057 /**
7058 * Translates block settings provided with metadata using the i18n schema.
7059 *
7060 * @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
7061 * @param {string|string[]|Object[]} settingValue Value for the block setting.
7062 * @param {string} textdomain Textdomain to use with translations.
7063 *
7064 * @return {string|string[]|Object[]} Translated setting.
7065 */
7066 function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
7067 if (typeof i18nSchema === 'string' && typeof settingValue === 'string') {
7068 // eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
7069 return (0,external_wp_i18n_namespaceObject._x)(settingValue, i18nSchema, textdomain);
7070 }
7071 if (Array.isArray(i18nSchema) && i18nSchema.length && Array.isArray(settingValue)) {
7072 return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
7073 }
7074 if (isObject(i18nSchema) && Object.entries(i18nSchema).length && isObject(settingValue)) {
7075 return Object.keys(settingValue).reduce((accumulator, key) => {
7076 if (!i18nSchema[key]) {
7077 accumulator[key] = settingValue[key];
7078 return accumulator;
7079 }
7080 accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
7081 return accumulator;
7082 }, {});
7083 }
7084 return settingValue;
7085 }
7086
7087 /**
7088 * Registers a new block collection to group blocks in the same namespace in the inserter.
7089 *
7090 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
7091 * @param {Object} settings The block collection settings.
7092 * @param {string} settings.title The title to display in the block inserter.
7093 * @param {Object} [settings.icon] The icon to display in the block inserter.
7094 *
7095 * @example
7096 * ```js
7097 * import { __ } from '@wordpress/i18n';
7098 * import { registerBlockCollection, registerBlockType } from '@wordpress/blocks';
7099 *
7100 * // Register the collection.
7101 * registerBlockCollection( 'my-collection', {
7102 * title: __( 'Custom Collection' ),
7103 * } );
7104 *
7105 * // Register a block in the same namespace to add it to the collection.
7106 * registerBlockType( 'my-collection/block-name', {
7107 * title: __( 'My First Block' ),
7108 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
7109 * save: () => <div>'Hello from the saved content!</div>,
7110 * } );
7111 * ```
7112 */
7113 function registerBlockCollection(namespace, {
7114 title,
7115 icon
7116 }) {
7117 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockCollection(namespace, title, icon);
7118 }
7119
7120 /**
7121 * Unregisters a block collection
7122 *
7123 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
7124 *
7125 * @example
7126 * ```js
7127 * import { unregisterBlockCollection } from '@wordpress/blocks';
7128 *
7129 * unregisterBlockCollection( 'my-collection' );
7130 * ```
7131 */
7132 function unregisterBlockCollection(namespace) {
7133 dispatch(blocksStore).removeBlockCollection(namespace);
7134 }
7135
7136 /**
7137 * Unregisters a block.
7138 *
7139 * @param {string} name Block name.
7140 *
7141 * @example
7142 * ```js
7143 * import { __ } from '@wordpress/i18n';
7144 * import { unregisterBlockType } from '@wordpress/blocks';
7145 *
7146 * const ExampleComponent = () => {
7147 * return (
7148 * <Button
7149 * onClick={ () =>
7150 * unregisterBlockType( 'my-collection/block-name' )
7151 * }
7152 * >
7153 * { __( 'Unregister my custom block.' ) }
7154 * </Button>
7155 * );
7156 * };
7157 * ```
7158 *
7159 * @return {WPBlockType | undefined} The previous block value, if it has been successfully
7160 * unregistered; otherwise `undefined`.
7161 */
7162 function unregisterBlockType(name) {
7163 const oldBlock = (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
7164 if (!oldBlock) {
7165 false ? 0 : void 0;
7166 return;
7167 }
7168 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockTypes(name);
7169 return oldBlock;
7170 }
7171
7172 /**
7173 * Assigns name of block for handling non-block content.
7174 *
7175 * @param {string} blockName Block name.
7176 */
7177 function setFreeformContentHandlerName(blockName) {
7178 (0,external_wp_data_namespaceObject.dispatch)(store).setFreeformFallbackBlockName(blockName);
7179 }
7180
7181 /**
7182 * Retrieves name of block handling non-block content, or undefined if no
7183 * handler has been defined.
7184 *
7185 * @return {?string} Block name.
7186 */
7187 function getFreeformContentHandlerName() {
7188 return (0,external_wp_data_namespaceObject.select)(store).getFreeformFallbackBlockName();
7189 }
7190
7191 /**
7192 * Retrieves name of block used for handling grouping interactions.
7193 *
7194 * @return {?string} Block name.
7195 */
7196 function getGroupingBlockName() {
7197 return (0,external_wp_data_namespaceObject.select)(store).getGroupingBlockName();
7198 }
7199
7200 /**
7201 * Assigns name of block handling unregistered block types.
7202 *
7203 * @param {string} blockName Block name.
7204 */
7205 function setUnregisteredTypeHandlerName(blockName) {
7206 (0,external_wp_data_namespaceObject.dispatch)(store).setUnregisteredFallbackBlockName(blockName);
7207 }
7208
7209 /**
7210 * Retrieves name of block handling unregistered block types, or undefined if no
7211 * handler has been defined.
7212 *
7213 * @return {?string} Block name.
7214 */
7215 function getUnregisteredTypeHandlerName() {
7216 return (0,external_wp_data_namespaceObject.select)(store).getUnregisteredFallbackBlockName();
7217 }
7218
7219 /**
7220 * Assigns the default block name.
7221 *
7222 * @param {string} name Block name.
7223 *
7224 * @example
7225 * ```js
7226 * import { setDefaultBlockName } from '@wordpress/blocks';
7227 *
7228 * const ExampleComponent = () => {
7229 *
7230 * return (
7231 * <Button onClick={ () => setDefaultBlockName( 'core/heading' ) }>
7232 * { __( 'Set the default block to Heading' ) }
7233 * </Button>
7234 * );
7235 * };
7236 * ```
7237 */
7238 function setDefaultBlockName(name) {
7239 (0,external_wp_data_namespaceObject.dispatch)(store).setDefaultBlockName(name);
7240 }
7241
7242 /**
7243 * Assigns name of block for handling block grouping interactions.
7244 *
7245 * This function lets you select a different block to group other blocks in instead of the
7246 * default `core/group` block. This function must be used in a component or when the DOM is fully
7247 * loaded. See https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dom-ready/
7248 *
7249 * @param {string} name Block name.
7250 *
7251 * @example
7252 * ```js
7253 * import { setGroupingBlockName } from '@wordpress/blocks';
7254 *
7255 * const ExampleComponent = () => {
7256 *
7257 * return (
7258 * <Button onClick={ () => setGroupingBlockName( 'core/columns' ) }>
7259 * { __( 'Wrap in columns' ) }
7260 * </Button>
7261 * );
7262 * };
7263 * ```
7264 */
7265 function setGroupingBlockName(name) {
7266 (0,external_wp_data_namespaceObject.dispatch)(store).setGroupingBlockName(name);
7267 }
7268
7269 /**
7270 * Retrieves the default block name.
7271 *
7272 * @return {?string} Block name.
7273 */
7274 function getDefaultBlockName() {
7275 return (0,external_wp_data_namespaceObject.select)(store).getDefaultBlockName();
7276 }
7277
7278 /**
7279 * Returns a registered block type.
7280 *
7281 * @param {string} name Block name.
7282 *
7283 * @return {?Object} Block type.
7284 */
7285 function getBlockType(name) {
7286 return (0,external_wp_data_namespaceObject.select)(store)?.getBlockType(name);
7287 }
7288
7289 /**
7290 * Returns all registered blocks.
7291 *
7292 * @return {Array} Block settings.
7293 */
7294 function getBlockTypes() {
7295 return (0,external_wp_data_namespaceObject.select)(store).getBlockTypes();
7296 }
7297
7298 /**
7299 * Returns the block support value for a feature, if defined.
7300 *
7301 * @param {(string|Object)} nameOrType Block name or type object
7302 * @param {string} feature Feature to retrieve
7303 * @param {*} defaultSupports Default value to return if not
7304 * explicitly defined
7305 *
7306 * @return {?*} Block support value
7307 */
7308 function getBlockSupport(nameOrType, feature, defaultSupports) {
7309 return (0,external_wp_data_namespaceObject.select)(store).getBlockSupport(nameOrType, feature, defaultSupports);
7310 }
7311
7312 /**
7313 * Returns true if the block defines support for a feature, or false otherwise.
7314 *
7315 * @param {(string|Object)} nameOrType Block name or type object.
7316 * @param {string} feature Feature to test.
7317 * @param {boolean} defaultSupports Whether feature is supported by
7318 * default if not explicitly defined.
7319 *
7320 * @return {boolean} Whether block supports feature.
7321 */
7322 function hasBlockSupport(nameOrType, feature, defaultSupports) {
7323 return (0,external_wp_data_namespaceObject.select)(store).hasBlockSupport(nameOrType, feature, defaultSupports);
7324 }
7325
7326 /**
7327 * Determines whether or not the given block is a reusable block. This is a
7328 * special block type that is used to point to a global block stored via the
7329 * API.
7330 *
7331 * @param {Object} blockOrType Block or Block Type to test.
7332 *
7333 * @return {boolean} Whether the given block is a reusable block.
7334 */
7335 function isReusableBlock(blockOrType) {
7336 return blockOrType?.name === 'core/block';
7337 }
7338
7339 /**
7340 * Determines whether or not the given block is a template part. This is a
7341 * special block type that allows composing a page template out of reusable
7342 * design elements.
7343 *
7344 * @param {Object} blockOrType Block or Block Type to test.
7345 *
7346 * @return {boolean} Whether the given block is a template part.
7347 */
7348 function isTemplatePart(blockOrType) {
7349 return blockOrType?.name === 'core/template-part';
7350 }
7351
7352 /**
7353 * Returns an array with the child blocks of a given block.
7354 *
7355 * @param {string} blockName Name of block (example: “latest-posts”).
7356 *
7357 * @return {Array} Array of child block names.
7358 */
7359 const getChildBlockNames = blockName => {
7360 return (0,external_wp_data_namespaceObject.select)(store).getChildBlockNames(blockName);
7361 };
7362
7363 /**
7364 * Returns a boolean indicating if a block has child blocks or not.
7365 *
7366 * @param {string} blockName Name of block (example: “latest-posts”).
7367 *
7368 * @return {boolean} True if a block contains child blocks and false otherwise.
7369 */
7370 const hasChildBlocks = blockName => {
7371 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocks(blockName);
7372 };
7373
7374 /**
7375 * Returns a boolean indicating if a block has at least one child block with inserter support.
7376 *
7377 * @param {string} blockName Block type name.
7378 *
7379 * @return {boolean} True if a block contains at least one child blocks with inserter support
7380 * and false otherwise.
7381 */
7382 const hasChildBlocksWithInserterSupport = blockName => {
7383 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocksWithInserterSupport(blockName);
7384 };
7385
7386 /**
7387 * Registers a new block style for the given block types.
7388 *
7389 * For more information on connecting the styles with CSS
7390 * [the official documentation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/#styles).
7391 *
7392 * @param {string|Array} blockNames Name of blocks e.g. “core/latest-posts” or `["core/group", "core/columns"]`.
7393 * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
7394 *
7395 * @example
7396 * ```js
7397 * import { __ } from '@wordpress/i18n';
7398 * import { registerBlockStyle } from '@wordpress/blocks';
7399 * import { Button } from '@wordpress/components';
7400 *
7401 *
7402 * const ExampleComponent = () => {
7403 * return (
7404 * <Button
7405 * onClick={ () => {
7406 * registerBlockStyle( 'core/quote', {
7407 * name: 'fancy-quote',
7408 * label: __( 'Fancy Quote' ),
7409 * } );
7410 * } }
7411 * >
7412 * { __( 'Add a new block style for core/quote' ) }
7413 * </Button>
7414 * );
7415 * };
7416 * ```
7417 */
7418 const registerBlockStyle = (blockNames, styleVariation) => {
7419 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockStyles(blockNames, styleVariation);
7420 };
7421
7422 /**
7423 * Unregisters a block style for the given block.
7424 *
7425 * @param {string} blockName Name of block (example: “core/latest-posts”).
7426 * @param {string} styleVariationName Name of class applied to the block.
7427 *
7428 * @example
7429 * ```js
7430 * import { __ } from '@wordpress/i18n';
7431 * import { unregisterBlockStyle } from '@wordpress/blocks';
7432 * import { Button } from '@wordpress/components';
7433 *
7434 * const ExampleComponent = () => {
7435 * return (
7436 * <Button
7437 * onClick={ () => {
7438 * unregisterBlockStyle( 'core/quote', 'plain' );
7439 * } }
7440 * >
7441 * { __( 'Remove the "Plain" block style for core/quote' ) }
7442 * </Button>
7443 * );
7444 * };
7445 * ```
7446 */
7447 const unregisterBlockStyle = (blockName, styleVariationName) => {
7448 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockStyles(blockName, styleVariationName);
7449 };
7450
7451 /**
7452 * Returns an array with the variations of a given block type.
7453 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
7454 *
7455 * @ignore
7456 *
7457 * @param {string} blockName Name of block (example: “core/columns”).
7458 * @param {WPBlockVariationScope} [scope] Block variation scope name.
7459 *
7460 * @return {(WPBlockVariation[]|void)} Block variations.
7461 */
7462 const getBlockVariations = (blockName, scope) => {
7463 return (0,external_wp_data_namespaceObject.select)(store).getBlockVariations(blockName, scope);
7464 };
7465
7466 /**
7467 * Registers a new block variation for the given block type.
7468 *
7469 * For more information on block variations see
7470 * [the official documentation ](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/).
7471 *
7472 * @param {string} blockName Name of the block (example: “core/columns”).
7473 * @param {WPBlockVariation} variation Object describing a block variation.
7474 *
7475 * @example
7476 * ```js
7477 * import { __ } from '@wordpress/i18n';
7478 * import { registerBlockVariation } from '@wordpress/blocks';
7479 * import { Button } from '@wordpress/components';
7480 *
7481 * const ExampleComponent = () => {
7482 * return (
7483 * <Button
7484 * onClick={ () => {
7485 * registerBlockVariation( 'core/embed', {
7486 * name: 'custom',
7487 * title: __( 'My Custom Embed' ),
7488 * attributes: { providerNameSlug: 'custom' },
7489 * } );
7490 * } }
7491 * >
7492 * __( 'Add a custom variation for core/embed' ) }
7493 * </Button>
7494 * );
7495 * };
7496 * ```
7497 */
7498 const registerBlockVariation = (blockName, variation) => {
7499 if (typeof variation.name !== 'string') {
7500 false ? 0 : void 0;
7501 }
7502 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockVariations(blockName, variation);
7503 };
7504
7505 /**
7506 * Unregisters a block variation defined for the given block type.
7507 *
7508 * @param {string} blockName Name of the block (example: “core/columns”).
7509 * @param {string} variationName Name of the variation defined for the block.
7510 *
7511 * @example
7512 * ```js
7513 * import { __ } from '@wordpress/i18n';
7514 * import { unregisterBlockVariation } from '@wordpress/blocks';
7515 * import { Button } from '@wordpress/components';
7516 *
7517 * const ExampleComponent = () => {
7518 * return (
7519 * <Button
7520 * onClick={ () => {
7521 * unregisterBlockVariation( 'core/embed', 'youtube' );
7522 * } }
7523 * >
7524 * { __( 'Remove the YouTube variation from core/embed' ) }
7525 * </Button>
7526 * );
7527 * };
7528 * ```
7529 */
7530 const unregisterBlockVariation = (blockName, variationName) => {
7531 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockVariations(blockName, variationName);
7532 };
7533
7534 /**
7535 * Registers a new block bindings source with an object defining its
7536 * behavior. Once registered, the source is available to be connected
7537 * to the supported block attributes.
7538 *
7539 * @since 6.7.0 Introduced in WordPress core.
7540 *
7541 * @param {Object} source Properties of the source to be registered.
7542 * @param {string} source.name The unique and machine-readable name.
7543 * @param {string} [source.label] Human-readable label. Optional when it is defined in the server.
7544 * @param {Array} [source.usesContext] Optional array of context needed by the source only in the editor.
7545 * @param {Function} [source.getValues] Optional function to get the values from the source.
7546 * @param {Function} [source.setValues] Optional function to update multiple values connected to the source.
7547 * @param {Function} [source.canUserEditValue] Optional function to determine if the user can edit the value.
7548 *
7549 * @example
7550 * ```js
7551 * import { _x } from '@wordpress/i18n';
7552 * import { registerBlockBindingsSource } from '@wordpress/blocks'
7553 *
7554 * registerBlockBindingsSource( {
7555 * name: 'plugin/my-custom-source',
7556 * label: _x( 'My Custom Source', 'block bindings source' ),
7557 * usesContext: [ 'postType' ],
7558 * getValues: getSourceValues,
7559 * setValues: updateMyCustomValuesInBatch,
7560 * canUserEditValue: () => true,
7561 * } );
7562 * ```
7563 */
7564 const registerBlockBindingsSource = source => {
7565 const {
7566 name,
7567 label,
7568 usesContext,
7569 getValues,
7570 setValues,
7571 canUserEditValue,
7572 getFieldsList
7573 } = source;
7574 const existingSource = unlock((0,external_wp_data_namespaceObject.select)(store)).getBlockBindingsSource(name);
7575
7576 /*
7577 * Check if the source has been already registered on the client.
7578 * If any property expected to be "client-only" is defined, return a warning.
7579 */
7580 const serverProps = ['label', 'usesContext'];
7581 for (const prop in existingSource) {
7582 if (!serverProps.includes(prop) && existingSource[prop]) {
7583 false ? 0 : void 0;
7584 return;
7585 }
7586 }
7587
7588 // Check the `name` property is correct.
7589 if (!name) {
7590 false ? 0 : void 0;
7591 return;
7592 }
7593 if (typeof name !== 'string') {
7594 false ? 0 : void 0;
7595 return;
7596 }
7597 if (/[A-Z]+/.test(name)) {
7598 false ? 0 : void 0;
7599 return;
7600 }
7601 if (!/^[a-z0-9/-]+$/.test(name)) {
7602 false ? 0 : void 0;
7603 return;
7604 }
7605 if (!/^[a-z0-9-]+\/[a-z0-9-]+$/.test(name)) {
7606 false ? 0 : void 0;
7607 return;
7608 }
7609
7610 // Check the `label` property is correct.
7611
7612 if (!label && !existingSource?.label) {
7613 false ? 0 : void 0;
7614 return;
7615 }
7616 if (label && typeof label !== 'string') {
7617 false ? 0 : void 0;
7618 return;
7619 }
7620 if (label && existingSource?.label && label !== existingSource?.label) {
7621 false ? 0 : void 0;
7622 }
7623
7624 // Check the `usesContext` property is correct.
7625 if (usesContext && !Array.isArray(usesContext)) {
7626 false ? 0 : void 0;
7627 return;
7628 }
7629
7630 // Check the `getValues` property is correct.
7631 if (getValues && typeof getValues !== 'function') {
7632 false ? 0 : void 0;
7633 return;
7634 }
7635
7636 // Check the `setValues` property is correct.
7637 if (setValues && typeof setValues !== 'function') {
7638 false ? 0 : void 0;
7639 return;
7640 }
7641
7642 // Check the `canUserEditValue` property is correct.
7643 if (canUserEditValue && typeof canUserEditValue !== 'function') {
7644 false ? 0 : void 0;
7645 return;
7646 }
7647
7648 // Check the `getFieldsList` property is correct.
7649 if (getFieldsList && typeof getFieldsList !== 'function') {
7650 // eslint-disable-next-line no-console
7651 false ? 0 : void 0;
7652 return;
7653 }
7654 return unlock((0,external_wp_data_namespaceObject.dispatch)(store)).addBlockBindingsSource(source);
7655 };
7656
7657 /**
7658 * Unregisters a block bindings source by providing its name.
7659 *
7660 * @since 6.7.0 Introduced in WordPress core.
7661 *
7662 * @param {string} name The name of the block bindings source to unregister.
7663 *
7664 * @example
7665 * ```js
7666 * import { unregisterBlockBindingsSource } from '@wordpress/blocks';
7667 *
7668 * unregisterBlockBindingsSource( 'plugin/my-custom-source' );
7669 * ```
7670 */
7671 function unregisterBlockBindingsSource(name) {
7672 const oldSource = getBlockBindingsSource(name);
7673 if (!oldSource) {
7674 false ? 0 : void 0;
7675 return;
7676 }
7677 unlock((0,external_wp_data_namespaceObject.dispatch)(store)).removeBlockBindingsSource(name);
7678 }
7679
7680 /**
7681 * Returns a registered block bindings source by its name.
7682 *
7683 * @since 6.7.0 Introduced in WordPress core.
7684 *
7685 * @param {string} name Block bindings source name.
7686 *
7687 * @return {?Object} Block bindings source.
7688 */
7689 function getBlockBindingsSource(name) {
7690 return unlock((0,external_wp_data_namespaceObject.select)(store)).getBlockBindingsSource(name);
7691 }
7692
7693 /**
7694 * Returns all registered block bindings sources.
7695 *
7696 * @since 6.7.0 Introduced in WordPress core.
7697 *
7698 * @return {Array} Block bindings sources.
7699 */
7700 function getBlockBindingsSources() {
7701 return unlock((0,external_wp_data_namespaceObject.select)(store)).getAllBlockBindingsSources();
7702 }
7703
7704 ;// ./packages/blocks/build-module/api/utils.js
7705 /**
7706 * External dependencies
7707 */
7708
7709
7710
7711
7712 /**
7713 * WordPress dependencies
7714 */
7715
7716
7717
7718
7719
7720
7721 /**
7722 * Internal dependencies
7723 */
7724
7725
7726 k([names, a11y]);
7727
7728 /**
7729 * Array of icon colors containing a color to be used if the icon color
7730 * was not explicitly set but the icon background color was.
7731 *
7732 * @type {Object}
7733 */
7734 const ICON_COLORS = ['#191e23', '#f8f9f9'];
7735
7736 /**
7737 * Determines whether the block's attribute is equal to the default attribute
7738 * which means the attribute is unmodified.
7739 * @param {Object} attributeDefinition The attribute's definition of the block type.
7740 * @param {*} value The attribute's value.
7741 * @return {boolean} Whether the attribute is unmodified.
7742 */
7743 function isUnmodifiedAttribute(attributeDefinition, value) {
7744 // Every attribute that has a default must match the default.
7745 if (attributeDefinition.hasOwnProperty('default')) {
7746 return value === attributeDefinition.default;
7747 }
7748
7749 // The rich text type is a bit different from the rest because it
7750 // has an implicit default value of an empty RichTextData instance,
7751 // so check the length of the value.
7752 if (attributeDefinition.type === 'rich-text') {
7753 return !value?.length;
7754 }
7755
7756 // Every attribute that doesn't have a default should be undefined.
7757 return value === undefined;
7758 }
7759
7760 /**
7761 * Determines whether the block's attributes are equal to the default attributes
7762 * which means the block is unmodified.
7763 *
7764 * @param {WPBlock} block Block Object
7765 *
7766 * @return {boolean} Whether the block is an unmodified block.
7767 */
7768 function isUnmodifiedBlock(block) {
7769 var _getBlockType$attribu;
7770 return Object.entries((_getBlockType$attribu = getBlockType(block.name)?.attributes) !== null && _getBlockType$attribu !== void 0 ? _getBlockType$attribu : {}).every(([key, definition]) => {
7771 const value = block.attributes[key];
7772 return isUnmodifiedAttribute(definition, value);
7773 });
7774 }
7775
7776 /**
7777 * Determines whether the block is a default block and its attributes are equal
7778 * to the default attributes which means the block is unmodified.
7779 *
7780 * @param {WPBlock} block Block Object
7781 *
7782 * @return {boolean} Whether the block is an unmodified default block.
7783 */
7784 function isUnmodifiedDefaultBlock(block) {
7785 return block.name === getDefaultBlockName() && isUnmodifiedBlock(block);
7786 }
7787
7788 /**
7789 * Determines whether the block content is unmodified. A block content is
7790 * considered unmodified if all the attributes that have a role of 'content'
7791 * are equal to the default attributes (or undefined).
7792 * If the block does not have any attributes with a role of 'content', it
7793 * will be considered unmodified if all the attributes are equal to the default
7794 * attributes (or undefined).
7795 *
7796 * @param {WPBlock} block Block Object
7797 * @return {boolean} Whether the block content is unmodified.
7798 */
7799 function isUnmodifiedBlockContent(block) {
7800 const contentAttributes = getBlockAttributesNamesByRole(block.name, 'content');
7801 if (contentAttributes.length === 0) {
7802 return isUnmodifiedBlock(block);
7803 }
7804 return contentAttributes.every(key => {
7805 const definition = getBlockType(block.name)?.attributes[key];
7806 const value = block.attributes[key];
7807 return isUnmodifiedAttribute(definition, value);
7808 });
7809 }
7810
7811 /**
7812 * Function that checks if the parameter is a valid icon.
7813 *
7814 * @param {*} icon Parameter to be checked.
7815 *
7816 * @return {boolean} True if the parameter is a valid icon and false otherwise.
7817 */
7818
7819 function isValidIcon(icon) {
7820 return !!icon && (typeof icon === 'string' || (0,external_wp_element_namespaceObject.isValidElement)(icon) || typeof icon === 'function' || icon instanceof external_wp_element_namespaceObject.Component);
7821 }
7822
7823 /**
7824 * Function that receives an icon as set by the blocks during the registration
7825 * and returns a new icon object that is normalized so we can rely on just on possible icon structure
7826 * in the codebase.
7827 *
7828 * @param {WPBlockTypeIconRender} icon Render behavior of a block type icon;
7829 * one of a Dashicon slug, an element, or a
7830 * component.
7831 *
7832 * @return {WPBlockTypeIconDescriptor} Object describing the icon.
7833 */
7834 function normalizeIconObject(icon) {
7835 icon = icon || BLOCK_ICON_DEFAULT;
7836 if (isValidIcon(icon)) {
7837 return {
7838 src: icon
7839 };
7840 }
7841 if ('background' in icon) {
7842 const colordBgColor = w(icon.background);
7843 const getColorContrast = iconColor => colordBgColor.contrast(iconColor);
7844 const maxContrast = Math.max(...ICON_COLORS.map(getColorContrast));
7845 return {
7846 ...icon,
7847 foreground: icon.foreground ? icon.foreground : ICON_COLORS.find(iconColor => getColorContrast(iconColor) === maxContrast),
7848 shadowColor: colordBgColor.alpha(0.3).toRgbString()
7849 };
7850 }
7851 return icon;
7852 }
7853
7854 /**
7855 * Normalizes block type passed as param. When string is passed then
7856 * it converts it to the matching block type object.
7857 * It passes the original object otherwise.
7858 *
7859 * @param {string|Object} blockTypeOrName Block type or name.
7860 *
7861 * @return {?Object} Block type.
7862 */
7863 function normalizeBlockType(blockTypeOrName) {
7864 if (typeof blockTypeOrName === 'string') {
7865 return getBlockType(blockTypeOrName);
7866 }
7867 return blockTypeOrName;
7868 }
7869
7870 /**
7871 * Get the label for the block, usually this is either the block title,
7872 * or the value of the block's `label` function when that's specified.
7873 *
7874 * @param {Object} blockType The block type.
7875 * @param {Object} attributes The values of the block's attributes.
7876 * @param {Object} context The intended use for the label.
7877 *
7878 * @return {string} The block label.
7879 */
7880 function getBlockLabel(blockType, attributes, context = 'visual') {
7881 const {
7882 __experimentalLabel: getLabel,
7883 title
7884 } = blockType;
7885 const label = getLabel && getLabel(attributes, {
7886 context
7887 });
7888 if (!label) {
7889 return title;
7890 }
7891 if (label.toPlainText) {
7892 return label.toPlainText();
7893 }
7894
7895 // Strip any HTML (i.e. RichText formatting) before returning.
7896 return (0,external_wp_dom_namespaceObject.__unstableStripHTML)(label);
7897 }
7898
7899 /**
7900 * Get a label for the block for use by screenreaders, this is more descriptive
7901 * than the visual label and includes the block title and the value of the
7902 * `getLabel` function if it's specified.
7903 *
7904 * @param {?Object} blockType The block type.
7905 * @param {Object} attributes The values of the block's attributes.
7906 * @param {?number} position The position of the block in the block list.
7907 * @param {string} [direction='vertical'] The direction of the block layout.
7908 *
7909 * @return {string} The block label.
7910 */
7911 function getAccessibleBlockLabel(blockType, attributes, position, direction = 'vertical') {
7912 // `title` is already localized, `label` is a user-supplied value.
7913 const title = blockType?.title;
7914 const label = blockType ? getBlockLabel(blockType, attributes, 'accessibility') : '';
7915 const hasPosition = position !== undefined;
7916
7917 // getBlockLabel returns the block title as a fallback when there's no label,
7918 // if it did return the title, this function needs to avoid adding the
7919 // title twice within the accessible label. Use this `hasLabel` boolean to
7920 // handle that.
7921 const hasLabel = label && label !== title;
7922 if (hasPosition && direction === 'vertical') {
7923 if (hasLabel) {
7924 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */
7925 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d. %3$s'), title, position, label);
7926 }
7927 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. 1: The block title. 2: The block row number. */
7928 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d'), title, position);
7929 } else if (hasPosition && direction === 'horizontal') {
7930 if (hasLabel) {
7931 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */
7932 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d. %3$s'), title, position, label);
7933 }
7934 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. 1: The block title. 2: The block column number. */
7935 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d'), title, position);
7936 }
7937 if (hasLabel) {
7938 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. %1: The block title. %2: The block label. */
7939 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. %2$s'), title, label);
7940 }
7941 return (0,external_wp_i18n_namespaceObject.sprintf)(/* translators: accessibility text. %s: The block title. */
7942 (0,external_wp_i18n_namespaceObject.__)('%s Block'), title);
7943 }
7944 function getDefault(attributeSchema) {
7945 if (attributeSchema.default !== undefined) {
7946 return attributeSchema.default;
7947 }
7948 if (attributeSchema.type === 'rich-text') {
7949 return new external_wp_richText_namespaceObject.RichTextData();
7950 }
7951 }
7952
7953 /**
7954 * Ensure attributes contains only values defined by block type, and merge
7955 * default values for missing attributes.
7956 *
7957 * @param {string} name The block's name.
7958 * @param {Object} attributes The block's attributes.
7959 * @return {Object} The sanitized attributes.
7960 */
7961 function __experimentalSanitizeBlockAttributes(name, attributes) {
7962 // Get the type definition associated with a registered block.
7963 const blockType = getBlockType(name);
7964 if (undefined === blockType) {
7965 throw new Error(`Block type '${name}' is not registered.`);
7966 }
7967 return Object.entries(blockType.attributes).reduce((accumulator, [key, schema]) => {
7968 const value = attributes[key];
7969 if (undefined !== value) {
7970 if (schema.type === 'rich-text') {
7971 if (value instanceof external_wp_richText_namespaceObject.RichTextData) {
7972 accumulator[key] = value;
7973 } else if (typeof value === 'string') {
7974 accumulator[key] = external_wp_richText_namespaceObject.RichTextData.fromHTMLString(value);
7975 }
7976 } else if (schema.type === 'string' && value instanceof external_wp_richText_namespaceObject.RichTextData) {
7977 accumulator[key] = value.toHTMLString();
7978 } else {
7979 accumulator[key] = value;
7980 }
7981 } else {
7982 const _default = getDefault(schema);
7983 if (undefined !== _default) {
7984 accumulator[key] = _default;
7985 }
7986 }
7987 if (['node', 'children'].indexOf(schema.source) !== -1) {
7988 // Ensure value passed is always an array, which we're expecting in
7989 // the RichText component to handle the deprecated value.
7990 if (typeof accumulator[key] === 'string') {
7991 accumulator[key] = [accumulator[key]];
7992 } else if (!Array.isArray(accumulator[key])) {
7993 accumulator[key] = [];
7994 }
7995 }
7996 return accumulator;
7997 }, {});
7998 }
7999
8000 /**
8001 * Filter block attributes by `role` and return their names.
8002 *
8003 * @param {string} name Block attribute's name.
8004 * @param {string} role The role of a block attribute.
8005 *
8006 * @return {string[]} The attribute names that have the provided role.
8007 */
8008 function getBlockAttributesNamesByRole(name, role) {
8009 const attributes = getBlockType(name)?.attributes;
8010 if (!attributes) {
8011 return [];
8012 }
8013 const attributesNames = Object.keys(attributes);
8014 if (!role) {
8015 return attributesNames;
8016 }
8017 return attributesNames.filter(attributeName => {
8018 const attribute = attributes[attributeName];
8019 if (attribute?.role === role) {
8020 return true;
8021 }
8022 if (attribute?.__experimentalRole === role) {
8023 external_wp_deprecated_default()('__experimentalRole attribute', {
8024 since: '6.7',
8025 version: '6.8',
8026 alternative: 'role attribute',
8027 hint: `Check the block.json of the ${name} block.`
8028 });
8029 return true;
8030 }
8031 return false;
8032 });
8033 }
8034 const __experimentalGetBlockAttributesNamesByRole = (...args) => {
8035 external_wp_deprecated_default()('__experimentalGetBlockAttributesNamesByRole', {
8036 since: '6.7',
8037 version: '6.8',
8038 alternative: 'getBlockAttributesNamesByRole'
8039 });
8040 return getBlockAttributesNamesByRole(...args);
8041 };
8042
8043 /**
8044 * Return a new object with the specified keys omitted.
8045 *
8046 * @param {Object} object Original object.
8047 * @param {Array} keys Keys to be omitted.
8048 *
8049 * @return {Object} Object with omitted keys.
8050 */
8051 function omit(object, keys) {
8052 return Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key)));
8053 }
8054
8055 ;// ./packages/blocks/build-module/store/reducer.js
8056 /* wp:polyfill */
8057 /**
8058 * External dependencies
8059 */
8060
8061
8062 /**
8063 * WordPress dependencies
8064 */
8065
8066
8067
8068 /**
8069 * Internal dependencies
8070 */
8071
8072
8073 /**
8074 * @typedef {Object} WPBlockCategory
8075 *
8076 * @property {string} slug Unique category slug.
8077 * @property {string} title Category label, for display in user interface.
8078 */
8079
8080 /**
8081 * Default set of categories.
8082 *
8083 * @type {WPBlockCategory[]}
8084 */
8085 const DEFAULT_CATEGORIES = [{
8086 slug: 'text',
8087 title: (0,external_wp_i18n_namespaceObject.__)('Text')
8088 }, {
8089 slug: 'media',
8090 title: (0,external_wp_i18n_namespaceObject.__)('Media')
8091 }, {
8092 slug: 'design',
8093 title: (0,external_wp_i18n_namespaceObject.__)('Design')
8094 }, {
8095 slug: 'widgets',
8096 title: (0,external_wp_i18n_namespaceObject.__)('Widgets')
8097 }, {
8098 slug: 'theme',
8099 title: (0,external_wp_i18n_namespaceObject.__)('Theme')
8100 }, {
8101 slug: 'embed',
8102 title: (0,external_wp_i18n_namespaceObject.__)('Embeds')
8103 }, {
8104 slug: 'reusable',
8105 title: (0,external_wp_i18n_namespaceObject.__)('Reusable blocks')
8106 }];
8107
8108 // Key block types by their name.
8109 function keyBlockTypesByName(types) {
8110 return types.reduce((newBlockTypes, block) => ({
8111 ...newBlockTypes,
8112 [block.name]: block
8113 }), {});
8114 }
8115
8116 // Filter items to ensure they're unique by their name.
8117 function getUniqueItemsByName(items) {
8118 return items.reduce((acc, currentItem) => {
8119 if (!acc.some(item => item.name === currentItem.name)) {
8120 acc.push(currentItem);
8121 }
8122 return acc;
8123 }, []);
8124 }
8125 function bootstrappedBlockTypes(state = {}, action) {
8126 switch (action.type) {
8127 case 'ADD_BOOTSTRAPPED_BLOCK_TYPE':
8128 const {
8129 name,
8130 blockType
8131 } = action;
8132 const serverDefinition = state[name];
8133 let newDefinition;
8134 // Don't overwrite if already set. It covers the case when metadata
8135 // was initialized from the server.
8136 if (serverDefinition) {
8137 // The `blockHooks` prop is not yet included in the server provided
8138 // definitions and needs to be polyfilled. This can be removed when the
8139 // minimum supported WordPress is >= 6.4.
8140 if (serverDefinition.blockHooks === undefined && blockType.blockHooks) {
8141 newDefinition = {
8142 ...serverDefinition,
8143 ...newDefinition,
8144 blockHooks: blockType.blockHooks
8145 };
8146 }
8147
8148 // The `allowedBlocks` prop is not yet included in the server provided
8149 // definitions and needs to be polyfilled. This can be removed when the
8150 // minimum supported WordPress is >= 6.5.
8151 if (serverDefinition.allowedBlocks === undefined && blockType.allowedBlocks) {
8152 newDefinition = {
8153 ...serverDefinition,
8154 ...newDefinition,
8155 allowedBlocks: blockType.allowedBlocks
8156 };
8157 }
8158 } else {
8159 newDefinition = Object.fromEntries(Object.entries(blockType).filter(([, value]) => value !== null && value !== undefined).map(([key, value]) => [camelCase(key), value]));
8160 newDefinition.name = name;
8161 }
8162 if (newDefinition) {
8163 return {
8164 ...state,
8165 [name]: newDefinition
8166 };
8167 }
8168 return state;
8169 case 'REMOVE_BLOCK_TYPES':
8170 return omit(state, action.names);
8171 }
8172 return state;
8173 }
8174
8175 /**
8176 * Reducer managing the unprocessed block types in a form passed when registering the by block.
8177 * It's for internal use only. It allows recomputing the processed block types on-demand after block type filters
8178 * get added or removed.
8179 *
8180 * @param {Object} state Current state.
8181 * @param {Object} action Dispatched action.
8182 *
8183 * @return {Object} Updated state.
8184 */
8185 function unprocessedBlockTypes(state = {}, action) {
8186 switch (action.type) {
8187 case 'ADD_UNPROCESSED_BLOCK_TYPE':
8188 return {
8189 ...state,
8190 [action.name]: action.blockType
8191 };
8192 case 'REMOVE_BLOCK_TYPES':
8193 return omit(state, action.names);
8194 }
8195 return state;
8196 }
8197
8198 /**
8199 * Reducer managing the processed block types with all filters applied.
8200 * The state is derived from the `unprocessedBlockTypes` reducer.
8201 *
8202 * @param {Object} state Current state.
8203 * @param {Object} action Dispatched action.
8204 *
8205 * @return {Object} Updated state.
8206 */
8207 function blockTypes(state = {}, action) {
8208 switch (action.type) {
8209 case 'ADD_BLOCK_TYPES':
8210 return {
8211 ...state,
8212 ...keyBlockTypesByName(action.blockTypes)
8213 };
8214 case 'REMOVE_BLOCK_TYPES':
8215 return omit(state, action.names);
8216 }
8217 return state;
8218 }
8219
8220 /**
8221 * Reducer managing the block styles.
8222 *
8223 * @param {Object} state Current state.
8224 * @param {Object} action Dispatched action.
8225 *
8226 * @return {Object} Updated state.
8227 */
8228 function blockStyles(state = {}, action) {
8229 var _state$action$blockNa;
8230 switch (action.type) {
8231 case 'ADD_BLOCK_TYPES':
8232 return {
8233 ...state,
8234 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8235 var _blockType$styles, _state$blockType$name;
8236 return [name, getUniqueItemsByName([...((_blockType$styles = blockType.styles) !== null && _blockType$styles !== void 0 ? _blockType$styles : []).map(style => ({
8237 ...style,
8238 source: 'block'
8239 })), ...((_state$blockType$name = state[blockType.name]) !== null && _state$blockType$name !== void 0 ? _state$blockType$name : []).filter(({
8240 source
8241 }) => 'block' !== source)])];
8242 }))
8243 };
8244 case 'ADD_BLOCK_STYLES':
8245 const updatedStyles = {};
8246 action.blockNames.forEach(blockName => {
8247 var _state$blockName;
8248 updatedStyles[blockName] = getUniqueItemsByName([...((_state$blockName = state[blockName]) !== null && _state$blockName !== void 0 ? _state$blockName : []), ...action.styles]);
8249 });
8250 return {
8251 ...state,
8252 ...updatedStyles
8253 };
8254 case 'REMOVE_BLOCK_STYLES':
8255 return {
8256 ...state,
8257 [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)
8258 };
8259 }
8260 return state;
8261 }
8262
8263 /**
8264 * Reducer managing the block variations.
8265 *
8266 * @param {Object} state Current state.
8267 * @param {Object} action Dispatched action.
8268 *
8269 * @return {Object} Updated state.
8270 */
8271 function blockVariations(state = {}, action) {
8272 var _state$action$blockNa2, _state$action$blockNa3;
8273 switch (action.type) {
8274 case 'ADD_BLOCK_TYPES':
8275 return {
8276 ...state,
8277 ...Object.fromEntries(Object.entries(keyBlockTypesByName(action.blockTypes)).map(([name, blockType]) => {
8278 var _blockType$variations, _state$blockType$name2;
8279 return [name, getUniqueItemsByName([...((_blockType$variations = blockType.variations) !== null && _blockType$variations !== void 0 ? _blockType$variations : []).map(variation => ({
8280 ...variation,
8281 source: 'block'
8282 })), ...((_state$blockType$name2 = state[blockType.name]) !== null && _state$blockType$name2 !== void 0 ? _state$blockType$name2 : []).filter(({
8283 source
8284 }) => 'block' !== source)])];
8285 }))
8286 };
8287 case 'ADD_BLOCK_VARIATIONS':
8288 return {
8289 ...state,
8290 [action.blockName]: getUniqueItemsByName([...((_state$action$blockNa2 = state[action.blockName]) !== null && _state$action$blockNa2 !== void 0 ? _state$action$blockNa2 : []), ...action.variations])
8291 };
8292 case 'REMOVE_BLOCK_VARIATIONS':
8293 return {
8294 ...state,
8295 [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)
8296 };
8297 }
8298 return state;
8299 }
8300
8301 /**
8302 * Higher-order Reducer creating a reducer keeping track of given block name.
8303 *
8304 * @param {string} setActionType Action type.
8305 *
8306 * @return {Function} Reducer.
8307 */
8308 function createBlockNameSetterReducer(setActionType) {
8309 return (state = null, action) => {
8310 switch (action.type) {
8311 case 'REMOVE_BLOCK_TYPES':
8312 if (action.names.indexOf(state) !== -1) {
8313 return null;
8314 }
8315 return state;
8316 case setActionType:
8317 return action.name || null;
8318 }
8319 return state;
8320 };
8321 }
8322 const defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
8323 const freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
8324 const unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
8325 const groupingBlockName = createBlockNameSetterReducer('SET_GROUPING_BLOCK_NAME');
8326
8327 /**
8328 * Reducer managing the categories
8329 *
8330 * @param {WPBlockCategory[]} state Current state.
8331 * @param {Object} action Dispatched action.
8332 *
8333 * @return {WPBlockCategory[]} Updated state.
8334 */
8335 function categories(state = DEFAULT_CATEGORIES, action) {
8336 switch (action.type) {
8337 case 'SET_CATEGORIES':
8338 // Ensure, that categories are unique by slug.
8339 const uniqueCategories = new Map();
8340 (action.categories || []).forEach(category => {
8341 uniqueCategories.set(category.slug, category);
8342 });
8343 return [...uniqueCategories.values()];
8344 case 'UPDATE_CATEGORY':
8345 {
8346 if (!action.category || !Object.keys(action.category).length) {
8347 return state;
8348 }
8349 const categoryToChange = state.find(({
8350 slug
8351 }) => slug === action.slug);
8352 if (categoryToChange) {
8353 return state.map(category => {
8354 if (category.slug === action.slug) {
8355 return {
8356 ...category,
8357 ...action.category
8358 };
8359 }
8360 return category;
8361 });
8362 }
8363 }
8364 }
8365 return state;
8366 }
8367 function collections(state = {}, action) {
8368 switch (action.type) {
8369 case 'ADD_BLOCK_COLLECTION':
8370 return {
8371 ...state,
8372 [action.namespace]: {
8373 title: action.title,
8374 icon: action.icon
8375 }
8376 };
8377 case 'REMOVE_BLOCK_COLLECTION':
8378 return omit(state, action.namespace);
8379 }
8380 return state;
8381 }
8382
8383 /**
8384 * Merges usesContext with existing values, potentially defined in the server registration.
8385 *
8386 * @param {string[]} existingUsesContext Existing `usesContext`.
8387 * @param {string[]} newUsesContext Newly added `usesContext`.
8388 * @return {string[]|undefined} Merged `usesContext`.
8389 */
8390 function getMergedUsesContext(existingUsesContext = [], newUsesContext = []) {
8391 const mergedArrays = Array.from(new Set(existingUsesContext.concat(newUsesContext)));
8392 return mergedArrays.length > 0 ? mergedArrays : undefined;
8393 }
8394 function blockBindingsSources(state = {}, action) {
8395 switch (action.type) {
8396 case 'ADD_BLOCK_BINDINGS_SOURCE':
8397 // Only open this API in Gutenberg and for `core/post-meta` for the moment.
8398 let getFieldsList;
8399 if (true) {
8400 getFieldsList = action.getFieldsList;
8401 } else {}
8402 return {
8403 ...state,
8404 [action.name]: {
8405 label: action.label || state[action.name]?.label,
8406 usesContext: getMergedUsesContext(state[action.name]?.usesContext, action.usesContext),
8407 getValues: action.getValues,
8408 setValues: action.setValues,
8409 // Only set `canUserEditValue` if `setValues` is also defined.
8410 canUserEditValue: action.setValues && action.canUserEditValue,
8411 getFieldsList
8412 }
8413 };
8414 case 'REMOVE_BLOCK_BINDINGS_SOURCE':
8415 return omit(state, action.name);
8416 }
8417 return state;
8418 }
8419 /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
8420 bootstrappedBlockTypes,
8421 unprocessedBlockTypes,
8422 blockTypes,
8423 blockStyles,
8424 blockVariations,
8425 defaultBlockName,
8426 freeformFallbackBlockName,
8427 unregisteredFallbackBlockName,
8428 groupingBlockName,
8429 categories,
8430 collections,
8431 blockBindingsSources
8432 }));
8433
8434 // EXTERNAL MODULE: ./node_modules/remove-accents/index.js
8435 var remove_accents = __webpack_require__(9681);
8436 var remove_accents_default = /*#__PURE__*/__webpack_require__.n(remove_accents);
8437 ;// ./packages/blocks/build-module/store/utils.js
8438 /**
8439 * Helper util to return a value from a certain path of the object.
8440 * Path is specified as either:
8441 * - a string of properties, separated by dots, for example: "x.y".
8442 * - an array of properties, for example `[ 'x', 'y' ]`.
8443 * You can also specify a default value in case the result is nullish.
8444 *
8445 * @param {Object} object Input object.
8446 * @param {string|Array} path Path to the object property.
8447 * @param {*} defaultValue Default value if the value at the specified path is nullish.
8448 * @return {*} Value of the object property at the specified path.
8449 */
8450 const getValueFromObjectPath = (object, path, defaultValue) => {
8451 var _value;
8452 const normalizedPath = Array.isArray(path) ? path : path.split('.');
8453 let value = object;
8454 normalizedPath.forEach(fieldName => {
8455 value = value?.[fieldName];
8456 });
8457 return (_value = value) !== null && _value !== void 0 ? _value : defaultValue;
8458 };
8459 function utils_isObject(candidate) {
8460 return typeof candidate === 'object' && candidate.constructor === Object && candidate !== null;
8461 }
8462
8463 /**
8464 * Determine whether a set of object properties matches a given object.
8465 *
8466 * Given an object of block attributes and an object of variation attributes,
8467 * this function checks recursively whether all the variation attributes are
8468 * present in the block attributes object.
8469 *
8470 * @param {Object} blockAttributes The object to inspect.
8471 * @param {Object} variationAttributes The object of property values to match.
8472 * @return {boolean} Whether the block attributes match the variation attributes.
8473 */
8474 function matchesAttributes(blockAttributes, variationAttributes) {
8475 if (utils_isObject(blockAttributes) && utils_isObject(variationAttributes)) {
8476 return Object.entries(variationAttributes).every(([key, value]) => matchesAttributes(blockAttributes?.[key], value));
8477 }
8478 return blockAttributes === variationAttributes;
8479 }
8480
8481 ;// ./packages/blocks/build-module/store/private-selectors.js
8482 /**
8483 * WordPress dependencies
8484 */
8485
8486
8487
8488 /**
8489 * Internal dependencies
8490 */
8491
8492
8493
8494 const ROOT_BLOCK_SUPPORTS = ['background', 'backgroundColor', 'color', 'linkColor', 'captionColor', 'buttonColor', 'headingColor', 'fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'lineHeight', 'padding', 'contentSize', 'wideSize', 'blockGap', 'textDecoration', 'textTransform', 'letterSpacing'];
8495
8496 /**
8497 * Filters the list of supported styles for a given element.
8498 *
8499 * @param {string[]} blockSupports list of supported styles.
8500 * @param {string|undefined} name block name.
8501 * @param {string|undefined} element element name.
8502 *
8503 * @return {string[]} filtered list of supported styles.
8504 */
8505 function filterElementBlockSupports(blockSupports, name, element) {
8506 return blockSupports.filter(support => {
8507 if (support === 'fontSize' && element === 'heading') {
8508 return false;
8509 }
8510
8511 // This is only available for links
8512 if (support === 'textDecoration' && !name && element !== 'link') {
8513 return false;
8514 }
8515
8516 // This is only available for heading, button, caption and text
8517 if (support === 'textTransform' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
8518 return false;
8519 }
8520
8521 // This is only available for heading, button, caption and text
8522 if (support === 'letterSpacing' && !name && !(['heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(element) || element === 'button' || element === 'caption' || element === 'text')) {
8523 return false;
8524 }
8525
8526 // Text columns is only available for blocks.
8527 if (support === 'textColumns' && !name) {
8528 return false;
8529 }
8530 return true;
8531 });
8532 }
8533
8534 /**
8535 * Returns the list of supported styles for a given block name and element.
8536 */
8537 const getSupportedStyles = (0,external_wp_data_namespaceObject.createSelector)((state, name, element) => {
8538 if (!name) {
8539 return filterElementBlockSupports(ROOT_BLOCK_SUPPORTS, name, element);
8540 }
8541 const blockType = selectors_getBlockType(state, name);
8542 if (!blockType) {
8543 return [];
8544 }
8545 const supportKeys = [];
8546
8547 // Check for blockGap support.
8548 // Block spacing support doesn't map directly to a single style property, so needs to be handled separately.
8549 if (blockType?.supports?.spacing?.blockGap) {
8550 supportKeys.push('blockGap');
8551 }
8552
8553 // check for shadow support
8554 if (blockType?.supports?.shadow) {
8555 supportKeys.push('shadow');
8556 }
8557 Object.keys(__EXPERIMENTAL_STYLE_PROPERTY).forEach(styleName => {
8558 if (!__EXPERIMENTAL_STYLE_PROPERTY[styleName].support) {
8559 return;
8560 }
8561
8562 // Opting out means that, for certain support keys like background color,
8563 // blocks have to explicitly set the support value false. If the key is
8564 // unset, we still enable it.
8565 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].requiresOptOut) {
8566 if (__EXPERIMENTAL_STYLE_PROPERTY[styleName].support[0] in blockType.supports && getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support) !== false) {
8567 supportKeys.push(styleName);
8568 return;
8569 }
8570 }
8571 if (getValueFromObjectPath(blockType.supports, __EXPERIMENTAL_STYLE_PROPERTY[styleName].support, false)) {
8572 supportKeys.push(styleName);
8573 }
8574 });
8575 return filterElementBlockSupports(supportKeys, name, element);
8576 }, (state, name) => [state.blockTypes[name]]);
8577
8578 /**
8579 * Returns the bootstrapped block type metadata for a give block name.
8580 *
8581 * @param {Object} state Data state.
8582 * @param {string} name Block name.
8583 *
8584 * @return {Object} Bootstrapped block type metadata for a block.
8585 */
8586 function getBootstrappedBlockType(state, name) {
8587 return state.bootstrappedBlockTypes[name];
8588 }
8589
8590 /**
8591 * Returns all the unprocessed (before applying the `registerBlockType` filter)
8592 * block type settings as passed during block registration.
8593 *
8594 * @param {Object} state Data state.
8595 *
8596 * @return {Array} Unprocessed block type settings for all blocks.
8597 */
8598 function getUnprocessedBlockTypes(state) {
8599 return state.unprocessedBlockTypes;
8600 }
8601
8602 /**
8603 * Returns all the block bindings sources registered.
8604 *
8605 * @param {Object} state Data state.
8606 *
8607 * @return {Object} All the registered sources and their properties.
8608 */
8609 function getAllBlockBindingsSources(state) {
8610 return state.blockBindingsSources;
8611 }
8612
8613 /**
8614 * Returns a specific block bindings source.
8615 *
8616 * @param {Object} state Data state.
8617 * @param {string} sourceName Name of the source to get.
8618 *
8619 * @return {Object} The specific block binding source and its properties.
8620 */
8621 function private_selectors_getBlockBindingsSource(state, sourceName) {
8622 return state.blockBindingsSources[sourceName];
8623 }
8624
8625 /**
8626 * Determines if any of the block type's attributes have
8627 * the content role attribute.
8628 *
8629 * @param {Object} state Data state.
8630 * @param {string} blockTypeName Block type name.
8631 * @return {boolean} Whether block type has content role attribute.
8632 */
8633 const hasContentRoleAttribute = (state, blockTypeName) => {
8634 const blockType = selectors_getBlockType(state, blockTypeName);
8635 if (!blockType) {
8636 return false;
8637 }
8638 return Object.values(blockType.attributes).some(({
8639 role,
8640 __experimentalRole
8641 }) => {
8642 if (role === 'content') {
8643 return true;
8644 }
8645 if (__experimentalRole === 'content') {
8646 external_wp_deprecated_default()('__experimentalRole attribute', {
8647 since: '6.7',
8648 version: '6.8',
8649 alternative: 'role attribute',
8650 hint: `Check the block.json of the ${blockTypeName} block.`
8651 });
8652 return true;
8653 }
8654 return false;
8655 });
8656 };
8657
8658 ;// ./packages/blocks/build-module/store/selectors.js
8659 /**
8660 * External dependencies
8661 */
8662
8663
8664 /**
8665 * WordPress dependencies
8666 */
8667
8668
8669
8670
8671 /**
8672 * Internal dependencies
8673 */
8674
8675
8676
8677 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
8678 /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
8679 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
8680
8681 /**
8682 * Given a block name or block type object, returns the corresponding
8683 * normalized block type object.
8684 *
8685 * @param {Object} state Blocks state.
8686 * @param {(string|Object)} nameOrType Block name or type object
8687 *
8688 * @return {Object} Block type object.
8689 */
8690 const getNormalizedBlockType = (state, nameOrType) => 'string' === typeof nameOrType ? selectors_getBlockType(state, nameOrType) : nameOrType;
8691
8692 /**
8693 * Returns all the available block types.
8694 *
8695 * @param {Object} state Data state.
8696 *
8697 * @example
8698 * ```js
8699 * import { store as blocksStore } from '@wordpress/blocks';
8700 * import { useSelect } from '@wordpress/data';
8701 *
8702 * const ExampleComponent = () => {
8703 * const blockTypes = useSelect(
8704 * ( select ) => select( blocksStore ).getBlockTypes(),
8705 * []
8706 * );
8707 *
8708 * return (
8709 * <ul>
8710 * { blockTypes.map( ( block ) => (
8711 * <li key={ block.name }>{ block.title }</li>
8712 * ) ) }
8713 * </ul>
8714 * );
8715 * };
8716 * ```
8717 *
8718 * @return {Array} Block Types.
8719 */
8720 const selectors_getBlockTypes = (0,external_wp_data_namespaceObject.createSelector)(state => Object.values(state.blockTypes), state => [state.blockTypes]);
8721
8722 /**
8723 * Returns a block type by name.
8724 *
8725 * @param {Object} state Data state.
8726 * @param {string} name Block type name.
8727 *
8728 * @example
8729 * ```js
8730 * import { store as blocksStore } from '@wordpress/blocks';
8731 * import { useSelect } from '@wordpress/data';
8732 *
8733 * const ExampleComponent = () => {
8734 * const paragraphBlock = useSelect( ( select ) =>
8735 * ( select ) => select( blocksStore ).getBlockType( 'core/paragraph' ),
8736 * []
8737 * );
8738 *
8739 * return (
8740 * <ul>
8741 * { paragraphBlock &&
8742 * Object.entries( paragraphBlock.supports ).map(
8743 * ( blockSupportsEntry ) => {
8744 * const [ propertyName, value ] = blockSupportsEntry;
8745 * return (
8746 * <li
8747 * key={ propertyName }
8748 * >{ `${ propertyName } : ${ value }` }</li>
8749 * );
8750 * }
8751 * ) }
8752 * </ul>
8753 * );
8754 * };
8755 * ```
8756 *
8757 * @return {Object?} Block Type.
8758 */
8759 function selectors_getBlockType(state, name) {
8760 return state.blockTypes[name];
8761 }
8762
8763 /**
8764 * Returns block styles by block name.
8765 *
8766 * @param {Object} state Data state.
8767 * @param {string} name Block type name.
8768 *
8769 * @example
8770 * ```js
8771 * import { store as blocksStore } from '@wordpress/blocks';
8772 * import { useSelect } from '@wordpress/data';
8773 *
8774 * const ExampleComponent = () => {
8775 * const buttonBlockStyles = useSelect( ( select ) =>
8776 * select( blocksStore ).getBlockStyles( 'core/button' ),
8777 * []
8778 * );
8779 *
8780 * return (
8781 * <ul>
8782 * { buttonBlockStyles &&
8783 * buttonBlockStyles.map( ( style ) => (
8784 * <li key={ style.name }>{ style.label }</li>
8785 * ) ) }
8786 * </ul>
8787 * );
8788 * };
8789 * ```
8790 *
8791 * @return {Array?} Block Styles.
8792 */
8793 function getBlockStyles(state, name) {
8794 return state.blockStyles[name];
8795 }
8796
8797 /**
8798 * Returns block variations by block name.
8799 *
8800 * @param {Object} state Data state.
8801 * @param {string} blockName Block type name.
8802 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8803 *
8804 * @example
8805 * ```js
8806 * import { store as blocksStore } from '@wordpress/blocks';
8807 * import { useSelect } from '@wordpress/data';
8808 *
8809 * const ExampleComponent = () => {
8810 * const socialLinkVariations = useSelect( ( select ) =>
8811 * select( blocksStore ).getBlockVariations( 'core/social-link' ),
8812 * []
8813 * );
8814 *
8815 * return (
8816 * <ul>
8817 * { socialLinkVariations &&
8818 * socialLinkVariations.map( ( variation ) => (
8819 * <li key={ variation.name }>{ variation.title }</li>
8820 * ) ) }
8821 * </ul>
8822 * );
8823 * };
8824 * ```
8825 *
8826 * @return {(WPBlockVariation[]|void)} Block variations.
8827 */
8828 const selectors_getBlockVariations = (0,external_wp_data_namespaceObject.createSelector)((state, blockName, scope) => {
8829 const variations = state.blockVariations[blockName];
8830 if (!variations || !scope) {
8831 return variations;
8832 }
8833 return variations.filter(variation => {
8834 // For backward compatibility reasons, variation's scope defaults to
8835 // `block` and `inserter` when not set.
8836 return (variation.scope || ['block', 'inserter']).includes(scope);
8837 });
8838 }, (state, blockName) => [state.blockVariations[blockName]]);
8839
8840 /**
8841 * Returns the active block variation for a given block based on its attributes.
8842 * Variations are determined by their `isActive` property.
8843 * Which is either an array of block attribute keys or a function.
8844 *
8845 * In case of an array of block attribute keys, the `attributes` are compared
8846 * to the variation's attributes using strict equality check.
8847 *
8848 * In case of function type, the function should accept a block's attributes
8849 * and the variation's attributes and determines if a variation is active.
8850 * A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
8851 *
8852 * @param {Object} state Data state.
8853 * @param {string} blockName Name of block (example: “core/columns”).
8854 * @param {Object} attributes Block attributes used to determine active variation.
8855 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8856 *
8857 * @example
8858 * ```js
8859 * import { __ } from '@wordpress/i18n';
8860 * import { store as blocksStore } from '@wordpress/blocks';
8861 * import { store as blockEditorStore } from '@wordpress/block-editor';
8862 * import { useSelect } from '@wordpress/data';
8863 *
8864 * const ExampleComponent = () => {
8865 * // This example assumes that a core/embed block is the first block in the Block Editor.
8866 * const activeBlockVariation = useSelect( ( select ) => {
8867 * // Retrieve the list of blocks.
8868 * const [ firstBlock ] = select( blockEditorStore ).getBlocks()
8869 *
8870 * // Return the active block variation for the first block.
8871 * return select( blocksStore ).getActiveBlockVariation(
8872 * firstBlock.name,
8873 * firstBlock.attributes
8874 * );
8875 * }, [] );
8876 *
8877 * return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
8878 * <p>{ __( 'Spotify variation' ) }</p>
8879 * ) : (
8880 * <p>{ __( 'Other variation' ) }</p>
8881 * );
8882 * };
8883 * ```
8884 *
8885 * @return {(WPBlockVariation|undefined)} Active block variation.
8886 */
8887 function getActiveBlockVariation(state, blockName, attributes, scope) {
8888 const variations = selectors_getBlockVariations(state, blockName, scope);
8889 if (!variations) {
8890 return variations;
8891 }
8892 const blockType = selectors_getBlockType(state, blockName);
8893 const attributeKeys = Object.keys(blockType?.attributes || {});
8894 let match;
8895 let maxMatchedAttributes = 0;
8896 for (const variation of variations) {
8897 if (Array.isArray(variation.isActive)) {
8898 const definedAttributes = variation.isActive.filter(attribute => {
8899 // We support nested attribute paths, e.g. `layout.type`.
8900 // In this case, we need to check if the part before the
8901 // first dot is a known attribute.
8902 const topLevelAttribute = attribute.split('.')[0];
8903 return attributeKeys.includes(topLevelAttribute);
8904 });
8905 const definedAttributesLength = definedAttributes.length;
8906 if (definedAttributesLength === 0) {
8907 continue;
8908 }
8909 const isMatch = definedAttributes.every(attribute => {
8910 const variationAttributeValue = getValueFromObjectPath(variation.attributes, attribute);
8911 if (variationAttributeValue === undefined) {
8912 return false;
8913 }
8914 let blockAttributeValue = getValueFromObjectPath(attributes, attribute);
8915 if (blockAttributeValue instanceof external_wp_richText_namespaceObject.RichTextData) {
8916 blockAttributeValue = blockAttributeValue.toHTMLString();
8917 }
8918 return matchesAttributes(blockAttributeValue, variationAttributeValue);
8919 });
8920 if (isMatch && definedAttributesLength > maxMatchedAttributes) {
8921 match = variation;
8922 maxMatchedAttributes = definedAttributesLength;
8923 }
8924 } else if (variation.isActive?.(attributes, variation.attributes)) {
8925 // If isActive is a function, we cannot know how many attributes it matches.
8926 // This means that we cannot compare the specificity of our matches,
8927 // and simply return the best match we have found.
8928 return match || variation;
8929 }
8930 }
8931 return match;
8932 }
8933
8934 /**
8935 * Returns the default block variation for the given block type.
8936 * When there are multiple variations annotated as the default one,
8937 * the last added item is picked. This simplifies registering overrides.
8938 * When there is no default variation set, it returns the first item.
8939 *
8940 * @param {Object} state Data state.
8941 * @param {string} blockName Block type name.
8942 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8943 *
8944 * @example
8945 * ```js
8946 * import { __, sprintf } from '@wordpress/i18n';
8947 * import { store as blocksStore } from '@wordpress/blocks';
8948 * import { useSelect } from '@wordpress/data';
8949 *
8950 * const ExampleComponent = () => {
8951 * const defaultEmbedBlockVariation = useSelect( ( select ) =>
8952 * select( blocksStore ).getDefaultBlockVariation( 'core/embed' ),
8953 * []
8954 * );
8955 *
8956 * return (
8957 * defaultEmbedBlockVariation && (
8958 * <p>
8959 * { sprintf(
8960 * __( 'core/embed default variation: %s' ),
8961 * defaultEmbedBlockVariation.title
8962 * ) }
8963 * </p>
8964 * )
8965 * );
8966 * };
8967 * ```
8968 *
8969 * @return {?WPBlockVariation} The default block variation.
8970 */
8971 function getDefaultBlockVariation(state, blockName, scope) {
8972 const variations = selectors_getBlockVariations(state, blockName, scope);
8973 const defaultVariation = [...variations].reverse().find(({
8974 isDefault
8975 }) => !!isDefault);
8976 return defaultVariation || variations[0];
8977 }
8978
8979 /**
8980 * Returns all the available block categories.
8981 *
8982 * @param {Object} state Data state.
8983 *
8984 * @example
8985 * ```js
8986 * import { store as blocksStore } from '@wordpress/blocks';
8987 * import { useSelect, } from '@wordpress/data';
8988 *
8989 * const ExampleComponent = () => {
8990 * const blockCategories = useSelect( ( select ) =>
8991 * select( blocksStore ).getCategories(),
8992 * []
8993 * );
8994 *
8995 * return (
8996 * <ul>
8997 * { blockCategories.map( ( category ) => (
8998 * <li key={ category.slug }>{ category.title }</li>
8999 * ) ) }
9000 * </ul>
9001 * );
9002 * };
9003 * ```
9004 *
9005 * @return {WPBlockCategory[]} Categories list.
9006 */
9007 function getCategories(state) {
9008 return state.categories;
9009 }
9010
9011 /**
9012 * Returns all the available collections.
9013 *
9014 * @param {Object} state Data state.
9015 *
9016 * @example
9017 * ```js
9018 * import { store as blocksStore } from '@wordpress/blocks';
9019 * import { useSelect } from '@wordpress/data';
9020 *
9021 * const ExampleComponent = () => {
9022 * const blockCollections = useSelect( ( select ) =>
9023 * select( blocksStore ).getCollections(),
9024 * []
9025 * );
9026 *
9027 * return (
9028 * <ul>
9029 * { Object.values( blockCollections ).length > 0 &&
9030 * Object.values( blockCollections ).map( ( collection ) => (
9031 * <li key={ collection.title }>{ collection.title }</li>
9032 * ) ) }
9033 * </ul>
9034 * );
9035 * };
9036 * ```
9037 *
9038 * @return {Object} Collections list.
9039 */
9040 function getCollections(state) {
9041 return state.collections;
9042 }
9043
9044 /**
9045 * Returns the name of the default block name.
9046 *
9047 * @param {Object} state Data state.
9048 *
9049 * @example
9050 * ```js
9051 * import { __, sprintf } from '@wordpress/i18n';
9052 * import { store as blocksStore } from '@wordpress/blocks';
9053 * import { useSelect } from '@wordpress/data';
9054 *
9055 * const ExampleComponent = () => {
9056 * const defaultBlockName = useSelect( ( select ) =>
9057 * select( blocksStore ).getDefaultBlockName(),
9058 * []
9059 * );
9060 *
9061 * return (
9062 * defaultBlockName && (
9063 * <p>
9064 * { sprintf( __( 'Default block name: %s' ), defaultBlockName ) }
9065 * </p>
9066 * )
9067 * );
9068 * };
9069 * ```
9070 *
9071 * @return {string?} Default block name.
9072 */
9073 function selectors_getDefaultBlockName(state) {
9074 return state.defaultBlockName;
9075 }
9076
9077 /**
9078 * Returns the name of the block for handling non-block content.
9079 *
9080 * @param {Object} state Data state.
9081 *
9082 * @example
9083 * ```js
9084 * import { __, sprintf } from '@wordpress/i18n';
9085 * import { store as blocksStore } from '@wordpress/blocks';
9086 * import { useSelect } from '@wordpress/data';
9087 *
9088 * const ExampleComponent = () => {
9089 * const freeformFallbackBlockName = useSelect( ( select ) =>
9090 * select( blocksStore ).getFreeformFallbackBlockName(),
9091 * []
9092 * );
9093 *
9094 * return (
9095 * freeformFallbackBlockName && (
9096 * <p>
9097 * { sprintf( __(
9098 * 'Freeform fallback block name: %s' ),
9099 * freeformFallbackBlockName
9100 * ) }
9101 * </p>
9102 * )
9103 * );
9104 * };
9105 * ```
9106 *
9107 * @return {string?} Name of the block for handling non-block content.
9108 */
9109 function getFreeformFallbackBlockName(state) {
9110 return state.freeformFallbackBlockName;
9111 }
9112
9113 /**
9114 * Returns the name of the block for handling unregistered blocks.
9115 *
9116 * @param {Object} state Data state.
9117 *
9118 * @example
9119 * ```js
9120 * import { __, sprintf } from '@wordpress/i18n';
9121 * import { store as blocksStore } from '@wordpress/blocks';
9122 * import { useSelect } from '@wordpress/data';
9123 *
9124 * const ExampleComponent = () => {
9125 * const unregisteredFallbackBlockName = useSelect( ( select ) =>
9126 * select( blocksStore ).getUnregisteredFallbackBlockName(),
9127 * []
9128 * );
9129 *
9130 * return (
9131 * unregisteredFallbackBlockName && (
9132 * <p>
9133 * { sprintf( __(
9134 * 'Unregistered fallback block name: %s' ),
9135 * unregisteredFallbackBlockName
9136 * ) }
9137 * </p>
9138 * )
9139 * );
9140 * };
9141 * ```
9142 *
9143 * @return {string?} Name of the block for handling unregistered blocks.
9144 */
9145 function getUnregisteredFallbackBlockName(state) {
9146 return state.unregisteredFallbackBlockName;
9147 }
9148
9149 /**
9150 * Returns the name of the block for handling the grouping of blocks.
9151 *
9152 * @param {Object} state Data state.
9153 *
9154 * @example
9155 * ```js
9156 * import { __, sprintf } from '@wordpress/i18n';
9157 * import { store as blocksStore } from '@wordpress/blocks';
9158 * import { useSelect } from '@wordpress/data';
9159 *
9160 * const ExampleComponent = () => {
9161 * const groupingBlockName = useSelect( ( select ) =>
9162 * select( blocksStore ).getGroupingBlockName(),
9163 * []
9164 * );
9165 *
9166 * return (
9167 * groupingBlockName && (
9168 * <p>
9169 * { sprintf(
9170 * __( 'Default grouping block name: %s' ),
9171 * groupingBlockName
9172 * ) }
9173 * </p>
9174 * )
9175 * );
9176 * };
9177 * ```
9178 *
9179 * @return {string?} Name of the block for handling the grouping of blocks.
9180 */
9181 function selectors_getGroupingBlockName(state) {
9182 return state.groupingBlockName;
9183 }
9184
9185 /**
9186 * Returns an array with the child blocks of a given block.
9187 *
9188 * @param {Object} state Data state.
9189 * @param {string} blockName Block type name.
9190 *
9191 * @example
9192 * ```js
9193 * import { store as blocksStore } from '@wordpress/blocks';
9194 * import { useSelect } from '@wordpress/data';
9195 *
9196 * const ExampleComponent = () => {
9197 * const childBlockNames = useSelect( ( select ) =>
9198 * select( blocksStore ).getChildBlockNames( 'core/navigation' ),
9199 * []
9200 * );
9201 *
9202 * return (
9203 * <ul>
9204 * { childBlockNames &&
9205 * childBlockNames.map( ( child ) => (
9206 * <li key={ child }>{ child }</li>
9207 * ) ) }
9208 * </ul>
9209 * );
9210 * };
9211 * ```
9212 *
9213 * @return {Array} Array of child block names.
9214 */
9215 const selectors_getChildBlockNames = (0,external_wp_data_namespaceObject.createSelector)((state, blockName) => {
9216 return selectors_getBlockTypes(state).filter(blockType => {
9217 return blockType.parent?.includes(blockName);
9218 }).map(({
9219 name
9220 }) => name);
9221 }, state => [state.blockTypes]);
9222
9223 /**
9224 * Returns the block support value for a feature, if defined.
9225 *
9226 * @param {Object} state Data state.
9227 * @param {(string|Object)} nameOrType Block name or type object
9228 * @param {Array|string} feature Feature to retrieve
9229 * @param {*} defaultSupports Default value to return if not
9230 * explicitly defined
9231 *
9232 * @example
9233 * ```js
9234 * import { __, sprintf } from '@wordpress/i18n';
9235 * import { store as blocksStore } from '@wordpress/blocks';
9236 * import { useSelect } from '@wordpress/data';
9237 *
9238 * const ExampleComponent = () => {
9239 * const paragraphBlockSupportValue = useSelect( ( select ) =>
9240 * select( blocksStore ).getBlockSupport( 'core/paragraph', 'anchor' ),
9241 * []
9242 * );
9243 *
9244 * return (
9245 * <p>
9246 * { sprintf(
9247 * __( 'core/paragraph supports.anchor value: %s' ),
9248 * paragraphBlockSupportValue
9249 * ) }
9250 * </p>
9251 * );
9252 * };
9253 * ```
9254 *
9255 * @return {?*} Block support value
9256 */
9257 const selectors_getBlockSupport = (state, nameOrType, feature, defaultSupports) => {
9258 const blockType = getNormalizedBlockType(state, nameOrType);
9259 if (!blockType?.supports) {
9260 return defaultSupports;
9261 }
9262 return getValueFromObjectPath(blockType.supports, feature, defaultSupports);
9263 };
9264
9265 /**
9266 * Returns true if the block defines support for a feature, or false otherwise.
9267 *
9268 * @param {Object} state Data state.
9269 * @param {(string|Object)} nameOrType Block name or type object.
9270 * @param {string} feature Feature to test.
9271 * @param {boolean} defaultSupports Whether feature is supported by
9272 * default if not explicitly defined.
9273 *
9274 * @example
9275 * ```js
9276 * import { __, sprintf } from '@wordpress/i18n';
9277 * import { store as blocksStore } from '@wordpress/blocks';
9278 * import { useSelect } from '@wordpress/data';
9279 *
9280 * const ExampleComponent = () => {
9281 * const paragraphBlockSupportClassName = useSelect( ( select ) =>
9282 * select( blocksStore ).hasBlockSupport( 'core/paragraph', 'className' ),
9283 * []
9284 * );
9285 *
9286 * return (
9287 * <p>
9288 * { sprintf(
9289 * __( 'core/paragraph supports custom class name?: %s' ),
9290 * paragraphBlockSupportClassName
9291 * ) }
9292 * /p>
9293 * );
9294 * };
9295 * ```
9296 *
9297 * @return {boolean} Whether block supports feature.
9298 */
9299 function selectors_hasBlockSupport(state, nameOrType, feature, defaultSupports) {
9300 return !!selectors_getBlockSupport(state, nameOrType, feature, defaultSupports);
9301 }
9302
9303 /**
9304 * Normalizes a search term string: removes accents, converts to lowercase, removes extra whitespace.
9305 *
9306 * @param {string|null|undefined} term Search term to normalize.
9307 * @return {string} Normalized search term.
9308 */
9309 function getNormalizedSearchTerm(term) {
9310 return remove_accents_default()(term !== null && term !== void 0 ? term : '').toLowerCase().trim();
9311 }
9312
9313 /**
9314 * Returns true if the block type by the given name or object value matches a
9315 * search term, or false otherwise.
9316 *
9317 * @param {Object} state Blocks state.
9318 * @param {(string|Object)} nameOrType Block name or type object.
9319 * @param {string} searchTerm Search term by which to filter.
9320 *
9321 * @example
9322 * ```js
9323 * import { __, sprintf } from '@wordpress/i18n';
9324 * import { store as blocksStore } from '@wordpress/blocks';
9325 * import { useSelect } from '@wordpress/data';
9326 *
9327 * const ExampleComponent = () => {
9328 * const termFound = useSelect(
9329 * ( select ) =>
9330 * select( blocksStore ).isMatchingSearchTerm(
9331 * 'core/navigation',
9332 * 'theme'
9333 * ),
9334 * []
9335 * );
9336 *
9337 * return (
9338 * <p>
9339 * { sprintf(
9340 * __(
9341 * 'Search term was found in the title, keywords, category or description in block.json: %s'
9342 * ),
9343 * termFound
9344 * ) }
9345 * </p>
9346 * );
9347 * };
9348 * ```
9349 *
9350 * @return {Object[]} Whether block type matches search term.
9351 */
9352 function isMatchingSearchTerm(state, nameOrType, searchTerm = '') {
9353 const blockType = getNormalizedBlockType(state, nameOrType);
9354 const normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
9355 const isSearchMatch = candidate => getNormalizedSearchTerm(candidate).includes(normalizedSearchTerm);
9356 return isSearchMatch(blockType.title) || blockType.keywords?.some(isSearchMatch) || isSearchMatch(blockType.category) || typeof blockType.description === 'string' && isSearchMatch(blockType.description);
9357 }
9358
9359 /**
9360 * Returns a boolean indicating if a block has child blocks or not.
9361 *
9362 * @param {Object} state Data state.
9363 * @param {string} blockName Block type name.
9364 *
9365 * @example
9366 * ```js
9367 * import { __, sprintf } from '@wordpress/i18n';
9368 * import { store as blocksStore } from '@wordpress/blocks';
9369 * import { useSelect } from '@wordpress/data';
9370 *
9371 * const ExampleComponent = () => {
9372 * const navigationBlockHasChildBlocks = useSelect( ( select ) =>
9373 * select( blocksStore ).hasChildBlocks( 'core/navigation' ),
9374 * []
9375 * );
9376 *
9377 * return (
9378 * <p>
9379 * { sprintf(
9380 * __( 'core/navigation has child blocks: %s' ),
9381 * navigationBlockHasChildBlocks
9382 * ) }
9383 * </p>
9384 * );
9385 * };
9386 * ```
9387 *
9388 * @return {boolean} True if a block contains child blocks and false otherwise.
9389 */
9390 const selectors_hasChildBlocks = (state, blockName) => {
9391 return selectors_getChildBlockNames(state, blockName).length > 0;
9392 };
9393
9394 /**
9395 * Returns a boolean indicating if a block has at least one child block with inserter support.
9396 *
9397 * @param {Object} state Data state.
9398 * @param {string} blockName Block type name.
9399 *
9400 * @example
9401 * ```js
9402 * import { __, sprintf } from '@wordpress/i18n';
9403 * import { store as blocksStore } from '@wordpress/blocks';
9404 * import { useSelect } from '@wordpress/data';
9405 *
9406 * const ExampleComponent = () => {
9407 * const navigationBlockHasChildBlocksWithInserterSupport = useSelect( ( select ) =>
9408 * select( blocksStore ).hasChildBlocksWithInserterSupport(
9409 * 'core/navigation'
9410 * ),
9411 * []
9412 * );
9413 *
9414 * return (
9415 * <p>
9416 * { sprintf(
9417 * __( 'core/navigation has child blocks with inserter support: %s' ),
9418 * navigationBlockHasChildBlocksWithInserterSupport
9419 * ) }
9420 * </p>
9421 * );
9422 * };
9423 * ```
9424 *
9425 * @return {boolean} True if a block contains at least one child blocks with inserter support
9426 * and false otherwise.
9427 */
9428 const selectors_hasChildBlocksWithInserterSupport = (state, blockName) => {
9429 return selectors_getChildBlockNames(state, blockName).some(childBlockName => {
9430 return selectors_hasBlockSupport(state, childBlockName, 'inserter', true);
9431 });
9432 };
9433 const __experimentalHasContentRoleAttribute = (...args) => {
9434 external_wp_deprecated_default()('__experimentalHasContentRoleAttribute', {
9435 since: '6.7',
9436 version: '6.8',
9437 hint: 'This is a private selector.'
9438 });
9439 return hasContentRoleAttribute(...args);
9440 };
9441
9442 ;// ./node_modules/is-plain-object/dist/is-plain-object.mjs
9443 /*!
9444 * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
9445 *
9446 * Copyright (c) 2014-2017, Jon Schlinkert.
9447 * Released under the MIT License.
9448 */
9449
9450 function is_plain_object_isObject(o) {
9451 return Object.prototype.toString.call(o) === '[object Object]';
9452 }
9453
9454 function isPlainObject(o) {
9455 var ctor,prot;
9456
9457 if (is_plain_object_isObject(o) === false) return false;
9458
9459 // If has modified constructor
9460 ctor = o.constructor;
9461 if (ctor === undefined) return true;
9462
9463 // If has modified prototype
9464 prot = ctor.prototype;
9465 if (is_plain_object_isObject(prot) === false) return false;
9466
9467 // If constructor does not have an Object-specific method
9468 if (prot.hasOwnProperty('isPrototypeOf') === false) {
9469 return false;
9470 }
9471
9472 // Most likely a plain Object
9473 return true;
9474 }
9475
9476
9477
9478 // EXTERNAL MODULE: ./packages/blocks/node_modules/react-is/index.js
9479 var react_is = __webpack_require__(4398);
9480 ;// external ["wp","hooks"]
9481 const external_wp_hooks_namespaceObject = window["wp"]["hooks"];
9482 ;// ./packages/blocks/build-module/store/process-block-type.js
9483 /**
9484 * External dependencies
9485 */
9486
9487
9488
9489 /**
9490 * WordPress dependencies
9491 */
9492
9493
9494
9495
9496 /**
9497 * Internal dependencies
9498 */
9499
9500
9501
9502 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9503
9504 /**
9505 * Mapping of legacy category slugs to their latest normal values, used to
9506 * accommodate updates of the default set of block categories.
9507 *
9508 * @type {Record<string,string>}
9509 */
9510 const LEGACY_CATEGORY_MAPPING = {
9511 common: 'text',
9512 formatting: 'text',
9513 layout: 'design'
9514 };
9515
9516 /**
9517 * Merge block variations bootstrapped from the server and client.
9518 *
9519 * When a variation is registered in both places, its properties are merged.
9520 *
9521 * @param {Array} bootstrappedVariations - A block type variations from the server.
9522 * @param {Array} clientVariations - A block type variations from the client.
9523 * @return {Array} The merged array of block variations.
9524 */
9525 function mergeBlockVariations(bootstrappedVariations = [], clientVariations = []) {
9526 const result = [...bootstrappedVariations];
9527 clientVariations.forEach(clientVariation => {
9528 const index = result.findIndex(bootstrappedVariation => bootstrappedVariation.name === clientVariation.name);
9529 if (index !== -1) {
9530 result[index] = {
9531 ...result[index],
9532 ...clientVariation
9533 };
9534 } else {
9535 result.push(clientVariation);
9536 }
9537 });
9538 return result;
9539 }
9540
9541 /**
9542 * Takes the unprocessed block type settings, merges them with block type metadata
9543 * and applies all the existing filters for the registered block type.
9544 * Next, it validates all the settings and performs additional processing to the block type definition.
9545 *
9546 * @param {string} name Block name.
9547 * @param {WPBlockType} blockSettings Unprocessed block type settings.
9548 *
9549 * @return {WPBlockType | undefined} The block, if it has been processed and can be registered; otherwise `undefined`.
9550 */
9551 const processBlockType = (name, blockSettings) => ({
9552 select
9553 }) => {
9554 const bootstrappedBlockType = select.getBootstrappedBlockType(name);
9555 const blockType = {
9556 name,
9557 icon: BLOCK_ICON_DEFAULT,
9558 keywords: [],
9559 attributes: {},
9560 providesContext: {},
9561 usesContext: [],
9562 selectors: {},
9563 supports: {},
9564 styles: [],
9565 blockHooks: {},
9566 save: () => null,
9567 ...bootstrappedBlockType,
9568 ...blockSettings,
9569 // blockType.variations can be defined as a filePath.
9570 variations: mergeBlockVariations(Array.isArray(bootstrappedBlockType?.variations) ? bootstrappedBlockType.variations : [], Array.isArray(blockSettings?.variations) ? blockSettings.variations : [])
9571 };
9572 const settings = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', blockType, name, null);
9573 if (settings.description && typeof settings.description !== 'string') {
9574 external_wp_deprecated_default()('Declaring non-string block descriptions', {
9575 since: '6.2'
9576 });
9577 }
9578 if (settings.deprecated) {
9579 settings.deprecated = settings.deprecated.map(deprecation => Object.fromEntries(Object.entries(
9580 // Only keep valid deprecation keys.
9581 (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType',
9582 // Merge deprecation keys with pre-filter settings
9583 // so that filters that depend on specific keys being
9584 // present don't fail.
9585 {
9586 // Omit deprecation keys here so that deprecations
9587 // can opt out of specific keys like "supports".
9588 ...omit(blockType, DEPRECATED_ENTRY_KEYS),
9589 ...deprecation
9590 }, blockType.name, deprecation)).filter(([key]) => DEPRECATED_ENTRY_KEYS.includes(key))));
9591 }
9592 if (!isPlainObject(settings)) {
9593 false ? 0 : void 0;
9594 return;
9595 }
9596 if (typeof settings.save !== 'function') {
9597 false ? 0 : void 0;
9598 return;
9599 }
9600 if ('edit' in settings && !(0,react_is.isValidElementType)(settings.edit)) {
9601 false ? 0 : void 0;
9602 return;
9603 }
9604
9605 // Canonicalize legacy categories to equivalent fallback.
9606 if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) {
9607 settings.category = LEGACY_CATEGORY_MAPPING[settings.category];
9608 }
9609 if ('category' in settings && !select.getCategories().some(({
9610 slug
9611 }) => slug === settings.category)) {
9612 false ? 0 : void 0;
9613 delete settings.category;
9614 }
9615 if (!('title' in settings) || settings.title === '') {
9616 false ? 0 : void 0;
9617 return;
9618 }
9619 if (typeof settings.title !== 'string') {
9620 false ? 0 : void 0;
9621 return;
9622 }
9623 settings.icon = normalizeIconObject(settings.icon);
9624 if (!isValidIcon(settings.icon.src)) {
9625 false ? 0 : void 0;
9626 return;
9627 }
9628 if (typeof settings?.parent === 'string' || settings?.parent instanceof String) {
9629 settings.parent = [settings.parent];
9630 false ? 0 : void 0;
9631 // Intentionally continue:
9632 //
9633 // While string values were never supported, they appeared to work with some unintended side-effects
9634 // that have been fixed by [#66250](https://github.com/WordPress/gutenberg/pull/66250).
9635 //
9636 // To be backwards-compatible, this code that automatically migrates strings to arrays.
9637 }
9638 if (!Array.isArray(settings?.parent) && settings?.parent !== undefined) {
9639 false ? 0 : void 0;
9640 return;
9641 }
9642 if (1 === settings?.parent?.length && name === settings.parent[0]) {
9643 false ? 0 : void 0;
9644 return;
9645 }
9646 return settings;
9647 };
9648
9649 ;// ./packages/blocks/build-module/store/actions.js
9650 /**
9651 * WordPress dependencies
9652 */
9653
9654
9655 /**
9656 * Internal dependencies
9657 */
9658
9659
9660 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
9661 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9662 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
9663
9664 /**
9665 * Returns an action object used in signalling that block types have been added.
9666 * Ignored from documentation as the recommended usage for this action through registerBlockType from @wordpress/blocks.
9667 *
9668 * @ignore
9669 *
9670 * @param {WPBlockType|WPBlockType[]} blockTypes Object or array of objects representing blocks to added.
9671 *
9672 *
9673 * @return {Object} Action object.
9674 */
9675 function addBlockTypes(blockTypes) {
9676 return {
9677 type: 'ADD_BLOCK_TYPES',
9678 blockTypes: Array.isArray(blockTypes) ? blockTypes : [blockTypes]
9679 };
9680 }
9681
9682 /**
9683 * Signals that all block types should be computed again.
9684 * It uses stored unprocessed block types and all the most recent list of registered filters.
9685 *
9686 * It addresses the issue where third party block filters get registered after third party blocks. A sample sequence:
9687 * 1. Filter A.
9688 * 2. Block B.
9689 * 3. Block C.
9690 * 4. Filter D.
9691 * 5. Filter E.
9692 * 6. Block F.
9693 * 7. Filter G.
9694 * In this scenario some filters would not get applied for all blocks because they are registered too late.
9695 */
9696 function reapplyBlockTypeFilters() {
9697 return ({
9698 dispatch,
9699 select
9700 }) => {
9701 const processedBlockTypes = [];
9702 for (const [name, settings] of Object.entries(select.getUnprocessedBlockTypes())) {
9703 const result = dispatch(processBlockType(name, settings));
9704 if (result) {
9705 processedBlockTypes.push(result);
9706 }
9707 }
9708 if (!processedBlockTypes.length) {
9709 return;
9710 }
9711 dispatch.addBlockTypes(processedBlockTypes);
9712 };
9713 }
9714 function __experimentalReapplyBlockFilters() {
9715 external_wp_deprecated_default()('wp.data.dispatch( "core/blocks" ).__experimentalReapplyBlockFilters', {
9716 since: '6.4',
9717 alternative: 'reapplyBlockFilters'
9718 });
9719 return reapplyBlockTypeFilters();
9720 }
9721
9722 /**
9723 * Returns an action object used to remove a registered block type.
9724 * Ignored from documentation as the recommended usage for this action through unregisterBlockType from @wordpress/blocks.
9725 *
9726 * @ignore
9727 *
9728 * @param {string|string[]} names Block name or array of block names to be removed.
9729 *
9730 *
9731 * @return {Object} Action object.
9732 */
9733 function removeBlockTypes(names) {
9734 return {
9735 type: 'REMOVE_BLOCK_TYPES',
9736 names: Array.isArray(names) ? names : [names]
9737 };
9738 }
9739
9740 /**
9741 * Returns an action object used in signalling that new block styles have been added.
9742 * Ignored from documentation as the recommended usage for this action through registerBlockStyle from @wordpress/blocks.
9743 *
9744 * @param {string|Array} blockNames Block names to register new styles for.
9745 * @param {Array|Object} styles Block style object or array of block style objects.
9746 *
9747 * @ignore
9748 *
9749 * @return {Object} Action object.
9750 */
9751 function addBlockStyles(blockNames, styles) {
9752 return {
9753 type: 'ADD_BLOCK_STYLES',
9754 styles: Array.isArray(styles) ? styles : [styles],
9755 blockNames: Array.isArray(blockNames) ? blockNames : [blockNames]
9756 };
9757 }
9758
9759 /**
9760 * Returns an action object used in signalling that block styles have been removed.
9761 * Ignored from documentation as the recommended usage for this action through unregisterBlockStyle from @wordpress/blocks.
9762 *
9763 * @ignore
9764 *
9765 * @param {string} blockName Block name.
9766 * @param {Array|string} styleNames Block style names or array of block style names.
9767 *
9768 * @return {Object} Action object.
9769 */
9770 function removeBlockStyles(blockName, styleNames) {
9771 return {
9772 type: 'REMOVE_BLOCK_STYLES',
9773 styleNames: Array.isArray(styleNames) ? styleNames : [styleNames],
9774 blockName
9775 };
9776 }
9777
9778 /**
9779 * Returns an action object used in signalling that new block variations have been added.
9780 * Ignored from documentation as the recommended usage for this action through registerBlockVariation from @wordpress/blocks.
9781 *
9782 * @ignore
9783 *
9784 * @param {string} blockName Block name.
9785 * @param {WPBlockVariation|WPBlockVariation[]} variations Block variations.
9786 *
9787 * @return {Object} Action object.
9788 */
9789 function addBlockVariations(blockName, variations) {
9790 return {
9791 type: 'ADD_BLOCK_VARIATIONS',
9792 variations: Array.isArray(variations) ? variations : [variations],
9793 blockName
9794 };
9795 }
9796
9797 /**
9798 * Returns an action object used in signalling that block variations have been removed.
9799 * Ignored from documentation as the recommended usage for this action through unregisterBlockVariation from @wordpress/blocks.
9800 *
9801 * @ignore
9802 *
9803 * @param {string} blockName Block name.
9804 * @param {string|string[]} variationNames Block variation names.
9805 *
9806 * @return {Object} Action object.
9807 */
9808 function removeBlockVariations(blockName, variationNames) {
9809 return {
9810 type: 'REMOVE_BLOCK_VARIATIONS',
9811 variationNames: Array.isArray(variationNames) ? variationNames : [variationNames],
9812 blockName
9813 };
9814 }
9815
9816 /**
9817 * Returns an action object used to set the default block name.
9818 * Ignored from documentation as the recommended usage for this action through setDefaultBlockName from @wordpress/blocks.
9819 *
9820 * @ignore
9821 *
9822 * @param {string} name Block name.
9823 *
9824 * @return {Object} Action object.
9825 */
9826 function actions_setDefaultBlockName(name) {
9827 return {
9828 type: 'SET_DEFAULT_BLOCK_NAME',
9829 name
9830 };
9831 }
9832
9833 /**
9834 * Returns an action object used to set the name of the block used as a fallback
9835 * for non-block content.
9836 * Ignored from documentation as the recommended usage for this action through setFreeformContentHandlerName from @wordpress/blocks.
9837 *
9838 * @ignore
9839 *
9840 * @param {string} name Block name.
9841 *
9842 * @return {Object} Action object.
9843 */
9844 function setFreeformFallbackBlockName(name) {
9845 return {
9846 type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
9847 name
9848 };
9849 }
9850
9851 /**
9852 * Returns an action object used to set the name of the block used as a fallback
9853 * for unregistered blocks.
9854 * Ignored from documentation as the recommended usage for this action through setUnregisteredTypeHandlerName from @wordpress/blocks.
9855 *
9856 * @ignore
9857 *
9858 * @param {string} name Block name.
9859 *
9860 * @return {Object} Action object.
9861 */
9862 function setUnregisteredFallbackBlockName(name) {
9863 return {
9864 type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
9865 name
9866 };
9867 }
9868
9869 /**
9870 * Returns an action object used to set the name of the block used
9871 * when grouping other blocks
9872 * eg: in "Group/Ungroup" interactions
9873 * Ignored from documentation as the recommended usage for this action through setGroupingBlockName from @wordpress/blocks.
9874 *
9875 * @ignore
9876 *
9877 * @param {string} name Block name.
9878 *
9879 * @return {Object} Action object.
9880 */
9881 function actions_setGroupingBlockName(name) {
9882 return {
9883 type: 'SET_GROUPING_BLOCK_NAME',
9884 name
9885 };
9886 }
9887
9888 /**
9889 * Returns an action object used to set block categories.
9890 * Ignored from documentation as the recommended usage for this action through setCategories from @wordpress/blocks.
9891 *
9892 * @ignore
9893 *
9894 * @param {WPBlockCategory[]} categories Block categories.
9895 *
9896 * @return {Object} Action object.
9897 */
9898 function setCategories(categories) {
9899 return {
9900 type: 'SET_CATEGORIES',
9901 categories
9902 };
9903 }
9904
9905 /**
9906 * Returns an action object used to update a category.
9907 * Ignored from documentation as the recommended usage for this action through updateCategory from @wordpress/blocks.
9908 *
9909 * @ignore
9910 *
9911 * @param {string} slug Block category slug.
9912 * @param {Object} category Object containing the category properties that should be updated.
9913 *
9914 * @return {Object} Action object.
9915 */
9916 function updateCategory(slug, category) {
9917 return {
9918 type: 'UPDATE_CATEGORY',
9919 slug,
9920 category
9921 };
9922 }
9923
9924 /**
9925 * Returns an action object used to add block collections
9926 * Ignored from documentation as the recommended usage for this action through registerBlockCollection from @wordpress/blocks.
9927 *
9928 * @ignore
9929 *
9930 * @param {string} namespace The namespace of the blocks to put in the collection
9931 * @param {string} title The title to display in the block inserter
9932 * @param {Object} icon (optional) The icon to display in the block inserter
9933 *
9934 * @return {Object} Action object.
9935 */
9936 function addBlockCollection(namespace, title, icon) {
9937 return {
9938 type: 'ADD_BLOCK_COLLECTION',
9939 namespace,
9940 title,
9941 icon
9942 };
9943 }
9944
9945 /**
9946 * Returns an action object used to remove block collections
9947 * Ignored from documentation as the recommended usage for this action through unregisterBlockCollection from @wordpress/blocks.
9948 *
9949 * @ignore
9950 *
9951 * @param {string} namespace The namespace of the blocks to put in the collection
9952 *
9953 * @return {Object} Action object.
9954 */
9955 function removeBlockCollection(namespace) {
9956 return {
9957 type: 'REMOVE_BLOCK_COLLECTION',
9958 namespace
9959 };
9960 }
9961
9962 ;// ./packages/blocks/build-module/store/private-actions.js
9963 /**
9964 * Internal dependencies
9965 */
9966
9967
9968 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9969
9970 /**
9971 * Add bootstrapped block type metadata to the store. These metadata usually come from
9972 * the `block.json` file and are either statically boostrapped from the server, or
9973 * passed as the `metadata` parameter to the `registerBlockType` function.
9974 *
9975 * @param {string} name Block name.
9976 * @param {WPBlockType} blockType Block type metadata.
9977 */
9978 function addBootstrappedBlockType(name, blockType) {
9979 return {
9980 type: 'ADD_BOOTSTRAPPED_BLOCK_TYPE',
9981 name,
9982 blockType
9983 };
9984 }
9985
9986 /**
9987 * Add unprocessed block type settings to the store. These data are passed as the
9988 * `settings` parameter to the client-side `registerBlockType` function.
9989 *
9990 * @param {string} name Block name.
9991 * @param {WPBlockType} blockType Unprocessed block type settings.
9992 */
9993 function addUnprocessedBlockType(name, blockType) {
9994 return ({
9995 dispatch
9996 }) => {
9997 dispatch({
9998 type: 'ADD_UNPROCESSED_BLOCK_TYPE',
9999 name,
10000 blockType
10001 });
10002 const processedBlockType = dispatch(processBlockType(name, blockType));
10003 if (!processedBlockType) {
10004 return;
10005 }
10006 dispatch.addBlockTypes(processedBlockType);
10007 };
10008 }
10009
10010 /**
10011 * Adds new block bindings source.
10012 *
10013 * @param {string} source Name of the source to register.
10014 */
10015 function addBlockBindingsSource(source) {
10016 return {
10017 type: 'ADD_BLOCK_BINDINGS_SOURCE',
10018 name: source.name,
10019 label: source.label,
10020 usesContext: source.usesContext,
10021 getValues: source.getValues,
10022 setValues: source.setValues,
10023 canUserEditValue: source.canUserEditValue,
10024 getFieldsList: source.getFieldsList
10025 };
10026 }
10027
10028 /**
10029 * Removes existing block bindings source.
10030 *
10031 * @param {string} name Name of the source to remove.
10032 */
10033 function removeBlockBindingsSource(name) {
10034 return {
10035 type: 'REMOVE_BLOCK_BINDINGS_SOURCE',
10036 name
10037 };
10038 }
10039
10040 ;// ./packages/blocks/build-module/store/constants.js
10041 const STORE_NAME = 'core/blocks';
10042
10043 ;// ./packages/blocks/build-module/store/index.js
10044 /**
10045 * WordPress dependencies
10046 */
10047
10048
10049 /**
10050 * Internal dependencies
10051 */
10052
10053
10054
10055
10056
10057
10058
10059
10060 /**
10061 * Store definition for the blocks namespace.
10062 *
10063 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
10064 *
10065 * @type {Object}
10066 */
10067 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
10068 reducer: reducer,
10069 selectors: selectors_namespaceObject,
10070 actions: actions_namespaceObject
10071 });
10072 (0,external_wp_data_namespaceObject.register)(store);
10073 unlock(store).registerPrivateSelectors(private_selectors_namespaceObject);
10074 unlock(store).registerPrivateActions(private_actions_namespaceObject);
10075
10076 ;// ./packages/blocks/node_modules/uuid/dist/esm-browser/rng.js
10077 // Unique ID creation requires a high quality random # generator. In the browser we therefore
10078 // require the crypto API and do not support built-in fallback to lower quality random number
10079 // generators (like Math.random()).
10080 var getRandomValues;
10081 var rnds8 = new Uint8Array(16);
10082 function rng() {
10083 // lazy load so that environments that need to polyfill have a chance to do so
10084 if (!getRandomValues) {
10085 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
10086 // find the complete implementation of crypto (msCrypto) on IE11.
10087 getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
10088
10089 if (!getRandomValues) {
10090 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
10091 }
10092 }
10093
10094 return getRandomValues(rnds8);
10095 }
10096 ;// ./packages/blocks/node_modules/uuid/dist/esm-browser/regex.js
10097 /* 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);
10098 ;// ./packages/blocks/node_modules/uuid/dist/esm-browser/validate.js
10099
10100
10101 function validate(uuid) {
10102 return typeof uuid === 'string' && regex.test(uuid);
10103 }
10104
10105 /* harmony default export */ const esm_browser_validate = (validate);
10106 ;// ./packages/blocks/node_modules/uuid/dist/esm-browser/stringify.js
10107
10108 /**
10109 * Convert array of 16 byte values to UUID string format of the form:
10110 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
10111 */
10112
10113 var byteToHex = [];
10114
10115 for (var stringify_i = 0; stringify_i < 256; ++stringify_i) {
10116 byteToHex.push((stringify_i + 0x100).toString(16).substr(1));
10117 }
10118
10119 function stringify(arr) {
10120 var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
10121 // Note: Be careful editing this code! It's been tuned for performance
10122 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
10123 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
10124 // of the following:
10125 // - One or more input array values don't map to a hex octet (leading to
10126 // "undefined" in the uuid)
10127 // - Invalid input values for the RFC `version` or `variant` fields
10128
10129 if (!esm_browser_validate(uuid)) {
10130 throw TypeError('Stringified UUID is invalid');
10131 }
10132
10133 return uuid;
10134 }
10135
10136 /* harmony default export */ const esm_browser_stringify = (stringify);
10137 ;// ./packages/blocks/node_modules/uuid/dist/esm-browser/v4.js
10138
10139
10140
10141 function v4(options, buf, offset) {
10142 options = options || {};
10143 var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
10144
10145 rnds[6] = rnds[6] & 0x0f | 0x40;
10146 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
10147
10148 if (buf) {
10149 offset = offset || 0;
10150
10151 for (var i = 0; i < 16; ++i) {
10152 buf[offset + i] = rnds[i];
10153 }
10154
10155 return buf;
10156 }
10157
10158 return esm_browser_stringify(rnds);
10159 }
10160
10161 /* harmony default export */ const esm_browser_v4 = (v4);
10162 ;// ./packages/blocks/build-module/api/factory.js
10163 /* wp:polyfill */
10164 /**
10165 * External dependencies
10166 */
10167
10168
10169 /**
10170 * WordPress dependencies
10171 */
10172
10173
10174 /**
10175 * Internal dependencies
10176 */
10177
10178
10179
10180 /**
10181 * Returns a block object given its type and attributes.
10182 *
10183 * @param {string} name Block name.
10184 * @param {Object} attributes Block attributes.
10185 * @param {?Array} innerBlocks Nested blocks.
10186 *
10187 * @return {Object} Block object.
10188 */
10189 function createBlock(name, attributes = {}, innerBlocks = []) {
10190 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, attributes);
10191 const clientId = esm_browser_v4();
10192
10193 // Blocks are stored with a unique ID, the assigned type name, the block
10194 // attributes, and their inner blocks.
10195 return {
10196 clientId,
10197 name,
10198 isValid: true,
10199 attributes: sanitizedAttributes,
10200 innerBlocks
10201 };
10202 }
10203
10204 /**
10205 * Given an array of InnerBlocks templates or Block Objects,
10206 * returns an array of created Blocks from them.
10207 * It handles the case of having InnerBlocks as Blocks by
10208 * converting them to the proper format to continue recursively.
10209 *
10210 * @param {Array} innerBlocksOrTemplate Nested blocks or InnerBlocks templates.
10211 *
10212 * @return {Object[]} Array of Block objects.
10213 */
10214 function createBlocksFromInnerBlocksTemplate(innerBlocksOrTemplate = []) {
10215 return innerBlocksOrTemplate.map(innerBlock => {
10216 const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [innerBlock.name, innerBlock.attributes, innerBlock.innerBlocks];
10217 const [name, attributes, innerBlocks = []] = innerBlockTemplate;
10218 return createBlock(name, attributes, createBlocksFromInnerBlocksTemplate(innerBlocks));
10219 });
10220 }
10221
10222 /**
10223 * Given a block object, returns a copy of the block object while sanitizing its attributes,
10224 * optionally merging new attributes and/or replacing its inner blocks.
10225 *
10226 * @param {Object} block Block instance.
10227 * @param {Object} mergeAttributes Block attributes.
10228 * @param {?Array} newInnerBlocks Nested blocks.
10229 *
10230 * @return {Object} A cloned block.
10231 */
10232 function __experimentalCloneSanitizedBlock(block, mergeAttributes = {}, newInnerBlocks) {
10233 const clientId = esm_browser_v4();
10234 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(block.name, {
10235 ...block.attributes,
10236 ...mergeAttributes
10237 });
10238 return {
10239 ...block,
10240 clientId,
10241 attributes: sanitizedAttributes,
10242 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => __experimentalCloneSanitizedBlock(innerBlock))
10243 };
10244 }
10245
10246 /**
10247 * Given a block object, returns a copy of the block object,
10248 * optionally merging new attributes and/or replacing its inner blocks.
10249 *
10250 * @param {Object} block Block instance.
10251 * @param {Object} mergeAttributes Block attributes.
10252 * @param {?Array} newInnerBlocks Nested blocks.
10253 *
10254 * @return {Object} A cloned block.
10255 */
10256 function cloneBlock(block, mergeAttributes = {}, newInnerBlocks) {
10257 const clientId = esm_browser_v4();
10258 return {
10259 ...block,
10260 clientId,
10261 attributes: {
10262 ...block.attributes,
10263 ...mergeAttributes
10264 },
10265 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => cloneBlock(innerBlock))
10266 };
10267 }
10268
10269 /**
10270 * Returns a boolean indicating whether a transform is possible based on
10271 * various bits of context.
10272 *
10273 * @param {Object} transform The transform object to validate.
10274 * @param {string} direction Is this a 'from' or 'to' transform.
10275 * @param {Array} blocks The blocks to transform from.
10276 *
10277 * @return {boolean} Is the transform possible?
10278 */
10279 const isPossibleTransformForSource = (transform, direction, blocks) => {
10280 if (!blocks.length) {
10281 return false;
10282 }
10283
10284 // If multiple blocks are selected, only multi block transforms
10285 // or wildcard transforms are allowed.
10286 const isMultiBlock = blocks.length > 1;
10287 const firstBlockName = blocks[0].name;
10288 const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
10289 if (!isValidForMultiBlocks) {
10290 return false;
10291 }
10292
10293 // Check non-wildcard transforms to ensure that transform is valid
10294 // for a block selection of multiple blocks of different types.
10295 if (!isWildcardBlockTransform(transform) && !blocks.every(block => block.name === firstBlockName)) {
10296 return false;
10297 }
10298
10299 // Only consider 'block' type transforms as valid.
10300 const isBlockType = transform.type === 'block';
10301 if (!isBlockType) {
10302 return false;
10303 }
10304
10305 // Check if the transform's block name matches the source block (or is a wildcard)
10306 // only if this is a transform 'from'.
10307 const sourceBlock = blocks[0];
10308 const hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
10309 if (!hasMatchingName) {
10310 return false;
10311 }
10312
10313 // Don't allow single Grouping blocks to be transformed into
10314 // a Grouping block.
10315 if (!isMultiBlock && direction === 'from' && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
10316 return false;
10317 }
10318
10319 // If the transform has a `isMatch` function specified, check that it returns true.
10320 if (!maybeCheckTransformIsMatch(transform, blocks)) {
10321 return false;
10322 }
10323 return true;
10324 };
10325
10326 /**
10327 * Returns block types that the 'blocks' can be transformed into, based on
10328 * 'from' transforms on other blocks.
10329 *
10330 * @param {Array} blocks The blocks to transform from.
10331 *
10332 * @return {Array} Block types that the blocks can be transformed into.
10333 */
10334 const getBlockTypesForPossibleFromTransforms = blocks => {
10335 if (!blocks.length) {
10336 return [];
10337 }
10338 const allBlockTypes = getBlockTypes();
10339
10340 // filter all blocks to find those with a 'from' transform.
10341 const blockTypesWithPossibleFromTransforms = allBlockTypes.filter(blockType => {
10342 const fromTransforms = getBlockTransforms('from', blockType.name);
10343 return !!findTransform(fromTransforms, transform => {
10344 return isPossibleTransformForSource(transform, 'from', blocks);
10345 });
10346 });
10347 return blockTypesWithPossibleFromTransforms;
10348 };
10349
10350 /**
10351 * Returns block types that the 'blocks' can be transformed into, based on
10352 * the source block's own 'to' transforms.
10353 *
10354 * @param {Array} blocks The blocks to transform from.
10355 *
10356 * @return {Array} Block types that the source can be transformed into.
10357 */
10358 const getBlockTypesForPossibleToTransforms = blocks => {
10359 if (!blocks.length) {
10360 return [];
10361 }
10362 const sourceBlock = blocks[0];
10363 const blockType = getBlockType(sourceBlock.name);
10364 const transformsTo = blockType ? getBlockTransforms('to', blockType.name) : [];
10365
10366 // filter all 'to' transforms to find those that are possible.
10367 const possibleTransforms = transformsTo.filter(transform => {
10368 return transform && isPossibleTransformForSource(transform, 'to', blocks);
10369 });
10370
10371 // Build a list of block names using the possible 'to' transforms.
10372 const blockNames = possibleTransforms.map(transformation => transformation.blocks).flat();
10373
10374 // Map block names to block types.
10375 return blockNames.map(getBlockType);
10376 };
10377
10378 /**
10379 * Determines whether transform is a "block" type
10380 * and if so whether it is a "wildcard" transform
10381 * ie: targets "any" block type
10382 *
10383 * @param {Object} t the Block transform object
10384 *
10385 * @return {boolean} whether transform is a wildcard transform
10386 */
10387 const isWildcardBlockTransform = t => t && t.type === 'block' && Array.isArray(t.blocks) && t.blocks.includes('*');
10388
10389 /**
10390 * Determines whether the given Block is the core Block which
10391 * acts as a container Block for other Blocks as part of the
10392 * Grouping mechanics
10393 *
10394 * @param {string} name the name of the Block to test against
10395 *
10396 * @return {boolean} whether or not the Block is the container Block type
10397 */
10398 const isContainerGroupBlock = name => name === getGroupingBlockName();
10399
10400 /**
10401 * Returns an array of block types that the set of blocks received as argument
10402 * can be transformed into.
10403 *
10404 * @param {Array} blocks Blocks array.
10405 *
10406 * @return {Array} Block types that the blocks argument can be transformed to.
10407 */
10408 function getPossibleBlockTransformations(blocks) {
10409 if (!blocks.length) {
10410 return [];
10411 }
10412 const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
10413 const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
10414 return [...new Set([...blockTypesForFromTransforms, ...blockTypesForToTransforms])];
10415 }
10416
10417 /**
10418 * Given an array of transforms, returns the highest-priority transform where
10419 * the predicate function returns a truthy value. A higher-priority transform
10420 * is one with a lower priority value (i.e. first in priority order). Returns
10421 * null if the transforms set is empty or the predicate function returns a
10422 * falsey value for all entries.
10423 *
10424 * @param {Object[]} transforms Transforms to search.
10425 * @param {Function} predicate Function returning true on matching transform.
10426 *
10427 * @return {?Object} Highest-priority transform candidate.
10428 */
10429 function findTransform(transforms, predicate) {
10430 // The hooks library already has built-in mechanisms for managing priority
10431 // queue, so leverage via locally-defined instance.
10432 const hooks = (0,external_wp_hooks_namespaceObject.createHooks)();
10433 for (let i = 0; i < transforms.length; i++) {
10434 const candidate = transforms[i];
10435 if (predicate(candidate)) {
10436 hooks.addFilter('transform', 'transform/' + i.toString(), result => result ? result : candidate, candidate.priority);
10437 }
10438 }
10439
10440 // Filter name is arbitrarily chosen but consistent with above aggregation.
10441 return hooks.applyFilters('transform', null);
10442 }
10443
10444 /**
10445 * Returns normal block transforms for a given transform direction, optionally
10446 * for a specific block by name, or an empty array if there are no transforms.
10447 * If no block name is provided, returns transforms for all blocks. A normal
10448 * transform object includes `blockName` as a property.
10449 *
10450 * @param {string} direction Transform direction ("to", "from").
10451 * @param {string|Object} blockTypeOrName Block type or name.
10452 *
10453 * @return {Array} Block transforms for direction.
10454 */
10455 function getBlockTransforms(direction, blockTypeOrName) {
10456 // When retrieving transforms for all block types, recurse into self.
10457 if (blockTypeOrName === undefined) {
10458 return getBlockTypes().map(({
10459 name
10460 }) => getBlockTransforms(direction, name)).flat();
10461 }
10462
10463 // Validate that block type exists and has array of direction.
10464 const blockType = normalizeBlockType(blockTypeOrName);
10465 const {
10466 name: blockName,
10467 transforms
10468 } = blockType || {};
10469 if (!transforms || !Array.isArray(transforms[direction])) {
10470 return [];
10471 }
10472 const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
10473 const filteredTransforms = usingMobileTransformations ? transforms[direction].filter(t => {
10474 if (t.type === 'raw') {
10475 return true;
10476 }
10477 if (t.type === 'prefix') {
10478 return true;
10479 }
10480 if (!t.blocks || !t.blocks.length) {
10481 return false;
10482 }
10483 if (isWildcardBlockTransform(t)) {
10484 return true;
10485 }
10486 return t.blocks.every(transformBlockName => transforms.supportedMobileTransforms.includes(transformBlockName));
10487 }) : transforms[direction];
10488
10489 // Map transforms to normal form.
10490 return filteredTransforms.map(transform => ({
10491 ...transform,
10492 blockName,
10493 usingMobileTransformations
10494 }));
10495 }
10496
10497 /**
10498 * Checks that a given transforms isMatch method passes for given source blocks.
10499 *
10500 * @param {Object} transform A transform object.
10501 * @param {Array} blocks Blocks array.
10502 *
10503 * @return {boolean} True if given blocks are a match for the transform.
10504 */
10505 function maybeCheckTransformIsMatch(transform, blocks) {
10506 if (typeof transform.isMatch !== 'function') {
10507 return true;
10508 }
10509 const sourceBlock = blocks[0];
10510 const attributes = transform.isMultiBlock ? blocks.map(block => block.attributes) : sourceBlock.attributes;
10511 const block = transform.isMultiBlock ? blocks : sourceBlock;
10512 return transform.isMatch(attributes, block);
10513 }
10514
10515 /**
10516 * Switch one or more blocks into one or more blocks of the new block type.
10517 *
10518 * @param {Array|Object} blocks Blocks array or block object.
10519 * @param {string} name Block name.
10520 *
10521 * @return {?Array} Array of blocks or null.
10522 */
10523 function switchToBlockType(blocks, name) {
10524 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
10525 const isMultiBlock = blocksArray.length > 1;
10526 const firstBlock = blocksArray[0];
10527 const sourceName = firstBlock.name;
10528
10529 // Find the right transformation by giving priority to the "to"
10530 // transformation.
10531 const transformationsFrom = getBlockTransforms('from', name);
10532 const transformationsTo = getBlockTransforms('to', sourceName);
10533 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));
10534
10535 // Stop if there is no valid transformation.
10536 if (!transformation) {
10537 return null;
10538 }
10539 let transformationResults;
10540 if (transformation.isMultiBlock) {
10541 if ('__experimentalConvert' in transformation) {
10542 transformationResults = transformation.__experimentalConvert(blocksArray);
10543 } else {
10544 transformationResults = transformation.transform(blocksArray.map(currentBlock => currentBlock.attributes), blocksArray.map(currentBlock => currentBlock.innerBlocks));
10545 }
10546 } else if ('__experimentalConvert' in transformation) {
10547 transformationResults = transformation.__experimentalConvert(firstBlock);
10548 } else {
10549 transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
10550 }
10551
10552 // Ensure that the transformation function returned an object or an array
10553 // of objects.
10554 if (transformationResults === null || typeof transformationResults !== 'object') {
10555 return null;
10556 }
10557
10558 // If the transformation function returned a single object, we want to work
10559 // with an array instead.
10560 transformationResults = Array.isArray(transformationResults) ? transformationResults : [transformationResults];
10561
10562 // Ensure that every block object returned by the transformation has a
10563 // valid block type.
10564 if (transformationResults.some(result => !getBlockType(result.name))) {
10565 return null;
10566 }
10567 const hasSwitchedBlock = transformationResults.some(result => result.name === name);
10568
10569 // Ensure that at least one block object returned by the transformation has
10570 // the expected "destination" block type.
10571 if (!hasSwitchedBlock) {
10572 return null;
10573 }
10574 const ret = transformationResults.map((result, index, results) => {
10575 /**
10576 * Filters an individual transform result from block transformation.
10577 * All of the original blocks are passed, since transformations are
10578 * many-to-many, not one-to-one.
10579 *
10580 * @param {Object} transformedBlock The transformed block.
10581 * @param {Object[]} blocks Original blocks transformed.
10582 * @param {Object[]} index Index of the transformed block on the array of results.
10583 * @param {Object[]} results An array all the blocks that resulted from the transformation.
10584 */
10585 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.switchToBlockType.transformedBlock', result, blocks, index, results);
10586 });
10587 return ret;
10588 }
10589
10590 /**
10591 * Create a block object from the example API.
10592 *
10593 * @param {string} name
10594 * @param {Object} example
10595 *
10596 * @return {Object} block.
10597 */
10598 const getBlockFromExample = (name, example) => {
10599 try {
10600 var _example$innerBlocks;
10601 return createBlock(name, example.attributes, ((_example$innerBlocks = example.innerBlocks) !== null && _example$innerBlocks !== void 0 ? _example$innerBlocks : []).map(innerBlock => getBlockFromExample(innerBlock.name, innerBlock)));
10602 } catch {
10603 return createBlock('core/missing', {
10604 originalName: name,
10605 originalContent: '',
10606 originalUndelimitedContent: ''
10607 });
10608 }
10609 };
10610
10611 ;// external ["wp","blockSerializationDefaultParser"]
10612 const external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
10613 ;// external ["wp","autop"]
10614 const external_wp_autop_namespaceObject = window["wp"]["autop"];
10615 ;// external ["wp","isShallowEqual"]
10616 const external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"];
10617 var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject);
10618 ;// ./packages/blocks/build-module/api/parser/serialize-raw-block.js
10619 /**
10620 * Internal dependencies
10621 */
10622
10623
10624 /**
10625 * @typedef {Object} Options Serialization options.
10626 * @property {boolean} [isCommentDelimited=true] Whether to output HTML comments around blocks.
10627 */
10628
10629 /** @typedef {import("./").WPRawBlock} WPRawBlock */
10630
10631 /**
10632 * Serializes a block node into the native HTML-comment-powered block format.
10633 * CAVEAT: This function is intended for re-serializing blocks as parsed by
10634 * valid parsers and skips any validation steps. This is NOT a generic
10635 * serialization function for in-memory blocks. For most purposes, see the
10636 * following functions available in the `@wordpress/blocks` package:
10637 *
10638 * @see serializeBlock
10639 * @see serialize
10640 *
10641 * For more on the format of block nodes as returned by valid parsers:
10642 *
10643 * @see `@wordpress/block-serialization-default-parser` package
10644 * @see `@wordpress/block-serialization-spec-parser` package
10645 *
10646 * @param {WPRawBlock} rawBlock A block node as returned by a valid parser.
10647 * @param {Options} [options={}] Serialization options.
10648 *
10649 * @return {string} An HTML string representing a block.
10650 */
10651 function serializeRawBlock(rawBlock, options = {}) {
10652 const {
10653 isCommentDelimited = true
10654 } = options;
10655 const {
10656 blockName,
10657 attrs = {},
10658 innerBlocks = [],
10659 innerContent = []
10660 } = rawBlock;
10661 let childIndex = 0;
10662 const content = innerContent.map(item =>
10663 // `null` denotes a nested block, otherwise we have an HTML fragment.
10664 item !== null ? item : serializeRawBlock(innerBlocks[childIndex++], options)).join('\n').replace(/\n+/g, '\n').trim();
10665 return isCommentDelimited ? getCommentDelimitedContent(blockName, attrs, content) : content;
10666 }
10667
10668 ;// external "ReactJSXRuntime"
10669 const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
10670 ;// ./packages/blocks/build-module/api/serializer.js
10671 /**
10672 * WordPress dependencies
10673 */
10674
10675
10676
10677
10678
10679
10680 /**
10681 * Internal dependencies
10682 */
10683
10684
10685
10686
10687 /** @typedef {import('./parser').WPBlock} WPBlock */
10688
10689 /**
10690 * @typedef {Object} WPBlockSerializationOptions Serialization Options.
10691 *
10692 * @property {boolean} isInnerBlocks Whether we are serializing inner blocks.
10693 */
10694
10695 /**
10696 * Returns the block's default classname from its name.
10697 *
10698 * @param {string} blockName The block name.
10699 *
10700 * @return {string} The block's default class.
10701 */
10702
10703 function getBlockDefaultClassName(blockName) {
10704 // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
10705 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10706 const className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10707 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockDefaultClassName', className, blockName);
10708 }
10709
10710 /**
10711 * Returns the block's default menu item classname from its name.
10712 *
10713 * @param {string} blockName The block name.
10714 *
10715 * @return {string} The block's default menu item class.
10716 */
10717 function getBlockMenuDefaultClassName(blockName) {
10718 // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
10719 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10720 const className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10721 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockMenuDefaultClassName', className, blockName);
10722 }
10723 const blockPropsProvider = {};
10724 const innerBlocksPropsProvider = {};
10725
10726 /**
10727 * Call within a save function to get the props for the block wrapper.
10728 *
10729 * @param {Object} props Optional. Props to pass to the element.
10730 */
10731 function getBlockProps(props = {}) {
10732 const {
10733 blockType,
10734 attributes
10735 } = blockPropsProvider;
10736 return getBlockProps.skipFilters ? props : (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', {
10737 ...props
10738 }, blockType, attributes);
10739 }
10740
10741 /**
10742 * Call within a save function to get the props for the inner blocks wrapper.
10743 *
10744 * @param {Object} props Optional. Props to pass to the element.
10745 */
10746 function getInnerBlocksProps(props = {}) {
10747 const {
10748 innerBlocks
10749 } = innerBlocksPropsProvider;
10750 // Allow a different component to be passed to getSaveElement to handle
10751 // inner blocks, bypassing the default serialisation.
10752 if (!Array.isArray(innerBlocks)) {
10753 return {
10754 ...props,
10755 children: innerBlocks
10756 };
10757 }
10758 // Value is an array of blocks, so defer to block serializer.
10759 const html = serialize(innerBlocks, {
10760 isInnerBlocks: true
10761 });
10762 // Use special-cased raw HTML tag to avoid default escaping.
10763 const children = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_element_namespaceObject.RawHTML, {
10764 children: html
10765 });
10766 return {
10767 ...props,
10768 children
10769 };
10770 }
10771
10772 /**
10773 * Given a block type containing a save render implementation and attributes, returns the
10774 * enhanced element to be saved or string when raw HTML expected.
10775 *
10776 * @param {string|Object} blockTypeOrName Block type or name.
10777 * @param {Object} attributes Block attributes.
10778 * @param {?Array} innerBlocks Nested blocks.
10779 *
10780 * @return {Object|string} Save element or raw HTML string.
10781 */
10782 function getSaveElement(blockTypeOrName, attributes, innerBlocks = []) {
10783 const blockType = normalizeBlockType(blockTypeOrName);
10784 if (!blockType?.save) {
10785 return null;
10786 }
10787 let {
10788 save
10789 } = blockType;
10790
10791 // Component classes are unsupported for save since serialization must
10792 // occur synchronously. For improved interoperability with higher-order
10793 // components which often return component class, emulate basic support.
10794 if (save.prototype instanceof external_wp_element_namespaceObject.Component) {
10795 const instance = new save({
10796 attributes
10797 });
10798 save = instance.render.bind(instance);
10799 }
10800 blockPropsProvider.blockType = blockType;
10801 blockPropsProvider.attributes = attributes;
10802 innerBlocksPropsProvider.innerBlocks = innerBlocks;
10803 let element = save({
10804 attributes,
10805 innerBlocks
10806 });
10807 if (element !== null && typeof element === 'object' && (0,external_wp_hooks_namespaceObject.hasFilter)('blocks.getSaveContent.extraProps') && !(blockType.apiVersion > 1)) {
10808 /**
10809 * Filters the props applied to the block save result element.
10810 *
10811 * @param {Object} props Props applied to save element.
10812 * @param {WPBlock} blockType Block type definition.
10813 * @param {Object} attributes Block attributes.
10814 */
10815 const props = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', {
10816 ...element.props
10817 }, blockType, attributes);
10818 if (!external_wp_isShallowEqual_default()(props, element.props)) {
10819 element = (0,external_wp_element_namespaceObject.cloneElement)(element, props);
10820 }
10821 }
10822
10823 /**
10824 * Filters the save result of a block during serialization.
10825 *
10826 * @param {Element} element Block save result.
10827 * @param {WPBlock} blockType Block type definition.
10828 * @param {Object} attributes Block attributes.
10829 */
10830 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveElement', element, blockType, attributes);
10831 }
10832
10833 /**
10834 * Given a block type containing a save render implementation and attributes, returns the
10835 * static markup to be saved.
10836 *
10837 * @param {string|Object} blockTypeOrName Block type or name.
10838 * @param {Object} attributes Block attributes.
10839 * @param {?Array} innerBlocks Nested blocks.
10840 *
10841 * @return {string} Save content.
10842 */
10843 function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
10844 const blockType = normalizeBlockType(blockTypeOrName);
10845 return (0,external_wp_element_namespaceObject.renderToString)(getSaveElement(blockType, attributes, innerBlocks));
10846 }
10847
10848 /**
10849 * Returns attributes which are to be saved and serialized into the block
10850 * comment delimiter.
10851 *
10852 * When a block exists in memory it contains as its attributes both those
10853 * parsed the block comment delimiter _and_ those which matched from the
10854 * contents of the block.
10855 *
10856 * This function returns only those attributes which are needed to persist and
10857 * which cannot be matched from the block content.
10858 *
10859 * @param {Object<string,*>} blockType Block type.
10860 * @param {Object<string,*>} attributes Attributes from in-memory block data.
10861 *
10862 * @return {Object<string,*>} Subset of attributes for comment serialization.
10863 */
10864 function getCommentAttributes(blockType, attributes) {
10865 var _blockType$attributes;
10866 return Object.entries((_blockType$attributes = blockType.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}).reduce((accumulator, [key, attributeSchema]) => {
10867 const value = attributes[key];
10868 // Ignore undefined values.
10869 if (undefined === value) {
10870 return accumulator;
10871 }
10872
10873 // Ignore all attributes but the ones with an "undefined" source
10874 // "undefined" source refers to attributes saved in the block comment.
10875 if (attributeSchema.source !== undefined) {
10876 return accumulator;
10877 }
10878
10879 // Ignore all local attributes
10880 if (attributeSchema.role === 'local') {
10881 return accumulator;
10882 }
10883 if (attributeSchema.__experimentalRole === 'local') {
10884 external_wp_deprecated_default()('__experimentalRole attribute', {
10885 since: '6.7',
10886 version: '6.8',
10887 alternative: 'role attribute',
10888 hint: `Check the block.json of the ${blockType?.name} block.`
10889 });
10890 return accumulator;
10891 }
10892
10893 // Ignore default value.
10894 if ('default' in attributeSchema && JSON.stringify(attributeSchema.default) === JSON.stringify(value)) {
10895 return accumulator;
10896 }
10897
10898 // Otherwise, include in comment set.
10899 accumulator[key] = value;
10900 return accumulator;
10901 }, {});
10902 }
10903
10904 /**
10905 * Given an attributes object, returns a string in the serialized attributes
10906 * format prepared for post content.
10907 *
10908 * @param {Object} attributes Attributes object.
10909 *
10910 * @return {string} Serialized attributes.
10911 */
10912 function serializeAttributes(attributes) {
10913 return JSON.stringify(attributes)
10914 // Don't break HTML comments.
10915 .replace(/--/g, '\\u002d\\u002d')
10916
10917 // Don't break non-standard-compliant tools.
10918 .replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026')
10919
10920 // Bypass server stripslashes behavior which would unescape stringify's
10921 // escaping of quotation mark.
10922 //
10923 // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
10924 .replace(/\\"/g, '\\u0022');
10925 }
10926
10927 /**
10928 * Given a block object, returns the Block's Inner HTML markup.
10929 *
10930 * @param {Object} block Block instance.
10931 *
10932 * @return {string} HTML.
10933 */
10934 function getBlockInnerHTML(block) {
10935 // If block was parsed as invalid or encounters an error while generating
10936 // save content, use original content instead to avoid content loss. If a
10937 // block contains nested content, exempt it from this condition because we
10938 // otherwise have no access to its original content and content loss would
10939 // still occur.
10940 let saveContent = block.originalContent;
10941 if (block.isValid || block.innerBlocks.length) {
10942 try {
10943 saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
10944 } catch (error) {}
10945 }
10946 return saveContent;
10947 }
10948
10949 /**
10950 * Returns the content of a block, including comment delimiters.
10951 *
10952 * @param {string} rawBlockName Block name.
10953 * @param {Object} attributes Block attributes.
10954 * @param {string} content Block save content.
10955 *
10956 * @return {string} Comment-delimited block content.
10957 */
10958 function getCommentDelimitedContent(rawBlockName, attributes, content) {
10959 const serializedAttributes = attributes && Object.entries(attributes).length ? serializeAttributes(attributes) + ' ' : '';
10960
10961 // Strip core blocks of their namespace prefix.
10962 const blockName = rawBlockName?.startsWith('core/') ? rawBlockName.slice(5) : rawBlockName;
10963
10964 // @todo make the `wp:` prefix potentially configurable.
10965
10966 if (!content) {
10967 return `<!-- wp:${blockName} ${serializedAttributes}/-->`;
10968 }
10969 return `<!-- wp:${blockName} ${serializedAttributes}-->\n` + content + `\n<!-- /wp:${blockName} -->`;
10970 }
10971
10972 /**
10973 * Returns the content of a block, including comment delimiters, determining
10974 * serialized attributes and content form from the current state of the block.
10975 *
10976 * @param {WPBlock} block Block instance.
10977 * @param {WPBlockSerializationOptions} options Serialization options.
10978 *
10979 * @return {string} Serialized block.
10980 */
10981 function serializeBlock(block, {
10982 isInnerBlocks = false
10983 } = {}) {
10984 if (!block.isValid && block.__unstableBlockSource) {
10985 return serializeRawBlock(block.__unstableBlockSource);
10986 }
10987 const blockName = block.name;
10988 const saveContent = getBlockInnerHTML(block);
10989 if (blockName === getUnregisteredTypeHandlerName() || !isInnerBlocks && blockName === getFreeformContentHandlerName()) {
10990 return saveContent;
10991 }
10992 const blockType = getBlockType(blockName);
10993 if (!blockType) {
10994 return saveContent;
10995 }
10996 const saveAttributes = getCommentAttributes(blockType, block.attributes);
10997 return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
10998 }
10999 function __unstableSerializeAndClean(blocks) {
11000 // A single unmodified default block is assumed to
11001 // be equivalent to an empty post.
11002 if (blocks.length === 1 && isUnmodifiedDefaultBlock(blocks[0])) {
11003 blocks = [];
11004 }
11005 let content = serialize(blocks);
11006
11007 // For compatibility, treat a post consisting of a
11008 // single freeform block as legacy content and apply
11009 // pre-block-editor removep'd content formatting.
11010 if (blocks.length === 1 && blocks[0].name === getFreeformContentHandlerName() && blocks[0].name === 'core/freeform') {
11011 content = (0,external_wp_autop_namespaceObject.removep)(content);
11012 }
11013 return content;
11014 }
11015
11016 /**
11017 * Takes a block or set of blocks and returns the serialized post content.
11018 *
11019 * @param {Array} blocks Block(s) to serialize.
11020 * @param {WPBlockSerializationOptions} options Serialization options.
11021 *
11022 * @return {string} The post content.
11023 */
11024 function serialize(blocks, options) {
11025 const blocksArray = Array.isArray(blocks) ? blocks : [blocks];
11026 return blocksArray.map(block => serializeBlock(block, options)).join('\n\n');
11027 }
11028
11029 ;// ./node_modules/simple-html-tokenizer/dist/es6/index.js
11030 /**
11031 * generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
11032 * do not edit
11033 */
11034 var namedCharRefs = {
11035 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"
11036 };
11037
11038 var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
11039 var CHARCODE = /^#([0-9]+)$/;
11040 var NAMED = /^([A-Za-z0-9]+)$/;
11041 var EntityParser = /** @class */ (function () {
11042 function EntityParser(named) {
11043 this.named = named;
11044 }
11045 EntityParser.prototype.parse = function (entity) {
11046 if (!entity) {
11047 return;
11048 }
11049 var matches = entity.match(HEXCHARCODE);
11050 if (matches) {
11051 return String.fromCharCode(parseInt(matches[1], 16));
11052 }
11053 matches = entity.match(CHARCODE);
11054 if (matches) {
11055 return String.fromCharCode(parseInt(matches[1], 10));
11056 }
11057 matches = entity.match(NAMED);
11058 if (matches) {
11059 return this.named[matches[1]];
11060 }
11061 };
11062 return EntityParser;
11063 }());
11064
11065 var WSP = /[\t\n\f ]/;
11066 var ALPHA = /[A-Za-z]/;
11067 var CRLF = /\r\n?/g;
11068 function isSpace(char) {
11069 return WSP.test(char);
11070 }
11071 function isAlpha(char) {
11072 return ALPHA.test(char);
11073 }
11074 function preprocessInput(input) {
11075 return input.replace(CRLF, '\n');
11076 }
11077
11078 var EventedTokenizer = /** @class */ (function () {
11079 function EventedTokenizer(delegate, entityParser) {
11080 this.delegate = delegate;
11081 this.entityParser = entityParser;
11082 this.state = "beforeData" /* beforeData */;
11083 this.line = -1;
11084 this.column = -1;
11085 this.input = '';
11086 this.index = -1;
11087 this.tagNameBuffer = '';
11088 this.states = {
11089 beforeData: function () {
11090 var char = this.peek();
11091 if (char === '<') {
11092 this.transitionTo("tagOpen" /* tagOpen */);
11093 this.markTagStart();
11094 this.consume();
11095 }
11096 else {
11097 if (char === '\n') {
11098 var tag = this.tagNameBuffer.toLowerCase();
11099 if (tag === 'pre' || tag === 'textarea') {
11100 this.consume();
11101 }
11102 }
11103 this.transitionTo("data" /* data */);
11104 this.delegate.beginData();
11105 }
11106 },
11107 data: function () {
11108 var char = this.peek();
11109 if (char === '<') {
11110 this.delegate.finishData();
11111 this.transitionTo("tagOpen" /* tagOpen */);
11112 this.markTagStart();
11113 this.consume();
11114 }
11115 else if (char === '&') {
11116 this.consume();
11117 this.delegate.appendToData(this.consumeCharRef() || '&');
11118 }
11119 else {
11120 this.consume();
11121 this.delegate.appendToData(char);
11122 }
11123 },
11124 tagOpen: function () {
11125 var char = this.consume();
11126 if (char === '!') {
11127 this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
11128 }
11129 else if (char === '/') {
11130 this.transitionTo("endTagOpen" /* endTagOpen */);
11131 }
11132 else if (char === '@' || char === ':' || isAlpha(char)) {
11133 this.transitionTo("tagName" /* tagName */);
11134 this.tagNameBuffer = '';
11135 this.delegate.beginStartTag();
11136 this.appendToTagName(char);
11137 }
11138 },
11139 markupDeclarationOpen: function () {
11140 var char = this.consume();
11141 if (char === '-' && this.input.charAt(this.index) === '-') {
11142 this.consume();
11143 this.transitionTo("commentStart" /* commentStart */);
11144 this.delegate.beginComment();
11145 }
11146 },
11147 commentStart: function () {
11148 var char = this.consume();
11149 if (char === '-') {
11150 this.transitionTo("commentStartDash" /* commentStartDash */);
11151 }
11152 else if (char === '>') {
11153 this.delegate.finishComment();
11154 this.transitionTo("beforeData" /* beforeData */);
11155 }
11156 else {
11157 this.delegate.appendToCommentData(char);
11158 this.transitionTo("comment" /* comment */);
11159 }
11160 },
11161 commentStartDash: function () {
11162 var char = this.consume();
11163 if (char === '-') {
11164 this.transitionTo("commentEnd" /* commentEnd */);
11165 }
11166 else if (char === '>') {
11167 this.delegate.finishComment();
11168 this.transitionTo("beforeData" /* beforeData */);
11169 }
11170 else {
11171 this.delegate.appendToCommentData('-');
11172 this.transitionTo("comment" /* comment */);
11173 }
11174 },
11175 comment: function () {
11176 var char = this.consume();
11177 if (char === '-') {
11178 this.transitionTo("commentEndDash" /* commentEndDash */);
11179 }
11180 else {
11181 this.delegate.appendToCommentData(char);
11182 }
11183 },
11184 commentEndDash: function () {
11185 var char = this.consume();
11186 if (char === '-') {
11187 this.transitionTo("commentEnd" /* commentEnd */);
11188 }
11189 else {
11190 this.delegate.appendToCommentData('-' + char);
11191 this.transitionTo("comment" /* comment */);
11192 }
11193 },
11194 commentEnd: function () {
11195 var char = this.consume();
11196 if (char === '>') {
11197 this.delegate.finishComment();
11198 this.transitionTo("beforeData" /* beforeData */);
11199 }
11200 else {
11201 this.delegate.appendToCommentData('--' + char);
11202 this.transitionTo("comment" /* comment */);
11203 }
11204 },
11205 tagName: function () {
11206 var char = this.consume();
11207 if (isSpace(char)) {
11208 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11209 }
11210 else if (char === '/') {
11211 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11212 }
11213 else if (char === '>') {
11214 this.delegate.finishTag();
11215 this.transitionTo("beforeData" /* beforeData */);
11216 }
11217 else {
11218 this.appendToTagName(char);
11219 }
11220 },
11221 beforeAttributeName: function () {
11222 var char = this.peek();
11223 if (isSpace(char)) {
11224 this.consume();
11225 return;
11226 }
11227 else if (char === '/') {
11228 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11229 this.consume();
11230 }
11231 else if (char === '>') {
11232 this.consume();
11233 this.delegate.finishTag();
11234 this.transitionTo("beforeData" /* beforeData */);
11235 }
11236 else if (char === '=') {
11237 this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
11238 this.transitionTo("attributeName" /* attributeName */);
11239 this.delegate.beginAttribute();
11240 this.consume();
11241 this.delegate.appendToAttributeName(char);
11242 }
11243 else {
11244 this.transitionTo("attributeName" /* attributeName */);
11245 this.delegate.beginAttribute();
11246 }
11247 },
11248 attributeName: function () {
11249 var char = this.peek();
11250 if (isSpace(char)) {
11251 this.transitionTo("afterAttributeName" /* afterAttributeName */);
11252 this.consume();
11253 }
11254 else if (char === '/') {
11255 this.delegate.beginAttributeValue(false);
11256 this.delegate.finishAttributeValue();
11257 this.consume();
11258 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11259 }
11260 else if (char === '=') {
11261 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
11262 this.consume();
11263 }
11264 else if (char === '>') {
11265 this.delegate.beginAttributeValue(false);
11266 this.delegate.finishAttributeValue();
11267 this.consume();
11268 this.delegate.finishTag();
11269 this.transitionTo("beforeData" /* beforeData */);
11270 }
11271 else if (char === '"' || char === "'" || char === '<') {
11272 this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
11273 this.consume();
11274 this.delegate.appendToAttributeName(char);
11275 }
11276 else {
11277 this.consume();
11278 this.delegate.appendToAttributeName(char);
11279 }
11280 },
11281 afterAttributeName: function () {
11282 var char = this.peek();
11283 if (isSpace(char)) {
11284 this.consume();
11285 return;
11286 }
11287 else if (char === '/') {
11288 this.delegate.beginAttributeValue(false);
11289 this.delegate.finishAttributeValue();
11290 this.consume();
11291 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11292 }
11293 else if (char === '=') {
11294 this.consume();
11295 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
11296 }
11297 else if (char === '>') {
11298 this.delegate.beginAttributeValue(false);
11299 this.delegate.finishAttributeValue();
11300 this.consume();
11301 this.delegate.finishTag();
11302 this.transitionTo("beforeData" /* beforeData */);
11303 }
11304 else {
11305 this.delegate.beginAttributeValue(false);
11306 this.delegate.finishAttributeValue();
11307 this.transitionTo("attributeName" /* attributeName */);
11308 this.delegate.beginAttribute();
11309 this.consume();
11310 this.delegate.appendToAttributeName(char);
11311 }
11312 },
11313 beforeAttributeValue: function () {
11314 var char = this.peek();
11315 if (isSpace(char)) {
11316 this.consume();
11317 }
11318 else if (char === '"') {
11319 this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
11320 this.delegate.beginAttributeValue(true);
11321 this.consume();
11322 }
11323 else if (char === "'") {
11324 this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
11325 this.delegate.beginAttributeValue(true);
11326 this.consume();
11327 }
11328 else if (char === '>') {
11329 this.delegate.beginAttributeValue(false);
11330 this.delegate.finishAttributeValue();
11331 this.consume();
11332 this.delegate.finishTag();
11333 this.transitionTo("beforeData" /* beforeData */);
11334 }
11335 else {
11336 this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
11337 this.delegate.beginAttributeValue(false);
11338 this.consume();
11339 this.delegate.appendToAttributeValue(char);
11340 }
11341 },
11342 attributeValueDoubleQuoted: function () {
11343 var char = this.consume();
11344 if (char === '"') {
11345 this.delegate.finishAttributeValue();
11346 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
11347 }
11348 else if (char === '&') {
11349 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11350 }
11351 else {
11352 this.delegate.appendToAttributeValue(char);
11353 }
11354 },
11355 attributeValueSingleQuoted: function () {
11356 var char = this.consume();
11357 if (char === "'") {
11358 this.delegate.finishAttributeValue();
11359 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
11360 }
11361 else if (char === '&') {
11362 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11363 }
11364 else {
11365 this.delegate.appendToAttributeValue(char);
11366 }
11367 },
11368 attributeValueUnquoted: function () {
11369 var char = this.peek();
11370 if (isSpace(char)) {
11371 this.delegate.finishAttributeValue();
11372 this.consume();
11373 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11374 }
11375 else if (char === '/') {
11376 this.delegate.finishAttributeValue();
11377 this.consume();
11378 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11379 }
11380 else if (char === '&') {
11381 this.consume();
11382 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
11383 }
11384 else if (char === '>') {
11385 this.delegate.finishAttributeValue();
11386 this.consume();
11387 this.delegate.finishTag();
11388 this.transitionTo("beforeData" /* beforeData */);
11389 }
11390 else {
11391 this.consume();
11392 this.delegate.appendToAttributeValue(char);
11393 }
11394 },
11395 afterAttributeValueQuoted: function () {
11396 var char = this.peek();
11397 if (isSpace(char)) {
11398 this.consume();
11399 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11400 }
11401 else if (char === '/') {
11402 this.consume();
11403 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
11404 }
11405 else if (char === '>') {
11406 this.consume();
11407 this.delegate.finishTag();
11408 this.transitionTo("beforeData" /* beforeData */);
11409 }
11410 else {
11411 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11412 }
11413 },
11414 selfClosingStartTag: function () {
11415 var char = this.peek();
11416 if (char === '>') {
11417 this.consume();
11418 this.delegate.markTagAsSelfClosing();
11419 this.delegate.finishTag();
11420 this.transitionTo("beforeData" /* beforeData */);
11421 }
11422 else {
11423 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
11424 }
11425 },
11426 endTagOpen: function () {
11427 var char = this.consume();
11428 if (char === '@' || char === ':' || isAlpha(char)) {
11429 this.transitionTo("tagName" /* tagName */);
11430 this.tagNameBuffer = '';
11431 this.delegate.beginEndTag();
11432 this.appendToTagName(char);
11433 }
11434 }
11435 };
11436 this.reset();
11437 }
11438 EventedTokenizer.prototype.reset = function () {
11439 this.transitionTo("beforeData" /* beforeData */);
11440 this.input = '';
11441 this.index = 0;
11442 this.line = 1;
11443 this.column = 0;
11444 this.delegate.reset();
11445 };
11446 EventedTokenizer.prototype.transitionTo = function (state) {
11447 this.state = state;
11448 };
11449 EventedTokenizer.prototype.tokenize = function (input) {
11450 this.reset();
11451 this.tokenizePart(input);
11452 this.tokenizeEOF();
11453 };
11454 EventedTokenizer.prototype.tokenizePart = function (input) {
11455 this.input += preprocessInput(input);
11456 while (this.index < this.input.length) {
11457 var handler = this.states[this.state];
11458 if (handler !== undefined) {
11459 handler.call(this);
11460 }
11461 else {
11462 throw new Error("unhandled state " + this.state);
11463 }
11464 }
11465 };
11466 EventedTokenizer.prototype.tokenizeEOF = function () {
11467 this.flushData();
11468 };
11469 EventedTokenizer.prototype.flushData = function () {
11470 if (this.state === 'data') {
11471 this.delegate.finishData();
11472 this.transitionTo("beforeData" /* beforeData */);
11473 }
11474 };
11475 EventedTokenizer.prototype.peek = function () {
11476 return this.input.charAt(this.index);
11477 };
11478 EventedTokenizer.prototype.consume = function () {
11479 var char = this.peek();
11480 this.index++;
11481 if (char === '\n') {
11482 this.line++;
11483 this.column = 0;
11484 }
11485 else {
11486 this.column++;
11487 }
11488 return char;
11489 };
11490 EventedTokenizer.prototype.consumeCharRef = function () {
11491 var endIndex = this.input.indexOf(';', this.index);
11492 if (endIndex === -1) {
11493 return;
11494 }
11495 var entity = this.input.slice(this.index, endIndex);
11496 var chars = this.entityParser.parse(entity);
11497 if (chars) {
11498 var count = entity.length;
11499 // consume the entity chars
11500 while (count) {
11501 this.consume();
11502 count--;
11503 }
11504 // consume the `;`
11505 this.consume();
11506 return chars;
11507 }
11508 };
11509 EventedTokenizer.prototype.markTagStart = function () {
11510 this.delegate.tagOpen();
11511 };
11512 EventedTokenizer.prototype.appendToTagName = function (char) {
11513 this.tagNameBuffer += char;
11514 this.delegate.appendToTagName(char);
11515 };
11516 return EventedTokenizer;
11517 }());
11518
11519 var Tokenizer = /** @class */ (function () {
11520 function Tokenizer(entityParser, options) {
11521 if (options === void 0) { options = {}; }
11522 this.options = options;
11523 this.token = null;
11524 this.startLine = 1;
11525 this.startColumn = 0;
11526 this.tokens = [];
11527 this.tokenizer = new EventedTokenizer(this, entityParser);
11528 this._currentAttribute = undefined;
11529 }
11530 Tokenizer.prototype.tokenize = function (input) {
11531 this.tokens = [];
11532 this.tokenizer.tokenize(input);
11533 return this.tokens;
11534 };
11535 Tokenizer.prototype.tokenizePart = function (input) {
11536 this.tokens = [];
11537 this.tokenizer.tokenizePart(input);
11538 return this.tokens;
11539 };
11540 Tokenizer.prototype.tokenizeEOF = function () {
11541 this.tokens = [];
11542 this.tokenizer.tokenizeEOF();
11543 return this.tokens[0];
11544 };
11545 Tokenizer.prototype.reset = function () {
11546 this.token = null;
11547 this.startLine = 1;
11548 this.startColumn = 0;
11549 };
11550 Tokenizer.prototype.current = function () {
11551 var token = this.token;
11552 if (token === null) {
11553 throw new Error('token was unexpectedly null');
11554 }
11555 if (arguments.length === 0) {
11556 return token;
11557 }
11558 for (var i = 0; i < arguments.length; i++) {
11559 if (token.type === arguments[i]) {
11560 return token;
11561 }
11562 }
11563 throw new Error("token type was unexpectedly " + token.type);
11564 };
11565 Tokenizer.prototype.push = function (token) {
11566 this.token = token;
11567 this.tokens.push(token);
11568 };
11569 Tokenizer.prototype.currentAttribute = function () {
11570 return this._currentAttribute;
11571 };
11572 Tokenizer.prototype.addLocInfo = function () {
11573 if (this.options.loc) {
11574 this.current().loc = {
11575 start: {
11576 line: this.startLine,
11577 column: this.startColumn
11578 },
11579 end: {
11580 line: this.tokenizer.line,
11581 column: this.tokenizer.column
11582 }
11583 };
11584 }
11585 this.startLine = this.tokenizer.line;
11586 this.startColumn = this.tokenizer.column;
11587 };
11588 // Data
11589 Tokenizer.prototype.beginData = function () {
11590 this.push({
11591 type: "Chars" /* Chars */,
11592 chars: ''
11593 });
11594 };
11595 Tokenizer.prototype.appendToData = function (char) {
11596 this.current("Chars" /* Chars */).chars += char;
11597 };
11598 Tokenizer.prototype.finishData = function () {
11599 this.addLocInfo();
11600 };
11601 // Comment
11602 Tokenizer.prototype.beginComment = function () {
11603 this.push({
11604 type: "Comment" /* Comment */,
11605 chars: ''
11606 });
11607 };
11608 Tokenizer.prototype.appendToCommentData = function (char) {
11609 this.current("Comment" /* Comment */).chars += char;
11610 };
11611 Tokenizer.prototype.finishComment = function () {
11612 this.addLocInfo();
11613 };
11614 // Tags - basic
11615 Tokenizer.prototype.tagOpen = function () { };
11616 Tokenizer.prototype.beginStartTag = function () {
11617 this.push({
11618 type: "StartTag" /* StartTag */,
11619 tagName: '',
11620 attributes: [],
11621 selfClosing: false
11622 });
11623 };
11624 Tokenizer.prototype.beginEndTag = function () {
11625 this.push({
11626 type: "EndTag" /* EndTag */,
11627 tagName: ''
11628 });
11629 };
11630 Tokenizer.prototype.finishTag = function () {
11631 this.addLocInfo();
11632 };
11633 Tokenizer.prototype.markTagAsSelfClosing = function () {
11634 this.current("StartTag" /* StartTag */).selfClosing = true;
11635 };
11636 // Tags - name
11637 Tokenizer.prototype.appendToTagName = function (char) {
11638 this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
11639 };
11640 // Tags - attributes
11641 Tokenizer.prototype.beginAttribute = function () {
11642 this._currentAttribute = ['', '', false];
11643 };
11644 Tokenizer.prototype.appendToAttributeName = function (char) {
11645 this.currentAttribute()[0] += char;
11646 };
11647 Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
11648 this.currentAttribute()[2] = isQuoted;
11649 };
11650 Tokenizer.prototype.appendToAttributeValue = function (char) {
11651 this.currentAttribute()[1] += char;
11652 };
11653 Tokenizer.prototype.finishAttributeValue = function () {
11654 this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
11655 };
11656 Tokenizer.prototype.reportSyntaxError = function (message) {
11657 this.current().syntaxError = message;
11658 };
11659 return Tokenizer;
11660 }());
11661
11662 function tokenize(input, options) {
11663 var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);
11664 return tokenizer.tokenize(input);
11665 }
11666
11667
11668
11669 // EXTERNAL MODULE: ./node_modules/fast-deep-equal/es6/index.js
11670 var es6 = __webpack_require__(7734);
11671 var es6_default = /*#__PURE__*/__webpack_require__.n(es6);
11672 ;// external ["wp","htmlEntities"]
11673 const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
11674 ;// ./packages/blocks/build-module/api/validation/logger.js
11675 /**
11676 * @typedef LoggerItem
11677 * @property {Function} log Which logger recorded the message
11678 * @property {Array<any>} args White arguments were supplied to the logger
11679 */
11680
11681 function createLogger() {
11682 /**
11683 * Creates a log handler with block validation prefix.
11684 *
11685 * @param {Function} logger Original logger function.
11686 *
11687 * @return {Function} Augmented logger function.
11688 */
11689 function createLogHandler(logger) {
11690 let log = (message, ...args) => logger('Block validation: ' + message, ...args);
11691
11692 // In test environments, pre-process string substitutions to improve
11693 // readability of error messages. We'd prefer to avoid pulling in this
11694 // dependency in runtime environments, and it can be dropped by a combo
11695 // of Webpack env substitution + UglifyJS dead code elimination.
11696 if (false) {}
11697 return log;
11698 }
11699 return {
11700 // eslint-disable-next-line no-console
11701 error: createLogHandler(console.error),
11702 // eslint-disable-next-line no-console
11703 warning: createLogHandler(console.warn),
11704 getItems() {
11705 return [];
11706 }
11707 };
11708 }
11709 function createQueuedLogger() {
11710 /**
11711 * The list of enqueued log actions to print.
11712 *
11713 * @type {Array<LoggerItem>}
11714 */
11715 const queue = [];
11716 const logger = createLogger();
11717 return {
11718 error(...args) {
11719 queue.push({
11720 log: logger.error,
11721 args
11722 });
11723 },
11724 warning(...args) {
11725 queue.push({
11726 log: logger.warning,
11727 args
11728 });
11729 },
11730 getItems() {
11731 return queue;
11732 }
11733 };
11734 }
11735
11736 ;// ./packages/blocks/build-module/api/validation/index.js
11737 /**
11738 * External dependencies
11739 */
11740
11741
11742
11743 /**
11744 * WordPress dependencies
11745 */
11746
11747
11748
11749 /**
11750 * Internal dependencies
11751 */
11752
11753
11754
11755
11756
11757 /** @typedef {import('../parser').WPBlock} WPBlock */
11758 /** @typedef {import('../registration').WPBlockType} WPBlockType */
11759 /** @typedef {import('./logger').LoggerItem} LoggerItem */
11760
11761 const identity = x => x;
11762
11763 /**
11764 * Globally matches any consecutive whitespace
11765 *
11766 * @type {RegExp}
11767 */
11768 const REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
11769
11770 /**
11771 * Matches a string containing only whitespace
11772 *
11773 * @type {RegExp}
11774 */
11775 const REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
11776
11777 /**
11778 * Matches a CSS URL type value
11779 *
11780 * @type {RegExp}
11781 */
11782 const REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
11783
11784 /**
11785 * Boolean attributes are attributes whose presence as being assigned is
11786 * meaningful, even if only empty.
11787 *
11788 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
11789 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11790 *
11791 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11792 * .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
11793 * .reduce( ( result, tr ) => Object.assign( result, {
11794 * [ tr.firstChild.textContent.trim() ]: true
11795 * } ), {} ) ).sort();
11796 *
11797 * @type {Array}
11798 */
11799 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'];
11800
11801 /**
11802 * Enumerated attributes are attributes which must be of a specific value form.
11803 * Like boolean attributes, these are meaningful if specified, even if not of a
11804 * valid enumerated value.
11805 *
11806 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
11807 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11808 *
11809 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11810 * .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
11811 * .reduce( ( result, tr ) => Object.assign( result, {
11812 * [ tr.firstChild.textContent.trim() ]: true
11813 * } ), {} ) ).sort();
11814 *
11815 * @type {Array}
11816 */
11817 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'];
11818
11819 /**
11820 * Meaningful attributes are those who cannot be safely ignored when omitted in
11821 * one HTML markup string and not another.
11822 *
11823 * @type {Array}
11824 */
11825 const MEANINGFUL_ATTRIBUTES = [...BOOLEAN_ATTRIBUTES, ...ENUMERATED_ATTRIBUTES];
11826
11827 /**
11828 * Array of functions which receive a text string on which to apply normalizing
11829 * behavior for consideration in text token equivalence, carefully ordered from
11830 * least-to-most expensive operations.
11831 *
11832 * @type {Array}
11833 */
11834 const TEXT_NORMALIZATIONS = [identity, getTextWithCollapsedWhitespace];
11835
11836 /**
11837 * Regular expression matching a named character reference. In lieu of bundling
11838 * a full set of references, the pattern covers the minimal necessary to test
11839 * positively against the full set.
11840 *
11841 * "The ampersand must be followed by one of the names given in the named
11842 * character references section, using the same case."
11843 *
11844 * Tested aginst "12.5 Named character references":
11845 *
11846 * ```
11847 * const references = Array.from( document.querySelectorAll(
11848 * '#named-character-references-table tr[id^=entity-] td:first-child'
11849 * ) ).map( ( code ) => code.textContent )
11850 * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
11851 * ```
11852 *
11853 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11854 * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
11855 *
11856 * @type {RegExp}
11857 */
11858 const REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
11859
11860 /**
11861 * Regular expression matching a decimal character reference.
11862 *
11863 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
11864 * followed by one or more ASCII digits, representing a base-ten integer"
11865 *
11866 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11867 *
11868 * @type {RegExp}
11869 */
11870 const REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
11871
11872 /**
11873 * Regular expression matching a hexadecimal character reference.
11874 *
11875 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
11876 * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
11877 * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
11878 * one or more ASCII hex digits, representing a hexadecimal integer"
11879 *
11880 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11881 *
11882 * @type {RegExp}
11883 */
11884 const REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
11885
11886 /**
11887 * Returns true if the given string is a valid character reference segment, or
11888 * false otherwise. The text should be stripped of `&` and `;` demarcations.
11889 *
11890 * @param {string} text Text to test.
11891 *
11892 * @return {boolean} Whether text is valid character reference.
11893 */
11894 function isValidCharacterReference(text) {
11895 return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
11896 }
11897
11898 /**
11899 * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
11900 * implementation of `decodeEntities` from `html-entities`, in order to avoid
11901 * bundling a massive named character reference.
11902 *
11903 * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts
11904 */
11905 class DecodeEntityParser {
11906 /**
11907 * Returns a substitute string for an entity string sequence between `&`
11908 * and `;`, or undefined if no substitution should occur.
11909 *
11910 * @param {string} entity Entity fragment discovered in HTML.
11911 *
11912 * @return {string | undefined} Entity substitute value.
11913 */
11914 parse(entity) {
11915 if (isValidCharacterReference(entity)) {
11916 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)('&' + entity + ';');
11917 }
11918 }
11919 }
11920
11921 /**
11922 * Given a specified string, returns an array of strings split by consecutive
11923 * whitespace, ignoring leading or trailing whitespace.
11924 *
11925 * @param {string} text Original text.
11926 *
11927 * @return {string[]} Text pieces split on whitespace.
11928 */
11929 function getTextPiecesSplitOnWhitespace(text) {
11930 return text.trim().split(REGEXP_WHITESPACE);
11931 }
11932
11933 /**
11934 * Given a specified string, returns a new trimmed string where all consecutive
11935 * whitespace is collapsed to a single space.
11936 *
11937 * @param {string} text Original text.
11938 *
11939 * @return {string} Trimmed text with consecutive whitespace collapsed.
11940 */
11941 function getTextWithCollapsedWhitespace(text) {
11942 // This is an overly simplified whitespace comparison. The specification is
11943 // more prescriptive of whitespace behavior in inline and block contexts.
11944 //
11945 // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
11946 return getTextPiecesSplitOnWhitespace(text).join(' ');
11947 }
11948
11949 /**
11950 * Returns attribute pairs of the given StartTag token, including only pairs
11951 * where the value is non-empty or the attribute is a boolean attribute, an
11952 * enumerated attribute, or a custom data- attribute.
11953 *
11954 * @see MEANINGFUL_ATTRIBUTES
11955 *
11956 * @param {Object} token StartTag token.
11957 *
11958 * @return {Array[]} Attribute pairs.
11959 */
11960 function getMeaningfulAttributePairs(token) {
11961 return token.attributes.filter(pair => {
11962 const [key, value] = pair;
11963 return value || key.indexOf('data-') === 0 || MEANINGFUL_ATTRIBUTES.includes(key);
11964 });
11965 }
11966
11967 /**
11968 * Returns true if two text tokens (with `chars` property) are equivalent, or
11969 * false otherwise.
11970 *
11971 * @param {Object} actual Actual token.
11972 * @param {Object} expected Expected token.
11973 * @param {Object} logger Validation logger object.
11974 *
11975 * @return {boolean} Whether two text tokens are equivalent.
11976 */
11977 function isEquivalentTextTokens(actual, expected, logger = createLogger()) {
11978 // This function is intentionally written as syntactically "ugly" as a hot
11979 // path optimization. Text is progressively normalized in order from least-
11980 // to-most operationally expensive, until the earliest point at which text
11981 // can be confidently inferred as being equal.
11982 let actualChars = actual.chars;
11983 let expectedChars = expected.chars;
11984 for (let i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
11985 const normalize = TEXT_NORMALIZATIONS[i];
11986 actualChars = normalize(actualChars);
11987 expectedChars = normalize(expectedChars);
11988 if (actualChars === expectedChars) {
11989 return true;
11990 }
11991 }
11992 logger.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
11993 return false;
11994 }
11995
11996 /**
11997 * Given a CSS length value, returns a normalized CSS length value for strict equality
11998 * comparison.
11999 *
12000 * @param {string} value CSS length value.
12001 *
12002 * @return {string} Normalized CSS length value.
12003 */
12004 function getNormalizedLength(value) {
12005 if (0 === parseFloat(value)) {
12006 return '0';
12007 }
12008 // Normalize strings with floats to always include a leading zero.
12009 if (value.indexOf('.') === 0) {
12010 return '0' + value;
12011 }
12012 return value;
12013 }
12014
12015 /**
12016 * Given a style value, returns a normalized style value for strict equality
12017 * comparison.
12018 *
12019 * @param {string} value Style value.
12020 *
12021 * @return {string} Normalized style value.
12022 */
12023 function getNormalizedStyleValue(value) {
12024 const textPieces = getTextPiecesSplitOnWhitespace(value);
12025 const normalizedPieces = textPieces.map(getNormalizedLength);
12026 const result = normalizedPieces.join(' ');
12027 return result
12028 // Normalize URL type to omit whitespace or quotes.
12029 .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
12030 }
12031
12032 /**
12033 * Given a style attribute string, returns an object of style properties.
12034 *
12035 * @param {string} text Style attribute.
12036 *
12037 * @return {Object} Style properties.
12038 */
12039 function getStyleProperties(text) {
12040 const pairs = text
12041 // Trim ending semicolon (avoid including in split)
12042 .replace(/;?\s*$/, '')
12043 // Split on property assignment.
12044 .split(';')
12045 // For each property assignment...
12046 .map(style => {
12047 // ...split further into key-value pairs.
12048 const [key, ...valueParts] = style.split(':');
12049 const value = valueParts.join(':');
12050 return [key.trim(), getNormalizedStyleValue(value.trim())];
12051 });
12052 return Object.fromEntries(pairs);
12053 }
12054
12055 /**
12056 * Attribute-specific equality handlers
12057 *
12058 * @type {Object}
12059 */
12060 const isEqualAttributesOfName = {
12061 class: (actual, expected) => {
12062 // Class matches if members are the same, even if out of order or
12063 // superfluous whitespace between.
12064 const [actualPieces, expectedPieces] = [actual, expected].map(getTextPiecesSplitOnWhitespace);
12065 const actualDiff = actualPieces.filter(c => !expectedPieces.includes(c));
12066 const expectedDiff = expectedPieces.filter(c => !actualPieces.includes(c));
12067 return actualDiff.length === 0 && expectedDiff.length === 0;
12068 },
12069 style: (actual, expected) => {
12070 return es6_default()(...[actual, expected].map(getStyleProperties));
12071 },
12072 // For each boolean attribute, mere presence of attribute in both is enough
12073 // to assume equivalence.
12074 ...Object.fromEntries(BOOLEAN_ATTRIBUTES.map(attribute => [attribute, () => true]))
12075 };
12076
12077 /**
12078 * Given two sets of attribute tuples, returns true if the attribute sets are
12079 * equivalent.
12080 *
12081 * @param {Array[]} actual Actual attributes tuples.
12082 * @param {Array[]} expected Expected attributes tuples.
12083 * @param {Object} logger Validation logger object.
12084 *
12085 * @return {boolean} Whether attributes are equivalent.
12086 */
12087 function isEqualTagAttributePairs(actual, expected, logger = createLogger()) {
12088 // Attributes is tokenized as tuples. Their lengths should match. This also
12089 // avoids us needing to check both attributes sets, since if A has any keys
12090 // which do not exist in B, we know the sets to be different.
12091 if (actual.length !== expected.length) {
12092 logger.warning('Expected attributes %o, instead saw %o.', expected, actual);
12093 return false;
12094 }
12095
12096 // Attributes are not guaranteed to occur in the same order. For validating
12097 // actual attributes, first convert the set of expected attribute values to
12098 // an object, for lookup by key.
12099 const expectedAttributes = {};
12100 for (let i = 0; i < expected.length; i++) {
12101 expectedAttributes[expected[i][0].toLowerCase()] = expected[i][1];
12102 }
12103 for (let i = 0; i < actual.length; i++) {
12104 const [name, actualValue] = actual[i];
12105 const nameLower = name.toLowerCase();
12106
12107 // As noted above, if missing member in B, assume different.
12108 if (!expectedAttributes.hasOwnProperty(nameLower)) {
12109 logger.warning('Encountered unexpected attribute `%s`.', name);
12110 return false;
12111 }
12112 const expectedValue = expectedAttributes[nameLower];
12113 const isEqualAttributes = isEqualAttributesOfName[nameLower];
12114 if (isEqualAttributes) {
12115 // Defer custom attribute equality handling.
12116 if (!isEqualAttributes(actualValue, expectedValue)) {
12117 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
12118 return false;
12119 }
12120 } else if (actualValue !== expectedValue) {
12121 // Otherwise strict inequality should bail.
12122 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
12123 return false;
12124 }
12125 }
12126 return true;
12127 }
12128
12129 /**
12130 * Token-type-specific equality handlers
12131 *
12132 * @type {Object}
12133 */
12134 const isEqualTokensOfType = {
12135 StartTag: (actual, expected, logger = createLogger()) => {
12136 if (actual.tagName !== expected.tagName &&
12137 // Optimization: Use short-circuit evaluation to defer case-
12138 // insensitive check on the assumption that the majority case will
12139 // have exactly equal tag names.
12140 actual.tagName.toLowerCase() !== expected.tagName.toLowerCase()) {
12141 logger.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
12142 return false;
12143 }
12144 return isEqualTagAttributePairs(...[actual, expected].map(getMeaningfulAttributePairs), logger);
12145 },
12146 Chars: isEquivalentTextTokens,
12147 Comment: isEquivalentTextTokens
12148 };
12149
12150 /**
12151 * Given an array of tokens, returns the first token which is not purely
12152 * whitespace.
12153 *
12154 * Mutates the tokens array.
12155 *
12156 * @param {Object[]} tokens Set of tokens to search.
12157 *
12158 * @return {Object | undefined} Next non-whitespace token.
12159 */
12160 function getNextNonWhitespaceToken(tokens) {
12161 let token;
12162 while (token = tokens.shift()) {
12163 if (token.type !== 'Chars') {
12164 return token;
12165 }
12166 if (!REGEXP_ONLY_WHITESPACE.test(token.chars)) {
12167 return token;
12168 }
12169 }
12170 }
12171
12172 /**
12173 * Tokenize an HTML string, gracefully handling any errors thrown during
12174 * underlying tokenization.
12175 *
12176 * @param {string} html HTML string to tokenize.
12177 * @param {Object} logger Validation logger object.
12178 *
12179 * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error
12180 */
12181 function getHTMLTokens(html, logger = createLogger()) {
12182 try {
12183 return new Tokenizer(new DecodeEntityParser()).tokenize(html);
12184 } catch (e) {
12185 logger.warning('Malformed HTML detected: %s', html);
12186 }
12187 return null;
12188 }
12189
12190 /**
12191 * Returns true if the next HTML token closes the current token.
12192 *
12193 * @param {Object} currentToken Current token to compare with.
12194 * @param {Object|undefined} nextToken Next token to compare against.
12195 *
12196 * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise
12197 */
12198 function isClosedByToken(currentToken, nextToken) {
12199 // Ensure this is a self closed token.
12200 if (!currentToken.selfClosing) {
12201 return false;
12202 }
12203
12204 // Check token names and determine if nextToken is the closing tag for currentToken.
12205 if (nextToken && nextToken.tagName === currentToken.tagName && nextToken.type === 'EndTag') {
12206 return true;
12207 }
12208 return false;
12209 }
12210
12211 /**
12212 * Returns true if the given HTML strings are effectively equivalent, or
12213 * false otherwise. Invalid HTML is not considered equivalent, even if the
12214 * strings directly match.
12215 *
12216 * @param {string} actual Actual HTML string.
12217 * @param {string} expected Expected HTML string.
12218 * @param {Object} logger Validation logger object.
12219 *
12220 * @return {boolean} Whether HTML strings are equivalent.
12221 */
12222 function isEquivalentHTML(actual, expected, logger = createLogger()) {
12223 // Short-circuit if markup is identical.
12224 if (actual === expected) {
12225 return true;
12226 }
12227
12228 // Tokenize input content and reserialized save content.
12229 const [actualTokens, expectedTokens] = [actual, expected].map(html => getHTMLTokens(html, logger));
12230
12231 // If either is malformed then stop comparing - the strings are not equivalent.
12232 if (!actualTokens || !expectedTokens) {
12233 return false;
12234 }
12235 let actualToken, expectedToken;
12236 while (actualToken = getNextNonWhitespaceToken(actualTokens)) {
12237 expectedToken = getNextNonWhitespaceToken(expectedTokens);
12238
12239 // Inequal if exhausted all expected tokens.
12240 if (!expectedToken) {
12241 logger.warning('Expected end of content, instead saw %o.', actualToken);
12242 return false;
12243 }
12244
12245 // Inequal if next non-whitespace token of each set are not same type.
12246 if (actualToken.type !== expectedToken.type) {
12247 logger.warning('Expected token of type `%s` (%o), instead saw `%s` (%o).', expectedToken.type, expectedToken, actualToken.type, actualToken);
12248 return false;
12249 }
12250
12251 // Defer custom token type equality handling, otherwise continue and
12252 // assume as equal.
12253 const isEqualTokens = isEqualTokensOfType[actualToken.type];
12254 if (isEqualTokens && !isEqualTokens(actualToken, expectedToken, logger)) {
12255 return false;
12256 }
12257
12258 // Peek at the next tokens (actual and expected) to see if they close
12259 // a self-closing tag.
12260 if (isClosedByToken(actualToken, expectedTokens[0])) {
12261 // Consume the next expected token that closes the current actual
12262 // self-closing token.
12263 getNextNonWhitespaceToken(expectedTokens);
12264 } else if (isClosedByToken(expectedToken, actualTokens[0])) {
12265 // Consume the next actual token that closes the current expected
12266 // self-closing token.
12267 getNextNonWhitespaceToken(actualTokens);
12268 }
12269 }
12270 if (expectedToken = getNextNonWhitespaceToken(expectedTokens)) {
12271 // If any non-whitespace tokens remain in expected token set, this
12272 // indicates inequality.
12273 logger.warning('Expected %o, instead saw end of content.', expectedToken);
12274 return false;
12275 }
12276 return true;
12277 }
12278
12279 /**
12280 * Returns an object with `isValid` property set to `true` if the parsed block
12281 * is valid given the input content. A block is considered valid if, when serialized
12282 * with assumed attributes, the content matches the original value. If block is
12283 * invalid, this function returns all validations issues as well.
12284 *
12285 * @param {string|Object} blockTypeOrName Block type.
12286 * @param {Object} attributes Parsed block attributes.
12287 * @param {string} originalBlockContent Original block content.
12288 * @param {Object} logger Validation logger object.
12289 *
12290 * @return {Object} Whether block is valid and contains validation messages.
12291 */
12292
12293 /**
12294 * Returns an object with `isValid` property set to `true` if the parsed block
12295 * is valid given the input content. A block is considered valid if, when serialized
12296 * with assumed attributes, the content matches the original value. If block is
12297 * invalid, this function returns all validations issues as well.
12298 *
12299 * @param {WPBlock} block block object.
12300 * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.
12301 *
12302 * @return {[boolean,Array<LoggerItem>]} validation results.
12303 */
12304 function validateBlock(block, blockTypeOrName = block.name) {
12305 const isFallbackBlock = block.name === getFreeformContentHandlerName() || block.name === getUnregisteredTypeHandlerName();
12306
12307 // Shortcut to avoid costly validation.
12308 if (isFallbackBlock) {
12309 return [true, []];
12310 }
12311 const logger = createQueuedLogger();
12312 const blockType = normalizeBlockType(blockTypeOrName);
12313 let generatedBlockContent;
12314 try {
12315 generatedBlockContent = getSaveContent(blockType, block.attributes);
12316 } catch (error) {
12317 logger.error('Block validation failed because an error occurred while generating block content:\n\n%s', error.toString());
12318 return [false, logger.getItems()];
12319 }
12320 const isValid = isEquivalentHTML(block.originalContent, generatedBlockContent, logger);
12321 if (!isValid) {
12322 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);
12323 }
12324 return [isValid, logger.getItems()];
12325 }
12326
12327 /**
12328 * Returns true if the parsed block is valid given the input content. A block
12329 * is considered valid if, when serialized with assumed attributes, the content
12330 * matches the original value.
12331 *
12332 * Logs to console in development environments when invalid.
12333 *
12334 * @deprecated Use validateBlock instead to avoid data loss.
12335 *
12336 * @param {string|Object} blockTypeOrName Block type.
12337 * @param {Object} attributes Parsed block attributes.
12338 * @param {string} originalBlockContent Original block content.
12339 *
12340 * @return {boolean} Whether block is valid.
12341 */
12342 function isValidBlockContent(blockTypeOrName, attributes, originalBlockContent) {
12343 external_wp_deprecated_default()('isValidBlockContent introduces opportunity for data loss', {
12344 since: '12.6',
12345 plugin: 'Gutenberg',
12346 alternative: 'validateBlock'
12347 });
12348 const blockType = normalizeBlockType(blockTypeOrName);
12349 const block = {
12350 name: blockType.name,
12351 attributes,
12352 innerBlocks: [],
12353 originalContent: originalBlockContent
12354 };
12355 const [isValid] = validateBlock(block, blockType);
12356 return isValid;
12357 }
12358
12359 ;// ./packages/blocks/build-module/api/parser/convert-legacy-block.js
12360 /**
12361 * Convert legacy blocks to their canonical form. This function is used
12362 * both in the parser level for previous content and to convert such blocks
12363 * used in Custom Post Types templates.
12364 *
12365 * @param {string} name The block's name
12366 * @param {Object} attributes The block's attributes
12367 *
12368 * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found
12369 */
12370 function convertLegacyBlockNameAndAttributes(name, attributes) {
12371 const newAttributes = {
12372 ...attributes
12373 };
12374 // Convert 'core/cover-image' block in existing content to 'core/cover'.
12375 if ('core/cover-image' === name) {
12376 name = 'core/cover';
12377 }
12378
12379 // Convert 'core/text' blocks in existing content to 'core/paragraph'.
12380 if ('core/text' === name || 'core/cover-text' === name) {
12381 name = 'core/paragraph';
12382 }
12383
12384 // Convert derivative blocks such as 'core/social-link-wordpress' to the
12385 // canonical form 'core/social-link'.
12386 if (name && name.indexOf('core/social-link-') === 0) {
12387 // Capture `social-link-wordpress` into `{"service":"wordpress"}`
12388 newAttributes.service = name.substring(17);
12389 name = 'core/social-link';
12390 }
12391
12392 // Convert derivative blocks such as 'core-embed/instagram' to the
12393 // canonical form 'core/embed'.
12394 if (name && name.indexOf('core-embed/') === 0) {
12395 // Capture `core-embed/instagram` into `{"providerNameSlug":"instagram"}`
12396 const providerSlug = name.substring(11);
12397 const deprecated = {
12398 speaker: 'speaker-deck',
12399 polldaddy: 'crowdsignal'
12400 };
12401 newAttributes.providerNameSlug = providerSlug in deprecated ? deprecated[providerSlug] : providerSlug;
12402 // This is needed as the `responsive` attribute was passed
12403 // in a different way before the refactoring to block variations.
12404 if (!['amazon-kindle', 'wordpress'].includes(providerSlug)) {
12405 newAttributes.responsive = true;
12406 }
12407 name = 'core/embed';
12408 }
12409
12410 // Convert Post Comment blocks in existing content to Comment blocks.
12411 // TODO: Remove these checks when WordPress 6.0 is released.
12412 if (name === 'core/post-comment-author') {
12413 name = 'core/comment-author-name';
12414 }
12415 if (name === 'core/post-comment-content') {
12416 name = 'core/comment-content';
12417 }
12418 if (name === 'core/post-comment-date') {
12419 name = 'core/comment-date';
12420 }
12421 if (name === 'core/comments-query-loop') {
12422 name = 'core/comments';
12423 const {
12424 className = ''
12425 } = newAttributes;
12426 if (!className.includes('wp-block-comments-query-loop')) {
12427 newAttributes.className = ['wp-block-comments-query-loop', className].join(' ');
12428 }
12429 // Note that we also had to add a deprecation to the block in order
12430 // for the ID change to work.
12431 }
12432 if (name === 'core/post-comments') {
12433 name = 'core/comments';
12434 newAttributes.legacy = true;
12435 }
12436
12437 // Column count was stored as a string from WP 6.3-6.6. Convert it to a number.
12438 if (attributes.layout?.type === 'grid' && typeof attributes.layout?.columnCount === 'string') {
12439 newAttributes.layout = {
12440 ...newAttributes.layout,
12441 columnCount: parseInt(attributes.layout.columnCount, 10)
12442 };
12443 }
12444
12445 // Column span and row span were stored as strings in WP 6.6. Convert them to numbers.
12446 if (typeof attributes.style?.layout?.columnSpan === 'string') {
12447 const columnSpanNumber = parseInt(attributes.style.layout.columnSpan, 10);
12448 newAttributes.style = {
12449 ...newAttributes.style,
12450 layout: {
12451 ...newAttributes.style.layout,
12452 columnSpan: isNaN(columnSpanNumber) ? undefined : columnSpanNumber
12453 }
12454 };
12455 }
12456 if (typeof attributes.style?.layout?.rowSpan === 'string') {
12457 const rowSpanNumber = parseInt(attributes.style.layout.rowSpan, 10);
12458 newAttributes.style = {
12459 ...newAttributes.style,
12460 layout: {
12461 ...newAttributes.style.layout,
12462 rowSpan: isNaN(rowSpanNumber) ? undefined : rowSpanNumber
12463 }
12464 };
12465 }
12466
12467 // The following code is only relevant for the Gutenberg plugin.
12468 // It's a stand-alone if statement for dead-code elimination.
12469 if (true) {
12470 // Convert pattern overrides added during experimental phase.
12471 // Only four blocks were supported initially.
12472 // These checks can be removed in WordPress 6.6.
12473 if (newAttributes.metadata?.bindings && (name === 'core/paragraph' || name === 'core/heading' || name === 'core/image' || name === 'core/button') && newAttributes.metadata.bindings.__default?.source !== 'core/pattern-overrides') {
12474 const bindings = ['content', 'url', 'title', 'id', 'alt', 'text', 'linkTarget'];
12475 // Delete any existing individual bindings and add a default binding.
12476 // It was only possible to add all the default attributes through the UI,
12477 // So as soon as we find an attribute, we can assume all default attributes are overridable.
12478 let hasPatternOverrides = false;
12479 bindings.forEach(binding => {
12480 if (newAttributes.metadata.bindings[binding]?.source === 'core/pattern-overrides') {
12481 hasPatternOverrides = true;
12482 newAttributes.metadata = {
12483 ...newAttributes.metadata,
12484 bindings: {
12485 ...newAttributes.metadata.bindings
12486 }
12487 };
12488 delete newAttributes.metadata.bindings[binding];
12489 }
12490 });
12491 if (hasPatternOverrides) {
12492 newAttributes.metadata.bindings.__default = {
12493 source: 'core/pattern-overrides'
12494 };
12495 }
12496 }
12497 }
12498 return [name, newAttributes];
12499 }
12500
12501 ;// ./node_modules/hpq/es/get-path.js
12502 /**
12503 * Given object and string of dot-delimited path segments, returns value at
12504 * path or undefined if path cannot be resolved.
12505 *
12506 * @param {Object} object Lookup object
12507 * @param {string} path Path to resolve
12508 * @return {?*} Resolved value
12509 */
12510 function getPath(object, path) {
12511 var segments = path.split('.');
12512 var segment;
12513
12514 while (segment = segments.shift()) {
12515 if (!(segment in object)) {
12516 return;
12517 }
12518
12519 object = object[segment];
12520 }
12521
12522 return object;
12523 }
12524 ;// ./node_modules/hpq/es/index.js
12525 /**
12526 * Internal dependencies
12527 */
12528
12529 /**
12530 * Function returning a DOM document created by `createHTMLDocument`. The same
12531 * document is returned between invocations.
12532 *
12533 * @return {Document} DOM document.
12534 */
12535
12536 var getDocument = function () {
12537 var doc;
12538 return function () {
12539 if (!doc) {
12540 doc = document.implementation.createHTMLDocument('');
12541 }
12542
12543 return doc;
12544 };
12545 }();
12546 /**
12547 * Given a markup string or DOM element, creates an object aligning with the
12548 * shape of the matchers object, or the value returned by the matcher.
12549 *
12550 * @param {(string|Element)} source Source content
12551 * @param {(Object|Function)} matchers Matcher function or object of matchers
12552 * @return {(Object|*)} Matched value(s), shaped by object
12553 */
12554
12555
12556 function parse(source, matchers) {
12557 if (!matchers) {
12558 return;
12559 } // Coerce to element
12560
12561
12562 if ('string' === typeof source) {
12563 var doc = getDocument();
12564 doc.body.innerHTML = source;
12565 source = doc.body;
12566 } // Return singular value
12567
12568
12569 if ('function' === typeof matchers) {
12570 return matchers(source);
12571 } // Bail if we can't handle matchers
12572
12573
12574 if (Object !== matchers.constructor) {
12575 return;
12576 } // Shape result by matcher object
12577
12578
12579 return Object.keys(matchers).reduce(function (memo, key) {
12580 memo[key] = parse(source, matchers[key]);
12581 return memo;
12582 }, {});
12583 }
12584 /**
12585 * Generates a function which matches node of type selector, returning an
12586 * attribute by property if the attribute exists. If no selector is passed,
12587 * returns property of the query element.
12588 *
12589 * @param {?string} selector Optional selector
12590 * @param {string} name Property name
12591 * @return {*} Property value
12592 */
12593
12594 function prop(selector, name) {
12595 if (1 === arguments.length) {
12596 name = selector;
12597 selector = undefined;
12598 }
12599
12600 return function (node) {
12601 var match = node;
12602
12603 if (selector) {
12604 match = node.querySelector(selector);
12605 }
12606
12607 if (match) {
12608 return getPath(match, name);
12609 }
12610 };
12611 }
12612 /**
12613 * Generates a function which matches node of type selector, returning an
12614 * attribute by name if the attribute exists. If no selector is passed,
12615 * returns attribute of the query element.
12616 *
12617 * @param {?string} selector Optional selector
12618 * @param {string} name Attribute name
12619 * @return {?string} Attribute value
12620 */
12621
12622 function attr(selector, name) {
12623 if (1 === arguments.length) {
12624 name = selector;
12625 selector = undefined;
12626 }
12627
12628 return function (node) {
12629 var attributes = prop(selector, 'attributes')(node);
12630
12631 if (attributes && attributes.hasOwnProperty(name)) {
12632 return attributes[name].value;
12633 }
12634 };
12635 }
12636 /**
12637 * Convenience for `prop( selector, 'innerHTML' )`.
12638 *
12639 * @see prop()
12640 *
12641 * @param {?string} selector Optional selector
12642 * @return {string} Inner HTML
12643 */
12644
12645 function html(selector) {
12646 return prop(selector, 'innerHTML');
12647 }
12648 /**
12649 * Convenience for `prop( selector, 'textContent' )`.
12650 *
12651 * @see prop()
12652 *
12653 * @param {?string} selector Optional selector
12654 * @return {string} Text content
12655 */
12656
12657 function es_text(selector) {
12658 return prop(selector, 'textContent');
12659 }
12660 /**
12661 * Creates a new matching context by first finding elements matching selector
12662 * using querySelectorAll before then running another `parse` on `matchers`
12663 * scoped to the matched elements.
12664 *
12665 * @see parse()
12666 *
12667 * @param {string} selector Selector to match
12668 * @param {(Object|Function)} matchers Matcher function or object of matchers
12669 * @return {Array.<*,Object>} Array of matched value(s)
12670 */
12671
12672 function query(selector, matchers) {
12673 return function (node) {
12674 var matches = node.querySelectorAll(selector);
12675 return [].map.call(matches, function (match) {
12676 return parse(match, matchers);
12677 });
12678 };
12679 }
12680 ;// ./node_modules/memize/dist/index.js
12681 /**
12682 * Memize options object.
12683 *
12684 * @typedef MemizeOptions
12685 *
12686 * @property {number} [maxSize] Maximum size of the cache.
12687 */
12688
12689 /**
12690 * Internal cache entry.
12691 *
12692 * @typedef MemizeCacheNode
12693 *
12694 * @property {?MemizeCacheNode|undefined} [prev] Previous node.
12695 * @property {?MemizeCacheNode|undefined} [next] Next node.
12696 * @property {Array<*>} args Function arguments for cache
12697 * entry.
12698 * @property {*} val Function result.
12699 */
12700
12701 /**
12702 * Properties of the enhanced function for controlling cache.
12703 *
12704 * @typedef MemizeMemoizedFunction
12705 *
12706 * @property {()=>void} clear Clear the cache.
12707 */
12708
12709 /**
12710 * Accepts a function to be memoized, and returns a new memoized function, with
12711 * optional options.
12712 *
12713 * @template {(...args: any[]) => any} F
12714 *
12715 * @param {F} fn Function to memoize.
12716 * @param {MemizeOptions} [options] Options object.
12717 *
12718 * @return {((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction} Memoized function.
12719 */
12720 function memize(fn, options) {
12721 var size = 0;
12722
12723 /** @type {?MemizeCacheNode|undefined} */
12724 var head;
12725
12726 /** @type {?MemizeCacheNode|undefined} */
12727 var tail;
12728
12729 options = options || {};
12730
12731 function memoized(/* ...args */) {
12732 var node = head,
12733 len = arguments.length,
12734 args,
12735 i;
12736
12737 searchCache: while (node) {
12738 // Perform a shallow equality test to confirm that whether the node
12739 // under test is a candidate for the arguments passed. Two arrays
12740 // are shallowly equal if their length matches and each entry is
12741 // strictly equal between the two sets. Avoid abstracting to a
12742 // function which could incur an arguments leaking deoptimization.
12743
12744 // Check whether node arguments match arguments length
12745 if (node.args.length !== arguments.length) {
12746 node = node.next;
12747 continue;
12748 }
12749
12750 // Check whether node arguments match arguments values
12751 for (i = 0; i < len; i++) {
12752 if (node.args[i] !== arguments[i]) {
12753 node = node.next;
12754 continue searchCache;
12755 }
12756 }
12757
12758 // At this point we can assume we've found a match
12759
12760 // Surface matched node to head if not already
12761 if (node !== head) {
12762 // As tail, shift to previous. Must only shift if not also
12763 // head, since if both head and tail, there is no previous.
12764 if (node === tail) {
12765 tail = node.prev;
12766 }
12767
12768 // Adjust siblings to point to each other. If node was tail,
12769 // this also handles new tail's empty `next` assignment.
12770 /** @type {MemizeCacheNode} */ (node.prev).next = node.next;
12771 if (node.next) {
12772 node.next.prev = node.prev;
12773 }
12774
12775 node.next = head;
12776 node.prev = null;
12777 /** @type {MemizeCacheNode} */ (head).prev = node;
12778 head = node;
12779 }
12780
12781 // Return immediately
12782 return node.val;
12783 }
12784
12785 // No cached value found. Continue to insertion phase:
12786
12787 // Create a copy of arguments (avoid leaking deoptimization)
12788 args = new Array(len);
12789 for (i = 0; i < len; i++) {
12790 args[i] = arguments[i];
12791 }
12792
12793 node = {
12794 args: args,
12795
12796 // Generate the result from original function
12797 val: fn.apply(null, args),
12798 };
12799
12800 // Don't need to check whether node is already head, since it would
12801 // have been returned above already if it was
12802
12803 // Shift existing head down list
12804 if (head) {
12805 head.prev = node;
12806 node.next = head;
12807 } else {
12808 // If no head, follows that there's no tail (at initial or reset)
12809 tail = node;
12810 }
12811
12812 // Trim tail if we're reached max size and are pending cache insertion
12813 if (size === /** @type {MemizeOptions} */ (options).maxSize) {
12814 tail = /** @type {MemizeCacheNode} */ (tail).prev;
12815 /** @type {MemizeCacheNode} */ (tail).next = null;
12816 } else {
12817 size++;
12818 }
12819
12820 head = node;
12821
12822 return node.val;
12823 }
12824
12825 memoized.clear = function () {
12826 head = null;
12827 tail = null;
12828 size = 0;
12829 };
12830
12831 // Ignore reason: There's not a clear solution to create an intersection of
12832 // the function with additional properties, where the goal is to retain the
12833 // function signature of the incoming argument and add control properties
12834 // on the return value.
12835
12836 // @ts-ignore
12837 return memoized;
12838 }
12839
12840
12841
12842 ;// ./packages/blocks/build-module/api/matchers.js
12843 /**
12844 * External dependencies
12845 */
12846
12847
12848 /**
12849 * WordPress dependencies
12850 */
12851
12852
12853 /**
12854 * Internal dependencies
12855 */
12856
12857
12858 function matchers_html(selector, multilineTag) {
12859 return domNode => {
12860 let match = domNode;
12861 if (selector) {
12862 match = domNode.querySelector(selector);
12863 }
12864 if (!match) {
12865 return '';
12866 }
12867 if (multilineTag) {
12868 let value = '';
12869 const length = match.children.length;
12870 for (let index = 0; index < length; index++) {
12871 const child = match.children[index];
12872 if (child.nodeName.toLowerCase() !== multilineTag) {
12873 continue;
12874 }
12875 value += child.outerHTML;
12876 }
12877 return value;
12878 }
12879 return match.innerHTML;
12880 };
12881 }
12882 const richText = (selector, preserveWhiteSpace) => el => {
12883 const target = selector ? el.querySelector(selector) : el;
12884 return target ? external_wp_richText_namespaceObject.RichTextData.fromHTMLElement(target, {
12885 preserveWhiteSpace
12886 }) : external_wp_richText_namespaceObject.RichTextData.empty();
12887 };
12888
12889 ;// ./packages/blocks/build-module/api/node.js
12890 /**
12891 * WordPress dependencies
12892 */
12893
12894
12895 /**
12896 * Internal dependencies
12897 */
12898
12899
12900 /**
12901 * A representation of a single node within a block's rich text value. If
12902 * representing a text node, the value is simply a string of the node value.
12903 * As representing an element node, it is an object of:
12904 *
12905 * 1. `type` (string): Tag name.
12906 * 2. `props` (object): Attributes and children array of WPBlockNode.
12907 *
12908 * @typedef {string|Object} WPBlockNode
12909 */
12910
12911 /**
12912 * Given a single node and a node type (e.g. `'br'`), returns true if the node
12913 * corresponds to that type, false otherwise.
12914 *
12915 * @param {WPBlockNode} node Block node to test
12916 * @param {string} type Node to type to test against.
12917 *
12918 * @return {boolean} Whether node is of intended type.
12919 */
12920 function isNodeOfType(node, type) {
12921 external_wp_deprecated_default()('wp.blocks.node.isNodeOfType', {
12922 since: '6.1',
12923 version: '6.3',
12924 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12925 });
12926 return node && node.type === type;
12927 }
12928
12929 /**
12930 * Given an object implementing the NamedNodeMap interface, returns a plain
12931 * object equivalent value of name, value key-value pairs.
12932 *
12933 * @see https://dom.spec.whatwg.org/#interface-namednodemap
12934 *
12935 * @param {NamedNodeMap} nodeMap NamedNodeMap to convert to object.
12936 *
12937 * @return {Object} Object equivalent value of NamedNodeMap.
12938 */
12939 function getNamedNodeMapAsObject(nodeMap) {
12940 const result = {};
12941 for (let i = 0; i < nodeMap.length; i++) {
12942 const {
12943 name,
12944 value
12945 } = nodeMap[i];
12946 result[name] = value;
12947 }
12948 return result;
12949 }
12950
12951 /**
12952 * Given a DOM Element or Text node, returns an equivalent block node. Throws
12953 * if passed any node type other than element or text.
12954 *
12955 * @throws {TypeError} If non-element/text node is passed.
12956 *
12957 * @param {Node} domNode DOM node to convert.
12958 *
12959 * @return {WPBlockNode} Block node equivalent to DOM node.
12960 */
12961 function fromDOM(domNode) {
12962 external_wp_deprecated_default()('wp.blocks.node.fromDOM', {
12963 since: '6.1',
12964 version: '6.3',
12965 alternative: 'wp.richText.create',
12966 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12967 });
12968 if (domNode.nodeType === domNode.TEXT_NODE) {
12969 return domNode.nodeValue;
12970 }
12971 if (domNode.nodeType !== domNode.ELEMENT_NODE) {
12972 throw new TypeError('A block node can only be created from a node of type text or ' + 'element.');
12973 }
12974 return {
12975 type: domNode.nodeName.toLowerCase(),
12976 props: {
12977 ...getNamedNodeMapAsObject(domNode.attributes),
12978 children: children_fromDOM(domNode.childNodes)
12979 }
12980 };
12981 }
12982
12983 /**
12984 * Given a block node, returns its HTML string representation.
12985 *
12986 * @param {WPBlockNode} node Block node to convert to string.
12987 *
12988 * @return {string} String HTML representation of block node.
12989 */
12990 function toHTML(node) {
12991 external_wp_deprecated_default()('wp.blocks.node.toHTML', {
12992 since: '6.1',
12993 version: '6.3',
12994 alternative: 'wp.richText.toHTMLString',
12995 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
12996 });
12997 return children_toHTML([node]);
12998 }
12999
13000 /**
13001 * Given a selector, returns an hpq matcher generating a WPBlockNode value
13002 * matching the selector result.
13003 *
13004 * @param {string} selector DOM selector.
13005 *
13006 * @return {Function} hpq matcher.
13007 */
13008 function matcher(selector) {
13009 external_wp_deprecated_default()('wp.blocks.node.matcher', {
13010 since: '6.1',
13011 version: '6.3',
13012 alternative: 'html source',
13013 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13014 });
13015 return domNode => {
13016 let match = domNode;
13017 if (selector) {
13018 match = domNode.querySelector(selector);
13019 }
13020 try {
13021 return fromDOM(match);
13022 } catch (error) {
13023 return null;
13024 }
13025 };
13026 }
13027
13028 /**
13029 * Object of utility functions used in managing block attribute values of
13030 * source `node`.
13031 *
13032 * @see https://github.com/WordPress/gutenberg/pull/10439
13033 *
13034 * @deprecated since 4.0. The `node` source should not be used, and can be
13035 * replaced by the `html` source.
13036 *
13037 * @private
13038 */
13039 /* harmony default export */ const node = ({
13040 isNodeOfType,
13041 fromDOM,
13042 toHTML,
13043 matcher
13044 });
13045
13046 ;// ./packages/blocks/build-module/api/children.js
13047 /**
13048 * WordPress dependencies
13049 */
13050
13051
13052
13053 /**
13054 * Internal dependencies
13055 */
13056
13057
13058 /**
13059 * A representation of a block's rich text value.
13060 *
13061 * @typedef {WPBlockNode[]} WPBlockChildren
13062 */
13063
13064 /**
13065 * Given block children, returns a serialize-capable WordPress element.
13066 *
13067 * @param {WPBlockChildren} children Block children object to convert.
13068 *
13069 * @return {Element} A serialize-capable element.
13070 */
13071 function getSerializeCapableElement(children) {
13072 // The fact that block children are compatible with the element serializer is
13073 // merely an implementation detail that currently serves to be true, but
13074 // should not be mistaken as being a guarantee on the external API. The
13075 // public API only offers guarantees to work with strings (toHTML) and DOM
13076 // elements (fromDOM), and should provide utilities to manipulate the value
13077 // rather than expect consumers to inspect or construct its shape (concat).
13078 return children;
13079 }
13080
13081 /**
13082 * Given block children, returns an array of block nodes.
13083 *
13084 * @param {WPBlockChildren} children Block children object to convert.
13085 *
13086 * @return {Array<WPBlockNode>} An array of individual block nodes.
13087 */
13088 function getChildrenArray(children) {
13089 external_wp_deprecated_default()('wp.blocks.children.getChildrenArray', {
13090 since: '6.1',
13091 version: '6.3',
13092 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13093 });
13094
13095 // The fact that block children are compatible with the element serializer
13096 // is merely an implementation detail that currently serves to be true, but
13097 // should not be mistaken as being a guarantee on the external API.
13098 return children;
13099 }
13100
13101 /**
13102 * Given two or more block nodes, returns a new block node representing a
13103 * concatenation of its values.
13104 *
13105 * @param {...WPBlockChildren} blockNodes Block nodes to concatenate.
13106 *
13107 * @return {WPBlockChildren} Concatenated block node.
13108 */
13109 function concat(...blockNodes) {
13110 external_wp_deprecated_default()('wp.blocks.children.concat', {
13111 since: '6.1',
13112 version: '6.3',
13113 alternative: 'wp.richText.concat',
13114 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13115 });
13116 const result = [];
13117 for (let i = 0; i < blockNodes.length; i++) {
13118 const blockNode = Array.isArray(blockNodes[i]) ? blockNodes[i] : [blockNodes[i]];
13119 for (let j = 0; j < blockNode.length; j++) {
13120 const child = blockNode[j];
13121 const canConcatToPreviousString = typeof child === 'string' && typeof result[result.length - 1] === 'string';
13122 if (canConcatToPreviousString) {
13123 result[result.length - 1] += child;
13124 } else {
13125 result.push(child);
13126 }
13127 }
13128 }
13129 return result;
13130 }
13131
13132 /**
13133 * Given an iterable set of DOM nodes, returns equivalent block children.
13134 * Ignores any non-element/text nodes included in set.
13135 *
13136 * @param {Iterable.<Node>} domNodes Iterable set of DOM nodes to convert.
13137 *
13138 * @return {WPBlockChildren} Block children equivalent to DOM nodes.
13139 */
13140 function children_fromDOM(domNodes) {
13141 external_wp_deprecated_default()('wp.blocks.children.fromDOM', {
13142 since: '6.1',
13143 version: '6.3',
13144 alternative: 'wp.richText.create',
13145 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13146 });
13147 const result = [];
13148 for (let i = 0; i < domNodes.length; i++) {
13149 try {
13150 result.push(fromDOM(domNodes[i]));
13151 } catch (error) {
13152 // Simply ignore if DOM node could not be converted.
13153 }
13154 }
13155 return result;
13156 }
13157
13158 /**
13159 * Given a block node, returns its HTML string representation.
13160 *
13161 * @param {WPBlockChildren} children Block node(s) to convert to string.
13162 *
13163 * @return {string} String HTML representation of block node.
13164 */
13165 function children_toHTML(children) {
13166 external_wp_deprecated_default()('wp.blocks.children.toHTML', {
13167 since: '6.1',
13168 version: '6.3',
13169 alternative: 'wp.richText.toHTMLString',
13170 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13171 });
13172 const element = getSerializeCapableElement(children);
13173 return (0,external_wp_element_namespaceObject.renderToString)(element);
13174 }
13175
13176 /**
13177 * Given a selector, returns an hpq matcher generating a WPBlockChildren value
13178 * matching the selector result.
13179 *
13180 * @param {string} selector DOM selector.
13181 *
13182 * @return {Function} hpq matcher.
13183 */
13184 function children_matcher(selector) {
13185 external_wp_deprecated_default()('wp.blocks.children.matcher', {
13186 since: '6.1',
13187 version: '6.3',
13188 alternative: 'html source',
13189 link: 'https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/'
13190 });
13191 return domNode => {
13192 let match = domNode;
13193 if (selector) {
13194 match = domNode.querySelector(selector);
13195 }
13196 if (match) {
13197 return children_fromDOM(match.childNodes);
13198 }
13199 return [];
13200 };
13201 }
13202
13203 /**
13204 * Object of utility functions used in managing block attribute values of
13205 * source `children`.
13206 *
13207 * @see https://github.com/WordPress/gutenberg/pull/10439
13208 *
13209 * @deprecated since 4.0. The `children` source should not be used, and can be
13210 * replaced by the `html` source.
13211 *
13212 * @private
13213 */
13214 /* harmony default export */ const children = ({
13215 concat,
13216 getChildrenArray,
13217 fromDOM: children_fromDOM,
13218 toHTML: children_toHTML,
13219 matcher: children_matcher
13220 });
13221
13222 ;// ./packages/blocks/build-module/api/parser/get-block-attributes.js
13223 /**
13224 * External dependencies
13225 */
13226
13227
13228
13229 /**
13230 * WordPress dependencies
13231 */
13232
13233
13234
13235 /**
13236 * Internal dependencies
13237 */
13238
13239
13240
13241 /**
13242 * Higher-order hpq matcher which enhances an attribute matcher to return true
13243 * or false depending on whether the original matcher returns undefined. This
13244 * is useful for boolean attributes (e.g. disabled) whose attribute values may
13245 * be technically falsey (empty string), though their mere presence should be
13246 * enough to infer as true.
13247 *
13248 * @param {Function} matcher Original hpq matcher.
13249 *
13250 * @return {Function} Enhanced hpq matcher.
13251 */
13252 const toBooleanAttributeMatcher = matcher => value => matcher(value) !== undefined;
13253
13254 /**
13255 * Returns true if value is of the given JSON schema type, or false otherwise.
13256 *
13257 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
13258 *
13259 * @param {*} value Value to test.
13260 * @param {string} type Type to test.
13261 *
13262 * @return {boolean} Whether value is of type.
13263 */
13264 function isOfType(value, type) {
13265 switch (type) {
13266 case 'rich-text':
13267 return value instanceof external_wp_richText_namespaceObject.RichTextData;
13268 case 'string':
13269 return typeof value === 'string';
13270 case 'boolean':
13271 return typeof value === 'boolean';
13272 case 'object':
13273 return !!value && value.constructor === Object;
13274 case 'null':
13275 return value === null;
13276 case 'array':
13277 return Array.isArray(value);
13278 case 'integer':
13279 case 'number':
13280 return typeof value === 'number';
13281 }
13282 return true;
13283 }
13284
13285 /**
13286 * Returns true if value is of an array of given JSON schema types, or false
13287 * otherwise.
13288 *
13289 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
13290 *
13291 * @param {*} value Value to test.
13292 * @param {string[]} types Types to test.
13293 *
13294 * @return {boolean} Whether value is of types.
13295 */
13296 function isOfTypes(value, types) {
13297 return types.some(type => isOfType(value, type));
13298 }
13299
13300 /**
13301 * Given an attribute key, an attribute's schema, a block's raw content and the
13302 * commentAttributes returns the attribute value depending on its source
13303 * definition of the given attribute key.
13304 *
13305 * @param {string} attributeKey Attribute key.
13306 * @param {Object} attributeSchema Attribute's schema.
13307 * @param {Node} innerDOM Parsed DOM of block's inner HTML.
13308 * @param {Object} commentAttributes Block's comment attributes.
13309 * @param {string} innerHTML Raw HTML from block node's innerHTML property.
13310 *
13311 * @return {*} Attribute value.
13312 */
13313 function getBlockAttribute(attributeKey, attributeSchema, innerDOM, commentAttributes, innerHTML) {
13314 let value;
13315 switch (attributeSchema.source) {
13316 // An undefined source means that it's an attribute serialized to the
13317 // block's "comment".
13318 case undefined:
13319 value = commentAttributes ? commentAttributes[attributeKey] : undefined;
13320 break;
13321 // raw source means that it's the original raw block content.
13322 case 'raw':
13323 value = innerHTML;
13324 break;
13325 case 'attribute':
13326 case 'property':
13327 case 'html':
13328 case 'text':
13329 case 'rich-text':
13330 case 'children':
13331 case 'node':
13332 case 'query':
13333 case 'tag':
13334 value = parseWithAttributeSchema(innerDOM, attributeSchema);
13335 break;
13336 }
13337 if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) {
13338 // Reject the value if it is not valid. Reverting to the undefined
13339 // value ensures the default is respected, if applicable.
13340 value = undefined;
13341 }
13342 if (value === undefined) {
13343 value = getDefault(attributeSchema);
13344 }
13345 return value;
13346 }
13347
13348 /**
13349 * Returns true if value is valid per the given block attribute schema type
13350 * definition, or false otherwise.
13351 *
13352 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1
13353 *
13354 * @param {*} value Value to test.
13355 * @param {?(Array<string>|string)} type Block attribute schema type.
13356 *
13357 * @return {boolean} Whether value is valid.
13358 */
13359 function isValidByType(value, type) {
13360 return type === undefined || isOfTypes(value, Array.isArray(type) ? type : [type]);
13361 }
13362
13363 /**
13364 * Returns true if value is valid per the given block attribute schema enum
13365 * definition, or false otherwise.
13366 *
13367 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2
13368 *
13369 * @param {*} value Value to test.
13370 * @param {?Array} enumSet Block attribute schema enum.
13371 *
13372 * @return {boolean} Whether value is valid.
13373 */
13374 function isValidByEnum(value, enumSet) {
13375 return !Array.isArray(enumSet) || enumSet.includes(value);
13376 }
13377
13378 /**
13379 * Returns an hpq matcher given a source object.
13380 *
13381 * @param {Object} sourceConfig Attribute Source object.
13382 *
13383 * @return {Function} A hpq Matcher.
13384 */
13385 const matcherFromSource = memize(sourceConfig => {
13386 switch (sourceConfig.source) {
13387 case 'attribute':
13388 {
13389 let matcher = attr(sourceConfig.selector, sourceConfig.attribute);
13390 if (sourceConfig.type === 'boolean') {
13391 matcher = toBooleanAttributeMatcher(matcher);
13392 }
13393 return matcher;
13394 }
13395 case 'html':
13396 return matchers_html(sourceConfig.selector, sourceConfig.multiline);
13397 case 'text':
13398 return es_text(sourceConfig.selector);
13399 case 'rich-text':
13400 return richText(sourceConfig.selector, sourceConfig.__unstablePreserveWhiteSpace);
13401 case 'children':
13402 return children_matcher(sourceConfig.selector);
13403 case 'node':
13404 return matcher(sourceConfig.selector);
13405 case 'query':
13406 const subMatchers = Object.fromEntries(Object.entries(sourceConfig.query).map(([key, subSourceConfig]) => [key, matcherFromSource(subSourceConfig)]));
13407 return query(sourceConfig.selector, subMatchers);
13408 case 'tag':
13409 {
13410 const matcher = prop(sourceConfig.selector, 'nodeName');
13411 return domNode => matcher(domNode)?.toLowerCase();
13412 }
13413 default:
13414 // eslint-disable-next-line no-console
13415 console.error(`Unknown source type "${sourceConfig.source}"`);
13416 }
13417 });
13418
13419 /**
13420 * Parse a HTML string into DOM tree.
13421 *
13422 * @param {string|Node} innerHTML HTML string or already parsed DOM node.
13423 *
13424 * @return {Node} Parsed DOM node.
13425 */
13426 function parseHtml(innerHTML) {
13427 return parse(innerHTML, h => h);
13428 }
13429
13430 /**
13431 * Given a block's raw content and an attribute's schema returns the attribute's
13432 * value depending on its source.
13433 *
13434 * @param {string|Node} innerHTML Block's raw content.
13435 * @param {Object} attributeSchema Attribute's schema.
13436 *
13437 * @return {*} Attribute value.
13438 */
13439 function parseWithAttributeSchema(innerHTML, attributeSchema) {
13440 return matcherFromSource(attributeSchema)(parseHtml(innerHTML));
13441 }
13442
13443 /**
13444 * Returns the block attributes of a registered block node given its type.
13445 *
13446 * @param {string|Object} blockTypeOrName Block type or name.
13447 * @param {string|Node} innerHTML Raw block content.
13448 * @param {?Object} attributes Known block attributes (from delimiters).
13449 *
13450 * @return {Object} All block attributes.
13451 */
13452 function getBlockAttributes(blockTypeOrName, innerHTML, attributes = {}) {
13453 var _blockType$attributes;
13454 const doc = parseHtml(innerHTML);
13455 const blockType = normalizeBlockType(blockTypeOrName);
13456 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)]));
13457 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockAttributes', blockAttributes, blockType, innerHTML, attributes);
13458 }
13459
13460 ;// ./packages/blocks/build-module/api/parser/fix-custom-classname.js
13461 /**
13462 * Internal dependencies
13463 */
13464
13465
13466
13467 const CLASS_ATTR_SCHEMA = {
13468 type: 'string',
13469 source: 'attribute',
13470 selector: '[data-custom-class-name] > *',
13471 attribute: 'class'
13472 };
13473
13474 /**
13475 * Given an HTML string, returns an array of class names assigned to the root
13476 * element in the markup.
13477 *
13478 * @param {string} innerHTML Markup string from which to extract classes.
13479 *
13480 * @return {string[]} Array of class names assigned to the root element.
13481 */
13482 function getHTMLRootElementClasses(innerHTML) {
13483 const parsed = parseWithAttributeSchema(`<div data-custom-class-name>${innerHTML}</div>`, CLASS_ATTR_SCHEMA);
13484 return parsed ? parsed.trim().split(/\s+/) : [];
13485 }
13486
13487 /**
13488 * Given a parsed set of block attributes, if the block supports custom class
13489 * names and an unknown class (per the block's serialization behavior) is
13490 * found, the unknown classes are treated as custom classes. This prevents the
13491 * block from being considered as invalid.
13492 *
13493 * @param {Object} blockAttributes Original block attributes.
13494 * @param {Object} blockType Block type settings.
13495 * @param {string} innerHTML Original block markup.
13496 *
13497 * @return {Object} Filtered block attributes.
13498 */
13499 function fixCustomClassname(blockAttributes, blockType, innerHTML) {
13500 if (!hasBlockSupport(blockType, 'customClassName', true)) {
13501 return blockAttributes;
13502 }
13503 const modifiedBlockAttributes = {
13504 ...blockAttributes
13505 };
13506 // To determine difference, serialize block given the known set of
13507 // attributes, with the exception of `className`. This will determine
13508 // the default set of classes. From there, any difference in innerHTML
13509 // can be considered as custom classes.
13510 const {
13511 className: omittedClassName,
13512 ...attributesSansClassName
13513 } = modifiedBlockAttributes;
13514 const serialized = getSaveContent(blockType, attributesSansClassName);
13515 const defaultClasses = getHTMLRootElementClasses(serialized);
13516 const actualClasses = getHTMLRootElementClasses(innerHTML);
13517 const customClasses = actualClasses.filter(className => !defaultClasses.includes(className));
13518 if (customClasses.length) {
13519 modifiedBlockAttributes.className = customClasses.join(' ');
13520 } else if (serialized) {
13521 delete modifiedBlockAttributes.className;
13522 }
13523 return modifiedBlockAttributes;
13524 }
13525
13526 ;// ./packages/blocks/build-module/api/parser/apply-built-in-validation-fixes.js
13527 /**
13528 * Internal dependencies
13529 */
13530
13531
13532 /**
13533 * Attempts to fix block invalidation by applying build-in validation fixes
13534 * like moving all extra classNames to the className attribute.
13535 *
13536 * @param {WPBlock} block block object.
13537 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13538 * can be inferred from the block name,
13539 * but it's here for performance reasons.
13540 *
13541 * @return {WPBlock} Fixed block object
13542 */
13543 function applyBuiltInValidationFixes(block, blockType) {
13544 const updatedBlockAttributes = fixCustomClassname(block.attributes, blockType, block.originalContent);
13545 return {
13546 ...block,
13547 attributes: updatedBlockAttributes
13548 };
13549 }
13550
13551 ;// ./packages/blocks/build-module/api/parser/apply-block-deprecated-versions.js
13552 /**
13553 * Internal dependencies
13554 */
13555
13556
13557
13558
13559
13560
13561 /**
13562 * Function that takes no arguments and always returns false.
13563 *
13564 * @return {boolean} Always returns false.
13565 */
13566 function stubFalse() {
13567 return false;
13568 }
13569
13570 /**
13571 * Given a block object, returns a new copy of the block with any applicable
13572 * deprecated migrations applied, or the original block if it was both valid
13573 * and no eligible migrations exist.
13574 *
13575 * @param {import(".").WPBlock} block Parsed and invalid block object.
13576 * @param {import(".").WPRawBlock} rawBlock Raw block object.
13577 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
13578 * can be inferred from the block name,
13579 * but it's here for performance reasons.
13580 *
13581 * @return {import(".").WPBlock} Migrated block object.
13582 */
13583 function applyBlockDeprecatedVersions(block, rawBlock, blockType) {
13584 const parsedAttributes = rawBlock.attrs;
13585 const {
13586 deprecated: deprecatedDefinitions
13587 } = blockType;
13588 // Bail early if there are no registered deprecations to be handled.
13589 if (!deprecatedDefinitions || !deprecatedDefinitions.length) {
13590 return block;
13591 }
13592
13593 // By design, blocks lack any sort of version tracking. Instead, to process
13594 // outdated content the system operates a queue out of all the defined
13595 // attribute shapes and tries each definition until the input produces a
13596 // valid result. This mechanism seeks to avoid polluting the user-space with
13597 // machine-specific code. An invalid block is thus a block that could not be
13598 // matched successfully with any of the registered deprecation definitions.
13599 for (let i = 0; i < deprecatedDefinitions.length; i++) {
13600 // A block can opt into a migration even if the block is valid by
13601 // defining `isEligible` on its deprecation. If the block is both valid
13602 // and does not opt to migrate, skip.
13603 const {
13604 isEligible = stubFalse
13605 } = deprecatedDefinitions[i];
13606 if (block.isValid && !isEligible(parsedAttributes, block.innerBlocks, {
13607 blockNode: rawBlock,
13608 block
13609 })) {
13610 continue;
13611 }
13612
13613 // Block type properties which could impact either serialization or
13614 // parsing are not considered in the deprecated block type by default,
13615 // and must be explicitly provided.
13616 const deprecatedBlockType = Object.assign(omit(blockType, DEPRECATED_ENTRY_KEYS), deprecatedDefinitions[i]);
13617 let migratedBlock = {
13618 ...block,
13619 attributes: getBlockAttributes(deprecatedBlockType, block.originalContent, parsedAttributes)
13620 };
13621
13622 // Ignore the deprecation if it produces a block which is not valid.
13623 let [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
13624
13625 // If the migrated block is not valid initially, try the built-in fixes.
13626 if (!isValid) {
13627 migratedBlock = applyBuiltInValidationFixes(migratedBlock, deprecatedBlockType);
13628 [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
13629 }
13630
13631 // An invalid block does not imply incorrect HTML but the fact block
13632 // source information could be lost on re-serialization.
13633 if (!isValid) {
13634 continue;
13635 }
13636 let migratedInnerBlocks = migratedBlock.innerBlocks;
13637 let migratedAttributes = migratedBlock.attributes;
13638
13639 // A block may provide custom behavior to assign new attributes and/or
13640 // inner blocks.
13641 const {
13642 migrate
13643 } = deprecatedBlockType;
13644 if (migrate) {
13645 let migrated = migrate(migratedAttributes, block.innerBlocks);
13646 if (!Array.isArray(migrated)) {
13647 migrated = [migrated];
13648 }
13649 [migratedAttributes = parsedAttributes, migratedInnerBlocks = block.innerBlocks] = migrated;
13650 }
13651 block = {
13652 ...block,
13653 attributes: migratedAttributes,
13654 innerBlocks: migratedInnerBlocks,
13655 isValid: true,
13656 validationIssues: []
13657 };
13658 }
13659 return block;
13660 }
13661
13662 ;// ./packages/blocks/build-module/api/parser/index.js
13663 /**
13664 * WordPress dependencies
13665 */
13666
13667
13668
13669 /**
13670 * Internal dependencies
13671 */
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681
13682 /**
13683 * The raw structure of a block includes its attributes, inner
13684 * blocks, and inner HTML. It is important to distinguish inner blocks from
13685 * the HTML content of the block as only the latter is relevant for block
13686 * validation and edit operations.
13687 *
13688 * @typedef WPRawBlock
13689 *
13690 * @property {string=} blockName Block name
13691 * @property {Object=} attrs Block raw or comment attributes.
13692 * @property {string} innerHTML HTML content of the block.
13693 * @property {(string|null)[]} innerContent Content without inner blocks.
13694 * @property {WPRawBlock[]} innerBlocks Inner Blocks.
13695 */
13696
13697 /**
13698 * Fully parsed block object.
13699 *
13700 * @typedef WPBlock
13701 *
13702 * @property {string} name Block name
13703 * @property {Object} attributes Block raw or comment attributes.
13704 * @property {WPBlock[]} innerBlocks Inner Blocks.
13705 * @property {string} originalContent Original content of the block before validation fixes.
13706 * @property {boolean} isValid Whether the block is valid.
13707 * @property {Object[]} validationIssues Validation issues.
13708 * @property {WPRawBlock} [__unstableBlockSource] Un-processed original copy of block if created through parser.
13709 */
13710
13711 /**
13712 * @typedef {Object} ParseOptions
13713 * @property {boolean?} __unstableSkipMigrationLogs If a block is migrated from a deprecated version, skip logging the migration details.
13714 * @property {boolean?} __unstableSkipAutop Whether to skip autop when processing freeform content.
13715 */
13716
13717 /**
13718 * Convert legacy blocks to their canonical form. This function is used
13719 * both in the parser level for previous content and to convert such blocks
13720 * used in Custom Post Types templates.
13721 *
13722 * @param {WPRawBlock} rawBlock
13723 *
13724 * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found
13725 */
13726 function convertLegacyBlocks(rawBlock) {
13727 const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(rawBlock.blockName, rawBlock.attrs);
13728 return {
13729 ...rawBlock,
13730 blockName: correctName,
13731 attrs: correctedAttributes
13732 };
13733 }
13734
13735 /**
13736 * Normalize the raw block by applying the fallback block name if none given,
13737 * sanitize the parsed HTML...
13738 *
13739 * @param {WPRawBlock} rawBlock The raw block object.
13740 * @param {ParseOptions?} options Extra options for handling block parsing.
13741 *
13742 * @return {WPRawBlock} The normalized block object.
13743 */
13744 function normalizeRawBlock(rawBlock, options) {
13745 const fallbackBlockName = getFreeformContentHandlerName();
13746
13747 // If the grammar parsing don't produce any block name, use the freeform block.
13748 const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
13749 const rawAttributes = rawBlock.attrs || {};
13750 const rawInnerBlocks = rawBlock.innerBlocks || [];
13751 let rawInnerHTML = rawBlock.innerHTML.trim();
13752
13753 // Fallback content may be upgraded from classic content expecting implicit
13754 // automatic paragraphs, so preserve them. Assumes wpautop is idempotent,
13755 // meaning there are no negative consequences to repeated autop calls.
13756 if (rawBlockName === fallbackBlockName && rawBlockName === 'core/freeform' && !options?.__unstableSkipAutop) {
13757 rawInnerHTML = (0,external_wp_autop_namespaceObject.autop)(rawInnerHTML).trim();
13758 }
13759 return {
13760 ...rawBlock,
13761 blockName: rawBlockName,
13762 attrs: rawAttributes,
13763 innerHTML: rawInnerHTML,
13764 innerBlocks: rawInnerBlocks
13765 };
13766 }
13767
13768 /**
13769 * Uses the "unregistered blockType" to create a block object.
13770 *
13771 * @param {WPRawBlock} rawBlock block.
13772 *
13773 * @return {WPRawBlock} The unregistered block object.
13774 */
13775 function createMissingBlockType(rawBlock) {
13776 const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName();
13777
13778 // Preserve undelimited content for use by the unregistered type
13779 // handler. A block node's `innerHTML` isn't enough, as that field only
13780 // carries the block's own HTML and not its nested blocks.
13781 const originalUndelimitedContent = serializeRawBlock(rawBlock, {
13782 isCommentDelimited: false
13783 });
13784
13785 // Preserve full block content for use by the unregistered type
13786 // handler, block boundaries included.
13787 const originalContent = serializeRawBlock(rawBlock, {
13788 isCommentDelimited: true
13789 });
13790 return {
13791 blockName: unregisteredFallbackBlock,
13792 attrs: {
13793 originalName: rawBlock.blockName,
13794 originalContent,
13795 originalUndelimitedContent
13796 },
13797 innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
13798 innerBlocks: rawBlock.innerBlocks,
13799 innerContent: rawBlock.innerContent
13800 };
13801 }
13802
13803 /**
13804 * Validates a block and wraps with validation meta.
13805 *
13806 * The name here is regrettable but `validateBlock` is already taken.
13807 *
13808 * @param {WPBlock} unvalidatedBlock
13809 * @param {import('../registration').WPBlockType} blockType
13810 * @return {WPBlock} validated block, with auto-fixes if initially invalid
13811 */
13812 function applyBlockValidation(unvalidatedBlock, blockType) {
13813 // Attempt to validate the block.
13814 const [isValid] = validateBlock(unvalidatedBlock, blockType);
13815 if (isValid) {
13816 return {
13817 ...unvalidatedBlock,
13818 isValid,
13819 validationIssues: []
13820 };
13821 }
13822
13823 // If the block is invalid, attempt some built-in fixes
13824 // like custom classNames handling.
13825 const fixedBlock = applyBuiltInValidationFixes(unvalidatedBlock, blockType);
13826 // Attempt to validate the block once again after the built-in fixes.
13827 const [isFixedValid, validationIssues] = validateBlock(fixedBlock, blockType);
13828 return {
13829 ...fixedBlock,
13830 isValid: isFixedValid,
13831 validationIssues
13832 };
13833 }
13834
13835 /**
13836 * Given a raw block returned by grammar parsing, returns a fully parsed block.
13837 *
13838 * @param {WPRawBlock} rawBlock The raw block object.
13839 * @param {ParseOptions} options Extra options for handling block parsing.
13840 *
13841 * @return {WPBlock | undefined} Fully parsed block.
13842 */
13843 function parseRawBlock(rawBlock, options) {
13844 let normalizedBlock = normalizeRawBlock(rawBlock, options);
13845
13846 // During the lifecycle of the project, we renamed some old blocks
13847 // and transformed others to new blocks. To avoid breaking existing content,
13848 // we added this function to properly parse the old content.
13849 normalizedBlock = convertLegacyBlocks(normalizedBlock);
13850
13851 // Try finding the type for known block name.
13852 let blockType = getBlockType(normalizedBlock.blockName);
13853
13854 // If not blockType is found for the specified name, fallback to the "unregistedBlockType".
13855 if (!blockType) {
13856 normalizedBlock = createMissingBlockType(normalizedBlock);
13857 blockType = getBlockType(normalizedBlock.blockName);
13858 }
13859
13860 // If it's an empty freeform block or there's no blockType (no missing block handler)
13861 // Then, just ignore the block.
13862 // It might be a good idea to throw a warning here.
13863 // TODO: I'm unsure about the unregisteredFallbackBlock check,
13864 // it might ignore some dynamic unregistered third party blocks wrongly.
13865 const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
13866 if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
13867 return;
13868 }
13869
13870 // Parse inner blocks recursively.
13871 const parsedInnerBlocks = normalizedBlock.innerBlocks.map(innerBlock => parseRawBlock(innerBlock, options))
13872 // See https://github.com/WordPress/gutenberg/pull/17164.
13873 .filter(innerBlock => !!innerBlock);
13874
13875 // Get the fully parsed block.
13876 const parsedBlock = createBlock(normalizedBlock.blockName, getBlockAttributes(blockType, normalizedBlock.innerHTML, normalizedBlock.attrs), parsedInnerBlocks);
13877 parsedBlock.originalContent = normalizedBlock.innerHTML;
13878 const validatedBlock = applyBlockValidation(parsedBlock, blockType);
13879 const {
13880 validationIssues
13881 } = validatedBlock;
13882
13883 // Run the block deprecation and migrations.
13884 // This is performed on both invalid and valid blocks because
13885 // migration using the `migrate` functions should run even
13886 // if the output is deemed valid.
13887 const updatedBlock = applyBlockDeprecatedVersions(validatedBlock, normalizedBlock, blockType);
13888 if (!updatedBlock.isValid) {
13889 // Preserve the original unprocessed version of the block
13890 // that we received (no fixes, no deprecations) so that
13891 // we can save it as close to exactly the same way as
13892 // we loaded it. This is important to avoid corruption
13893 // and data loss caused by block implementations trying
13894 // to process data that isn't fully recognized.
13895 updatedBlock.__unstableBlockSource = rawBlock;
13896 }
13897 if (!validatedBlock.isValid && updatedBlock.isValid && !options?.__unstableSkipMigrationLogs) {
13898 /* eslint-disable no-console */
13899 console.groupCollapsed('Updated Block: %s', blockType.name);
13900 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);
13901 console.groupEnd();
13902 /* eslint-enable no-console */
13903 } else if (!validatedBlock.isValid && !updatedBlock.isValid) {
13904 validationIssues.forEach(({
13905 log,
13906 args
13907 }) => log(...args));
13908 }
13909 return updatedBlock;
13910 }
13911
13912 /**
13913 * Utilizes an optimized token-driven parser based on the Gutenberg grammar spec
13914 * defined through a parsing expression grammar to take advantage of the regular
13915 * cadence provided by block delimiters -- composed syntactically through HTML
13916 * comments -- which, given a general HTML document as an input, returns a block
13917 * list array representation.
13918 *
13919 * This is a recursive-descent parser that scans linearly once through the input
13920 * document. Instead of directly recursing it utilizes a trampoline mechanism to
13921 * prevent stack overflow. This initial pass is mainly interested in separating
13922 * and isolating the blocks serialized in the document and manifestly not in the
13923 * content within the blocks.
13924 *
13925 * @see
13926 * https://developer.wordpress.org/block-editor/packages/packages-block-serialization-default-parser/
13927 *
13928 * @param {string} content The post content.
13929 * @param {ParseOptions} options Extra options for handling block parsing.
13930 *
13931 * @return {Array} Block list.
13932 */
13933 function parser_parse(content, options) {
13934 return (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(content).reduce((accumulator, rawBlock) => {
13935 const block = parseRawBlock(rawBlock, options);
13936 if (block) {
13937 accumulator.push(block);
13938 }
13939 return accumulator;
13940 }, []);
13941 }
13942
13943 ;// ./packages/blocks/build-module/api/raw-handling/get-raw-transforms.js
13944 /**
13945 * Internal dependencies
13946 */
13947
13948 function getRawTransforms() {
13949 return getBlockTransforms('from').filter(({
13950 type
13951 }) => type === 'raw').map(transform => {
13952 return transform.isMatch ? transform : {
13953 ...transform,
13954 isMatch: node => transform.selector && node.matches(transform.selector)
13955 };
13956 });
13957 }
13958
13959 ;// ./packages/blocks/build-module/api/raw-handling/html-to-blocks.js
13960 /**
13961 * WordPress dependencies
13962 */
13963
13964
13965 /**
13966 * Internal dependencies
13967 */
13968
13969
13970
13971
13972
13973 /**
13974 * Converts HTML directly to blocks. Looks for a matching transform for each
13975 * top-level tag. The HTML should be filtered to not have any text between
13976 * top-level tags and formatted in a way that blocks can handle the HTML.
13977 *
13978 * @param {string} html HTML to convert.
13979 * @param {Function} handler The handler calling htmlToBlocks: either rawHandler
13980 * or pasteHandler.
13981 *
13982 * @return {Array} An array of blocks.
13983 */
13984 function htmlToBlocks(html, handler) {
13985 const doc = document.implementation.createHTMLDocument('');
13986 doc.body.innerHTML = html;
13987 return Array.from(doc.body.children).flatMap(node => {
13988 const rawTransform = findTransform(getRawTransforms(), ({
13989 isMatch
13990 }) => isMatch(node));
13991 if (!rawTransform) {
13992 // Until the HTML block is supported in the native version, we'll parse it
13993 // instead of creating the block to generate it as an unsupported block.
13994 if (external_wp_element_namespaceObject.Platform.isNative) {
13995 return parser_parse(`<!-- wp:html -->${node.outerHTML}<!-- /wp:html -->`);
13996 }
13997 return createBlock(
13998 // Should not be hardcoded.
13999 'core/html', getBlockAttributes('core/html', node.outerHTML));
14000 }
14001 const {
14002 transform,
14003 blockName
14004 } = rawTransform;
14005 if (transform) {
14006 const block = transform(node, handler);
14007 if (node.hasAttribute('class')) {
14008 block.attributes.className = node.getAttribute('class');
14009 }
14010 return block;
14011 }
14012 return createBlock(blockName, getBlockAttributes(blockName, node.outerHTML));
14013 });
14014 }
14015
14016 ;// ./packages/blocks/build-module/api/raw-handling/normalise-blocks.js
14017 /**
14018 * WordPress dependencies
14019 */
14020
14021 function normaliseBlocks(HTML, options = {}) {
14022 const decuDoc = document.implementation.createHTMLDocument('');
14023 const accuDoc = document.implementation.createHTMLDocument('');
14024 const decu = decuDoc.body;
14025 const accu = accuDoc.body;
14026 decu.innerHTML = HTML;
14027 while (decu.firstChild) {
14028 const node = decu.firstChild;
14029
14030 // Text nodes: wrap in a paragraph, or append to previous.
14031 if (node.nodeType === node.TEXT_NODE) {
14032 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
14033 decu.removeChild(node);
14034 } else {
14035 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
14036 accu.appendChild(accuDoc.createElement('P'));
14037 }
14038 accu.lastChild.appendChild(node);
14039 }
14040 // Element nodes.
14041 } else if (node.nodeType === node.ELEMENT_NODE) {
14042 // BR nodes: create a new paragraph on double, or append to previous.
14043 if (node.nodeName === 'BR') {
14044 if (node.nextSibling && node.nextSibling.nodeName === 'BR') {
14045 accu.appendChild(accuDoc.createElement('P'));
14046 decu.removeChild(node.nextSibling);
14047 }
14048
14049 // Don't append to an empty paragraph.
14050 if (accu.lastChild && accu.lastChild.nodeName === 'P' && accu.lastChild.hasChildNodes()) {
14051 accu.lastChild.appendChild(node);
14052 } else {
14053 decu.removeChild(node);
14054 }
14055 } else if (node.nodeName === 'P') {
14056 // Only append non-empty paragraph nodes.
14057 if ((0,external_wp_dom_namespaceObject.isEmpty)(node) && !options.raw) {
14058 decu.removeChild(node);
14059 } else {
14060 accu.appendChild(node);
14061 }
14062 } else if ((0,external_wp_dom_namespaceObject.isPhrasingContent)(node)) {
14063 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
14064 accu.appendChild(accuDoc.createElement('P'));
14065 }
14066 accu.lastChild.appendChild(node);
14067 } else {
14068 accu.appendChild(node);
14069 }
14070 } else {
14071 decu.removeChild(node);
14072 }
14073 }
14074 return accu.innerHTML;
14075 }
14076
14077 ;// ./packages/blocks/build-module/api/raw-handling/special-comment-converter.js
14078 /**
14079 * WordPress dependencies
14080 */
14081
14082
14083 /**
14084 * Looks for `<!--nextpage-->` and `<!--more-->` comments and
14085 * replaces them with a custom element representing a future block.
14086 *
14087 * The custom element is a way to bypass the rest of the `raw-handling`
14088 * transforms, which would eliminate other kinds of node with which to carry
14089 * `<!--more-->`'s data: nodes with `data` attributes, empty paragraphs, etc.
14090 *
14091 * The custom element is then expected to be recognized by any registered
14092 * block's `raw` transform.
14093 *
14094 * @param {Node} node The node to be processed.
14095 * @param {Document} doc The document of the node.
14096 * @return {void}
14097 */
14098 function specialCommentConverter(node, doc) {
14099 if (node.nodeType !== node.COMMENT_NODE) {
14100 return;
14101 }
14102 if (node.nodeValue !== 'nextpage' && node.nodeValue.indexOf('more') !== 0) {
14103 return;
14104 }
14105 const block = special_comment_converter_createBlock(node, doc);
14106
14107 // If our `<!--more-->` comment is in the middle of a paragraph, we should
14108 // split the paragraph in two and insert the more block in between. If it's
14109 // inside an empty paragraph, we should still move it out of the paragraph
14110 // and remove the paragraph. If there's no paragraph, fall back to simply
14111 // replacing the comment.
14112 if (!node.parentNode || node.parentNode.nodeName !== 'P') {
14113 (0,external_wp_dom_namespaceObject.replace)(node, block);
14114 } else {
14115 const childNodes = Array.from(node.parentNode.childNodes);
14116 const nodeIndex = childNodes.indexOf(node);
14117 const wrapperNode = node.parentNode.parentNode || doc.body;
14118 const paragraphBuilder = (acc, child) => {
14119 if (!acc) {
14120 acc = doc.createElement('p');
14121 }
14122 acc.appendChild(child);
14123 return acc;
14124 };
14125
14126 // Split the original parent node and insert our more block
14127 [childNodes.slice(0, nodeIndex).reduce(paragraphBuilder, null), block, childNodes.slice(nodeIndex + 1).reduce(paragraphBuilder, null)].forEach(element => element && wrapperNode.insertBefore(element, node.parentNode));
14128
14129 // Remove the old parent paragraph
14130 (0,external_wp_dom_namespaceObject.remove)(node.parentNode);
14131 }
14132 }
14133 function special_comment_converter_createBlock(commentNode, doc) {
14134 if (commentNode.nodeValue === 'nextpage') {
14135 return createNextpage(doc);
14136 }
14137
14138 // Grab any custom text in the comment.
14139 const customText = commentNode.nodeValue.slice(4).trim();
14140
14141 /*
14142 * When a `<!--more-->` comment is found, we need to look for any
14143 * `<!--noteaser-->` sibling, but it may not be a direct sibling
14144 * (whitespace typically lies in between)
14145 */
14146 let sibling = commentNode;
14147 let noTeaser = false;
14148 while (sibling = sibling.nextSibling) {
14149 if (sibling.nodeType === sibling.COMMENT_NODE && sibling.nodeValue === 'noteaser') {
14150 noTeaser = true;
14151 (0,external_wp_dom_namespaceObject.remove)(sibling);
14152 break;
14153 }
14154 }
14155 return createMore(customText, noTeaser, doc);
14156 }
14157 function createMore(customText, noTeaser, doc) {
14158 const node = doc.createElement('wp-block');
14159 node.dataset.block = 'core/more';
14160 if (customText) {
14161 node.dataset.customText = customText;
14162 }
14163 if (noTeaser) {
14164 // "Boolean" data attribute.
14165 node.dataset.noTeaser = '';
14166 }
14167 return node;
14168 }
14169 function createNextpage(doc) {
14170 const node = doc.createElement('wp-block');
14171 node.dataset.block = 'core/nextpage';
14172 return node;
14173 }
14174
14175 ;// ./packages/blocks/build-module/api/raw-handling/list-reducer.js
14176 /**
14177 * WordPress dependencies
14178 */
14179
14180 function isList(node) {
14181 return node.nodeName === 'OL' || node.nodeName === 'UL';
14182 }
14183 function shallowTextContent(element) {
14184 return Array.from(element.childNodes).map(({
14185 nodeValue = ''
14186 }) => nodeValue).join('');
14187 }
14188 function listReducer(node) {
14189 if (!isList(node)) {
14190 return;
14191 }
14192 const list = node;
14193 const prevElement = node.previousElementSibling;
14194
14195 // Merge with previous list if:
14196 // * There is a previous list of the same type.
14197 // * There is only one list item.
14198 if (prevElement && prevElement.nodeName === node.nodeName && list.children.length === 1) {
14199 // Move all child nodes, including any text nodes, if any.
14200 while (list.firstChild) {
14201 prevElement.appendChild(list.firstChild);
14202 }
14203 list.parentNode.removeChild(list);
14204 }
14205 const parentElement = node.parentNode;
14206
14207 // Nested list with empty parent item.
14208 if (parentElement && parentElement.nodeName === 'LI' && parentElement.children.length === 1 && !/\S/.test(shallowTextContent(parentElement))) {
14209 const parentListItem = parentElement;
14210 const prevListItem = parentListItem.previousElementSibling;
14211 const parentList = parentListItem.parentNode;
14212 if (prevListItem) {
14213 prevListItem.appendChild(list);
14214 parentList.removeChild(parentListItem);
14215 }
14216 }
14217
14218 // Invalid: OL/UL > OL/UL.
14219 if (parentElement && isList(parentElement)) {
14220 const prevListItem = node.previousElementSibling;
14221 if (prevListItem) {
14222 prevListItem.appendChild(node);
14223 } else {
14224 (0,external_wp_dom_namespaceObject.unwrap)(node);
14225 }
14226 }
14227 }
14228
14229 ;// ./packages/blocks/build-module/api/raw-handling/blockquote-normaliser.js
14230 /**
14231 * Internal dependencies
14232 */
14233
14234 function blockquoteNormaliser(options) {
14235 return node => {
14236 if (node.nodeName !== 'BLOCKQUOTE') {
14237 return;
14238 }
14239 node.innerHTML = normaliseBlocks(node.innerHTML, options);
14240 };
14241 }
14242
14243 ;// ./packages/blocks/build-module/api/raw-handling/figure-content-reducer.js
14244 /**
14245 * WordPress dependencies
14246 */
14247
14248
14249 /**
14250 * Whether or not the given node is figure content.
14251 *
14252 * @param {Node} node The node to check.
14253 * @param {Object} schema The schema to use.
14254 *
14255 * @return {boolean} True if figure content, false if not.
14256 */
14257 function isFigureContent(node, schema) {
14258 var _schema$figure$childr;
14259 const tag = node.nodeName.toLowerCase();
14260
14261 // We are looking for tags that can be a child of the figure tag, excluding
14262 // `figcaption` and any phrasing content.
14263 if (tag === 'figcaption' || (0,external_wp_dom_namespaceObject.isTextContent)(node)) {
14264 return false;
14265 }
14266 return tag in ((_schema$figure$childr = schema?.figure?.children) !== null && _schema$figure$childr !== void 0 ? _schema$figure$childr : {});
14267 }
14268
14269 /**
14270 * Whether or not the given node can have an anchor.
14271 *
14272 * @param {Node} node The node to check.
14273 * @param {Object} schema The schema to use.
14274 *
14275 * @return {boolean} True if it can, false if not.
14276 */
14277 function canHaveAnchor(node, schema) {
14278 var _schema$figure$childr2;
14279 const tag = node.nodeName.toLowerCase();
14280 return tag in ((_schema$figure$childr2 = schema?.figure?.children?.a?.children) !== null && _schema$figure$childr2 !== void 0 ? _schema$figure$childr2 : {});
14281 }
14282
14283 /**
14284 * Wraps the given element in a figure element.
14285 *
14286 * @param {Element} element The element to wrap.
14287 * @param {Element} beforeElement The element before which to place the figure.
14288 */
14289 function wrapFigureContent(element, beforeElement = element) {
14290 const figure = element.ownerDocument.createElement('figure');
14291 beforeElement.parentNode.insertBefore(figure, beforeElement);
14292 figure.appendChild(element);
14293 }
14294
14295 /**
14296 * This filter takes figure content out of paragraphs, wraps it in a figure
14297 * element, and moves any anchors with it if needed.
14298 *
14299 * @param {Node} node The node to filter.
14300 * @param {Document} doc The document of the node.
14301 * @param {Object} schema The schema to use.
14302 *
14303 * @return {void}
14304 */
14305 function figureContentReducer(node, doc, schema) {
14306 if (!isFigureContent(node, schema)) {
14307 return;
14308 }
14309 let nodeToInsert = node;
14310 const parentNode = node.parentNode;
14311
14312 // If the figure content can have an anchor and its parent is an anchor with
14313 // only the figure content, take the anchor out instead of just the content.
14314 if (canHaveAnchor(node, schema) && parentNode.nodeName === 'A' && parentNode.childNodes.length === 1) {
14315 nodeToInsert = node.parentNode;
14316 }
14317 const wrapper = nodeToInsert.closest('p,div');
14318
14319 // If wrapped in a paragraph or div, only extract if it's aligned or if
14320 // there is no text content.
14321 // Otherwise, if directly at the root, wrap in a figure element.
14322 if (wrapper) {
14323 // In jsdom-jscore, 'node.classList' can be undefined.
14324 // In this case, default to extract as it offers a better UI experience on mobile.
14325 if (!node.classList) {
14326 wrapFigureContent(nodeToInsert, wrapper);
14327 } else if (node.classList.contains('alignright') || node.classList.contains('alignleft') || node.classList.contains('aligncenter') || !wrapper.textContent.trim()) {
14328 wrapFigureContent(nodeToInsert, wrapper);
14329 }
14330 } else {
14331 wrapFigureContent(nodeToInsert);
14332 }
14333 }
14334
14335 ;// external ["wp","shortcode"]
14336 const external_wp_shortcode_namespaceObject = window["wp"]["shortcode"];
14337 ;// ./packages/blocks/build-module/api/raw-handling/shortcode-converter.js
14338 /**
14339 * WordPress dependencies
14340 */
14341
14342
14343 /**
14344 * Internal dependencies
14345 */
14346
14347
14348
14349
14350 const castArray = maybeArray => Array.isArray(maybeArray) ? maybeArray : [maybeArray];
14351 const beforeLineRegexp = /(\n|<p>)\s*$/;
14352 const afterLineRegexp = /^\s*(\n|<\/p>)/;
14353 function segmentHTMLToShortcodeBlock(HTML, lastIndex = 0, excludedBlockNames = []) {
14354 // Get all matches.
14355 const transformsFrom = getBlockTransforms('from');
14356 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)));
14357 if (!transformation) {
14358 return [HTML];
14359 }
14360 const transformTags = castArray(transformation.tag);
14361 const transformTag = transformTags.find(tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML));
14362 let match;
14363 const previousIndex = lastIndex;
14364 if (match = (0,external_wp_shortcode_namespaceObject.next)(transformTag, HTML, lastIndex)) {
14365 lastIndex = match.index + match.content.length;
14366 const beforeHTML = HTML.substr(0, match.index);
14367 const afterHTML = HTML.substr(lastIndex);
14368
14369 // If the shortcode content does not contain HTML and the shortcode is
14370 // not on a new line (or in paragraph from Markdown converter),
14371 // consider the shortcode as inline text, and thus skip conversion for
14372 // this segment.
14373 if (!match.shortcode.content?.includes('<') && !(beforeLineRegexp.test(beforeHTML) && afterLineRegexp.test(afterHTML))) {
14374 return segmentHTMLToShortcodeBlock(HTML, lastIndex);
14375 }
14376
14377 // If a transformation's `isMatch` predicate fails for the inbound
14378 // shortcode, try again by excluding the current block type.
14379 //
14380 // This is the only call to `segmentHTMLToShortcodeBlock` that should
14381 // ever carry over `excludedBlockNames`. Other calls in the module
14382 // should skip that argument as a way to reset the exclusion state, so
14383 // that one `isMatch` fail in an HTML fragment doesn't prevent any
14384 // valid matches in subsequent fragments.
14385 if (transformation.isMatch && !transformation.isMatch(match.shortcode.attrs)) {
14386 return segmentHTMLToShortcodeBlock(HTML, previousIndex, [...excludedBlockNames, transformation.blockName]);
14387 }
14388 let blocks = [];
14389 if (typeof transformation.transform === 'function') {
14390 // Passing all of `match` as second argument is intentionally broad
14391 // but shouldn't be too relied upon.
14392 //
14393 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14394 blocks = [].concat(transformation.transform(match.shortcode.attrs, match));
14395
14396 // Applying the built-in fixes can enhance the attributes with missing content like "className".
14397 blocks = blocks.map(block => {
14398 block.originalContent = match.shortcode.content;
14399 return applyBuiltInValidationFixes(block, getBlockType(block.name));
14400 });
14401 } else {
14402 const attributes = Object.fromEntries(Object.entries(transformation.attributes).filter(([, schema]) => schema.shortcode)
14403 // Passing all of `match` as second argument is intentionally broad
14404 // but shouldn't be too relied upon.
14405 //
14406 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
14407 .map(([key, schema]) => [key, schema.shortcode(match.shortcode.attrs, match)]));
14408 const blockType = getBlockType(transformation.blockName);
14409 if (!blockType) {
14410 return [HTML];
14411 }
14412 const transformationBlockType = {
14413 ...blockType,
14414 attributes: transformation.attributes
14415 };
14416 let block = createBlock(transformation.blockName, getBlockAttributes(transformationBlockType, match.shortcode.content, attributes));
14417
14418 // Applying the built-in fixes can enhance the attributes with missing content like "className".
14419 block.originalContent = match.shortcode.content;
14420 block = applyBuiltInValidationFixes(block, transformationBlockType);
14421 blocks = [block];
14422 }
14423 return [...segmentHTMLToShortcodeBlock(beforeHTML.replace(beforeLineRegexp, '')), ...blocks, ...segmentHTMLToShortcodeBlock(afterHTML.replace(afterLineRegexp, ''))];
14424 }
14425 return [HTML];
14426 }
14427 /* harmony default export */ const shortcode_converter = (segmentHTMLToShortcodeBlock);
14428
14429 ;// ./packages/blocks/build-module/api/raw-handling/utils.js
14430 /**
14431 * WordPress dependencies
14432 */
14433
14434
14435 /**
14436 * Internal dependencies
14437 */
14438
14439
14440 function getBlockContentSchemaFromTransforms(transforms, context) {
14441 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14442 const schemaArgs = {
14443 phrasingContentSchema,
14444 isPaste: context === 'paste'
14445 };
14446 const schemas = transforms.map(({
14447 isMatch,
14448 blockName,
14449 schema
14450 }) => {
14451 const hasAnchorSupport = hasBlockSupport(blockName, 'anchor');
14452 schema = typeof schema === 'function' ? schema(schemaArgs) : schema;
14453
14454 // If the block does not has anchor support and the transform does not
14455 // provides an isMatch we can return the schema right away.
14456 if (!hasAnchorSupport && !isMatch) {
14457 return schema;
14458 }
14459 if (!schema) {
14460 return {};
14461 }
14462 return Object.fromEntries(Object.entries(schema).map(([key, value]) => {
14463 let attributes = value.attributes || [];
14464 // If the block supports the "anchor" functionality, it needs to keep its ID attribute.
14465 if (hasAnchorSupport) {
14466 attributes = [...attributes, 'id'];
14467 }
14468 return [key, {
14469 ...value,
14470 attributes,
14471 isMatch: isMatch ? isMatch : undefined
14472 }];
14473 }));
14474 });
14475 function mergeTagNameSchemaProperties(objValue, srcValue, key) {
14476 switch (key) {
14477 case 'children':
14478 {
14479 if (objValue === '*' || srcValue === '*') {
14480 return '*';
14481 }
14482 return {
14483 ...objValue,
14484 ...srcValue
14485 };
14486 }
14487 case 'attributes':
14488 case 'require':
14489 {
14490 return [...(objValue || []), ...(srcValue || [])];
14491 }
14492 case 'isMatch':
14493 {
14494 // If one of the values being merge is undefined (matches everything),
14495 // the result of the merge will be undefined.
14496 if (!objValue || !srcValue) {
14497 return undefined;
14498 }
14499 // When merging two isMatch functions, the result is a new function
14500 // that returns if one of the source functions returns true.
14501 return (...args) => {
14502 return objValue(...args) || srcValue(...args);
14503 };
14504 }
14505 }
14506 }
14507
14508 // A tagName schema is an object with children, attributes, require, and
14509 // isMatch properties.
14510 function mergeTagNameSchemas(a, b) {
14511 for (const key in b) {
14512 a[key] = a[key] ? mergeTagNameSchemaProperties(a[key], b[key], key) : {
14513 ...b[key]
14514 };
14515 }
14516 return a;
14517 }
14518
14519 // A schema is an object with tagName schemas by tag name.
14520 function mergeSchemas(a, b) {
14521 for (const key in b) {
14522 a[key] = a[key] ? mergeTagNameSchemas(a[key], b[key]) : {
14523 ...b[key]
14524 };
14525 }
14526 return a;
14527 }
14528 return schemas.reduce(mergeSchemas, {});
14529 }
14530
14531 /**
14532 * Gets the block content schema, which is extracted and merged from all
14533 * registered blocks with raw transfroms.
14534 *
14535 * @param {string} context Set to "paste" when in paste context, where the
14536 * schema is more strict.
14537 *
14538 * @return {Object} A complete block content schema.
14539 */
14540 function getBlockContentSchema(context) {
14541 return getBlockContentSchemaFromTransforms(getRawTransforms(), context);
14542 }
14543
14544 /**
14545 * Checks whether HTML can be considered plain text. That is, it does not contain
14546 * any elements that are not line breaks.
14547 *
14548 * @param {string} HTML The HTML to check.
14549 *
14550 * @return {boolean} Whether the HTML can be considered plain text.
14551 */
14552 function isPlain(HTML) {
14553 return !/<(?!br[ />])/i.test(HTML);
14554 }
14555
14556 /**
14557 * Given node filters, deeply filters and mutates a NodeList.
14558 *
14559 * @param {NodeList} nodeList The nodeList to filter.
14560 * @param {Array} filters An array of functions that can mutate with the provided node.
14561 * @param {Document} doc The document of the nodeList.
14562 * @param {Object} schema The schema to use.
14563 */
14564 function deepFilterNodeList(nodeList, filters, doc, schema) {
14565 Array.from(nodeList).forEach(node => {
14566 deepFilterNodeList(node.childNodes, filters, doc, schema);
14567 filters.forEach(item => {
14568 // Make sure the node is still attached to the document.
14569 if (!doc.contains(node)) {
14570 return;
14571 }
14572 item(node, doc, schema);
14573 });
14574 });
14575 }
14576
14577 /**
14578 * Given node filters, deeply filters HTML tags.
14579 * Filters from the deepest nodes to the top.
14580 *
14581 * @param {string} HTML The HTML to filter.
14582 * @param {Array} filters An array of functions that can mutate with the provided node.
14583 * @param {Object} schema The schema to use.
14584 *
14585 * @return {string} The filtered HTML.
14586 */
14587 function deepFilterHTML(HTML, filters = [], schema) {
14588 const doc = document.implementation.createHTMLDocument('');
14589 doc.body.innerHTML = HTML;
14590 deepFilterNodeList(doc.body.childNodes, filters, doc, schema);
14591 return doc.body.innerHTML;
14592 }
14593
14594 /**
14595 * Gets a sibling within text-level context.
14596 *
14597 * @param {Element} node The subject node.
14598 * @param {string} which "next" or "previous".
14599 */
14600 function getSibling(node, which) {
14601 const sibling = node[`${which}Sibling`];
14602 if (sibling && (0,external_wp_dom_namespaceObject.isPhrasingContent)(sibling)) {
14603 return sibling;
14604 }
14605 const {
14606 parentNode
14607 } = node;
14608 if (!parentNode || !(0,external_wp_dom_namespaceObject.isPhrasingContent)(parentNode)) {
14609 return;
14610 }
14611 return getSibling(parentNode, which);
14612 }
14613
14614 ;// ./packages/blocks/build-module/api/raw-handling/index.js
14615 /**
14616 * WordPress dependencies
14617 */
14618
14619
14620
14621 /**
14622 * Internal dependencies
14623 */
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634 function deprecatedGetPhrasingContentSchema(context) {
14635 external_wp_deprecated_default()('wp.blocks.getPhrasingContentSchema', {
14636 since: '5.6',
14637 alternative: 'wp.dom.getPhrasingContentSchema'
14638 });
14639 return (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
14640 }
14641
14642 /**
14643 * Converts an HTML string to known blocks.
14644 *
14645 * @param {Object} $1
14646 * @param {string} $1.HTML The HTML to convert.
14647 *
14648 * @return {Array} A list of blocks.
14649 */
14650 function rawHandler({
14651 HTML = ''
14652 }) {
14653 // If we detect block delimiters, parse entirely as blocks.
14654 if (HTML.indexOf('<!-- wp:') !== -1) {
14655 const parseResult = parser_parse(HTML);
14656 const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform';
14657 if (!isSingleFreeFormBlock) {
14658 return parseResult;
14659 }
14660 }
14661
14662 // An array of HTML strings and block objects. The blocks replace matched
14663 // shortcodes.
14664 const pieces = shortcode_converter(HTML);
14665 const blockContentSchema = getBlockContentSchema();
14666 return pieces.map(piece => {
14667 // Already a block from shortcode.
14668 if (typeof piece !== 'string') {
14669 return piece;
14670 }
14671
14672 // These filters are essential for some blocks to be able to transform
14673 // from raw HTML. These filters move around some content or add
14674 // additional tags, they do not remove any content.
14675 const filters = [
14676 // Needed to adjust invalid lists.
14677 listReducer,
14678 // Needed to create more and nextpage blocks.
14679 specialCommentConverter,
14680 // Needed to create media blocks.
14681 figureContentReducer,
14682 // Needed to create the quote block, which cannot handle text
14683 // without wrapper paragraphs.
14684 blockquoteNormaliser({
14685 raw: true
14686 })];
14687 piece = deepFilterHTML(piece, filters, blockContentSchema);
14688 piece = normaliseBlocks(piece, {
14689 raw: true
14690 });
14691 return htmlToBlocks(piece, rawHandler);
14692 }).flat().filter(Boolean);
14693 }
14694
14695 ;// ./packages/blocks/build-module/api/raw-handling/comment-remover.js
14696 /**
14697 * WordPress dependencies
14698 */
14699
14700
14701 /**
14702 * Looks for comments, and removes them.
14703 *
14704 * @param {Node} node The node to be processed.
14705 * @return {void}
14706 */
14707 function commentRemover(node) {
14708 if (node.nodeType === node.COMMENT_NODE) {
14709 (0,external_wp_dom_namespaceObject.remove)(node);
14710 }
14711 }
14712
14713 ;// ./packages/blocks/build-module/api/raw-handling/is-inline-content.js
14714 /**
14715 * WordPress dependencies
14716 */
14717
14718
14719 /**
14720 * Checks if the given node should be considered inline content, optionally
14721 * depending on a context tag.
14722 *
14723 * @param {Node} node Node name.
14724 * @param {string} contextTag Tag name.
14725 *
14726 * @return {boolean} True if the node is inline content, false if nohe.
14727 */
14728 function isInline(node, contextTag) {
14729 if ((0,external_wp_dom_namespaceObject.isTextContent)(node)) {
14730 return true;
14731 }
14732 if (!contextTag) {
14733 return false;
14734 }
14735 const tag = node.nodeName.toLowerCase();
14736 const inlineAllowedTagGroups = [['ul', 'li', 'ol'], ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']];
14737 return inlineAllowedTagGroups.some(tagGroup => [tag, contextTag].filter(t => !tagGroup.includes(t)).length === 0);
14738 }
14739 function deepCheck(nodes, contextTag) {
14740 return nodes.every(node => isInline(node, contextTag) && deepCheck(Array.from(node.children), contextTag));
14741 }
14742 function isDoubleBR(node) {
14743 return node.nodeName === 'BR' && node.previousSibling && node.previousSibling.nodeName === 'BR';
14744 }
14745 function isInlineContent(HTML, contextTag) {
14746 const doc = document.implementation.createHTMLDocument('');
14747 doc.body.innerHTML = HTML;
14748 const nodes = Array.from(doc.body.children);
14749 return !nodes.some(isDoubleBR) && deepCheck(nodes, contextTag);
14750 }
14751
14752 ;// ./packages/blocks/build-module/api/raw-handling/phrasing-content-reducer.js
14753 /**
14754 * WordPress dependencies
14755 */
14756
14757 function phrasingContentReducer(node, doc) {
14758 // In jsdom-jscore, 'node.style' can be null.
14759 // TODO: Explore fixing this by patching jsdom-jscore.
14760 if (node.nodeName === 'SPAN' && node.style) {
14761 const {
14762 fontWeight,
14763 fontStyle,
14764 textDecorationLine,
14765 textDecoration,
14766 verticalAlign
14767 } = node.style;
14768 if (fontWeight === 'bold' || fontWeight === '700') {
14769 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('strong'), node);
14770 }
14771 if (fontStyle === 'italic') {
14772 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('em'), node);
14773 }
14774
14775 // Some DOM implementations (Safari, JSDom) don't support
14776 // style.textDecorationLine, so we check style.textDecoration as a
14777 // fallback.
14778 if (textDecorationLine === 'line-through' || textDecoration.includes('line-through')) {
14779 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('s'), node);
14780 }
14781 if (verticalAlign === 'super') {
14782 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sup'), node);
14783 } else if (verticalAlign === 'sub') {
14784 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sub'), node);
14785 }
14786 } else if (node.nodeName === 'B') {
14787 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'strong');
14788 } else if (node.nodeName === 'I') {
14789 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'em');
14790 } else if (node.nodeName === 'A') {
14791 // In jsdom-jscore, 'node.target' can be null.
14792 // TODO: Explore fixing this by patching jsdom-jscore.
14793 if (node.target && node.target.toLowerCase() === '_blank') {
14794 node.rel = 'noreferrer noopener';
14795 } else {
14796 node.removeAttribute('target');
14797 node.removeAttribute('rel');
14798 }
14799
14800 // Saves anchor elements name attribute as id
14801 if (node.name && !node.id) {
14802 node.id = node.name;
14803 }
14804
14805 // Keeps id only if there is an internal link pointing to it
14806 if (node.id && !node.ownerDocument.querySelector(`[href="#${node.id}"]`)) {
14807 node.removeAttribute('id');
14808 }
14809 }
14810 }
14811
14812 ;// ./packages/blocks/build-module/api/raw-handling/head-remover.js
14813 function headRemover(node) {
14814 if (node.nodeName !== 'SCRIPT' && node.nodeName !== 'NOSCRIPT' && node.nodeName !== 'TEMPLATE' && node.nodeName !== 'STYLE') {
14815 return;
14816 }
14817 node.parentNode.removeChild(node);
14818 }
14819
14820 ;// ./packages/blocks/build-module/api/raw-handling/ms-list-ignore.js
14821 /**
14822 * Looks for comments, and removes them.
14823 *
14824 * @param {Node} node The node to be processed.
14825 * @return {void}
14826 */
14827 function msListIgnore(node) {
14828 if (node.nodeType !== node.ELEMENT_NODE) {
14829 return;
14830 }
14831 const style = node.getAttribute('style');
14832 if (!style || !style.includes('mso-list')) {
14833 return;
14834 }
14835 const rules = style.split(';').reduce((acc, rule) => {
14836 const [key, value] = rule.split(':');
14837 if (key && value) {
14838 acc[key.trim().toLowerCase()] = value.trim().toLowerCase();
14839 }
14840 return acc;
14841 }, {});
14842 if (rules['mso-list'] === 'ignore') {
14843 node.remove();
14844 }
14845 }
14846
14847 ;// ./packages/blocks/build-module/api/raw-handling/ms-list-converter.js
14848 /**
14849 * Internal dependencies
14850 */
14851
14852
14853 function ms_list_converter_isList(node) {
14854 return node.nodeName === 'OL' || node.nodeName === 'UL';
14855 }
14856 function msListConverter(node, doc) {
14857 if (node.nodeName !== 'P') {
14858 return;
14859 }
14860 const style = node.getAttribute('style');
14861 if (!style || !style.includes('mso-list')) {
14862 return;
14863 }
14864 const prevNode = node.previousElementSibling;
14865
14866 // Add new list if no previous.
14867 if (!prevNode || !ms_list_converter_isList(prevNode)) {
14868 // See https://html.spec.whatwg.org/multipage/grouping-content.html#attr-ol-type.
14869 const type = node.textContent.trim().slice(0, 1);
14870 const isNumeric = /[1iIaA]/.test(type);
14871 const newListNode = doc.createElement(isNumeric ? 'ol' : 'ul');
14872 if (isNumeric) {
14873 newListNode.setAttribute('type', type);
14874 }
14875 node.parentNode.insertBefore(newListNode, node);
14876 }
14877 const listNode = node.previousElementSibling;
14878 const listType = listNode.nodeName;
14879 const listItem = doc.createElement('li');
14880 let receivingNode = listNode;
14881
14882 // Add content.
14883 listItem.innerHTML = deepFilterHTML(node.innerHTML, [msListIgnore]);
14884 const matches = /mso-list\s*:[^;]+level([0-9]+)/i.exec(style);
14885 let level = matches ? parseInt(matches[1], 10) - 1 || 0 : 0;
14886
14887 // Change pointer depending on indentation level.
14888 while (level--) {
14889 receivingNode = receivingNode.lastChild || receivingNode;
14890
14891 // If it's a list, move pointer to the last item.
14892 if (ms_list_converter_isList(receivingNode)) {
14893 receivingNode = receivingNode.lastChild || receivingNode;
14894 }
14895 }
14896
14897 // Make sure we append to a list.
14898 if (!ms_list_converter_isList(receivingNode)) {
14899 receivingNode = receivingNode.appendChild(doc.createElement(listType));
14900 }
14901
14902 // Append the list item to the list.
14903 receivingNode.appendChild(listItem);
14904
14905 // Remove the wrapper paragraph.
14906 node.parentNode.removeChild(node);
14907 }
14908
14909 ;// external ["wp","blob"]
14910 const external_wp_blob_namespaceObject = window["wp"]["blob"];
14911 ;// ./packages/blocks/build-module/api/raw-handling/image-corrector.js
14912 /* wp:polyfill */
14913 /**
14914 * WordPress dependencies
14915 */
14916
14917 function imageCorrector(node) {
14918 if (node.nodeName !== 'IMG') {
14919 return;
14920 }
14921 if (node.src.indexOf('file:') === 0) {
14922 node.src = '';
14923 }
14924
14925 // This piece cannot be tested outside a browser env.
14926 if (node.src.indexOf('data:') === 0) {
14927 const [properties, data] = node.src.split(',');
14928 const [type] = properties.slice(5).split(';');
14929 if (!data || !type) {
14930 node.src = '';
14931 return;
14932 }
14933 let decoded;
14934
14935 // Can throw DOMException!
14936 try {
14937 decoded = atob(data);
14938 } catch (e) {
14939 node.src = '';
14940 return;
14941 }
14942 const uint8Array = new Uint8Array(decoded.length);
14943 for (let i = 0; i < uint8Array.length; i++) {
14944 uint8Array[i] = decoded.charCodeAt(i);
14945 }
14946 const name = type.replace('/', '.');
14947 const file = new window.File([uint8Array], name, {
14948 type
14949 });
14950 node.src = (0,external_wp_blob_namespaceObject.createBlobURL)(file);
14951 }
14952
14953 // Remove trackers and hardly visible images.
14954 if (node.height === 1 || node.width === 1) {
14955 node.parentNode.removeChild(node);
14956 }
14957 }
14958
14959 ;// ./packages/blocks/build-module/api/raw-handling/div-normaliser.js
14960 /**
14961 * Internal dependencies
14962 */
14963
14964 function divNormaliser(node) {
14965 if (node.nodeName !== 'DIV') {
14966 return;
14967 }
14968 node.innerHTML = normaliseBlocks(node.innerHTML);
14969 }
14970
14971 // EXTERNAL MODULE: ./node_modules/showdown/dist/showdown.js
14972 var showdown = __webpack_require__(1030);
14973 var showdown_default = /*#__PURE__*/__webpack_require__.n(showdown);
14974 ;// ./packages/blocks/build-module/api/raw-handling/markdown-converter.js
14975 /**
14976 * External dependencies
14977 */
14978
14979
14980 // Reuse the same showdown converter.
14981 const converter = new (showdown_default()).Converter({
14982 noHeaderId: true,
14983 tables: true,
14984 literalMidWordUnderscores: true,
14985 omitExtraWLInCodeBlocks: true,
14986 simpleLineBreaks: true,
14987 strikethrough: true
14988 });
14989
14990 /**
14991 * Corrects the Slack Markdown variant of the code block.
14992 * If uncorrected, it will be converted to inline code.
14993 *
14994 * @see https://get.slack.help/hc/en-us/articles/202288908-how-can-i-add-formatting-to-my-messages-#code-blocks
14995 *
14996 * @param {string} text The potential Markdown text to correct.
14997 *
14998 * @return {string} The corrected Markdown.
14999 */
15000 function slackMarkdownVariantCorrector(text) {
15001 return text.replace(/((?:^|\n)```)([^\n`]+)(```(?:$|\n))/, (match, p1, p2, p3) => `${p1}\n${p2}\n${p3}`);
15002 }
15003 function bulletsToAsterisks(text) {
15004 return text.replace(/(^|\n)•( +)/g, '$1*$2');
15005 }
15006
15007 /**
15008 * Converts a piece of text into HTML based on any Markdown present.
15009 * Also decodes any encoded HTML.
15010 *
15011 * @param {string} text The plain text to convert.
15012 *
15013 * @return {string} HTML.
15014 */
15015 function markdownConverter(text) {
15016 return converter.makeHtml(slackMarkdownVariantCorrector(bulletsToAsterisks(text)));
15017 }
15018
15019 ;// ./packages/blocks/build-module/api/raw-handling/iframe-remover.js
15020 /**
15021 * Removes iframes.
15022 *
15023 * @param {Node} node The node to check.
15024 *
15025 * @return {void}
15026 */
15027 function iframeRemover(node) {
15028 if (node.nodeName === 'IFRAME') {
15029 const text = node.ownerDocument.createTextNode(node.src);
15030 node.parentNode.replaceChild(text, node);
15031 }
15032 }
15033
15034 ;// ./packages/blocks/build-module/api/raw-handling/google-docs-uid-remover.js
15035 /**
15036 * WordPress dependencies
15037 */
15038
15039 function googleDocsUIdRemover(node) {
15040 if (!node.id || node.id.indexOf('docs-internal-guid-') !== 0) {
15041 return;
15042 }
15043
15044 // Google Docs sometimes wraps the content in a B tag. We don't want to keep
15045 // this.
15046 if (node.tagName === 'B') {
15047 (0,external_wp_dom_namespaceObject.unwrap)(node);
15048 } else {
15049 node.removeAttribute('id');
15050 }
15051 }
15052
15053 ;// ./packages/blocks/build-module/api/raw-handling/html-formatting-remover.js
15054 /**
15055 * Internal dependencies
15056 */
15057
15058 function isFormattingSpace(character) {
15059 return character === ' ' || character === '\r' || character === '\n' || character === '\t';
15060 }
15061
15062 /**
15063 * Removes spacing that formats HTML.
15064 *
15065 * @see https://www.w3.org/TR/css-text-3/#white-space-processing
15066 *
15067 * @param {Node} node The node to be processed.
15068 * @return {void}
15069 */
15070 function htmlFormattingRemover(node) {
15071 if (node.nodeType !== node.TEXT_NODE) {
15072 return;
15073 }
15074
15075 // Ignore pre content. Note that this does not use Element#closest due to
15076 // a combination of (a) node may not be Element and (b) node.parentElement
15077 // does not have full support in all browsers (Internet Exporer).
15078 //
15079 // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility
15080
15081 /** @type {Node?} */
15082 let parent = node;
15083 while (parent = parent.parentNode) {
15084 if (parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE') {
15085 return;
15086 }
15087 }
15088
15089 // First, replace any sequence of HTML formatting space with a single space.
15090 let newData = node.data.replace(/[ \r\n\t]+/g, ' ');
15091
15092 // Remove the leading space if the text element is at the start of a block,
15093 // is preceded by a line break element, or has a space in the previous
15094 // node.
15095 if (newData[0] === ' ') {
15096 const previousSibling = getSibling(node, 'previous');
15097 if (!previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice(-1) === ' ') {
15098 newData = newData.slice(1);
15099 }
15100 }
15101
15102 // Remove the trailing space if the text element is at the end of a block,
15103 // is succeded by a line break element, or has a space in the next text
15104 // node.
15105 if (newData[newData.length - 1] === ' ') {
15106 const nextSibling = getSibling(node, 'next');
15107 if (!nextSibling || nextSibling.nodeName === 'BR' || nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace(nextSibling.textContent[0])) {
15108 newData = newData.slice(0, -1);
15109 }
15110 }
15111
15112 // If there's no data left, remove the node, so `previousSibling` stays
15113 // accurate. Otherwise, update the node data.
15114 if (!newData) {
15115 node.parentNode.removeChild(node);
15116 } else {
15117 node.data = newData;
15118 }
15119 }
15120
15121 ;// ./packages/blocks/build-module/api/raw-handling/br-remover.js
15122 /**
15123 * Internal dependencies
15124 */
15125
15126
15127 /**
15128 * Removes trailing br elements from text-level content.
15129 *
15130 * @param {Element} node Node to check.
15131 */
15132 function brRemover(node) {
15133 if (node.nodeName !== 'BR') {
15134 return;
15135 }
15136 if (getSibling(node, 'next')) {
15137 return;
15138 }
15139 node.parentNode.removeChild(node);
15140 }
15141
15142 ;// ./packages/blocks/build-module/api/raw-handling/empty-paragraph-remover.js
15143 /**
15144 * Removes empty paragraph elements.
15145 *
15146 * @param {Element} node Node to check.
15147 */
15148 function emptyParagraphRemover(node) {
15149 if (node.nodeName !== 'P') {
15150 return;
15151 }
15152 if (node.hasChildNodes()) {
15153 return;
15154 }
15155 node.parentNode.removeChild(node);
15156 }
15157
15158 ;// ./packages/blocks/build-module/api/raw-handling/slack-paragraph-corrector.js
15159 /**
15160 * Replaces Slack paragraph markup with a double line break (later converted to
15161 * a proper paragraph).
15162 *
15163 * @param {Element} node Node to check.
15164 */
15165 function slackParagraphCorrector(node) {
15166 if (node.nodeName !== 'SPAN') {
15167 return;
15168 }
15169 if (node.getAttribute('data-stringify-type') !== 'paragraph-break') {
15170 return;
15171 }
15172 const {
15173 parentNode
15174 } = node;
15175 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
15176 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
15177 parentNode.removeChild(node);
15178 }
15179
15180 ;// ./packages/blocks/build-module/api/raw-handling/paste-handler.js
15181 /**
15182 * WordPress dependencies
15183 */
15184
15185
15186 /**
15187 * Internal dependencies
15188 */
15189
15190
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208
15209
15210
15211
15212
15213
15214
15215 const log = (...args) => window?.console?.log?.(...args);
15216
15217 /**
15218 * Filters HTML to only contain phrasing content.
15219 *
15220 * @param {string} HTML The HTML to filter.
15221 *
15222 * @return {string} HTML only containing phrasing content.
15223 */
15224 function filterInlineHTML(HTML) {
15225 HTML = deepFilterHTML(HTML, [headRemover, googleDocsUIdRemover, msListIgnore, phrasingContentReducer, commentRemover]);
15226 HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
15227 inline: true
15228 });
15229 HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
15230
15231 // Allows us to ask for this information when we get a report.
15232 log('Processed inline HTML:\n\n', HTML);
15233 return HTML;
15234 }
15235
15236 /**
15237 * Converts an HTML string to known blocks. Strips everything else.
15238 *
15239 * @param {Object} options
15240 * @param {string} [options.HTML] The HTML to convert.
15241 * @param {string} [options.plainText] Plain text version.
15242 * @param {string} [options.mode] Handle content as blocks or inline content.
15243 * * 'AUTO': Decide based on the content passed.
15244 * * 'INLINE': Always handle as inline content, and return string.
15245 * * 'BLOCKS': Always handle as blocks, and return array of blocks.
15246 * @param {Array} [options.tagName] The tag into which content will be inserted.
15247 *
15248 * @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
15249 */
15250 function pasteHandler({
15251 HTML = '',
15252 plainText = '',
15253 mode = 'AUTO',
15254 tagName
15255 }) {
15256 // First of all, strip any meta tags.
15257 HTML = HTML.replace(/<meta[^>]+>/g, '');
15258 // Strip Windows markers.
15259 HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
15260 HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, '');
15261
15262 // If we detect block delimiters in HTML, parse entirely as blocks.
15263 if (mode !== 'INLINE') {
15264 // Check plain text if there is no HTML.
15265 const content = HTML ? HTML : plainText;
15266 if (content.indexOf('<!-- wp:') !== -1) {
15267 const parseResult = parser_parse(content);
15268 const isSingleFreeFormBlock = parseResult.length === 1 && parseResult[0].name === 'core/freeform';
15269 if (!isSingleFreeFormBlock) {
15270 return parseResult;
15271 }
15272 }
15273 }
15274
15275 // Normalize unicode to use composed characters.
15276 // Not normalizing the content will only affect older browsers and won't
15277 // entirely break the app.
15278 // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
15279 // See: https://core.trac.wordpress.org/ticket/30130
15280 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
15281 if (String.prototype.normalize) {
15282 HTML = HTML.normalize();
15283 }
15284
15285 // Must be run before checking if it's inline content.
15286 HTML = deepFilterHTML(HTML, [slackParagraphCorrector]);
15287
15288 // Consider plain text if:
15289 // * There is a plain text version.
15290 // * There is no HTML version, or it has no formatting.
15291 const isPlainText = plainText && (!HTML || isPlain(HTML));
15292
15293 // Parse Markdown (and encoded HTML) if it's considered plain text.
15294 if (isPlainText) {
15295 HTML = plainText;
15296
15297 // The markdown converter (Showdown) trims whitespace.
15298 if (!/^\s+$/.test(plainText)) {
15299 HTML = markdownConverter(HTML);
15300 }
15301 }
15302
15303 // An array of HTML strings and block objects. The blocks replace matched
15304 // shortcodes.
15305 const pieces = shortcode_converter(HTML);
15306
15307 // The call to shortcodeConverter will always return more than one element
15308 // if shortcodes are matched. The reason is when shortcodes are matched
15309 // empty HTML strings are included.
15310 const hasShortcodes = pieces.length > 1;
15311 if (isPlainText && !hasShortcodes) {
15312 // Switch to inline mode if:
15313 // * The current mode is AUTO.
15314 // * The original plain text had no line breaks.
15315 // * The original plain text was not an HTML paragraph.
15316 // * The converted text is just a paragraph.
15317 if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
15318 mode = 'INLINE';
15319 }
15320 }
15321 if (mode === 'INLINE') {
15322 return filterInlineHTML(HTML);
15323 }
15324 if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
15325 return filterInlineHTML(HTML);
15326 }
15327 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
15328 const blockContentSchema = getBlockContentSchema('paste');
15329 const blocks = pieces.map(piece => {
15330 // Already a block from shortcode.
15331 if (typeof piece !== 'string') {
15332 return piece;
15333 }
15334 const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser(), divNormaliser];
15335 const schema = {
15336 ...blockContentSchema,
15337 // Keep top-level phrasing content, normalised by `normaliseBlocks`.
15338 ...phrasingContentSchema
15339 };
15340 piece = deepFilterHTML(piece, filters, blockContentSchema);
15341 piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
15342 piece = normaliseBlocks(piece);
15343 piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema);
15344
15345 // Allows us to ask for this information when we get a report.
15346 log('Processed HTML piece:\n\n', piece);
15347 return htmlToBlocks(piece, pasteHandler);
15348 }).flat().filter(Boolean);
15349
15350 // If we're allowed to return inline content, and there is only one
15351 // inlineable block, and the original plain text content does not have any
15352 // line breaks, then treat it as inline paste.
15353 if (mode === 'AUTO' && blocks.length === 1 && hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
15354 const trimRegex = /^[\n]+|[\n]+$/g;
15355 // Don't catch line breaks at the start or end.
15356 const trimmedPlainText = plainText.replace(trimRegex, '');
15357 if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
15358 return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema).replace(trimRegex, '');
15359 }
15360 }
15361 return blocks;
15362 }
15363
15364 ;// ./packages/blocks/build-module/api/categories.js
15365 /**
15366 * WordPress dependencies
15367 */
15368
15369
15370 /**
15371 * Internal dependencies
15372 */
15373
15374
15375 /** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
15376
15377 /**
15378 * Returns all the block categories.
15379 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
15380 *
15381 * @ignore
15382 *
15383 * @return {WPBlockCategory[]} Block categories.
15384 */
15385 function categories_getCategories() {
15386 return (0,external_wp_data_namespaceObject.select)(store).getCategories();
15387 }
15388
15389 /**
15390 * Sets the block categories.
15391 *
15392 * @param {WPBlockCategory[]} categories Block categories.
15393 *
15394 * @example
15395 * ```js
15396 * import { __ } from '@wordpress/i18n';
15397 * import { store as blocksStore, setCategories } from '@wordpress/blocks';
15398 * import { useSelect } from '@wordpress/data';
15399 * import { Button } from '@wordpress/components';
15400 *
15401 * const ExampleComponent = () => {
15402 * // Retrieve the list of current categories.
15403 * const blockCategories = useSelect(
15404 * ( select ) => select( blocksStore ).getCategories(),
15405 * []
15406 * );
15407 *
15408 * return (
15409 * <Button
15410 * onClick={ () => {
15411 * // Add a custom category to the existing list.
15412 * setCategories( [
15413 * ...blockCategories,
15414 * { title: 'Custom Category', slug: 'custom-category' },
15415 * ] );
15416 * } }
15417 * >
15418 * { __( 'Add a new custom block category' ) }
15419 * </Button>
15420 * );
15421 * };
15422 * ```
15423 */
15424 function categories_setCategories(categories) {
15425 (0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
15426 }
15427
15428 /**
15429 * Updates a category.
15430 *
15431 * @param {string} slug Block category slug.
15432 * @param {WPBlockCategory} category Object containing the category properties
15433 * that should be updated.
15434 *
15435 * @example
15436 * ```js
15437 * import { __ } from '@wordpress/i18n';
15438 * import { updateCategory } from '@wordpress/blocks';
15439 * import { Button } from '@wordpress/components';
15440 *
15441 * const ExampleComponent = () => {
15442 * return (
15443 * <Button
15444 * onClick={ () => {
15445 * updateCategory( 'text', { title: __( 'Written Word' ) } );
15446 * } }
15447 * >
15448 * { __( 'Update Text category title' ) }
15449 * </Button>
15450 * ) ;
15451 * };
15452 * ```
15453 */
15454 function categories_updateCategory(slug, category) {
15455 (0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
15456 }
15457
15458 ;// ./packages/blocks/build-module/api/templates.js
15459 /**
15460 * WordPress dependencies
15461 */
15462
15463
15464 /**
15465 * Internal dependencies
15466 */
15467
15468
15469
15470
15471 /**
15472 * Checks whether a list of blocks matches a template by comparing the block names.
15473 *
15474 * @param {Array} blocks Block list.
15475 * @param {Array} template Block template.
15476 *
15477 * @return {boolean} Whether the list of blocks matches a templates.
15478 */
15479 function doBlocksMatchTemplate(blocks = [], template = []) {
15480 return blocks.length === template.length && template.every(([name,, innerBlocksTemplate], index) => {
15481 const block = blocks[index];
15482 return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
15483 });
15484 }
15485 const isHTMLAttribute = attributeDefinition => attributeDefinition?.source === 'html';
15486 const isQueryAttribute = attributeDefinition => attributeDefinition?.source === 'query';
15487 function normalizeAttributes(schema, values) {
15488 if (!values) {
15489 return {};
15490 }
15491 return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, normalizeAttribute(schema[key], value)]));
15492 }
15493 function normalizeAttribute(definition, value) {
15494 if (isHTMLAttribute(definition) && Array.isArray(value)) {
15495 // Introduce a deprecated call at this point
15496 // When we're confident that "children" format should be removed from the templates.
15497
15498 return (0,external_wp_element_namespaceObject.renderToString)(value);
15499 }
15500 if (isQueryAttribute(definition) && value) {
15501 return value.map(subValues => {
15502 return normalizeAttributes(definition.query, subValues);
15503 });
15504 }
15505 return value;
15506 }
15507
15508 /**
15509 * Synchronize a block list with a block template.
15510 *
15511 * Synchronizing a block list with a block template means that we loop over the blocks
15512 * keep the block as is if it matches the block at the same position in the template
15513 * (If it has the same name) and if doesn't match, we create a new block based on the template.
15514 * Extra blocks not present in the template are removed.
15515 *
15516 * @param {Array} blocks Block list.
15517 * @param {Array} template Block template.
15518 *
15519 * @return {Array} Updated Block list.
15520 */
15521 function synchronizeBlocksWithTemplate(blocks = [], template) {
15522 // If no template is provided, return blocks unmodified.
15523 if (!template) {
15524 return blocks;
15525 }
15526 return template.map(([name, attributes, innerBlocksTemplate], index) => {
15527 var _blockType$attributes;
15528 const block = blocks[index];
15529 if (block && block.name === name) {
15530 const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
15531 return {
15532 ...block,
15533 innerBlocks
15534 };
15535 }
15536
15537 // To support old templates that were using the "children" format
15538 // for the attributes using "html" strings now, we normalize the template attributes
15539 // before creating the blocks.
15540
15541 const blockType = getBlockType(name);
15542 const normalizedAttributes = normalizeAttributes((_blockType$attributes = blockType?.attributes) !== null && _blockType$attributes !== void 0 ? _blockType$attributes : {}, attributes);
15543 let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes);
15544
15545 // If a Block is undefined at this point, use the core/missing block as
15546 // a placeholder for a better user experience.
15547 if (undefined === getBlockType(blockName)) {
15548 blockAttributes = {
15549 originalName: name,
15550 originalContent: '',
15551 originalUndelimitedContent: ''
15552 };
15553 blockName = 'core/missing';
15554 }
15555 return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
15556 });
15557 }
15558
15559 ;// ./packages/blocks/build-module/api/index.js
15560 /**
15561 * Internal dependencies
15562 */
15563
15564
15565
15566 // The blocktype is the most important concept within the block API. It defines
15567 // all aspects of the block configuration and its interfaces, including `edit`
15568 // and `save`. The transforms specification allows converting one blocktype to
15569 // another through formulas defined by either the source or the destination.
15570 // Switching a blocktype is to be considered a one-way operation implying a
15571 // transformation in the opposite way has to be handled explicitly.
15572
15573
15574 // The block tree is composed of a collection of block nodes. Blocks contained
15575 // within other blocks are called inner blocks. An important design
15576 // consideration is that inner blocks are -- conceptually -- not part of the
15577 // territory established by the parent block that contains them.
15578 //
15579 // This has multiple practical implications: when parsing, we can safely dispose
15580 // of any block boundary found within a block from the innerHTML property when
15581 // transfering to state. Not doing so would have a compounding effect on memory
15582 // and uncertainty over the source of truth. This can be illustrated in how,
15583 // given a tree of `n` nested blocks, the entry node would have to contain the
15584 // actual content of each block while each subsequent block node in the state
15585 // tree would replicate the entire chain `n-1`, meaning the extreme end node
15586 // would have been replicated `n` times as the tree is traversed and would
15587 // generate uncertainty as to which one is to hold the current value of the
15588 // block. For composition, it also means inner blocks can effectively be child
15589 // components whose mechanisms can be shielded from the `edit` implementation
15590 // and just passed along.
15591
15592
15593
15594
15595 // While block transformations account for a specific surface of the API, there
15596 // are also raw transformations which handle arbitrary sources not made out of
15597 // blocks but producing block basaed on various heursitics. This includes
15598 // pasting rich text or HTML data.
15599
15600
15601 // The process of serialization aims to deflate the internal memory of the block
15602 // editor and its state representation back into an HTML valid string. This
15603 // process restores the document integrity and inserts invisible delimiters
15604 // around each block with HTML comment boundaries which can contain any extra
15605 // attributes needed to operate with the block later on.
15606
15607
15608 // Validation is the process of comparing a block source with its output before
15609 // there is any user input or interaction with a block. When this operation
15610 // fails -- for whatever reason -- the block is to be considered invalid. As
15611 // part of validating a block the system will attempt to run the source against
15612 // any provided deprecation definitions.
15613 //
15614 // Worth emphasizing that validation is not a case of whether the markup is
15615 // merely HTML spec-compliant but about how the editor knows to create such
15616 // markup and that its inability to create an identical result can be a strong
15617 // indicator of potential data loss (the invalidation is then a protective
15618 // measure).
15619 //
15620 // The invalidation process can also be deconstructed in phases: 1) validate the
15621 // block exists; 2) validate the source matches the output; 3) validate the
15622 // source matches deprecated outputs; 4) work through the significance of
15623 // differences. These are stacked in a way that favors performance and optimizes
15624 // for the majority of cases. That is to say, the evaluation logic can become
15625 // more sophisticated the further down it goes in the process as the cost is
15626 // accounted for. The first logic checks have to be extremely efficient since
15627 // they will be run for all valid and invalid blocks alike. However, once a
15628 // block is detected as invalid -- failing the three first steps -- it is
15629 // adequate to spend more time determining validity before throwing a conflict.
15630
15631
15632
15633 // Blocks are inherently indifferent about where the data they operate with ends
15634 // up being saved. For example, all blocks can have a static and dynamic aspect
15635 // to them depending on the needs. The static nature of a block is the `save()`
15636 // definition that is meant to be serialized into HTML and which can be left
15637 // void. Any block can also register a `render_callback` on the server, which
15638 // makes its output dynamic either in part or in its totality.
15639 //
15640 // Child blocks are defined as a relationship that builds on top of the inner
15641 // blocks mechanism. A child block is a block node of a particular type that can
15642 // only exist within the inner block boundaries of a specific parent type. This
15643 // allows block authors to compose specific blocks that are not meant to be used
15644 // outside of a specified parent block context. Thus, child blocks extend the
15645 // concept of inner blocks to support a more direct relationship between sets of
15646 // blocks. The addition of parent–child would be a subset of the inner block
15647 // functionality under the premise that certain blocks only make sense as
15648 // children of another block.
15649
15650
15651
15652 // Templates are, in a general sense, a basic collection of block nodes with any
15653 // given set of predefined attributes that are supplied as the initial state of
15654 // an inner blocks group. These nodes can, in turn, contain any number of nested
15655 // blocks within their definition. Templates allow both to specify a default
15656 // state for an editor session or a default set of blocks for any inner block
15657 // implementation within a specific block.
15658
15659
15660
15661
15662 const privateApis = {};
15663 lock(privateApis, {
15664 isUnmodifiedBlockContent: isUnmodifiedBlockContent
15665 });
15666
15667 ;// ./packages/blocks/build-module/deprecated.js
15668 /**
15669 * WordPress dependencies
15670 */
15671
15672
15673 /**
15674 * A Higher Order Component used to inject BlockContent using context to the
15675 * wrapped component.
15676 *
15677 * @deprecated
15678 *
15679 * @param {Component} OriginalComponent The component to enhance.
15680 * @return {Component} The same component.
15681 */
15682 function withBlockContentContext(OriginalComponent) {
15683 external_wp_deprecated_default()('wp.blocks.withBlockContentContext', {
15684 since: '6.1'
15685 });
15686 return OriginalComponent;
15687 }
15688
15689 ;// ./packages/blocks/build-module/index.js
15690 // A "block" is the abstract term used to describe units of markup that,
15691 // when composed together, form the content or layout of a page.
15692 // The API for blocks is exposed via `wp.blocks`.
15693 //
15694 // Supported blocks are registered by calling `registerBlockType`. Once registered,
15695 // the block is made available as an option to the editor interface.
15696 //
15697 // Blocks are inferred from the HTML source of a post through a parsing mechanism
15698 // and then stored as objects in state, from which it is then rendered for editing.
15699
15700
15701
15702
15703
15704 })();
15705
15706 (window.wp = window.wp || {}).blocks = __webpack_exports__;
15707 /******/ })()
15708 ;