PluginProbe
Gutenberg / 14.0.2
Gutenberg v14.0.2
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 14.0.2, at build/blocks/index.js

14,954 lines 507.5 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 /***/ 9756:
5 /***/ ((module) => {
6
7 /**
8 * Memize options object.
9 *
10 * @typedef MemizeOptions
11 *
12 * @property {number} [maxSize] Maximum size of the cache.
13 */
14
15 /**
16 * Internal cache entry.
17 *
18 * @typedef MemizeCacheNode
19 *
20 * @property {?MemizeCacheNode|undefined} [prev] Previous node.
21 * @property {?MemizeCacheNode|undefined} [next] Next node.
22 * @property {Array<*>} args Function arguments for cache
23 * entry.
24 * @property {*} val Function result.
25 */
26
27 /**
28 * Properties of the enhanced function for controlling cache.
29 *
30 * @typedef MemizeMemoizedFunction
31 *
32 * @property {()=>void} clear Clear the cache.
33 */
34
35 /**
36 * Accepts a function to be memoized, and returns a new memoized function, with
37 * optional options.
38 *
39 * @template {Function} F
40 *
41 * @param {F} fn Function to memoize.
42 * @param {MemizeOptions} [options] Options object.
43 *
44 * @return {F & MemizeMemoizedFunction} Memoized function.
45 */
46 function memize( fn, options ) {
47 var size = 0;
48
49 /** @type {?MemizeCacheNode|undefined} */
50 var head;
51
52 /** @type {?MemizeCacheNode|undefined} */
53 var tail;
54
55 options = options || {};
56
57 function memoized( /* ...args */ ) {
58 var node = head,
59 len = arguments.length,
60 args, i;
61
62 searchCache: while ( node ) {
63 // Perform a shallow equality test to confirm that whether the node
64 // under test is a candidate for the arguments passed. Two arrays
65 // are shallowly equal if their length matches and each entry is
66 // strictly equal between the two sets. Avoid abstracting to a
67 // function which could incur an arguments leaking deoptimization.
68
69 // Check whether node arguments match arguments length
70 if ( node.args.length !== arguments.length ) {
71 node = node.next;
72 continue;
73 }
74
75 // Check whether node arguments match arguments values
76 for ( i = 0; i < len; i++ ) {
77 if ( node.args[ i ] !== arguments[ i ] ) {
78 node = node.next;
79 continue searchCache;
80 }
81 }
82
83 // At this point we can assume we've found a match
84
85 // Surface matched node to head if not already
86 if ( node !== head ) {
87 // As tail, shift to previous. Must only shift if not also
88 // head, since if both head and tail, there is no previous.
89 if ( node === tail ) {
90 tail = node.prev;
91 }
92
93 // Adjust siblings to point to each other. If node was tail,
94 // this also handles new tail's empty `next` assignment.
95 /** @type {MemizeCacheNode} */ ( node.prev ).next = node.next;
96 if ( node.next ) {
97 node.next.prev = node.prev;
98 }
99
100 node.next = head;
101 node.prev = null;
102 /** @type {MemizeCacheNode} */ ( head ).prev = node;
103 head = node;
104 }
105
106 // Return immediately
107 return node.val;
108 }
109
110 // No cached value found. Continue to insertion phase:
111
112 // Create a copy of arguments (avoid leaking deoptimization)
113 args = new Array( len );
114 for ( i = 0; i < len; i++ ) {
115 args[ i ] = arguments[ i ];
116 }
117
118 node = {
119 args: args,
120
121 // Generate the result from original function
122 val: fn.apply( null, args ),
123 };
124
125 // Don't need to check whether node is already head, since it would
126 // have been returned above already if it was
127
128 // Shift existing head down list
129 if ( head ) {
130 head.prev = node;
131 node.next = head;
132 } else {
133 // If no head, follows that there's no tail (at initial or reset)
134 tail = node;
135 }
136
137 // Trim tail if we're reached max size and are pending cache insertion
138 if ( size === /** @type {MemizeOptions} */ ( options ).maxSize ) {
139 tail = /** @type {MemizeCacheNode} */ ( tail ).prev;
140 /** @type {MemizeCacheNode} */ ( tail ).next = null;
141 } else {
142 size++;
143 }
144
145 head = node;
146
147 return node.val;
148 }
149
150 memoized.clear = function() {
151 head = null;
152 tail = null;
153 size = 0;
154 };
155
156 if ( false ) {}
157
158 // Ignore reason: There's not a clear solution to create an intersection of
159 // the function with additional properties, where the goal is to retain the
160 // function signature of the incoming argument and add control properties
161 // on the return value.
162
163 // @ts-ignore
164 return memoized;
165 }
166
167 module.exports = memize;
168
169
170 /***/ }),
171
172 /***/ 4793:
173 /***/ ((module) => {
174
175 var characterMap = {
176 "À": "A",
177 "Á": "A",
178 "Â": "A",
179 "Ã": "A",
180 "Ä": "A",
181 "Å": "A",
182 "Ấ": "A",
183 "Ắ": "A",
184 "Ẳ": "A",
185 "Ẵ": "A",
186 "Ặ": "A",
187 "Æ": "AE",
188 "Ầ": "A",
189 "Ằ": "A",
190 "Ȃ": "A",
191 "Ç": "C",
192 "Ḉ": "C",
193 "È": "E",
194 "É": "E",
195 "Ê": "E",
196 "Ë": "E",
197 "Ế": "E",
198 "Ḗ": "E",
199 "Ề": "E",
200 "Ḕ": "E",
201 "Ḝ": "E",
202 "Ȇ": "E",
203 "Ì": "I",
204 "Í": "I",
205 "Î": "I",
206 "Ï": "I",
207 "Ḯ": "I",
208 "Ȋ": "I",
209 "Ð": "D",
210 "Ñ": "N",
211 "Ò": "O",
212 "Ó": "O",
213 "Ô": "O",
214 "Õ": "O",
215 "Ö": "O",
216 "Ø": "O",
217 "Ố": "O",
218 "Ṍ": "O",
219 "Ṓ": "O",
220 "Ȏ": "O",
221 "Ù": "U",
222 "Ú": "U",
223 "Û": "U",
224 "Ü": "U",
225 "Ý": "Y",
226 "à": "a",
227 "á": "a",
228 "â": "a",
229 "ã": "a",
230 "ä": "a",
231 "å": "a",
232 "ấ": "a",
233 "ắ": "a",
234 "ẳ": "a",
235 "ẵ": "a",
236 "ặ": "a",
237 "æ": "ae",
238 "ầ": "a",
239 "ằ": "a",
240 "ȃ": "a",
241 "ç": "c",
242 "ḉ": "c",
243 "è": "e",
244 "é": "e",
245 "ê": "e",
246 "ë": "e",
247 "ế": "e",
248 "ḗ": "e",
249 "ề": "e",
250 "ḕ": "e",
251 "ḝ": "e",
252 "ȇ": "e",
253 "ì": "i",
254 "í": "i",
255 "î": "i",
256 "ï": "i",
257 "ḯ": "i",
258 "ȋ": "i",
259 "ð": "d",
260 "ñ": "n",
261 "ò": "o",
262 "ó": "o",
263 "ô": "o",
264 "õ": "o",
265 "ö": "o",
266 "ø": "o",
267 "ố": "o",
268 "ṍ": "o",
269 "ṓ": "o",
270 "ȏ": "o",
271 "ù": "u",
272 "ú": "u",
273 "û": "u",
274 "ü": "u",
275 "ý": "y",
276 "ÿ": "y",
277 "Ā": "A",
278 "ā": "a",
279 "Ă": "A",
280 "ă": "a",
281 "Ą": "A",
282 "ą": "a",
283 "Ć": "C",
284 "ć": "c",
285 "Ĉ": "C",
286 "ĉ": "c",
287 "Ċ": "C",
288 "ċ": "c",
289 "Č": "C",
290 "č": "c",
291 "C̆": "C",
292 "c̆": "c",
293 "Ď": "D",
294 "ď": "d",
295 "Đ": "D",
296 "đ": "d",
297 "Ē": "E",
298 "ē": "e",
299 "Ĕ": "E",
300 "ĕ": "e",
301 "Ė": "E",
302 "ė": "e",
303 "Ę": "E",
304 "ę": "e",
305 "Ě": "E",
306 "ě": "e",
307 "Ĝ": "G",
308 "Ǵ": "G",
309 "ĝ": "g",
310 "ǵ": "g",
311 "Ğ": "G",
312 "ğ": "g",
313 "Ġ": "G",
314 "ġ": "g",
315 "Ģ": "G",
316 "ģ": "g",
317 "Ĥ": "H",
318 "ĥ": "h",
319 "Ħ": "H",
320 "ħ": "h",
321 "Ḫ": "H",
322 "ḫ": "h",
323 "Ĩ": "I",
324 "ĩ": "i",
325 "Ī": "I",
326 "ī": "i",
327 "Ĭ": "I",
328 "ĭ": "i",
329 "Į": "I",
330 "į": "i",
331 "İ": "I",
332 "ı": "i",
333 "IJ": "IJ",
334 "ij": "ij",
335 "Ĵ": "J",
336 "ĵ": "j",
337 "Ķ": "K",
338 "ķ": "k",
339 "Ḱ": "K",
340 "ḱ": "k",
341 "K̆": "K",
342 "k̆": "k",
343 "Ĺ": "L",
344 "ĺ": "l",
345 "Ļ": "L",
346 "ļ": "l",
347 "Ľ": "L",
348 "ľ": "l",
349 "Ŀ": "L",
350 "ŀ": "l",
351 "Ł": "l",
352 "ł": "l",
353 "Ḿ": "M",
354 "ḿ": "m",
355 "M̆": "M",
356 "m̆": "m",
357 "Ń": "N",
358 "ń": "n",
359 "Ņ": "N",
360 "ņ": "n",
361 "Ň": "N",
362 "ň": "n",
363 "ʼn": "n",
364 "N̆": "N",
365 "n̆": "n",
366 "Ō": "O",
367 "ō": "o",
368 "Ŏ": "O",
369 "ŏ": "o",
370 "Ő": "O",
371 "ő": "o",
372 "Œ": "OE",
373 "œ": "oe",
374 "P̆": "P",
375 "p̆": "p",
376 "Ŕ": "R",
377 "ŕ": "r",
378 "Ŗ": "R",
379 "ŗ": "r",
380 "Ř": "R",
381 "ř": "r",
382 "R̆": "R",
383 "r̆": "r",
384 "Ȓ": "R",
385 "ȓ": "r",
386 "Ś": "S",
387 "ś": "s",
388 "Ŝ": "S",
389 "ŝ": "s",
390 "Ş": "S",
391 "Ș": "S",
392 "ș": "s",
393 "ş": "s",
394 "Š": "S",
395 "š": "s",
396 "Ţ": "T",
397 "ţ": "t",
398 "ț": "t",
399 "Ț": "T",
400 "Ť": "T",
401 "ť": "t",
402 "Ŧ": "T",
403 "ŧ": "t",
404 "T̆": "T",
405 "t̆": "t",
406 "Ũ": "U",
407 "ũ": "u",
408 "Ū": "U",
409 "ū": "u",
410 "Ŭ": "U",
411 "ŭ": "u",
412 "Ů": "U",
413 "ů": "u",
414 "Ű": "U",
415 "ű": "u",
416 "Ų": "U",
417 "ų": "u",
418 "Ȗ": "U",
419 "ȗ": "u",
420 "V̆": "V",
421 "v̆": "v",
422 "Ŵ": "W",
423 "ŵ": "w",
424 "Ẃ": "W",
425 "ẃ": "w",
426 "X̆": "X",
427 "x̆": "x",
428 "Ŷ": "Y",
429 "ŷ": "y",
430 "Ÿ": "Y",
431 "Y̆": "Y",
432 "y̆": "y",
433 "Ź": "Z",
434 "ź": "z",
435 "Ż": "Z",
436 "ż": "z",
437 "Ž": "Z",
438 "ž": "z",
439 "ſ": "s",
440 "ƒ": "f",
441 "Ơ": "O",
442 "ơ": "o",
443 "Ư": "U",
444 "ư": "u",
445 "Ǎ": "A",
446 "ǎ": "a",
447 "Ǐ": "I",
448 "ǐ": "i",
449 "Ǒ": "O",
450 "ǒ": "o",
451 "Ǔ": "U",
452 "ǔ": "u",
453 "Ǖ": "U",
454 "ǖ": "u",
455 "Ǘ": "U",
456 "ǘ": "u",
457 "Ǚ": "U",
458 "ǚ": "u",
459 "Ǜ": "U",
460 "ǜ": "u",
461 "Ứ": "U",
462 "ứ": "u",
463 "Ṹ": "U",
464 "ṹ": "u",
465 "Ǻ": "A",
466 "ǻ": "a",
467 "Ǽ": "AE",
468 "ǽ": "ae",
469 "Ǿ": "O",
470 "ǿ": "o",
471 "Þ": "TH",
472 "þ": "th",
473 "Ṕ": "P",
474 "ṕ": "p",
475 "Ṥ": "S",
476 "ṥ": "s",
477 "X́": "X",
478 "x́": "x",
479 "Ѓ": "Г",
480 "ѓ": "г",
481 "Ќ": "К",
482 "ќ": "к",
483 "A̋": "A",
484 "a̋": "a",
485 "E̋": "E",
486 "e̋": "e",
487 "I̋": "I",
488 "i̋": "i",
489 "Ǹ": "N",
490 "ǹ": "n",
491 "Ồ": "O",
492 "ồ": "o",
493 "Ṑ": "O",
494 "ṑ": "o",
495 "Ừ": "U",
496 "ừ": "u",
497 "Ẁ": "W",
498 "ẁ": "w",
499 "Ỳ": "Y",
500 "ỳ": "y",
501 "Ȁ": "A",
502 "ȁ": "a",
503 "Ȅ": "E",
504 "ȅ": "e",
505 "Ȉ": "I",
506 "ȉ": "i",
507 "Ȍ": "O",
508 "ȍ": "o",
509 "Ȑ": "R",
510 "ȑ": "r",
511 "Ȕ": "U",
512 "ȕ": "u",
513 "B̌": "B",
514 "b̌": "b",
515 "Č̣": "C",
516 "č̣": "c",
517 "Ê̌": "E",
518 "ê̌": "e",
519 "F̌": "F",
520 "f̌": "f",
521 "Ǧ": "G",
522 "ǧ": "g",
523 "Ȟ": "H",
524 "ȟ": "h",
525 "J̌": "J",
526 "ǰ": "j",
527 "Ǩ": "K",
528 "ǩ": "k",
529 "M̌": "M",
530 "m̌": "m",
531 "P̌": "P",
532 "p̌": "p",
533 "Q̌": "Q",
534 "q̌": "q",
535 "Ř̩": "R",
536 "ř̩": "r",
537 "Ṧ": "S",
538 "ṧ": "s",
539 "V̌": "V",
540 "v̌": "v",
541 "W̌": "W",
542 "w̌": "w",
543 "X̌": "X",
544 "x̌": "x",
545 "Y̌": "Y",
546 "y̌": "y",
547 "A̧": "A",
548 "a̧": "a",
549 "B̧": "B",
550 "b̧": "b",
551 "Ḑ": "D",
552 "ḑ": "d",
553 "Ȩ": "E",
554 "ȩ": "e",
555 "Ɛ̧": "E",
556 "ɛ̧": "e",
557 "Ḩ": "H",
558 "ḩ": "h",
559 "I̧": "I",
560 "i̧": "i",
561 "Ɨ̧": "I",
562 "ɨ̧": "i",
563 "M̧": "M",
564 "m̧": "m",
565 "O̧": "O",
566 "o̧": "o",
567 "Q̧": "Q",
568 "q̧": "q",
569 "U̧": "U",
570 "u̧": "u",
571 "X̧": "X",
572 "x̧": "x",
573 "Z̧": "Z",
574 "z̧": "z",
575 };
576
577 var chars = Object.keys(characterMap).join('|');
578 var allAccents = new RegExp(chars, 'g');
579 var firstAccent = new RegExp(chars, '');
580
581 var removeAccents = function(string) {
582 return string.replace(allAccents, function(match) {
583 return characterMap[match];
584 });
585 };
586
587 var hasAccents = function(string) {
588 return !!string.match(firstAccent);
589 };
590
591 module.exports = removeAccents;
592 module.exports.has = hasAccents;
593 module.exports.remove = removeAccents;
594
595
596 /***/ }),
597
598 /***/ 7308:
599 /***/ (function(module, exports, __webpack_require__) {
600
601 var __WEBPACK_AMD_DEFINE_RESULT__;;/*! showdown v 1.9.1 - 02-11-2019 */
602 (function(){
603 /**
604 * Created by Tivie on 13-07-2015.
605 */
606
607 function getDefaultOpts (simple) {
608 'use strict';
609
610 var defaultOptions = {
611 omitExtraWLInCodeBlocks: {
612 defaultValue: false,
613 describe: 'Omit the default extra whiteline added to code blocks',
614 type: 'boolean'
615 },
616 noHeaderId: {
617 defaultValue: false,
618 describe: 'Turn on/off generated header id',
619 type: 'boolean'
620 },
621 prefixHeaderId: {
622 defaultValue: false,
623 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',
624 type: 'string'
625 },
626 rawPrefixHeaderId: {
627 defaultValue: false,
628 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)',
629 type: 'boolean'
630 },
631 ghCompatibleHeaderId: {
632 defaultValue: false,
633 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
634 type: 'boolean'
635 },
636 rawHeaderId: {
637 defaultValue: false,
638 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
639 type: 'boolean'
640 },
641 headerLevelStart: {
642 defaultValue: false,
643 describe: 'The header blocks level start',
644 type: 'integer'
645 },
646 parseImgDimensions: {
647 defaultValue: false,
648 describe: 'Turn on/off image dimension parsing',
649 type: 'boolean'
650 },
651 simplifiedAutoLink: {
652 defaultValue: false,
653 describe: 'Turn on/off GFM autolink style',
654 type: 'boolean'
655 },
656 excludeTrailingPunctuationFromURLs: {
657 defaultValue: false,
658 describe: 'Excludes trailing punctuation from links generated with autoLinking',
659 type: 'boolean'
660 },
661 literalMidWordUnderscores: {
662 defaultValue: false,
663 describe: 'Parse midword underscores as literal underscores',
664 type: 'boolean'
665 },
666 literalMidWordAsterisks: {
667 defaultValue: false,
668 describe: 'Parse midword asterisks as literal asterisks',
669 type: 'boolean'
670 },
671 strikethrough: {
672 defaultValue: false,
673 describe: 'Turn on/off strikethrough support',
674 type: 'boolean'
675 },
676 tables: {
677 defaultValue: false,
678 describe: 'Turn on/off tables support',
679 type: 'boolean'
680 },
681 tablesHeaderId: {
682 defaultValue: false,
683 describe: 'Add an id to table headers',
684 type: 'boolean'
685 },
686 ghCodeBlocks: {
687 defaultValue: true,
688 describe: 'Turn on/off GFM fenced code blocks support',
689 type: 'boolean'
690 },
691 tasklists: {
692 defaultValue: false,
693 describe: 'Turn on/off GFM tasklist support',
694 type: 'boolean'
695 },
696 smoothLivePreview: {
697 defaultValue: false,
698 describe: 'Prevents weird effects in live previews due to incomplete input',
699 type: 'boolean'
700 },
701 smartIndentationFix: {
702 defaultValue: false,
703 description: 'Tries to smartly fix indentation in es6 strings',
704 type: 'boolean'
705 },
706 disableForced4SpacesIndentedSublists: {
707 defaultValue: false,
708 description: 'Disables the requirement of indenting nested sublists by 4 spaces',
709 type: 'boolean'
710 },
711 simpleLineBreaks: {
712 defaultValue: false,
713 description: 'Parses simple line breaks as <br> (GFM Style)',
714 type: 'boolean'
715 },
716 requireSpaceBeforeHeadingText: {
717 defaultValue: false,
718 description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
719 type: 'boolean'
720 },
721 ghMentions: {
722 defaultValue: false,
723 description: 'Enables github @mentions',
724 type: 'boolean'
725 },
726 ghMentionsLink: {
727 defaultValue: 'https://github.com/{u}',
728 description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
729 type: 'string'
730 },
731 encodeEmails: {
732 defaultValue: true,
733 description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
734 type: 'boolean'
735 },
736 openLinksInNewWindow: {
737 defaultValue: false,
738 description: 'Open all links in new windows',
739 type: 'boolean'
740 },
741 backslashEscapesHTMLTags: {
742 defaultValue: false,
743 description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
744 type: 'boolean'
745 },
746 emoji: {
747 defaultValue: false,
748 description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
749 type: 'boolean'
750 },
751 underline: {
752 defaultValue: false,
753 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>`',
754 type: 'boolean'
755 },
756 completeHTMLDocument: {
757 defaultValue: false,
758 description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
759 type: 'boolean'
760 },
761 metadata: {
762 defaultValue: false,
763 description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
764 type: 'boolean'
765 },
766 splitAdjacentBlockquotes: {
767 defaultValue: false,
768 description: 'Split adjacent blockquote blocks',
769 type: 'boolean'
770 }
771 };
772 if (simple === false) {
773 return JSON.parse(JSON.stringify(defaultOptions));
774 }
775 var ret = {};
776 for (var opt in defaultOptions) {
777 if (defaultOptions.hasOwnProperty(opt)) {
778 ret[opt] = defaultOptions[opt].defaultValue;
779 }
780 }
781 return ret;
782 }
783
784 function allOptionsOn () {
785 'use strict';
786 var options = getDefaultOpts(true),
787 ret = {};
788 for (var opt in options) {
789 if (options.hasOwnProperty(opt)) {
790 ret[opt] = true;
791 }
792 }
793 return ret;
794 }
795
796 /**
797 * Created by Tivie on 06-01-2015.
798 */
799
800 // Private properties
801 var showdown = {},
802 parsers = {},
803 extensions = {},
804 globalOptions = getDefaultOpts(true),
805 setFlavor = 'vanilla',
806 flavor = {
807 github: {
808 omitExtraWLInCodeBlocks: true,
809 simplifiedAutoLink: true,
810 excludeTrailingPunctuationFromURLs: true,
811 literalMidWordUnderscores: true,
812 strikethrough: true,
813 tables: true,
814 tablesHeaderId: true,
815 ghCodeBlocks: true,
816 tasklists: true,
817 disableForced4SpacesIndentedSublists: true,
818 simpleLineBreaks: true,
819 requireSpaceBeforeHeadingText: true,
820 ghCompatibleHeaderId: true,
821 ghMentions: true,
822 backslashEscapesHTMLTags: true,
823 emoji: true,
824 splitAdjacentBlockquotes: true
825 },
826 original: {
827 noHeaderId: true,
828 ghCodeBlocks: false
829 },
830 ghost: {
831 omitExtraWLInCodeBlocks: true,
832 parseImgDimensions: true,
833 simplifiedAutoLink: true,
834 excludeTrailingPunctuationFromURLs: true,
835 literalMidWordUnderscores: true,
836 strikethrough: true,
837 tables: true,
838 tablesHeaderId: true,
839 ghCodeBlocks: true,
840 tasklists: true,
841 smoothLivePreview: true,
842 simpleLineBreaks: true,
843 requireSpaceBeforeHeadingText: true,
844 ghMentions: false,
845 encodeEmails: true
846 },
847 vanilla: getDefaultOpts(true),
848 allOn: allOptionsOn()
849 };
850
851 /**
852 * helper namespace
853 * @type {{}}
854 */
855 showdown.helper = {};
856
857 /**
858 * TODO LEGACY SUPPORT CODE
859 * @type {{}}
860 */
861 showdown.extensions = {};
862
863 /**
864 * Set a global option
865 * @static
866 * @param {string} key
867 * @param {*} value
868 * @returns {showdown}
869 */
870 showdown.setOption = function (key, value) {
871 'use strict';
872 globalOptions[key] = value;
873 return this;
874 };
875
876 /**
877 * Get a global option
878 * @static
879 * @param {string} key
880 * @returns {*}
881 */
882 showdown.getOption = function (key) {
883 'use strict';
884 return globalOptions[key];
885 };
886
887 /**
888 * Get the global options
889 * @static
890 * @returns {{}}
891 */
892 showdown.getOptions = function () {
893 'use strict';
894 return globalOptions;
895 };
896
897 /**
898 * Reset global options to the default values
899 * @static
900 */
901 showdown.resetOptions = function () {
902 'use strict';
903 globalOptions = getDefaultOpts(true);
904 };
905
906 /**
907 * Set the flavor showdown should use as default
908 * @param {string} name
909 */
910 showdown.setFlavor = function (name) {
911 'use strict';
912 if (!flavor.hasOwnProperty(name)) {
913 throw Error(name + ' flavor was not found');
914 }
915 showdown.resetOptions();
916 var preset = flavor[name];
917 setFlavor = name;
918 for (var option in preset) {
919 if (preset.hasOwnProperty(option)) {
920 globalOptions[option] = preset[option];
921 }
922 }
923 };
924
925 /**
926 * Get the currently set flavor
927 * @returns {string}
928 */
929 showdown.getFlavor = function () {
930 'use strict';
931 return setFlavor;
932 };
933
934 /**
935 * Get the options of a specified flavor. Returns undefined if the flavor was not found
936 * @param {string} name Name of the flavor
937 * @returns {{}|undefined}
938 */
939 showdown.getFlavorOptions = function (name) {
940 'use strict';
941 if (flavor.hasOwnProperty(name)) {
942 return flavor[name];
943 }
944 };
945
946 /**
947 * Get the default options
948 * @static
949 * @param {boolean} [simple=true]
950 * @returns {{}}
951 */
952 showdown.getDefaultOptions = function (simple) {
953 'use strict';
954 return getDefaultOpts(simple);
955 };
956
957 /**
958 * Get or set a subParser
959 *
960 * subParser(name) - Get a registered subParser
961 * subParser(name, func) - Register a subParser
962 * @static
963 * @param {string} name
964 * @param {function} [func]
965 * @returns {*}
966 */
967 showdown.subParser = function (name, func) {
968 'use strict';
969 if (showdown.helper.isString(name)) {
970 if (typeof func !== 'undefined') {
971 parsers[name] = func;
972 } else {
973 if (parsers.hasOwnProperty(name)) {
974 return parsers[name];
975 } else {
976 throw Error('SubParser named ' + name + ' not registered!');
977 }
978 }
979 }
980 };
981
982 /**
983 * Gets or registers an extension
984 * @static
985 * @param {string} name
986 * @param {object|function=} ext
987 * @returns {*}
988 */
989 showdown.extension = function (name, ext) {
990 'use strict';
991
992 if (!showdown.helper.isString(name)) {
993 throw Error('Extension \'name\' must be a string');
994 }
995
996 name = showdown.helper.stdExtName(name);
997
998 // Getter
999 if (showdown.helper.isUndefined(ext)) {
1000 if (!extensions.hasOwnProperty(name)) {
1001 throw Error('Extension named ' + name + ' is not registered!');
1002 }
1003 return extensions[name];
1004
1005 // Setter
1006 } else {
1007 // Expand extension if it's wrapped in a function
1008 if (typeof ext === 'function') {
1009 ext = ext();
1010 }
1011
1012 // Ensure extension is an array
1013 if (!showdown.helper.isArray(ext)) {
1014 ext = [ext];
1015 }
1016
1017 var validExtension = validate(ext, name);
1018
1019 if (validExtension.valid) {
1020 extensions[name] = ext;
1021 } else {
1022 throw Error(validExtension.error);
1023 }
1024 }
1025 };
1026
1027 /**
1028 * Gets all extensions registered
1029 * @returns {{}}
1030 */
1031 showdown.getAllExtensions = function () {
1032 'use strict';
1033 return extensions;
1034 };
1035
1036 /**
1037 * Remove an extension
1038 * @param {string} name
1039 */
1040 showdown.removeExtension = function (name) {
1041 'use strict';
1042 delete extensions[name];
1043 };
1044
1045 /**
1046 * Removes all extensions
1047 */
1048 showdown.resetExtensions = function () {
1049 'use strict';
1050 extensions = {};
1051 };
1052
1053 /**
1054 * Validate extension
1055 * @param {array} extension
1056 * @param {string} name
1057 * @returns {{valid: boolean, error: string}}
1058 */
1059 function validate (extension, name) {
1060 'use strict';
1061
1062 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
1063 ret = {
1064 valid: true,
1065 error: ''
1066 };
1067
1068 if (!showdown.helper.isArray(extension)) {
1069 extension = [extension];
1070 }
1071
1072 for (var i = 0; i < extension.length; ++i) {
1073 var baseMsg = errMsg + ' sub-extension ' + i + ': ',
1074 ext = extension[i];
1075 if (typeof ext !== 'object') {
1076 ret.valid = false;
1077 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
1078 return ret;
1079 }
1080
1081 if (!showdown.helper.isString(ext.type)) {
1082 ret.valid = false;
1083 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
1084 return ret;
1085 }
1086
1087 var type = ext.type = ext.type.toLowerCase();
1088
1089 // normalize extension type
1090 if (type === 'language') {
1091 type = ext.type = 'lang';
1092 }
1093
1094 if (type === 'html') {
1095 type = ext.type = 'output';
1096 }
1097
1098 if (type !== 'lang' && type !== 'output' && type !== 'listener') {
1099 ret.valid = false;
1100 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
1101 return ret;
1102 }
1103
1104 if (type === 'listener') {
1105 if (showdown.helper.isUndefined(ext.listeners)) {
1106 ret.valid = false;
1107 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
1108 return ret;
1109 }
1110 } else {
1111 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
1112 ret.valid = false;
1113 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
1114 return ret;
1115 }
1116 }
1117
1118 if (ext.listeners) {
1119 if (typeof ext.listeners !== 'object') {
1120 ret.valid = false;
1121 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
1122 return ret;
1123 }
1124 for (var ln in ext.listeners) {
1125 if (ext.listeners.hasOwnProperty(ln)) {
1126 if (typeof ext.listeners[ln] !== 'function') {
1127 ret.valid = false;
1128 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
1129 ' must be a function but ' + typeof ext.listeners[ln] + ' given';
1130 return ret;
1131 }
1132 }
1133 }
1134 }
1135
1136 if (ext.filter) {
1137 if (typeof ext.filter !== 'function') {
1138 ret.valid = false;
1139 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
1140 return ret;
1141 }
1142 } else if (ext.regex) {
1143 if (showdown.helper.isString(ext.regex)) {
1144 ext.regex = new RegExp(ext.regex, 'g');
1145 }
1146 if (!(ext.regex instanceof RegExp)) {
1147 ret.valid = false;
1148 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
1149 return ret;
1150 }
1151 if (showdown.helper.isUndefined(ext.replace)) {
1152 ret.valid = false;
1153 ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
1154 return ret;
1155 }
1156 }
1157 }
1158 return ret;
1159 }
1160
1161 /**
1162 * Validate extension
1163 * @param {object} ext
1164 * @returns {boolean}
1165 */
1166 showdown.validateExtension = function (ext) {
1167 'use strict';
1168
1169 var validateExtension = validate(ext, null);
1170 if (!validateExtension.valid) {
1171 console.warn(validateExtension.error);
1172 return false;
1173 }
1174 return true;
1175 };
1176
1177 /**
1178 * showdownjs helper functions
1179 */
1180
1181 if (!showdown.hasOwnProperty('helper')) {
1182 showdown.helper = {};
1183 }
1184
1185 /**
1186 * Check if var is string
1187 * @static
1188 * @param {string} a
1189 * @returns {boolean}
1190 */
1191 showdown.helper.isString = function (a) {
1192 'use strict';
1193 return (typeof a === 'string' || a instanceof String);
1194 };
1195
1196 /**
1197 * Check if var is a function
1198 * @static
1199 * @param {*} a
1200 * @returns {boolean}
1201 */
1202 showdown.helper.isFunction = function (a) {
1203 'use strict';
1204 var getType = {};
1205 return a && getType.toString.call(a) === '[object Function]';
1206 };
1207
1208 /**
1209 * isArray helper function
1210 * @static
1211 * @param {*} a
1212 * @returns {boolean}
1213 */
1214 showdown.helper.isArray = function (a) {
1215 'use strict';
1216 return Array.isArray(a);
1217 };
1218
1219 /**
1220 * Check if value is undefined
1221 * @static
1222 * @param {*} value The value to check.
1223 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
1224 */
1225 showdown.helper.isUndefined = function (value) {
1226 'use strict';
1227 return typeof value === 'undefined';
1228 };
1229
1230 /**
1231 * ForEach helper function
1232 * Iterates over Arrays and Objects (own properties only)
1233 * @static
1234 * @param {*} obj
1235 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
1236 */
1237 showdown.helper.forEach = function (obj, callback) {
1238 'use strict';
1239 // check if obj is defined
1240 if (showdown.helper.isUndefined(obj)) {
1241 throw new Error('obj param is required');
1242 }
1243
1244 if (showdown.helper.isUndefined(callback)) {
1245 throw new Error('callback param is required');
1246 }
1247
1248 if (!showdown.helper.isFunction(callback)) {
1249 throw new Error('callback param must be a function/closure');
1250 }
1251
1252 if (typeof obj.forEach === 'function') {
1253 obj.forEach(callback);
1254 } else if (showdown.helper.isArray(obj)) {
1255 for (var i = 0; i < obj.length; i++) {
1256 callback(obj[i], i, obj);
1257 }
1258 } else if (typeof (obj) === 'object') {
1259 for (var prop in obj) {
1260 if (obj.hasOwnProperty(prop)) {
1261 callback(obj[prop], prop, obj);
1262 }
1263 }
1264 } else {
1265 throw new Error('obj does not seem to be an array or an iterable object');
1266 }
1267 };
1268
1269 /**
1270 * Standardidize extension name
1271 * @static
1272 * @param {string} s extension name
1273 * @returns {string}
1274 */
1275 showdown.helper.stdExtName = function (s) {
1276 'use strict';
1277 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
1278 };
1279
1280 function escapeCharactersCallback (wholeMatch, m1) {
1281 'use strict';
1282 var charCodeToEscape = m1.charCodeAt(0);
1283 return '¨E' + charCodeToEscape + 'E';
1284 }
1285
1286 /**
1287 * Callback used to escape characters when passing through String.replace
1288 * @static
1289 * @param {string} wholeMatch
1290 * @param {string} m1
1291 * @returns {string}
1292 */
1293 showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
1294
1295 /**
1296 * Escape characters in a string
1297 * @static
1298 * @param {string} text
1299 * @param {string} charsToEscape
1300 * @param {boolean} afterBackslash
1301 * @returns {XML|string|void|*}
1302 */
1303 showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
1304 'use strict';
1305 // First we have to escape the escape characters so that
1306 // we can build a character class out of them
1307 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
1308
1309 if (afterBackslash) {
1310 regexString = '\\\\' + regexString;
1311 }
1312
1313 var regex = new RegExp(regexString, 'g');
1314 text = text.replace(regex, escapeCharactersCallback);
1315
1316 return text;
1317 };
1318
1319 /**
1320 * Unescape HTML entities
1321 * @param txt
1322 * @returns {string}
1323 */
1324 showdown.helper.unescapeHTMLEntities = function (txt) {
1325 'use strict';
1326
1327 return txt
1328 .replace(/&quot;/g, '"')
1329 .replace(/&lt;/g, '<')
1330 .replace(/&gt;/g, '>')
1331 .replace(/&amp;/g, '&');
1332 };
1333
1334 var rgxFindMatchPos = function (str, left, right, flags) {
1335 'use strict';
1336 var f = flags || '',
1337 g = f.indexOf('g') > -1,
1338 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
1339 l = new RegExp(left, f.replace(/g/g, '')),
1340 pos = [],
1341 t, s, m, start, end;
1342
1343 do {
1344 t = 0;
1345 while ((m = x.exec(str))) {
1346 if (l.test(m[0])) {
1347 if (!(t++)) {
1348 s = x.lastIndex;
1349 start = s - m[0].length;
1350 }
1351 } else if (t) {
1352 if (!--t) {
1353 end = m.index + m[0].length;
1354 var obj = {
1355 left: {start: start, end: s},
1356 match: {start: s, end: m.index},
1357 right: {start: m.index, end: end},
1358 wholeMatch: {start: start, end: end}
1359 };
1360 pos.push(obj);
1361 if (!g) {
1362 return pos;
1363 }
1364 }
1365 }
1366 }
1367 } while (t && (x.lastIndex = s));
1368
1369 return pos;
1370 };
1371
1372 /**
1373 * matchRecursiveRegExp
1374 *
1375 * (c) 2007 Steven Levithan <stevenlevithan.com>
1376 * MIT License
1377 *
1378 * Accepts a string to search, a left and right format delimiter
1379 * as regex patterns, and optional regex flags. Returns an array
1380 * of matches, allowing nested instances of left/right delimiters.
1381 * Use the "g" flag to return all matches, otherwise only the
1382 * first is returned. Be careful to ensure that the left and
1383 * right format delimiters produce mutually exclusive matches.
1384 * Backreferences are not supported within the right delimiter
1385 * due to how it is internally combined with the left delimiter.
1386 * When matching strings whose format delimiters are unbalanced
1387 * to the left or right, the output is intentionally as a
1388 * conventional regex library with recursion support would
1389 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
1390 * "<" and ">" as the delimiters (both strings contain a single,
1391 * balanced instance of "<x>").
1392 *
1393 * examples:
1394 * matchRecursiveRegExp("test", "\\(", "\\)")
1395 * returns: []
1396 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
1397 * returns: ["t<<e>><s>", ""]
1398 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
1399 * returns: ["test"]
1400 */
1401 showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
1402 'use strict';
1403
1404 var matchPos = rgxFindMatchPos (str, left, right, flags),
1405 results = [];
1406
1407 for (var i = 0; i < matchPos.length; ++i) {
1408 results.push([
1409 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1410 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1411 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1412 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1413 ]);
1414 }
1415 return results;
1416 };
1417
1418 /**
1419 *
1420 * @param {string} str
1421 * @param {string|function} replacement
1422 * @param {string} left
1423 * @param {string} right
1424 * @param {string} flags
1425 * @returns {string}
1426 */
1427 showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
1428 'use strict';
1429
1430 if (!showdown.helper.isFunction(replacement)) {
1431 var repStr = replacement;
1432 replacement = function () {
1433 return repStr;
1434 };
1435 }
1436
1437 var matchPos = rgxFindMatchPos(str, left, right, flags),
1438 finalStr = str,
1439 lng = matchPos.length;
1440
1441 if (lng > 0) {
1442 var bits = [];
1443 if (matchPos[0].wholeMatch.start !== 0) {
1444 bits.push(str.slice(0, matchPos[0].wholeMatch.start));
1445 }
1446 for (var i = 0; i < lng; ++i) {
1447 bits.push(
1448 replacement(
1449 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1450 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1451 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1452 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1453 )
1454 );
1455 if (i < lng - 1) {
1456 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
1457 }
1458 }
1459 if (matchPos[lng - 1].wholeMatch.end < str.length) {
1460 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
1461 }
1462 finalStr = bits.join('');
1463 }
1464 return finalStr;
1465 };
1466
1467 /**
1468 * Returns the index within the passed String object of the first occurrence of the specified regex,
1469 * starting the search at fromIndex. Returns -1 if the value is not found.
1470 *
1471 * @param {string} str string to search
1472 * @param {RegExp} regex Regular expression to search
1473 * @param {int} [fromIndex = 0] Index to start the search
1474 * @returns {Number}
1475 * @throws InvalidArgumentError
1476 */
1477 showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
1478 'use strict';
1479 if (!showdown.helper.isString(str)) {
1480 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1481 }
1482 if (regex instanceof RegExp === false) {
1483 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
1484 }
1485 var indexOf = str.substring(fromIndex || 0).search(regex);
1486 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
1487 };
1488
1489 /**
1490 * Splits the passed string object at the defined index, and returns an array composed of the two substrings
1491 * @param {string} str string to split
1492 * @param {int} index index to split string at
1493 * @returns {[string,string]}
1494 * @throws InvalidArgumentError
1495 */
1496 showdown.helper.splitAtIndex = function (str, index) {
1497 'use strict';
1498 if (!showdown.helper.isString(str)) {
1499 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1500 }
1501 return [str.substring(0, index), str.substring(index)];
1502 };
1503
1504 /**
1505 * Obfuscate an e-mail address through the use of Character Entities,
1506 * transforming ASCII characters into their equivalent decimal or hex entities.
1507 *
1508 * Since it has a random component, subsequent calls to this function produce different results
1509 *
1510 * @param {string} mail
1511 * @returns {string}
1512 */
1513 showdown.helper.encodeEmailAddress = function (mail) {
1514 'use strict';
1515 var encode = [
1516 function (ch) {
1517 return '&#' + ch.charCodeAt(0) + ';';
1518 },
1519 function (ch) {
1520 return '&#x' + ch.charCodeAt(0).toString(16) + ';';
1521 },
1522 function (ch) {
1523 return ch;
1524 }
1525 ];
1526
1527 mail = mail.replace(/./g, function (ch) {
1528 if (ch === '@') {
1529 // this *must* be encoded. I insist.
1530 ch = encode[Math.floor(Math.random() * 2)](ch);
1531 } else {
1532 var r = Math.random();
1533 // roughly 10% raw, 45% hex, 45% dec
1534 ch = (
1535 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1536 );
1537 }
1538 return ch;
1539 });
1540
1541 return mail;
1542 };
1543
1544 /**
1545 *
1546 * @param str
1547 * @param targetLength
1548 * @param padString
1549 * @returns {string}
1550 */
1551 showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
1552 'use strict';
1553 /*jshint bitwise: false*/
1554 // eslint-disable-next-line space-infix-ops
1555 targetLength = targetLength>>0; //floor if number or convert non-number to 0;
1556 /*jshint bitwise: true*/
1557 padString = String(padString || ' ');
1558 if (str.length > targetLength) {
1559 return String(str);
1560 } else {
1561 targetLength = targetLength - str.length;
1562 if (targetLength > padString.length) {
1563 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
1564 }
1565 return String(str) + padString.slice(0,targetLength);
1566 }
1567 };
1568
1569 /**
1570 * POLYFILLS
1571 */
1572 // use this instead of builtin is undefined for IE8 compatibility
1573 if (typeof console === 'undefined') {
1574 console = {
1575 warn: function (msg) {
1576 'use strict';
1577 alert(msg);
1578 },
1579 log: function (msg) {
1580 'use strict';
1581 alert(msg);
1582 },
1583 error: function (msg) {
1584 'use strict';
1585 throw msg;
1586 }
1587 };
1588 }
1589
1590 /**
1591 * Common regexes.
1592 * We declare some common regexes to improve performance
1593 */
1594 showdown.helper.regexes = {
1595 asteriskDashAndColon: /([*_:~])/g
1596 };
1597
1598 /**
1599 * EMOJIS LIST
1600 */
1601 showdown.helper.emojis = {
1602 '+1':'\ud83d\udc4d',
1603 '-1':'\ud83d\udc4e',
1604 '100':'\ud83d\udcaf',
1605 '1234':'\ud83d\udd22',
1606 '1st_place_medal':'\ud83e\udd47',
1607 '2nd_place_medal':'\ud83e\udd48',
1608 '3rd_place_medal':'\ud83e\udd49',
1609 '8ball':'\ud83c\udfb1',
1610 'a':'\ud83c\udd70\ufe0f',
1611 'ab':'\ud83c\udd8e',
1612 'abc':'\ud83d\udd24',
1613 'abcd':'\ud83d\udd21',
1614 'accept':'\ud83c\ude51',
1615 'aerial_tramway':'\ud83d\udea1',
1616 'airplane':'\u2708\ufe0f',
1617 'alarm_clock':'\u23f0',
1618 'alembic':'\u2697\ufe0f',
1619 'alien':'\ud83d\udc7d',
1620 'ambulance':'\ud83d\ude91',
1621 'amphora':'\ud83c\udffa',
1622 'anchor':'\u2693\ufe0f',
1623 'angel':'\ud83d\udc7c',
1624 'anger':'\ud83d\udca2',
1625 'angry':'\ud83d\ude20',
1626 'anguished':'\ud83d\ude27',
1627 'ant':'\ud83d\udc1c',
1628 'apple':'\ud83c\udf4e',
1629 'aquarius':'\u2652\ufe0f',
1630 'aries':'\u2648\ufe0f',
1631 'arrow_backward':'\u25c0\ufe0f',
1632 'arrow_double_down':'\u23ec',
1633 'arrow_double_up':'\u23eb',
1634 'arrow_down':'\u2b07\ufe0f',
1635 'arrow_down_small':'\ud83d\udd3d',
1636 'arrow_forward':'\u25b6\ufe0f',
1637 'arrow_heading_down':'\u2935\ufe0f',
1638 'arrow_heading_up':'\u2934\ufe0f',
1639 'arrow_left':'\u2b05\ufe0f',
1640 'arrow_lower_left':'\u2199\ufe0f',
1641 'arrow_lower_right':'\u2198\ufe0f',
1642 'arrow_right':'\u27a1\ufe0f',
1643 'arrow_right_hook':'\u21aa\ufe0f',
1644 'arrow_up':'\u2b06\ufe0f',
1645 'arrow_up_down':'\u2195\ufe0f',
1646 'arrow_up_small':'\ud83d\udd3c',
1647 'arrow_upper_left':'\u2196\ufe0f',
1648 'arrow_upper_right':'\u2197\ufe0f',
1649 'arrows_clockwise':'\ud83d\udd03',
1650 'arrows_counterclockwise':'\ud83d\udd04',
1651 'art':'\ud83c\udfa8',
1652 'articulated_lorry':'\ud83d\ude9b',
1653 'artificial_satellite':'\ud83d\udef0',
1654 'astonished':'\ud83d\ude32',
1655 'athletic_shoe':'\ud83d\udc5f',
1656 'atm':'\ud83c\udfe7',
1657 'atom_symbol':'\u269b\ufe0f',
1658 'avocado':'\ud83e\udd51',
1659 'b':'\ud83c\udd71\ufe0f',
1660 'baby':'\ud83d\udc76',
1661 'baby_bottle':'\ud83c\udf7c',
1662 'baby_chick':'\ud83d\udc24',
1663 'baby_symbol':'\ud83d\udebc',
1664 'back':'\ud83d\udd19',
1665 'bacon':'\ud83e\udd53',
1666 'badminton':'\ud83c\udff8',
1667 'baggage_claim':'\ud83d\udec4',
1668 'baguette_bread':'\ud83e\udd56',
1669 'balance_scale':'\u2696\ufe0f',
1670 'balloon':'\ud83c\udf88',
1671 'ballot_box':'\ud83d\uddf3',
1672 'ballot_box_with_check':'\u2611\ufe0f',
1673 'bamboo':'\ud83c\udf8d',
1674 'banana':'\ud83c\udf4c',
1675 'bangbang':'\u203c\ufe0f',
1676 'bank':'\ud83c\udfe6',
1677 'bar_chart':'\ud83d\udcca',
1678 'barber':'\ud83d\udc88',
1679 'baseball':'\u26be\ufe0f',
1680 'basketball':'\ud83c\udfc0',
1681 'basketball_man':'\u26f9\ufe0f',
1682 'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1683 'bat':'\ud83e\udd87',
1684 'bath':'\ud83d\udec0',
1685 'bathtub':'\ud83d\udec1',
1686 'battery':'\ud83d\udd0b',
1687 'beach_umbrella':'\ud83c\udfd6',
1688 'bear':'\ud83d\udc3b',
1689 'bed':'\ud83d\udecf',
1690 'bee':'\ud83d\udc1d',
1691 'beer':'\ud83c\udf7a',
1692 'beers':'\ud83c\udf7b',
1693 'beetle':'\ud83d\udc1e',
1694 'beginner':'\ud83d\udd30',
1695 'bell':'\ud83d\udd14',
1696 'bellhop_bell':'\ud83d\udece',
1697 'bento':'\ud83c\udf71',
1698 'biking_man':'\ud83d\udeb4',
1699 'bike':'\ud83d\udeb2',
1700 'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1701 'bikini':'\ud83d\udc59',
1702 'biohazard':'\u2623\ufe0f',
1703 'bird':'\ud83d\udc26',
1704 'birthday':'\ud83c\udf82',
1705 'black_circle':'\u26ab\ufe0f',
1706 'black_flag':'\ud83c\udff4',
1707 'black_heart':'\ud83d\udda4',
1708 'black_joker':'\ud83c\udccf',
1709 'black_large_square':'\u2b1b\ufe0f',
1710 'black_medium_small_square':'\u25fe\ufe0f',
1711 'black_medium_square':'\u25fc\ufe0f',
1712 'black_nib':'\u2712\ufe0f',
1713 'black_small_square':'\u25aa\ufe0f',
1714 'black_square_button':'\ud83d\udd32',
1715 'blonde_man':'\ud83d\udc71',
1716 'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1717 'blossom':'\ud83c\udf3c',
1718 'blowfish':'\ud83d\udc21',
1719 'blue_book':'\ud83d\udcd8',
1720 'blue_car':'\ud83d\ude99',
1721 'blue_heart':'\ud83d\udc99',
1722 'blush':'\ud83d\ude0a',
1723 'boar':'\ud83d\udc17',
1724 'boat':'\u26f5\ufe0f',
1725 'bomb':'\ud83d\udca3',
1726 'book':'\ud83d\udcd6',
1727 'bookmark':'\ud83d\udd16',
1728 'bookmark_tabs':'\ud83d\udcd1',
1729 'books':'\ud83d\udcda',
1730 'boom':'\ud83d\udca5',
1731 'boot':'\ud83d\udc62',
1732 'bouquet':'\ud83d\udc90',
1733 'bowing_man':'\ud83d\ude47',
1734 'bow_and_arrow':'\ud83c\udff9',
1735 'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1736 'bowling':'\ud83c\udfb3',
1737 'boxing_glove':'\ud83e\udd4a',
1738 'boy':'\ud83d\udc66',
1739 'bread':'\ud83c\udf5e',
1740 'bride_with_veil':'\ud83d\udc70',
1741 'bridge_at_night':'\ud83c\udf09',
1742 'briefcase':'\ud83d\udcbc',
1743 'broken_heart':'\ud83d\udc94',
1744 'bug':'\ud83d\udc1b',
1745 'building_construction':'\ud83c\udfd7',
1746 'bulb':'\ud83d\udca1',
1747 'bullettrain_front':'\ud83d\ude85',
1748 'bullettrain_side':'\ud83d\ude84',
1749 'burrito':'\ud83c\udf2f',
1750 'bus':'\ud83d\ude8c',
1751 'business_suit_levitating':'\ud83d\udd74',
1752 'busstop':'\ud83d\ude8f',
1753 'bust_in_silhouette':'\ud83d\udc64',
1754 'busts_in_silhouette':'\ud83d\udc65',
1755 'butterfly':'\ud83e\udd8b',
1756 'cactus':'\ud83c\udf35',
1757 'cake':'\ud83c\udf70',
1758 'calendar':'\ud83d\udcc6',
1759 'call_me_hand':'\ud83e\udd19',
1760 'calling':'\ud83d\udcf2',
1761 'camel':'\ud83d\udc2b',
1762 'camera':'\ud83d\udcf7',
1763 'camera_flash':'\ud83d\udcf8',
1764 'camping':'\ud83c\udfd5',
1765 'cancer':'\u264b\ufe0f',
1766 'candle':'\ud83d\udd6f',
1767 'candy':'\ud83c\udf6c',
1768 'canoe':'\ud83d\udef6',
1769 'capital_abcd':'\ud83d\udd20',
1770 'capricorn':'\u2651\ufe0f',
1771 'car':'\ud83d\ude97',
1772 'card_file_box':'\ud83d\uddc3',
1773 'card_index':'\ud83d\udcc7',
1774 'card_index_dividers':'\ud83d\uddc2',
1775 'carousel_horse':'\ud83c\udfa0',
1776 'carrot':'\ud83e\udd55',
1777 'cat':'\ud83d\udc31',
1778 'cat2':'\ud83d\udc08',
1779 'cd':'\ud83d\udcbf',
1780 'chains':'\u26d3',
1781 'champagne':'\ud83c\udf7e',
1782 'chart':'\ud83d\udcb9',
1783 'chart_with_downwards_trend':'\ud83d\udcc9',
1784 'chart_with_upwards_trend':'\ud83d\udcc8',
1785 'checkered_flag':'\ud83c\udfc1',
1786 'cheese':'\ud83e\uddc0',
1787 'cherries':'\ud83c\udf52',
1788 'cherry_blossom':'\ud83c\udf38',
1789 'chestnut':'\ud83c\udf30',
1790 'chicken':'\ud83d\udc14',
1791 'children_crossing':'\ud83d\udeb8',
1792 'chipmunk':'\ud83d\udc3f',
1793 'chocolate_bar':'\ud83c\udf6b',
1794 'christmas_tree':'\ud83c\udf84',
1795 'church':'\u26ea\ufe0f',
1796 'cinema':'\ud83c\udfa6',
1797 'circus_tent':'\ud83c\udfaa',
1798 'city_sunrise':'\ud83c\udf07',
1799 'city_sunset':'\ud83c\udf06',
1800 'cityscape':'\ud83c\udfd9',
1801 'cl':'\ud83c\udd91',
1802 'clamp':'\ud83d\udddc',
1803 'clap':'\ud83d\udc4f',
1804 'clapper':'\ud83c\udfac',
1805 'classical_building':'\ud83c\udfdb',
1806 'clinking_glasses':'\ud83e\udd42',
1807 'clipboard':'\ud83d\udccb',
1808 'clock1':'\ud83d\udd50',
1809 'clock10':'\ud83d\udd59',
1810 'clock1030':'\ud83d\udd65',
1811 'clock11':'\ud83d\udd5a',
1812 'clock1130':'\ud83d\udd66',
1813 'clock12':'\ud83d\udd5b',
1814 'clock1230':'\ud83d\udd67',
1815 'clock130':'\ud83d\udd5c',
1816 'clock2':'\ud83d\udd51',
1817 'clock230':'\ud83d\udd5d',
1818 'clock3':'\ud83d\udd52',
1819 'clock330':'\ud83d\udd5e',
1820 'clock4':'\ud83d\udd53',
1821 'clock430':'\ud83d\udd5f',
1822 'clock5':'\ud83d\udd54',
1823 'clock530':'\ud83d\udd60',
1824 'clock6':'\ud83d\udd55',
1825 'clock630':'\ud83d\udd61',
1826 'clock7':'\ud83d\udd56',
1827 'clock730':'\ud83d\udd62',
1828 'clock8':'\ud83d\udd57',
1829 'clock830':'\ud83d\udd63',
1830 'clock9':'\ud83d\udd58',
1831 'clock930':'\ud83d\udd64',
1832 'closed_book':'\ud83d\udcd5',
1833 'closed_lock_with_key':'\ud83d\udd10',
1834 'closed_umbrella':'\ud83c\udf02',
1835 'cloud':'\u2601\ufe0f',
1836 'cloud_with_lightning':'\ud83c\udf29',
1837 'cloud_with_lightning_and_rain':'\u26c8',
1838 'cloud_with_rain':'\ud83c\udf27',
1839 'cloud_with_snow':'\ud83c\udf28',
1840 'clown_face':'\ud83e\udd21',
1841 'clubs':'\u2663\ufe0f',
1842 'cocktail':'\ud83c\udf78',
1843 'coffee':'\u2615\ufe0f',
1844 'coffin':'\u26b0\ufe0f',
1845 'cold_sweat':'\ud83d\ude30',
1846 'comet':'\u2604\ufe0f',
1847 'computer':'\ud83d\udcbb',
1848 'computer_mouse':'\ud83d\uddb1',
1849 'confetti_ball':'\ud83c\udf8a',
1850 'confounded':'\ud83d\ude16',
1851 'confused':'\ud83d\ude15',
1852 'congratulations':'\u3297\ufe0f',
1853 'construction':'\ud83d\udea7',
1854 'construction_worker_man':'\ud83d\udc77',
1855 'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1856 'control_knobs':'\ud83c\udf9b',
1857 'convenience_store':'\ud83c\udfea',
1858 'cookie':'\ud83c\udf6a',
1859 'cool':'\ud83c\udd92',
1860 'policeman':'\ud83d\udc6e',
1861 'copyright':'\u00a9\ufe0f',
1862 'corn':'\ud83c\udf3d',
1863 'couch_and_lamp':'\ud83d\udecb',
1864 'couple':'\ud83d\udc6b',
1865 'couple_with_heart_woman_man':'\ud83d\udc91',
1866 'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1867 'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1868 'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1869 'couplekiss_man_woman':'\ud83d\udc8f',
1870 'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1871 'cow':'\ud83d\udc2e',
1872 'cow2':'\ud83d\udc04',
1873 'cowboy_hat_face':'\ud83e\udd20',
1874 'crab':'\ud83e\udd80',
1875 'crayon':'\ud83d\udd8d',
1876 'credit_card':'\ud83d\udcb3',
1877 'crescent_moon':'\ud83c\udf19',
1878 'cricket':'\ud83c\udfcf',
1879 'crocodile':'\ud83d\udc0a',
1880 'croissant':'\ud83e\udd50',
1881 'crossed_fingers':'\ud83e\udd1e',
1882 'crossed_flags':'\ud83c\udf8c',
1883 'crossed_swords':'\u2694\ufe0f',
1884 'crown':'\ud83d\udc51',
1885 'cry':'\ud83d\ude22',
1886 'crying_cat_face':'\ud83d\ude3f',
1887 'crystal_ball':'\ud83d\udd2e',
1888 'cucumber':'\ud83e\udd52',
1889 'cupid':'\ud83d\udc98',
1890 'curly_loop':'\u27b0',
1891 'currency_exchange':'\ud83d\udcb1',
1892 'curry':'\ud83c\udf5b',
1893 'custard':'\ud83c\udf6e',
1894 'customs':'\ud83d\udec3',
1895 'cyclone':'\ud83c\udf00',
1896 'dagger':'\ud83d\udde1',
1897 'dancer':'\ud83d\udc83',
1898 'dancing_women':'\ud83d\udc6f',
1899 'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1900 'dango':'\ud83c\udf61',
1901 'dark_sunglasses':'\ud83d\udd76',
1902 'dart':'\ud83c\udfaf',
1903 'dash':'\ud83d\udca8',
1904 'date':'\ud83d\udcc5',
1905 'deciduous_tree':'\ud83c\udf33',
1906 'deer':'\ud83e\udd8c',
1907 'department_store':'\ud83c\udfec',
1908 'derelict_house':'\ud83c\udfda',
1909 'desert':'\ud83c\udfdc',
1910 'desert_island':'\ud83c\udfdd',
1911 'desktop_computer':'\ud83d\udda5',
1912 'male_detective':'\ud83d\udd75\ufe0f',
1913 'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1914 'diamonds':'\u2666\ufe0f',
1915 'disappointed':'\ud83d\ude1e',
1916 'disappointed_relieved':'\ud83d\ude25',
1917 'dizzy':'\ud83d\udcab',
1918 'dizzy_face':'\ud83d\ude35',
1919 'do_not_litter':'\ud83d\udeaf',
1920 'dog':'\ud83d\udc36',
1921 'dog2':'\ud83d\udc15',
1922 'dollar':'\ud83d\udcb5',
1923 'dolls':'\ud83c\udf8e',
1924 'dolphin':'\ud83d\udc2c',
1925 'door':'\ud83d\udeaa',
1926 'doughnut':'\ud83c\udf69',
1927 'dove':'\ud83d\udd4a',
1928 'dragon':'\ud83d\udc09',
1929 'dragon_face':'\ud83d\udc32',
1930 'dress':'\ud83d\udc57',
1931 'dromedary_camel':'\ud83d\udc2a',
1932 'drooling_face':'\ud83e\udd24',
1933 'droplet':'\ud83d\udca7',
1934 'drum':'\ud83e\udd41',
1935 'duck':'\ud83e\udd86',
1936 'dvd':'\ud83d\udcc0',
1937 'e-mail':'\ud83d\udce7',
1938 'eagle':'\ud83e\udd85',
1939 'ear':'\ud83d\udc42',
1940 'ear_of_rice':'\ud83c\udf3e',
1941 'earth_africa':'\ud83c\udf0d',
1942 'earth_americas':'\ud83c\udf0e',
1943 'earth_asia':'\ud83c\udf0f',
1944 'egg':'\ud83e\udd5a',
1945 'eggplant':'\ud83c\udf46',
1946 'eight_pointed_black_star':'\u2734\ufe0f',
1947 'eight_spoked_asterisk':'\u2733\ufe0f',
1948 'electric_plug':'\ud83d\udd0c',
1949 'elephant':'\ud83d\udc18',
1950 'email':'\u2709\ufe0f',
1951 'end':'\ud83d\udd1a',
1952 'envelope_with_arrow':'\ud83d\udce9',
1953 'euro':'\ud83d\udcb6',
1954 'european_castle':'\ud83c\udff0',
1955 'european_post_office':'\ud83c\udfe4',
1956 'evergreen_tree':'\ud83c\udf32',
1957 'exclamation':'\u2757\ufe0f',
1958 'expressionless':'\ud83d\ude11',
1959 'eye':'\ud83d\udc41',
1960 'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
1961 'eyeglasses':'\ud83d\udc53',
1962 'eyes':'\ud83d\udc40',
1963 'face_with_head_bandage':'\ud83e\udd15',
1964 'face_with_thermometer':'\ud83e\udd12',
1965 'fist_oncoming':'\ud83d\udc4a',
1966 'factory':'\ud83c\udfed',
1967 'fallen_leaf':'\ud83c\udf42',
1968 'family_man_woman_boy':'\ud83d\udc6a',
1969 'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
1970 'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1971 'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1972 'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1973 'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1974 'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1975 'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1976 'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1977 'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1978 'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1979 'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1980 'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1981 'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1982 'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1983 'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1984 'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1985 'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1986 'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1987 'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1988 'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1989 'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1990 'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1991 'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1992 'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1993 'fast_forward':'\u23e9',
1994 'fax':'\ud83d\udce0',
1995 'fearful':'\ud83d\ude28',
1996 'feet':'\ud83d\udc3e',
1997 'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
1998 'ferris_wheel':'\ud83c\udfa1',
1999 'ferry':'\u26f4',
2000 'field_hockey':'\ud83c\udfd1',
2001 'file_cabinet':'\ud83d\uddc4',
2002 'file_folder':'\ud83d\udcc1',
2003 'film_projector':'\ud83d\udcfd',
2004 'film_strip':'\ud83c\udf9e',
2005 'fire':'\ud83d\udd25',
2006 'fire_engine':'\ud83d\ude92',
2007 'fireworks':'\ud83c\udf86',
2008 'first_quarter_moon':'\ud83c\udf13',
2009 'first_quarter_moon_with_face':'\ud83c\udf1b',
2010 'fish':'\ud83d\udc1f',
2011 'fish_cake':'\ud83c\udf65',
2012 'fishing_pole_and_fish':'\ud83c\udfa3',
2013 'fist_raised':'\u270a',
2014 'fist_left':'\ud83e\udd1b',
2015 'fist_right':'\ud83e\udd1c',
2016 'flags':'\ud83c\udf8f',
2017 'flashlight':'\ud83d\udd26',
2018 'fleur_de_lis':'\u269c\ufe0f',
2019 'flight_arrival':'\ud83d\udeec',
2020 'flight_departure':'\ud83d\udeeb',
2021 'floppy_disk':'\ud83d\udcbe',
2022 'flower_playing_cards':'\ud83c\udfb4',
2023 'flushed':'\ud83d\ude33',
2024 'fog':'\ud83c\udf2b',
2025 'foggy':'\ud83c\udf01',
2026 'football':'\ud83c\udfc8',
2027 'footprints':'\ud83d\udc63',
2028 'fork_and_knife':'\ud83c\udf74',
2029 'fountain':'\u26f2\ufe0f',
2030 'fountain_pen':'\ud83d\udd8b',
2031 'four_leaf_clover':'\ud83c\udf40',
2032 'fox_face':'\ud83e\udd8a',
2033 'framed_picture':'\ud83d\uddbc',
2034 'free':'\ud83c\udd93',
2035 'fried_egg':'\ud83c\udf73',
2036 'fried_shrimp':'\ud83c\udf64',
2037 'fries':'\ud83c\udf5f',
2038 'frog':'\ud83d\udc38',
2039 'frowning':'\ud83d\ude26',
2040 'frowning_face':'\u2639\ufe0f',
2041 'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
2042 'frowning_woman':'\ud83d\ude4d',
2043 'middle_finger':'\ud83d\udd95',
2044 'fuelpump':'\u26fd\ufe0f',
2045 'full_moon':'\ud83c\udf15',
2046 'full_moon_with_face':'\ud83c\udf1d',
2047 'funeral_urn':'\u26b1\ufe0f',
2048 'game_die':'\ud83c\udfb2',
2049 'gear':'\u2699\ufe0f',
2050 'gem':'\ud83d\udc8e',
2051 'gemini':'\u264a\ufe0f',
2052 'ghost':'\ud83d\udc7b',
2053 'gift':'\ud83c\udf81',
2054 'gift_heart':'\ud83d\udc9d',
2055 'girl':'\ud83d\udc67',
2056 'globe_with_meridians':'\ud83c\udf10',
2057 'goal_net':'\ud83e\udd45',
2058 'goat':'\ud83d\udc10',
2059 'golf':'\u26f3\ufe0f',
2060 'golfing_man':'\ud83c\udfcc\ufe0f',
2061 'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
2062 'gorilla':'\ud83e\udd8d',
2063 'grapes':'\ud83c\udf47',
2064 'green_apple':'\ud83c\udf4f',
2065 'green_book':'\ud83d\udcd7',
2066 'green_heart':'\ud83d\udc9a',
2067 'green_salad':'\ud83e\udd57',
2068 'grey_exclamation':'\u2755',
2069 'grey_question':'\u2754',
2070 'grimacing':'\ud83d\ude2c',
2071 'grin':'\ud83d\ude01',
2072 'grinning':'\ud83d\ude00',
2073 'guardsman':'\ud83d\udc82',
2074 'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
2075 'guitar':'\ud83c\udfb8',
2076 'gun':'\ud83d\udd2b',
2077 'haircut_woman':'\ud83d\udc87',
2078 'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
2079 'hamburger':'\ud83c\udf54',
2080 'hammer':'\ud83d\udd28',
2081 'hammer_and_pick':'\u2692',
2082 'hammer_and_wrench':'\ud83d\udee0',
2083 'hamster':'\ud83d\udc39',
2084 'hand':'\u270b',
2085 'handbag':'\ud83d\udc5c',
2086 'handshake':'\ud83e\udd1d',
2087 'hankey':'\ud83d\udca9',
2088 'hatched_chick':'\ud83d\udc25',
2089 'hatching_chick':'\ud83d\udc23',
2090 'headphones':'\ud83c\udfa7',
2091 'hear_no_evil':'\ud83d\ude49',
2092 'heart':'\u2764\ufe0f',
2093 'heart_decoration':'\ud83d\udc9f',
2094 'heart_eyes':'\ud83d\ude0d',
2095 'heart_eyes_cat':'\ud83d\ude3b',
2096 'heartbeat':'\ud83d\udc93',
2097 'heartpulse':'\ud83d\udc97',
2098 'hearts':'\u2665\ufe0f',
2099 'heavy_check_mark':'\u2714\ufe0f',
2100 'heavy_division_sign':'\u2797',
2101 'heavy_dollar_sign':'\ud83d\udcb2',
2102 'heavy_heart_exclamation':'\u2763\ufe0f',
2103 'heavy_minus_sign':'\u2796',
2104 'heavy_multiplication_x':'\u2716\ufe0f',
2105 'heavy_plus_sign':'\u2795',
2106 'helicopter':'\ud83d\ude81',
2107 'herb':'\ud83c\udf3f',
2108 'hibiscus':'\ud83c\udf3a',
2109 'high_brightness':'\ud83d\udd06',
2110 'high_heel':'\ud83d\udc60',
2111 'hocho':'\ud83d\udd2a',
2112 'hole':'\ud83d\udd73',
2113 'honey_pot':'\ud83c\udf6f',
2114 'horse':'\ud83d\udc34',
2115 'horse_racing':'\ud83c\udfc7',
2116 'hospital':'\ud83c\udfe5',
2117 'hot_pepper':'\ud83c\udf36',
2118 'hotdog':'\ud83c\udf2d',
2119 'hotel':'\ud83c\udfe8',
2120 'hotsprings':'\u2668\ufe0f',
2121 'hourglass':'\u231b\ufe0f',
2122 'hourglass_flowing_sand':'\u23f3',
2123 'house':'\ud83c\udfe0',
2124 'house_with_garden':'\ud83c\udfe1',
2125 'houses':'\ud83c\udfd8',
2126 'hugs':'\ud83e\udd17',
2127 'hushed':'\ud83d\ude2f',
2128 'ice_cream':'\ud83c\udf68',
2129 'ice_hockey':'\ud83c\udfd2',
2130 'ice_skate':'\u26f8',
2131 'icecream':'\ud83c\udf66',
2132 'id':'\ud83c\udd94',
2133 'ideograph_advantage':'\ud83c\ude50',
2134 'imp':'\ud83d\udc7f',
2135 'inbox_tray':'\ud83d\udce5',
2136 'incoming_envelope':'\ud83d\udce8',
2137 'tipping_hand_woman':'\ud83d\udc81',
2138 'information_source':'\u2139\ufe0f',
2139 'innocent':'\ud83d\ude07',
2140 'interrobang':'\u2049\ufe0f',
2141 'iphone':'\ud83d\udcf1',
2142 'izakaya_lantern':'\ud83c\udfee',
2143 'jack_o_lantern':'\ud83c\udf83',
2144 'japan':'\ud83d\uddfe',
2145 'japanese_castle':'\ud83c\udfef',
2146 'japanese_goblin':'\ud83d\udc7a',
2147 'japanese_ogre':'\ud83d\udc79',
2148 'jeans':'\ud83d\udc56',
2149 'joy':'\ud83d\ude02',
2150 'joy_cat':'\ud83d\ude39',
2151 'joystick':'\ud83d\udd79',
2152 'kaaba':'\ud83d\udd4b',
2153 'key':'\ud83d\udd11',
2154 'keyboard':'\u2328\ufe0f',
2155 'keycap_ten':'\ud83d\udd1f',
2156 'kick_scooter':'\ud83d\udef4',
2157 'kimono':'\ud83d\udc58',
2158 'kiss':'\ud83d\udc8b',
2159 'kissing':'\ud83d\ude17',
2160 'kissing_cat':'\ud83d\ude3d',
2161 'kissing_closed_eyes':'\ud83d\ude1a',
2162 'kissing_heart':'\ud83d\ude18',
2163 'kissing_smiling_eyes':'\ud83d\ude19',
2164 'kiwi_fruit':'\ud83e\udd5d',
2165 'koala':'\ud83d\udc28',
2166 'koko':'\ud83c\ude01',
2167 'label':'\ud83c\udff7',
2168 'large_blue_circle':'\ud83d\udd35',
2169 'large_blue_diamond':'\ud83d\udd37',
2170 'large_orange_diamond':'\ud83d\udd36',
2171 'last_quarter_moon':'\ud83c\udf17',
2172 'last_quarter_moon_with_face':'\ud83c\udf1c',
2173 'latin_cross':'\u271d\ufe0f',
2174 'laughing':'\ud83d\ude06',
2175 'leaves':'\ud83c\udf43',
2176 'ledger':'\ud83d\udcd2',
2177 'left_luggage':'\ud83d\udec5',
2178 'left_right_arrow':'\u2194\ufe0f',
2179 'leftwards_arrow_with_hook':'\u21a9\ufe0f',
2180 'lemon':'\ud83c\udf4b',
2181 'leo':'\u264c\ufe0f',
2182 'leopard':'\ud83d\udc06',
2183 'level_slider':'\ud83c\udf9a',
2184 'libra':'\u264e\ufe0f',
2185 'light_rail':'\ud83d\ude88',
2186 'link':'\ud83d\udd17',
2187 'lion':'\ud83e\udd81',
2188 'lips':'\ud83d\udc44',
2189 'lipstick':'\ud83d\udc84',
2190 'lizard':'\ud83e\udd8e',
2191 'lock':'\ud83d\udd12',
2192 'lock_with_ink_pen':'\ud83d\udd0f',
2193 'lollipop':'\ud83c\udf6d',
2194 'loop':'\u27bf',
2195 'loud_sound':'\ud83d\udd0a',
2196 'loudspeaker':'\ud83d\udce2',
2197 'love_hotel':'\ud83c\udfe9',
2198 'love_letter':'\ud83d\udc8c',
2199 'low_brightness':'\ud83d\udd05',
2200 'lying_face':'\ud83e\udd25',
2201 'm':'\u24c2\ufe0f',
2202 'mag':'\ud83d\udd0d',
2203 'mag_right':'\ud83d\udd0e',
2204 'mahjong':'\ud83c\udc04\ufe0f',
2205 'mailbox':'\ud83d\udceb',
2206 'mailbox_closed':'\ud83d\udcea',
2207 'mailbox_with_mail':'\ud83d\udcec',
2208 'mailbox_with_no_mail':'\ud83d\udced',
2209 'man':'\ud83d\udc68',
2210 'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
2211 'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
2212 'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
2213 'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
2214 'man_dancing':'\ud83d\udd7a',
2215 'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
2216 'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
2217 'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
2218 'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
2219 'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
2220 'man_in_tuxedo':'\ud83e\udd35',
2221 'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
2222 'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
2223 'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
2224 'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
2225 'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
2226 'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
2227 'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
2228 'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
2229 'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
2230 'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
2231 'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
2232 'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
2233 'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
2234 'man_with_gua_pi_mao':'\ud83d\udc72',
2235 'man_with_turban':'\ud83d\udc73',
2236 'tangerine':'\ud83c\udf4a',
2237 'mans_shoe':'\ud83d\udc5e',
2238 'mantelpiece_clock':'\ud83d\udd70',
2239 'maple_leaf':'\ud83c\udf41',
2240 'martial_arts_uniform':'\ud83e\udd4b',
2241 'mask':'\ud83d\ude37',
2242 'massage_woman':'\ud83d\udc86',
2243 'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
2244 'meat_on_bone':'\ud83c\udf56',
2245 'medal_military':'\ud83c\udf96',
2246 'medal_sports':'\ud83c\udfc5',
2247 'mega':'\ud83d\udce3',
2248 'melon':'\ud83c\udf48',
2249 'memo':'\ud83d\udcdd',
2250 'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
2251 'menorah':'\ud83d\udd4e',
2252 'mens':'\ud83d\udeb9',
2253 'metal':'\ud83e\udd18',
2254 'metro':'\ud83d\ude87',
2255 'microphone':'\ud83c\udfa4',
2256 'microscope':'\ud83d\udd2c',
2257 'milk_glass':'\ud83e\udd5b',
2258 'milky_way':'\ud83c\udf0c',
2259 'minibus':'\ud83d\ude90',
2260 'minidisc':'\ud83d\udcbd',
2261 'mobile_phone_off':'\ud83d\udcf4',
2262 'money_mouth_face':'\ud83e\udd11',
2263 'money_with_wings':'\ud83d\udcb8',
2264 'moneybag':'\ud83d\udcb0',
2265 'monkey':'\ud83d\udc12',
2266 'monkey_face':'\ud83d\udc35',
2267 'monorail':'\ud83d\ude9d',
2268 'moon':'\ud83c\udf14',
2269 'mortar_board':'\ud83c\udf93',
2270 'mosque':'\ud83d\udd4c',
2271 'motor_boat':'\ud83d\udee5',
2272 'motor_scooter':'\ud83d\udef5',
2273 'motorcycle':'\ud83c\udfcd',
2274 'motorway':'\ud83d\udee3',
2275 'mount_fuji':'\ud83d\uddfb',
2276 'mountain':'\u26f0',
2277 'mountain_biking_man':'\ud83d\udeb5',
2278 'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
2279 'mountain_cableway':'\ud83d\udea0',
2280 'mountain_railway':'\ud83d\ude9e',
2281 'mountain_snow':'\ud83c\udfd4',
2282 'mouse':'\ud83d\udc2d',
2283 'mouse2':'\ud83d\udc01',
2284 'movie_camera':'\ud83c\udfa5',
2285 'moyai':'\ud83d\uddff',
2286 'mrs_claus':'\ud83e\udd36',
2287 'muscle':'\ud83d\udcaa',
2288 'mushroom':'\ud83c\udf44',
2289 'musical_keyboard':'\ud83c\udfb9',
2290 'musical_note':'\ud83c\udfb5',
2291 'musical_score':'\ud83c\udfbc',
2292 'mute':'\ud83d\udd07',
2293 'nail_care':'\ud83d\udc85',
2294 'name_badge':'\ud83d\udcdb',
2295 'national_park':'\ud83c\udfde',
2296 'nauseated_face':'\ud83e\udd22',
2297 'necktie':'\ud83d\udc54',
2298 'negative_squared_cross_mark':'\u274e',
2299 'nerd_face':'\ud83e\udd13',
2300 'neutral_face':'\ud83d\ude10',
2301 'new':'\ud83c\udd95',
2302 'new_moon':'\ud83c\udf11',
2303 'new_moon_with_face':'\ud83c\udf1a',
2304 'newspaper':'\ud83d\udcf0',
2305 'newspaper_roll':'\ud83d\uddde',
2306 'next_track_button':'\u23ed',
2307 'ng':'\ud83c\udd96',
2308 'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
2309 'no_good_woman':'\ud83d\ude45',
2310 'night_with_stars':'\ud83c\udf03',
2311 'no_bell':'\ud83d\udd15',
2312 'no_bicycles':'\ud83d\udeb3',
2313 'no_entry':'\u26d4\ufe0f',
2314 'no_entry_sign':'\ud83d\udeab',
2315 'no_mobile_phones':'\ud83d\udcf5',
2316 'no_mouth':'\ud83d\ude36',
2317 'no_pedestrians':'\ud83d\udeb7',
2318 'no_smoking':'\ud83d\udead',
2319 'non-potable_water':'\ud83d\udeb1',
2320 'nose':'\ud83d\udc43',
2321 'notebook':'\ud83d\udcd3',
2322 'notebook_with_decorative_cover':'\ud83d\udcd4',
2323 'notes':'\ud83c\udfb6',
2324 'nut_and_bolt':'\ud83d\udd29',
2325 'o':'\u2b55\ufe0f',
2326 'o2':'\ud83c\udd7e\ufe0f',
2327 'ocean':'\ud83c\udf0a',
2328 'octopus':'\ud83d\udc19',
2329 'oden':'\ud83c\udf62',
2330 'office':'\ud83c\udfe2',
2331 'oil_drum':'\ud83d\udee2',
2332 'ok':'\ud83c\udd97',
2333 'ok_hand':'\ud83d\udc4c',
2334 'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
2335 'ok_woman':'\ud83d\ude46',
2336 'old_key':'\ud83d\udddd',
2337 'older_man':'\ud83d\udc74',
2338 'older_woman':'\ud83d\udc75',
2339 'om':'\ud83d\udd49',
2340 'on':'\ud83d\udd1b',
2341 'oncoming_automobile':'\ud83d\ude98',
2342 'oncoming_bus':'\ud83d\ude8d',
2343 'oncoming_police_car':'\ud83d\ude94',
2344 'oncoming_taxi':'\ud83d\ude96',
2345 'open_file_folder':'\ud83d\udcc2',
2346 'open_hands':'\ud83d\udc50',
2347 'open_mouth':'\ud83d\ude2e',
2348 'open_umbrella':'\u2602\ufe0f',
2349 'ophiuchus':'\u26ce',
2350 'orange_book':'\ud83d\udcd9',
2351 'orthodox_cross':'\u2626\ufe0f',
2352 'outbox_tray':'\ud83d\udce4',
2353 'owl':'\ud83e\udd89',
2354 'ox':'\ud83d\udc02',
2355 'package':'\ud83d\udce6',
2356 'page_facing_up':'\ud83d\udcc4',
2357 'page_with_curl':'\ud83d\udcc3',
2358 'pager':'\ud83d\udcdf',
2359 'paintbrush':'\ud83d\udd8c',
2360 'palm_tree':'\ud83c\udf34',
2361 'pancakes':'\ud83e\udd5e',
2362 'panda_face':'\ud83d\udc3c',
2363 'paperclip':'\ud83d\udcce',
2364 'paperclips':'\ud83d\udd87',
2365 'parasol_on_ground':'\u26f1',
2366 'parking':'\ud83c\udd7f\ufe0f',
2367 'part_alternation_mark':'\u303d\ufe0f',
2368 'partly_sunny':'\u26c5\ufe0f',
2369 'passenger_ship':'\ud83d\udef3',
2370 'passport_control':'\ud83d\udec2',
2371 'pause_button':'\u23f8',
2372 'peace_symbol':'\u262e\ufe0f',
2373 'peach':'\ud83c\udf51',
2374 'peanuts':'\ud83e\udd5c',
2375 'pear':'\ud83c\udf50',
2376 'pen':'\ud83d\udd8a',
2377 'pencil2':'\u270f\ufe0f',
2378 'penguin':'\ud83d\udc27',
2379 'pensive':'\ud83d\ude14',
2380 'performing_arts':'\ud83c\udfad',
2381 'persevere':'\ud83d\ude23',
2382 'person_fencing':'\ud83e\udd3a',
2383 'pouting_woman':'\ud83d\ude4e',
2384 'phone':'\u260e\ufe0f',
2385 'pick':'\u26cf',
2386 'pig':'\ud83d\udc37',
2387 'pig2':'\ud83d\udc16',
2388 'pig_nose':'\ud83d\udc3d',
2389 'pill':'\ud83d\udc8a',
2390 'pineapple':'\ud83c\udf4d',
2391 'ping_pong':'\ud83c\udfd3',
2392 'pisces':'\u2653\ufe0f',
2393 'pizza':'\ud83c\udf55',
2394 'place_of_worship':'\ud83d\uded0',
2395 'plate_with_cutlery':'\ud83c\udf7d',
2396 'play_or_pause_button':'\u23ef',
2397 'point_down':'\ud83d\udc47',
2398 'point_left':'\ud83d\udc48',
2399 'point_right':'\ud83d\udc49',
2400 'point_up':'\u261d\ufe0f',
2401 'point_up_2':'\ud83d\udc46',
2402 'police_car':'\ud83d\ude93',
2403 'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
2404 'poodle':'\ud83d\udc29',
2405 'popcorn':'\ud83c\udf7f',
2406 'post_office':'\ud83c\udfe3',
2407 'postal_horn':'\ud83d\udcef',
2408 'postbox':'\ud83d\udcee',
2409 'potable_water':'\ud83d\udeb0',
2410 'potato':'\ud83e\udd54',
2411 'pouch':'\ud83d\udc5d',
2412 'poultry_leg':'\ud83c\udf57',
2413 'pound':'\ud83d\udcb7',
2414 'rage':'\ud83d\ude21',
2415 'pouting_cat':'\ud83d\ude3e',
2416 'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
2417 'pray':'\ud83d\ude4f',
2418 'prayer_beads':'\ud83d\udcff',
2419 'pregnant_woman':'\ud83e\udd30',
2420 'previous_track_button':'\u23ee',
2421 'prince':'\ud83e\udd34',
2422 'princess':'\ud83d\udc78',
2423 'printer':'\ud83d\udda8',
2424 'purple_heart':'\ud83d\udc9c',
2425 'purse':'\ud83d\udc5b',
2426 'pushpin':'\ud83d\udccc',
2427 'put_litter_in_its_place':'\ud83d\udeae',
2428 'question':'\u2753',
2429 'rabbit':'\ud83d\udc30',
2430 'rabbit2':'\ud83d\udc07',
2431 'racehorse':'\ud83d\udc0e',
2432 'racing_car':'\ud83c\udfce',
2433 'radio':'\ud83d\udcfb',
2434 'radio_button':'\ud83d\udd18',
2435 'radioactive':'\u2622\ufe0f',
2436 'railway_car':'\ud83d\ude83',
2437 'railway_track':'\ud83d\udee4',
2438 'rainbow':'\ud83c\udf08',
2439 'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
2440 'raised_back_of_hand':'\ud83e\udd1a',
2441 'raised_hand_with_fingers_splayed':'\ud83d\udd90',
2442 'raised_hands':'\ud83d\ude4c',
2443 'raising_hand_woman':'\ud83d\ude4b',
2444 'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
2445 'ram':'\ud83d\udc0f',
2446 'ramen':'\ud83c\udf5c',
2447 'rat':'\ud83d\udc00',
2448 'record_button':'\u23fa',
2449 'recycle':'\u267b\ufe0f',
2450 'red_circle':'\ud83d\udd34',
2451 'registered':'\u00ae\ufe0f',
2452 'relaxed':'\u263a\ufe0f',
2453 'relieved':'\ud83d\ude0c',
2454 'reminder_ribbon':'\ud83c\udf97',
2455 'repeat':'\ud83d\udd01',
2456 'repeat_one':'\ud83d\udd02',
2457 'rescue_worker_helmet':'\u26d1',
2458 'restroom':'\ud83d\udebb',
2459 'revolving_hearts':'\ud83d\udc9e',
2460 'rewind':'\u23ea',
2461 'rhinoceros':'\ud83e\udd8f',
2462 'ribbon':'\ud83c\udf80',
2463 'rice':'\ud83c\udf5a',
2464 'rice_ball':'\ud83c\udf59',
2465 'rice_cracker':'\ud83c\udf58',
2466 'rice_scene':'\ud83c\udf91',
2467 'right_anger_bubble':'\ud83d\uddef',
2468 'ring':'\ud83d\udc8d',
2469 'robot':'\ud83e\udd16',
2470 'rocket':'\ud83d\ude80',
2471 'rofl':'\ud83e\udd23',
2472 'roll_eyes':'\ud83d\ude44',
2473 'roller_coaster':'\ud83c\udfa2',
2474 'rooster':'\ud83d\udc13',
2475 'rose':'\ud83c\udf39',
2476 'rosette':'\ud83c\udff5',
2477 'rotating_light':'\ud83d\udea8',
2478 'round_pushpin':'\ud83d\udccd',
2479 'rowing_man':'\ud83d\udea3',
2480 'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
2481 'rugby_football':'\ud83c\udfc9',
2482 'running_man':'\ud83c\udfc3',
2483 'running_shirt_with_sash':'\ud83c\udfbd',
2484 'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
2485 'sa':'\ud83c\ude02\ufe0f',
2486 'sagittarius':'\u2650\ufe0f',
2487 'sake':'\ud83c\udf76',
2488 'sandal':'\ud83d\udc61',
2489 'santa':'\ud83c\udf85',
2490 'satellite':'\ud83d\udce1',
2491 'saxophone':'\ud83c\udfb7',
2492 'school':'\ud83c\udfeb',
2493 'school_satchel':'\ud83c\udf92',
2494 'scissors':'\u2702\ufe0f',
2495 'scorpion':'\ud83e\udd82',
2496 'scorpius':'\u264f\ufe0f',
2497 'scream':'\ud83d\ude31',
2498 'scream_cat':'\ud83d\ude40',
2499 'scroll':'\ud83d\udcdc',
2500 'seat':'\ud83d\udcba',
2501 'secret':'\u3299\ufe0f',
2502 'see_no_evil':'\ud83d\ude48',
2503 'seedling':'\ud83c\udf31',
2504 'selfie':'\ud83e\udd33',
2505 'shallow_pan_of_food':'\ud83e\udd58',
2506 'shamrock':'\u2618\ufe0f',
2507 'shark':'\ud83e\udd88',
2508 'shaved_ice':'\ud83c\udf67',
2509 'sheep':'\ud83d\udc11',
2510 'shell':'\ud83d\udc1a',
2511 'shield':'\ud83d\udee1',
2512 'shinto_shrine':'\u26e9',
2513 'ship':'\ud83d\udea2',
2514 'shirt':'\ud83d\udc55',
2515 'shopping':'\ud83d\udecd',
2516 'shopping_cart':'\ud83d\uded2',
2517 'shower':'\ud83d\udebf',
2518 'shrimp':'\ud83e\udd90',
2519 'signal_strength':'\ud83d\udcf6',
2520 'six_pointed_star':'\ud83d\udd2f',
2521 'ski':'\ud83c\udfbf',
2522 'skier':'\u26f7',
2523 'skull':'\ud83d\udc80',
2524 'skull_and_crossbones':'\u2620\ufe0f',
2525 'sleeping':'\ud83d\ude34',
2526 'sleeping_bed':'\ud83d\udecc',
2527 'sleepy':'\ud83d\ude2a',
2528 'slightly_frowning_face':'\ud83d\ude41',
2529 'slightly_smiling_face':'\ud83d\ude42',
2530 'slot_machine':'\ud83c\udfb0',
2531 'small_airplane':'\ud83d\udee9',
2532 'small_blue_diamond':'\ud83d\udd39',
2533 'small_orange_diamond':'\ud83d\udd38',
2534 'small_red_triangle':'\ud83d\udd3a',
2535 'small_red_triangle_down':'\ud83d\udd3b',
2536 'smile':'\ud83d\ude04',
2537 'smile_cat':'\ud83d\ude38',
2538 'smiley':'\ud83d\ude03',
2539 'smiley_cat':'\ud83d\ude3a',
2540 'smiling_imp':'\ud83d\ude08',
2541 'smirk':'\ud83d\ude0f',
2542 'smirk_cat':'\ud83d\ude3c',
2543 'smoking':'\ud83d\udeac',
2544 'snail':'\ud83d\udc0c',
2545 'snake':'\ud83d\udc0d',
2546 'sneezing_face':'\ud83e\udd27',
2547 'snowboarder':'\ud83c\udfc2',
2548 'snowflake':'\u2744\ufe0f',
2549 'snowman':'\u26c4\ufe0f',
2550 'snowman_with_snow':'\u2603\ufe0f',
2551 'sob':'\ud83d\ude2d',
2552 'soccer':'\u26bd\ufe0f',
2553 'soon':'\ud83d\udd1c',
2554 'sos':'\ud83c\udd98',
2555 'sound':'\ud83d\udd09',
2556 'space_invader':'\ud83d\udc7e',
2557 'spades':'\u2660\ufe0f',
2558 'spaghetti':'\ud83c\udf5d',
2559 'sparkle':'\u2747\ufe0f',
2560 'sparkler':'\ud83c\udf87',
2561 'sparkles':'\u2728',
2562 'sparkling_heart':'\ud83d\udc96',
2563 'speak_no_evil':'\ud83d\ude4a',
2564 'speaker':'\ud83d\udd08',
2565 'speaking_head':'\ud83d\udde3',
2566 'speech_balloon':'\ud83d\udcac',
2567 'speedboat':'\ud83d\udea4',
2568 'spider':'\ud83d\udd77',
2569 'spider_web':'\ud83d\udd78',
2570 'spiral_calendar':'\ud83d\uddd3',
2571 'spiral_notepad':'\ud83d\uddd2',
2572 'spoon':'\ud83e\udd44',
2573 'squid':'\ud83e\udd91',
2574 'stadium':'\ud83c\udfdf',
2575 'star':'\u2b50\ufe0f',
2576 'star2':'\ud83c\udf1f',
2577 'star_and_crescent':'\u262a\ufe0f',
2578 'star_of_david':'\u2721\ufe0f',
2579 'stars':'\ud83c\udf20',
2580 'station':'\ud83d\ude89',
2581 'statue_of_liberty':'\ud83d\uddfd',
2582 'steam_locomotive':'\ud83d\ude82',
2583 'stew':'\ud83c\udf72',
2584 'stop_button':'\u23f9',
2585 'stop_sign':'\ud83d\uded1',
2586 'stopwatch':'\u23f1',
2587 'straight_ruler':'\ud83d\udccf',
2588 'strawberry':'\ud83c\udf53',
2589 'stuck_out_tongue':'\ud83d\ude1b',
2590 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2591 'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2592 'studio_microphone':'\ud83c\udf99',
2593 'stuffed_flatbread':'\ud83e\udd59',
2594 'sun_behind_large_cloud':'\ud83c\udf25',
2595 'sun_behind_rain_cloud':'\ud83c\udf26',
2596 'sun_behind_small_cloud':'\ud83c\udf24',
2597 'sun_with_face':'\ud83c\udf1e',
2598 'sunflower':'\ud83c\udf3b',
2599 'sunglasses':'\ud83d\ude0e',
2600 'sunny':'\u2600\ufe0f',
2601 'sunrise':'\ud83c\udf05',
2602 'sunrise_over_mountains':'\ud83c\udf04',
2603 'surfing_man':'\ud83c\udfc4',
2604 'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2605 'sushi':'\ud83c\udf63',
2606 'suspension_railway':'\ud83d\ude9f',
2607 'sweat':'\ud83d\ude13',
2608 'sweat_drops':'\ud83d\udca6',
2609 'sweat_smile':'\ud83d\ude05',
2610 'sweet_potato':'\ud83c\udf60',
2611 'swimming_man':'\ud83c\udfca',
2612 'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2613 'symbols':'\ud83d\udd23',
2614 'synagogue':'\ud83d\udd4d',
2615 'syringe':'\ud83d\udc89',
2616 'taco':'\ud83c\udf2e',
2617 'tada':'\ud83c\udf89',
2618 'tanabata_tree':'\ud83c\udf8b',
2619 'taurus':'\u2649\ufe0f',
2620 'taxi':'\ud83d\ude95',
2621 'tea':'\ud83c\udf75',
2622 'telephone_receiver':'\ud83d\udcde',
2623 'telescope':'\ud83d\udd2d',
2624 'tennis':'\ud83c\udfbe',
2625 'tent':'\u26fa\ufe0f',
2626 'thermometer':'\ud83c\udf21',
2627 'thinking':'\ud83e\udd14',
2628 'thought_balloon':'\ud83d\udcad',
2629 'ticket':'\ud83c\udfab',
2630 'tickets':'\ud83c\udf9f',
2631 'tiger':'\ud83d\udc2f',
2632 'tiger2':'\ud83d\udc05',
2633 'timer_clock':'\u23f2',
2634 'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2635 'tired_face':'\ud83d\ude2b',
2636 'tm':'\u2122\ufe0f',
2637 'toilet':'\ud83d\udebd',
2638 'tokyo_tower':'\ud83d\uddfc',
2639 'tomato':'\ud83c\udf45',
2640 'tongue':'\ud83d\udc45',
2641 'top':'\ud83d\udd1d',
2642 'tophat':'\ud83c\udfa9',
2643 'tornado':'\ud83c\udf2a',
2644 'trackball':'\ud83d\uddb2',
2645 'tractor':'\ud83d\ude9c',
2646 'traffic_light':'\ud83d\udea5',
2647 'train':'\ud83d\ude8b',
2648 'train2':'\ud83d\ude86',
2649 'tram':'\ud83d\ude8a',
2650 'triangular_flag_on_post':'\ud83d\udea9',
2651 'triangular_ruler':'\ud83d\udcd0',
2652 'trident':'\ud83d\udd31',
2653 'triumph':'\ud83d\ude24',
2654 'trolleybus':'\ud83d\ude8e',
2655 'trophy':'\ud83c\udfc6',
2656 'tropical_drink':'\ud83c\udf79',
2657 'tropical_fish':'\ud83d\udc20',
2658 'truck':'\ud83d\ude9a',
2659 'trumpet':'\ud83c\udfba',
2660 'tulip':'\ud83c\udf37',
2661 'tumbler_glass':'\ud83e\udd43',
2662 'turkey':'\ud83e\udd83',
2663 'turtle':'\ud83d\udc22',
2664 'tv':'\ud83d\udcfa',
2665 'twisted_rightwards_arrows':'\ud83d\udd00',
2666 'two_hearts':'\ud83d\udc95',
2667 'two_men_holding_hands':'\ud83d\udc6c',
2668 'two_women_holding_hands':'\ud83d\udc6d',
2669 'u5272':'\ud83c\ude39',
2670 'u5408':'\ud83c\ude34',
2671 'u55b6':'\ud83c\ude3a',
2672 'u6307':'\ud83c\ude2f\ufe0f',
2673 'u6708':'\ud83c\ude37\ufe0f',
2674 'u6709':'\ud83c\ude36',
2675 'u6e80':'\ud83c\ude35',
2676 'u7121':'\ud83c\ude1a\ufe0f',
2677 'u7533':'\ud83c\ude38',
2678 'u7981':'\ud83c\ude32',
2679 'u7a7a':'\ud83c\ude33',
2680 'umbrella':'\u2614\ufe0f',
2681 'unamused':'\ud83d\ude12',
2682 'underage':'\ud83d\udd1e',
2683 'unicorn':'\ud83e\udd84',
2684 'unlock':'\ud83d\udd13',
2685 'up':'\ud83c\udd99',
2686 'upside_down_face':'\ud83d\ude43',
2687 'v':'\u270c\ufe0f',
2688 'vertical_traffic_light':'\ud83d\udea6',
2689 'vhs':'\ud83d\udcfc',
2690 'vibration_mode':'\ud83d\udcf3',
2691 'video_camera':'\ud83d\udcf9',
2692 'video_game':'\ud83c\udfae',
2693 'violin':'\ud83c\udfbb',
2694 'virgo':'\u264d\ufe0f',
2695 'volcano':'\ud83c\udf0b',
2696 'volleyball':'\ud83c\udfd0',
2697 'vs':'\ud83c\udd9a',
2698 'vulcan_salute':'\ud83d\udd96',
2699 'walking_man':'\ud83d\udeb6',
2700 'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2701 'waning_crescent_moon':'\ud83c\udf18',
2702 'waning_gibbous_moon':'\ud83c\udf16',
2703 'warning':'\u26a0\ufe0f',
2704 'wastebasket':'\ud83d\uddd1',
2705 'watch':'\u231a\ufe0f',
2706 'water_buffalo':'\ud83d\udc03',
2707 'watermelon':'\ud83c\udf49',
2708 'wave':'\ud83d\udc4b',
2709 'wavy_dash':'\u3030\ufe0f',
2710 'waxing_crescent_moon':'\ud83c\udf12',
2711 'wc':'\ud83d\udebe',
2712 'weary':'\ud83d\ude29',
2713 'wedding':'\ud83d\udc92',
2714 'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2715 'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2716 'whale':'\ud83d\udc33',
2717 'whale2':'\ud83d\udc0b',
2718 'wheel_of_dharma':'\u2638\ufe0f',
2719 'wheelchair':'\u267f\ufe0f',
2720 'white_check_mark':'\u2705',
2721 'white_circle':'\u26aa\ufe0f',
2722 'white_flag':'\ud83c\udff3\ufe0f',
2723 'white_flower':'\ud83d\udcae',
2724 'white_large_square':'\u2b1c\ufe0f',
2725 'white_medium_small_square':'\u25fd\ufe0f',
2726 'white_medium_square':'\u25fb\ufe0f',
2727 'white_small_square':'\u25ab\ufe0f',
2728 'white_square_button':'\ud83d\udd33',
2729 'wilted_flower':'\ud83e\udd40',
2730 'wind_chime':'\ud83c\udf90',
2731 'wind_face':'\ud83c\udf2c',
2732 'wine_glass':'\ud83c\udf77',
2733 'wink':'\ud83d\ude09',
2734 'wolf':'\ud83d\udc3a',
2735 'woman':'\ud83d\udc69',
2736 'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2737 'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2738 'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2739 'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2740 'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2741 'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2742 'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2743 'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2744 'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2745 'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2746 'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2747 'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2748 'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2749 'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2750 'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2751 'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2752 'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2753 'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2754 'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2755 'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2756 'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2757 'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2758 'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2759 'womans_clothes':'\ud83d\udc5a',
2760 'womans_hat':'\ud83d\udc52',
2761 'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2762 'womens':'\ud83d\udeba',
2763 'world_map':'\ud83d\uddfa',
2764 'worried':'\ud83d\ude1f',
2765 'wrench':'\ud83d\udd27',
2766 'writing_hand':'\u270d\ufe0f',
2767 'x':'\u274c',
2768 'yellow_heart':'\ud83d\udc9b',
2769 'yen':'\ud83d\udcb4',
2770 'yin_yang':'\u262f\ufe0f',
2771 'yum':'\ud83d\ude0b',
2772 'zap':'\u26a1\ufe0f',
2773 'zipper_mouth_face':'\ud83e\udd10',
2774 'zzz':'\ud83d\udca4',
2775
2776 /* special emojis :P */
2777 'octocat': '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
2778 '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>'
2779 };
2780
2781 /**
2782 * Created by Estevao on 31-05-2015.
2783 */
2784
2785 /**
2786 * Showdown Converter class
2787 * @class
2788 * @param {object} [converterOptions]
2789 * @returns {Converter}
2790 */
2791 showdown.Converter = function (converterOptions) {
2792 'use strict';
2793
2794 var
2795 /**
2796 * Options used by this converter
2797 * @private
2798 * @type {{}}
2799 */
2800 options = {},
2801
2802 /**
2803 * Language extensions used by this converter
2804 * @private
2805 * @type {Array}
2806 */
2807 langExtensions = [],
2808
2809 /**
2810 * Output modifiers extensions used by this converter
2811 * @private
2812 * @type {Array}
2813 */
2814 outputModifiers = [],
2815
2816 /**
2817 * Event listeners
2818 * @private
2819 * @type {{}}
2820 */
2821 listeners = {},
2822
2823 /**
2824 * The flavor set in this converter
2825 */
2826 setConvFlavor = setFlavor,
2827
2828 /**
2829 * Metadata of the document
2830 * @type {{parsed: {}, raw: string, format: string}}
2831 */
2832 metadata = {
2833 parsed: {},
2834 raw: '',
2835 format: ''
2836 };
2837
2838 _constructor();
2839
2840 /**
2841 * Converter constructor
2842 * @private
2843 */
2844 function _constructor () {
2845 converterOptions = converterOptions || {};
2846
2847 for (var gOpt in globalOptions) {
2848 if (globalOptions.hasOwnProperty(gOpt)) {
2849 options[gOpt] = globalOptions[gOpt];
2850 }
2851 }
2852
2853 // Merge options
2854 if (typeof converterOptions === 'object') {
2855 for (var opt in converterOptions) {
2856 if (converterOptions.hasOwnProperty(opt)) {
2857 options[opt] = converterOptions[opt];
2858 }
2859 }
2860 } else {
2861 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
2862 ' was passed instead.');
2863 }
2864
2865 if (options.extensions) {
2866 showdown.helper.forEach(options.extensions, _parseExtension);
2867 }
2868 }
2869
2870 /**
2871 * Parse extension
2872 * @param {*} ext
2873 * @param {string} [name='']
2874 * @private
2875 */
2876 function _parseExtension (ext, name) {
2877
2878 name = name || null;
2879 // If it's a string, the extension was previously loaded
2880 if (showdown.helper.isString(ext)) {
2881 ext = showdown.helper.stdExtName(ext);
2882 name = ext;
2883
2884 // LEGACY_SUPPORT CODE
2885 if (showdown.extensions[ext]) {
2886 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
2887 'Please inform the developer that the extension should be updated!');
2888 legacyExtensionLoading(showdown.extensions[ext], ext);
2889 return;
2890 // END LEGACY SUPPORT CODE
2891
2892 } else if (!showdown.helper.isUndefined(extensions[ext])) {
2893 ext = extensions[ext];
2894
2895 } else {
2896 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
2897 }
2898 }
2899
2900 if (typeof ext === 'function') {
2901 ext = ext();
2902 }
2903
2904 if (!showdown.helper.isArray(ext)) {
2905 ext = [ext];
2906 }
2907
2908 var validExt = validate(ext, name);
2909 if (!validExt.valid) {
2910 throw Error(validExt.error);
2911 }
2912
2913 for (var i = 0; i < ext.length; ++i) {
2914 switch (ext[i].type) {
2915
2916 case 'lang':
2917 langExtensions.push(ext[i]);
2918 break;
2919
2920 case 'output':
2921 outputModifiers.push(ext[i]);
2922 break;
2923 }
2924 if (ext[i].hasOwnProperty('listeners')) {
2925 for (var ln in ext[i].listeners) {
2926 if (ext[i].listeners.hasOwnProperty(ln)) {
2927 listen(ln, ext[i].listeners[ln]);
2928 }
2929 }
2930 }
2931 }
2932
2933 }
2934
2935 /**
2936 * LEGACY_SUPPORT
2937 * @param {*} ext
2938 * @param {string} name
2939 */
2940 function legacyExtensionLoading (ext, name) {
2941 if (typeof ext === 'function') {
2942 ext = ext(new showdown.Converter());
2943 }
2944 if (!showdown.helper.isArray(ext)) {
2945 ext = [ext];
2946 }
2947 var valid = validate(ext, name);
2948
2949 if (!valid.valid) {
2950 throw Error(valid.error);
2951 }
2952
2953 for (var i = 0; i < ext.length; ++i) {
2954 switch (ext[i].type) {
2955 case 'lang':
2956 langExtensions.push(ext[i]);
2957 break;
2958 case 'output':
2959 outputModifiers.push(ext[i]);
2960 break;
2961 default:// should never reach here
2962 throw Error('Extension loader error: Type unrecognized!!!');
2963 }
2964 }
2965 }
2966
2967 /**
2968 * Listen to an event
2969 * @param {string} name
2970 * @param {function} callback
2971 */
2972 function listen (name, callback) {
2973 if (!showdown.helper.isString(name)) {
2974 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
2975 }
2976
2977 if (typeof callback !== 'function') {
2978 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
2979 }
2980
2981 if (!listeners.hasOwnProperty(name)) {
2982 listeners[name] = [];
2983 }
2984 listeners[name].push(callback);
2985 }
2986
2987 function rTrimInputText (text) {
2988 var rsp = text.match(/^\s*/)[0].length,
2989 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
2990 return text.replace(rgx, '');
2991 }
2992
2993 /**
2994 * Dispatch an event
2995 * @private
2996 * @param {string} evtName Event name
2997 * @param {string} text Text
2998 * @param {{}} options Converter Options
2999 * @param {{}} globals
3000 * @returns {string}
3001 */
3002 this._dispatch = function dispatch (evtName, text, options, globals) {
3003 if (listeners.hasOwnProperty(evtName)) {
3004 for (var ei = 0; ei < listeners[evtName].length; ++ei) {
3005 var nText = listeners[evtName][ei](evtName, text, this, options, globals);
3006 if (nText && typeof nText !== 'undefined') {
3007 text = nText;
3008 }
3009 }
3010 }
3011 return text;
3012 };
3013
3014 /**
3015 * Listen to an event
3016 * @param {string} name
3017 * @param {function} callback
3018 * @returns {showdown.Converter}
3019 */
3020 this.listen = function (name, callback) {
3021 listen(name, callback);
3022 return this;
3023 };
3024
3025 /**
3026 * Converts a markdown string into HTML
3027 * @param {string} text
3028 * @returns {*}
3029 */
3030 this.makeHtml = function (text) {
3031 //check if text is not falsy
3032 if (!text) {
3033 return text;
3034 }
3035
3036 var globals = {
3037 gHtmlBlocks: [],
3038 gHtmlMdBlocks: [],
3039 gHtmlSpans: [],
3040 gUrls: {},
3041 gTitles: {},
3042 gDimensions: {},
3043 gListLevel: 0,
3044 hashLinkCounts: {},
3045 langExtensions: langExtensions,
3046 outputModifiers: outputModifiers,
3047 converter: this,
3048 ghCodeBlocks: [],
3049 metadata: {
3050 parsed: {},
3051 raw: '',
3052 format: ''
3053 }
3054 };
3055
3056 // This lets us use ¨ trema as an escape char to avoid md5 hashes
3057 // The choice of character is arbitrary; anything that isn't
3058 // magic in Markdown will work.
3059 text = text.replace(/¨/g, '¨T');
3060
3061 // Replace $ with ¨D
3062 // RegExp interprets $ as a special character
3063 // when it's in a replacement string
3064 text = text.replace(/\$/g, '¨D');
3065
3066 // Standardize line endings
3067 text = text.replace(/\r\n/g, '\n'); // DOS to Unix
3068 text = text.replace(/\r/g, '\n'); // Mac to Unix
3069
3070 // Stardardize line spaces
3071 text = text.replace(/\u00A0/g, '&nbsp;');
3072
3073 if (options.smartIndentationFix) {
3074 text = rTrimInputText(text);
3075 }
3076
3077 // Make sure text begins and ends with a couple of newlines:
3078 text = '\n\n' + text + '\n\n';
3079
3080 // detab
3081 text = showdown.subParser('detab')(text, options, globals);
3082
3083 /**
3084 * Strip any lines consisting only of spaces and tabs.
3085 * This makes subsequent regexs easier to write, because we can
3086 * match consecutive blank lines with /\n+/ instead of something
3087 * contorted like /[ \t]*\n+/
3088 */
3089 text = text.replace(/^[ \t]+$/mg, '');
3090
3091 //run languageExtensions
3092 showdown.helper.forEach(langExtensions, function (ext) {
3093 text = showdown.subParser('runExtension')(ext, text, options, globals);
3094 });
3095
3096 // run the sub parsers
3097 text = showdown.subParser('metadata')(text, options, globals);
3098 text = showdown.subParser('hashPreCodeTags')(text, options, globals);
3099 text = showdown.subParser('githubCodeBlocks')(text, options, globals);
3100 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3101 text = showdown.subParser('hashCodeTags')(text, options, globals);
3102 text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
3103 text = showdown.subParser('blockGamut')(text, options, globals);
3104 text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
3105 text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
3106
3107 // attacklab: Restore dollar signs
3108 text = text.replace(/¨D/g, '$$');
3109
3110 // attacklab: Restore tremas
3111 text = text.replace(/¨T/g, '¨');
3112
3113 // render a complete html document instead of a partial if the option is enabled
3114 text = showdown.subParser('completeHTMLDocument')(text, options, globals);
3115
3116 // Run output modifiers
3117 showdown.helper.forEach(outputModifiers, function (ext) {
3118 text = showdown.subParser('runExtension')(ext, text, options, globals);
3119 });
3120
3121 // update metadata
3122 metadata = globals.metadata;
3123 return text;
3124 };
3125
3126 /**
3127 * Converts an HTML string into a markdown string
3128 * @param src
3129 * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
3130 * @returns {string}
3131 */
3132 this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
3133
3134 // replace \r\n with \n
3135 src = src.replace(/\r\n/g, '\n');
3136 src = src.replace(/\r/g, '\n'); // old macs
3137
3138 // due to an edge case, we need to find this: > <
3139 // to prevent removing of non silent white spaces
3140 // ex: <em>this is</em> <strong>sparta</strong>
3141 src = src.replace(/>[ \t]+</, '>¨NBSP;<');
3142
3143 if (!HTMLParser) {
3144 if (window && window.document) {
3145 HTMLParser = window.document;
3146 } else {
3147 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');
3148 }
3149 }
3150
3151 var doc = HTMLParser.createElement('div');
3152 doc.innerHTML = src;
3153
3154 var globals = {
3155 preList: substitutePreCodeTags(doc)
3156 };
3157
3158 // remove all newlines and collapse spaces
3159 clean(doc);
3160
3161 // some stuff, like accidental reference links must now be escaped
3162 // TODO
3163 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
3164
3165 var nodes = doc.childNodes,
3166 mdDoc = '';
3167
3168 for (var i = 0; i < nodes.length; i++) {
3169 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
3170 }
3171
3172 function clean (node) {
3173 for (var n = 0; n < node.childNodes.length; ++n) {
3174 var child = node.childNodes[n];
3175 if (child.nodeType === 3) {
3176 if (!/\S/.test(child.nodeValue)) {
3177 node.removeChild(child);
3178 --n;
3179 } else {
3180 child.nodeValue = child.nodeValue.split('\n').join(' ');
3181 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
3182 }
3183 } else if (child.nodeType === 1) {
3184 clean(child);
3185 }
3186 }
3187 }
3188
3189 // find all pre tags and replace contents with placeholder
3190 // we need this so that we can remove all indentation from html
3191 // to ease up parsing
3192 function substitutePreCodeTags (doc) {
3193
3194 var pres = doc.querySelectorAll('pre'),
3195 presPH = [];
3196
3197 for (var i = 0; i < pres.length; ++i) {
3198
3199 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
3200 var content = pres[i].firstChild.innerHTML.trim(),
3201 language = pres[i].firstChild.getAttribute('data-language') || '';
3202
3203 // if data-language attribute is not defined, then we look for class language-*
3204 if (language === '') {
3205 var classes = pres[i].firstChild.className.split(' ');
3206 for (var c = 0; c < classes.length; ++c) {
3207 var matches = classes[c].match(/^language-(.+)$/);
3208 if (matches !== null) {
3209 language = matches[1];
3210 break;
3211 }
3212 }
3213 }
3214
3215 // unescape html entities in content
3216 content = showdown.helper.unescapeHTMLEntities(content);
3217
3218 presPH.push(content);
3219 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
3220 } else {
3221 presPH.push(pres[i].innerHTML);
3222 pres[i].innerHTML = '';
3223 pres[i].setAttribute('prenum', i.toString());
3224 }
3225 }
3226 return presPH;
3227 }
3228
3229 return mdDoc;
3230 };
3231
3232 /**
3233 * Set an option of this Converter instance
3234 * @param {string} key
3235 * @param {*} value
3236 */
3237 this.setOption = function (key, value) {
3238 options[key] = value;
3239 };
3240
3241 /**
3242 * Get the option of this Converter instance
3243 * @param {string} key
3244 * @returns {*}
3245 */
3246 this.getOption = function (key) {
3247 return options[key];
3248 };
3249
3250 /**
3251 * Get the options of this Converter instance
3252 * @returns {{}}
3253 */
3254 this.getOptions = function () {
3255 return options;
3256 };
3257
3258 /**
3259 * Add extension to THIS converter
3260 * @param {{}} extension
3261 * @param {string} [name=null]
3262 */
3263 this.addExtension = function (extension, name) {
3264 name = name || null;
3265 _parseExtension(extension, name);
3266 };
3267
3268 /**
3269 * Use a global registered extension with THIS converter
3270 * @param {string} extensionName Name of the previously registered extension
3271 */
3272 this.useExtension = function (extensionName) {
3273 _parseExtension(extensionName);
3274 };
3275
3276 /**
3277 * Set the flavor THIS converter should use
3278 * @param {string} name
3279 */
3280 this.setFlavor = function (name) {
3281 if (!flavor.hasOwnProperty(name)) {
3282 throw Error(name + ' flavor was not found');
3283 }
3284 var preset = flavor[name];
3285 setConvFlavor = name;
3286 for (var option in preset) {
3287 if (preset.hasOwnProperty(option)) {
3288 options[option] = preset[option];
3289 }
3290 }
3291 };
3292
3293 /**
3294 * Get the currently set flavor of this converter
3295 * @returns {string}
3296 */
3297 this.getFlavor = function () {
3298 return setConvFlavor;
3299 };
3300
3301 /**
3302 * Remove an extension from THIS converter.
3303 * Note: This is a costly operation. It's better to initialize a new converter
3304 * and specify the extensions you wish to use
3305 * @param {Array} extension
3306 */
3307 this.removeExtension = function (extension) {
3308 if (!showdown.helper.isArray(extension)) {
3309 extension = [extension];
3310 }
3311 for (var a = 0; a < extension.length; ++a) {
3312 var ext = extension[a];
3313 for (var i = 0; i < langExtensions.length; ++i) {
3314 if (langExtensions[i] === ext) {
3315 langExtensions[i].splice(i, 1);
3316 }
3317 }
3318 for (var ii = 0; ii < outputModifiers.length; ++i) {
3319 if (outputModifiers[ii] === ext) {
3320 outputModifiers[ii].splice(i, 1);
3321 }
3322 }
3323 }
3324 };
3325
3326 /**
3327 * Get all extension of THIS converter
3328 * @returns {{language: Array, output: Array}}
3329 */
3330 this.getAllExtensions = function () {
3331 return {
3332 language: langExtensions,
3333 output: outputModifiers
3334 };
3335 };
3336
3337 /**
3338 * Get the metadata of the previously parsed document
3339 * @param raw
3340 * @returns {string|{}}
3341 */
3342 this.getMetadata = function (raw) {
3343 if (raw) {
3344 return metadata.raw;
3345 } else {
3346 return metadata.parsed;
3347 }
3348 };
3349
3350 /**
3351 * Get the metadata format of the previously parsed document
3352 * @returns {string}
3353 */
3354 this.getMetadataFormat = function () {
3355 return metadata.format;
3356 };
3357
3358 /**
3359 * Private: set a single key, value metadata pair
3360 * @param {string} key
3361 * @param {string} value
3362 */
3363 this._setMetadataPair = function (key, value) {
3364 metadata.parsed[key] = value;
3365 };
3366
3367 /**
3368 * Private: set metadata format
3369 * @param {string} format
3370 */
3371 this._setMetadataFormat = function (format) {
3372 metadata.format = format;
3373 };
3374
3375 /**
3376 * Private: set metadata raw text
3377 * @param {string} raw
3378 */
3379 this._setMetadataRaw = function (raw) {
3380 metadata.raw = raw;
3381 };
3382 };
3383
3384 /**
3385 * Turn Markdown link shortcuts into XHTML <a> tags.
3386 */
3387 showdown.subParser('anchors', function (text, options, globals) {
3388 'use strict';
3389
3390 text = globals.converter._dispatch('anchors.before', text, options, globals);
3391
3392 var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
3393 if (showdown.helper.isUndefined(title)) {
3394 title = '';
3395 }
3396 linkId = linkId.toLowerCase();
3397
3398 // Special case for explicit empty url
3399 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3400 url = '';
3401 } else if (!url) {
3402 if (!linkId) {
3403 // lower-case and turn embedded newlines into spaces
3404 linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
3405 }
3406 url = '#' + linkId;
3407
3408 if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
3409 url = globals.gUrls[linkId];
3410 if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
3411 title = globals.gTitles[linkId];
3412 }
3413 } else {
3414 return wholeMatch;
3415 }
3416 }
3417
3418 //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
3419 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3420
3421 var result = '<a href="' + url + '"';
3422
3423 if (title !== '' && title !== null) {
3424 title = title.replace(/"/g, '&quot;');
3425 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3426 title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3427 result += ' title="' + title + '"';
3428 }
3429
3430 // optionLinksInNewWindow only applies
3431 // to external links. Hash links (#) open in same page
3432 if (options.openLinksInNewWindow && !/^#/.test(url)) {
3433 // escaped _
3434 result += ' rel="noopener noreferrer" target="¨E95Eblank"';
3435 }
3436
3437 result += '>' + linkText + '</a>';
3438
3439 return result;
3440 };
3441
3442 // First, handle reference-style links: [link text] [id]
3443 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
3444
3445 // Next, inline-style links: [link text](url "optional title")
3446 // cases with crazy urls like ./image/cat1).png
3447 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3448 writeAnchorTag);
3449
3450 // normal cases
3451 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3452 writeAnchorTag);
3453
3454 // handle reference-style shortcuts: [link text]
3455 // These must come last in case you've also got [link test][1]
3456 // or [link test](/foo)
3457 text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
3458
3459 // Lastly handle GithubMentions if option is enabled
3460 if (options.ghMentions) {
3461 text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
3462 if (escape === '\\') {
3463 return st + mentions;
3464 }
3465
3466 //check if options.ghMentionsLink is a string
3467 if (!showdown.helper.isString(options.ghMentionsLink)) {
3468 throw new Error('ghMentionsLink option must be a string');
3469 }
3470 var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
3471 target = '';
3472 if (options.openLinksInNewWindow) {
3473 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3474 }
3475 return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
3476 });
3477 }
3478
3479 text = globals.converter._dispatch('anchors.after', text, options, globals);
3480 return text;
3481 });
3482
3483 // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
3484
3485 var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
3486 simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
3487 delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
3488 simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
3489 delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
3490
3491 replaceLink = function (options) {
3492 'use strict';
3493 return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
3494 link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3495 var lnkTxt = link,
3496 append = '',
3497 target = '',
3498 lmc = leadingMagicChars || '',
3499 tmc = trailingMagicChars || '';
3500 if (/^www\./i.test(link)) {
3501 link = link.replace(/^www\./i, 'http://www.');
3502 }
3503 if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
3504 append = trailingPunctuation;
3505 }
3506 if (options.openLinksInNewWindow) {
3507 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3508 }
3509 return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
3510 };
3511 },
3512
3513 replaceMail = function (options, globals) {
3514 'use strict';
3515 return function (wholeMatch, b, mail) {
3516 var href = 'mailto:';
3517 b = b || '';
3518 mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
3519 if (options.encodeEmails) {
3520 href = showdown.helper.encodeEmailAddress(href + mail);
3521 mail = showdown.helper.encodeEmailAddress(mail);
3522 } else {
3523 href = href + mail;
3524 }
3525 return b + '<a href="' + href + '">' + mail + '</a>';
3526 };
3527 };
3528
3529 showdown.subParser('autoLinks', function (text, options, globals) {
3530 'use strict';
3531
3532 text = globals.converter._dispatch('autoLinks.before', text, options, globals);
3533
3534 text = text.replace(delimUrlRegex, replaceLink(options));
3535 text = text.replace(delimMailRegex, replaceMail(options, globals));
3536
3537 text = globals.converter._dispatch('autoLinks.after', text, options, globals);
3538
3539 return text;
3540 });
3541
3542 showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
3543 'use strict';
3544
3545 if (!options.simplifiedAutoLink) {
3546 return text;
3547 }
3548
3549 text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
3550
3551 if (options.excludeTrailingPunctuationFromURLs) {
3552 text = text.replace(simpleURLRegex2, replaceLink(options));
3553 } else {
3554 text = text.replace(simpleURLRegex, replaceLink(options));
3555 }
3556 text = text.replace(simpleMailRegex, replaceMail(options, globals));
3557
3558 text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
3559
3560 return text;
3561 });
3562
3563 /**
3564 * These are all the transformations that form block-level
3565 * tags like paragraphs, headers, and list items.
3566 */
3567 showdown.subParser('blockGamut', function (text, options, globals) {
3568 'use strict';
3569
3570 text = globals.converter._dispatch('blockGamut.before', text, options, globals);
3571
3572 // we parse blockquotes first so that we can have headings and hrs
3573 // inside blockquotes
3574 text = showdown.subParser('blockQuotes')(text, options, globals);
3575 text = showdown.subParser('headers')(text, options, globals);
3576
3577 // Do Horizontal Rules:
3578 text = showdown.subParser('horizontalRule')(text, options, globals);
3579
3580 text = showdown.subParser('lists')(text, options, globals);
3581 text = showdown.subParser('codeBlocks')(text, options, globals);
3582 text = showdown.subParser('tables')(text, options, globals);
3583
3584 // We already ran _HashHTMLBlocks() before, in Markdown(), but that
3585 // was to escape raw HTML in the original Markdown source. This time,
3586 // we're escaping the markup we've just created, so that we don't wrap
3587 // <p> tags around block-level tags.
3588 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3589 text = showdown.subParser('paragraphs')(text, options, globals);
3590
3591 text = globals.converter._dispatch('blockGamut.after', text, options, globals);
3592
3593 return text;
3594 });
3595
3596 showdown.subParser('blockQuotes', function (text, options, globals) {
3597 'use strict';
3598
3599 text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
3600
3601 // add a couple extra lines after the text and endtext mark
3602 text = text + '\n\n';
3603
3604 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
3605
3606 if (options.splitAdjacentBlockquotes) {
3607 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
3608 }
3609
3610 text = text.replace(rgx, function (bq) {
3611 // attacklab: hack around Konqueror 3.5.4 bug:
3612 // "----------bug".replace(/^-/g,"") == "bug"
3613 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
3614
3615 // attacklab: clean up hack
3616 bq = bq.replace(/¨0/g, '');
3617
3618 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
3619 bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
3620 bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
3621
3622 bq = bq.replace(/(^|\n)/g, '$1 ');
3623 // These leading spaces screw with <pre> content, so we need to fix that:
3624 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
3625 var pre = m1;
3626 // attacklab: hack around Konqueror 3.5.4 bug:
3627 pre = pre.replace(/^ /mg, '¨0');
3628 pre = pre.replace(/¨0/g, '');
3629 return pre;
3630 });
3631
3632 return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
3633 });
3634
3635 text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
3636 return text;
3637 });
3638
3639 /**
3640 * Process Markdown `<pre><code>` blocks.
3641 */
3642 showdown.subParser('codeBlocks', function (text, options, globals) {
3643 'use strict';
3644
3645 text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
3646
3647 // sentinel workarounds for lack of \A and \Z, safari\khtml bug
3648 text += '¨0';
3649
3650 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
3651 text = text.replace(pattern, function (wholeMatch, m1, m2) {
3652 var codeblock = m1,
3653 nextChar = m2,
3654 end = '\n';
3655
3656 codeblock = showdown.subParser('outdent')(codeblock, options, globals);
3657 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3658 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3659 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3660 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
3661
3662 if (options.omitExtraWLInCodeBlocks) {
3663 end = '';
3664 }
3665
3666 codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
3667
3668 return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
3669 });
3670
3671 // strip sentinel
3672 text = text.replace(/¨0/, '');
3673
3674 text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
3675 return text;
3676 });
3677
3678 /**
3679 *
3680 * * Backtick quotes are used for <code></code> spans.
3681 *
3682 * * You can use multiple backticks as the delimiters if you want to
3683 * include literal backticks in the code span. So, this input:
3684 *
3685 * Just type ``foo `bar` baz`` at the prompt.
3686 *
3687 * Will translate to:
3688 *
3689 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
3690 *
3691 * There's no arbitrary limit to the number of backticks you
3692 * can use as delimters. If you need three consecutive backticks
3693 * in your code, use four for delimiters, etc.
3694 *
3695 * * You can use spaces to get literal backticks at the edges:
3696 *
3697 * ... type `` `bar` `` ...
3698 *
3699 * Turns to:
3700 *
3701 * ... type <code>`bar`</code> ...
3702 */
3703 showdown.subParser('codeSpans', function (text, options, globals) {
3704 'use strict';
3705
3706 text = globals.converter._dispatch('codeSpans.before', text, options, globals);
3707
3708 if (typeof text === 'undefined') {
3709 text = '';
3710 }
3711 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
3712 function (wholeMatch, m1, m2, m3) {
3713 var c = m3;
3714 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
3715 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
3716 c = showdown.subParser('encodeCode')(c, options, globals);
3717 c = m1 + '<code>' + c + '</code>';
3718 c = showdown.subParser('hashHTMLSpans')(c, options, globals);
3719 return c;
3720 }
3721 );
3722
3723 text = globals.converter._dispatch('codeSpans.after', text, options, globals);
3724 return text;
3725 });
3726
3727 /**
3728 * Create a full HTML document from the processed markdown
3729 */
3730 showdown.subParser('completeHTMLDocument', function (text, options, globals) {
3731 'use strict';
3732
3733 if (!options.completeHTMLDocument) {
3734 return text;
3735 }
3736
3737 text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
3738
3739 var doctype = 'html',
3740 doctypeParsed = '<!DOCTYPE HTML>\n',
3741 title = '',
3742 charset = '<meta charset="utf-8">\n',
3743 lang = '',
3744 metadata = '';
3745
3746 if (typeof globals.metadata.parsed.doctype !== 'undefined') {
3747 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n';
3748 doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
3749 if (doctype === 'html' || doctype === 'html5') {
3750 charset = '<meta charset="utf-8">';
3751 }
3752 }
3753
3754 for (var meta in globals.metadata.parsed) {
3755 if (globals.metadata.parsed.hasOwnProperty(meta)) {
3756 switch (meta.toLowerCase()) {
3757 case 'doctype':
3758 break;
3759
3760 case 'title':
3761 title = '<title>' + globals.metadata.parsed.title + '</title>\n';
3762 break;
3763
3764 case 'charset':
3765 if (doctype === 'html' || doctype === 'html5') {
3766 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
3767 } else {
3768 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
3769 }
3770 break;
3771
3772 case 'language':
3773 case 'lang':
3774 lang = ' lang="' + globals.metadata.parsed[meta] + '"';
3775 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3776 break;
3777
3778 default:
3779 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3780 }
3781 }
3782 }
3783
3784 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
3785
3786 text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
3787 return text;
3788 });
3789
3790 /**
3791 * Convert all tabs to spaces
3792 */
3793 showdown.subParser('detab', function (text, options, globals) {
3794 'use strict';
3795 text = globals.converter._dispatch('detab.before', text, options, globals);
3796
3797 // expand first n-1 tabs
3798 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
3799
3800 // replace the nth with two sentinels
3801 text = text.replace(/\t/g, '¨A¨B');
3802
3803 // use the sentinel to anchor our regex so it doesn't explode
3804 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
3805 var leadingText = m1,
3806 numSpaces = 4 - leadingText.length % 4; // g_tab_width
3807
3808 // there *must* be a better way to do this:
3809 for (var i = 0; i < numSpaces; i++) {
3810 leadingText += ' ';
3811 }
3812
3813 return leadingText;
3814 });
3815
3816 // clean up sentinels
3817 text = text.replace(/¨A/g, ' '); // g_tab_width
3818 text = text.replace(/¨B/g, '');
3819
3820 text = globals.converter._dispatch('detab.after', text, options, globals);
3821 return text;
3822 });
3823
3824 showdown.subParser('ellipsis', function (text, options, globals) {
3825 'use strict';
3826
3827 text = globals.converter._dispatch('ellipsis.before', text, options, globals);
3828
3829 text = text.replace(/\.\.\./g, '…');
3830
3831 text = globals.converter._dispatch('ellipsis.after', text, options, globals);
3832
3833 return text;
3834 });
3835
3836 /**
3837 * Turn emoji codes into emojis
3838 *
3839 * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
3840 */
3841 showdown.subParser('emoji', function (text, options, globals) {
3842 'use strict';
3843
3844 if (!options.emoji) {
3845 return text;
3846 }
3847
3848 text = globals.converter._dispatch('emoji.before', text, options, globals);
3849
3850 var emojiRgx = /:([\S]+?):/g;
3851
3852 text = text.replace(emojiRgx, function (wm, emojiCode) {
3853 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
3854 return showdown.helper.emojis[emojiCode];
3855 }
3856 return wm;
3857 });
3858
3859 text = globals.converter._dispatch('emoji.after', text, options, globals);
3860
3861 return text;
3862 });
3863
3864 /**
3865 * Smart processing for ampersands and angle brackets that need to be encoded.
3866 */
3867 showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
3868 'use strict';
3869 text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
3870
3871 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
3872 // http://bumppo.net/projects/amputator/
3873 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
3874
3875 // Encode naked <'s
3876 text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3877
3878 // Encode <
3879 text = text.replace(/</g, '&lt;');
3880
3881 // Encode >
3882 text = text.replace(/>/g, '&gt;');
3883
3884 text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
3885 return text;
3886 });
3887
3888 /**
3889 * Returns the string, with after processing the following backslash escape sequences.
3890 *
3891 * attacklab: The polite way to do this is with the new escapeCharacters() function:
3892 *
3893 * text = escapeCharacters(text,"\\",true);
3894 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
3895 *
3896 * ...but we're sidestepping its use of the (slow) RegExp constructor
3897 * as an optimization for Firefox. This function gets called a LOT.
3898 */
3899 showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
3900 'use strict';
3901 text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
3902
3903 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
3904 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
3905
3906 text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
3907 return text;
3908 });
3909
3910 /**
3911 * Encode/escape certain characters inside Markdown code runs.
3912 * The point is that in code, these characters are literals,
3913 * and lose their special Markdown meanings.
3914 */
3915 showdown.subParser('encodeCode', function (text, options, globals) {
3916 'use strict';
3917
3918 text = globals.converter._dispatch('encodeCode.before', text, options, globals);
3919
3920 // Encode all ampersands; HTML entities are not
3921 // entities within a Markdown code span.
3922 text = text
3923 .replace(/&/g, '&amp;')
3924 // Do the angle bracket song and dance:
3925 .replace(/</g, '&lt;')
3926 .replace(/>/g, '&gt;')
3927 // Now, escape characters that are magic in Markdown:
3928 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
3929
3930 text = globals.converter._dispatch('encodeCode.after', text, options, globals);
3931 return text;
3932 });
3933
3934 /**
3935 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
3936 * don't conflict with their use in Markdown for code, italics and strong.
3937 */
3938 showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
3939 'use strict';
3940 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
3941
3942 // Build a regex to find HTML tags.
3943 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
3944 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
3945
3946 text = text.replace(tags, function (wholeMatch) {
3947 return wholeMatch
3948 .replace(/(.)<\/?code>(?=.)/g, '$1`')
3949 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3950 });
3951
3952 text = text.replace(comments, function (wholeMatch) {
3953 return wholeMatch
3954 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3955 });
3956
3957 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
3958 return text;
3959 });
3960
3961 /**
3962 * Handle github codeblocks prior to running HashHTML so that
3963 * HTML contained within the codeblock gets escaped properly
3964 * Example:
3965 * ```ruby
3966 * def hello_world(x)
3967 * puts "Hello, #{x}"
3968 * end
3969 * ```
3970 */
3971 showdown.subParser('githubCodeBlocks', function (text, options, globals) {
3972 'use strict';
3973
3974 // early exit if option is not enabled
3975 if (!options.ghCodeBlocks) {
3976 return text;
3977 }
3978
3979 text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
3980
3981 text += '¨0';
3982
3983 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
3984 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
3985
3986 // First parse the github code block
3987 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3988 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3989 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3990 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
3991
3992 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
3993
3994 codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
3995
3996 // Since GHCodeblocks can be false positives, we need to
3997 // store the primitive text and the parsed text in a global var,
3998 // and then return a token
3999 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
4000 });
4001
4002 // attacklab: strip sentinel
4003 text = text.replace(/¨0/, '');
4004
4005 return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
4006 });
4007
4008 showdown.subParser('hashBlock', function (text, options, globals) {
4009 'use strict';
4010 text = globals.converter._dispatch('hashBlock.before', text, options, globals);
4011 text = text.replace(/(^\n+|\n+$)/g, '');
4012 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
4013 text = globals.converter._dispatch('hashBlock.after', text, options, globals);
4014 return text;
4015 });
4016
4017 /**
4018 * Hash and escape <code> elements that should not be parsed as markdown
4019 */
4020 showdown.subParser('hashCodeTags', function (text, options, globals) {
4021 'use strict';
4022 text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
4023
4024 var repFunc = function (wholeMatch, match, left, right) {
4025 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4026 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
4027 };
4028
4029 // Hash naked <code>
4030 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
4031
4032 text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
4033 return text;
4034 });
4035
4036 showdown.subParser('hashElement', function (text, options, globals) {
4037 'use strict';
4038
4039 return function (wholeMatch, m1) {
4040 var blockText = m1;
4041
4042 // Undo double lines
4043 blockText = blockText.replace(/\n\n/g, '\n');
4044 blockText = blockText.replace(/^\n/, '');
4045
4046 // strip trailing blank lines
4047 blockText = blockText.replace(/\n+$/g, '');
4048
4049 // Replace the element text with a marker ("¨KxK" where x is its key)
4050 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
4051
4052 return blockText;
4053 };
4054 });
4055
4056 showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
4057 'use strict';
4058 text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
4059
4060 var blockTags = [
4061 'pre',
4062 'div',
4063 'h1',
4064 'h2',
4065 'h3',
4066 'h4',
4067 'h5',
4068 'h6',
4069 'blockquote',
4070 'table',
4071 'dl',
4072 'ol',
4073 'ul',
4074 'script',
4075 'noscript',
4076 'form',
4077 'fieldset',
4078 'iframe',
4079 'math',
4080 'style',
4081 'section',
4082 'header',
4083 'footer',
4084 'nav',
4085 'article',
4086 'aside',
4087 'address',
4088 'audio',
4089 'canvas',
4090 'figure',
4091 'hgroup',
4092 'output',
4093 'video',
4094 'p'
4095 ],
4096 repFunc = function (wholeMatch, match, left, right) {
4097 var txt = wholeMatch;
4098 // check if this html element is marked as markdown
4099 // if so, it's contents should be parsed as markdown
4100 if (left.search(/\bmarkdown\b/) !== -1) {
4101 txt = left + globals.converter.makeHtml(match) + right;
4102 }
4103 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4104 };
4105
4106 if (options.backslashEscapesHTMLTags) {
4107 // encode backslash escaped HTML tags
4108 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
4109 return '&lt;' + inside + '&gt;';
4110 });
4111 }
4112
4113 // hash HTML Blocks
4114 for (var i = 0; i < blockTags.length; ++i) {
4115
4116 var opTagPos,
4117 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
4118 patLeft = '<' + blockTags[i] + '\\b[^>]*>',
4119 patRight = '</' + blockTags[i] + '>';
4120 // 1. Look for the first position of the first opening HTML tag in the text
4121 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
4122
4123 // if the HTML tag is \ escaped, we need to escape it and break
4124
4125
4126 //2. Split the text in that position
4127 var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
4128 //3. Match recursively
4129 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
4130
4131 // prevent an infinite loop
4132 if (newSubText1 === subTexts[1]) {
4133 break;
4134 }
4135 text = subTexts[0].concat(newSubText1);
4136 }
4137 }
4138 // HR SPECIAL CASE
4139 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
4140 showdown.subParser('hashElement')(text, options, globals));
4141
4142 // Special case for standalone HTML comments
4143 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
4144 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
4145 }, '^ {0,3}<!--', '-->', 'gm');
4146
4147 // PHP and ASP-style processor instructions (<?...?> and <%...%>)
4148 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
4149 showdown.subParser('hashElement')(text, options, globals));
4150
4151 text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
4152 return text;
4153 });
4154
4155 /**
4156 * Hash span elements that should not be parsed as markdown
4157 */
4158 showdown.subParser('hashHTMLSpans', function (text, options, globals) {
4159 'use strict';
4160 text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
4161
4162 function hashHTMLSpan (html) {
4163 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
4164 }
4165
4166 // Hash Self Closing tags
4167 text = text.replace(/<[^>]+?\/>/gi, function (wm) {
4168 return hashHTMLSpan(wm);
4169 });
4170
4171 // Hash tags without properties
4172 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
4173 return hashHTMLSpan(wm);
4174 });
4175
4176 // Hash tags with properties
4177 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
4178 return hashHTMLSpan(wm);
4179 });
4180
4181 // Hash self closing tags without />
4182 text = text.replace(/<[^>]+?>/gi, function (wm) {
4183 return hashHTMLSpan(wm);
4184 });
4185
4186 /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
4187
4188 text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
4189 return text;
4190 });
4191
4192 /**
4193 * Unhash HTML spans
4194 */
4195 showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
4196 'use strict';
4197 text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
4198
4199 for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
4200 var repText = globals.gHtmlSpans[i],
4201 // limiter to prevent infinite loop (assume 10 as limit for recurse)
4202 limit = 0;
4203
4204 while (/¨C(\d+)C/.test(repText)) {
4205 var num = RegExp.$1;
4206 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
4207 if (limit === 10) {
4208 console.error('maximum nesting of 10 spans reached!!!');
4209 break;
4210 }
4211 ++limit;
4212 }
4213 text = text.replace('¨C' + i + 'C', repText);
4214 }
4215
4216 text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
4217 return text;
4218 });
4219
4220 /**
4221 * Hash and escape <pre><code> elements that should not be parsed as markdown
4222 */
4223 showdown.subParser('hashPreCodeTags', function (text, options, globals) {
4224 'use strict';
4225 text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
4226
4227 var repFunc = function (wholeMatch, match, left, right) {
4228 // encode html entities
4229 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
4230 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
4231 };
4232
4233 // Hash <pre><code>
4234 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
4235
4236 text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
4237 return text;
4238 });
4239
4240 showdown.subParser('headers', function (text, options, globals) {
4241 'use strict';
4242
4243 text = globals.converter._dispatch('headers.before', text, options, globals);
4244
4245 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
4246
4247 // Set text-style headers:
4248 // Header 1
4249 // ========
4250 //
4251 // Header 2
4252 // --------
4253 //
4254 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
4255 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
4256
4257 text = text.replace(setextRegexH1, function (wholeMatch, m1) {
4258
4259 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4260 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4261 hLevel = headerLevelStart,
4262 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4263 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4264 });
4265
4266 text = text.replace(setextRegexH2, function (matchFound, m1) {
4267 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
4268 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
4269 hLevel = headerLevelStart + 1,
4270 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
4271 return showdown.subParser('hashBlock')(hashBlock, options, globals);
4272 });
4273
4274 // atx-style headers:
4275 // # Header 1
4276 // ## Header 2
4277 // ## Header 2 with closing hashes ##
4278 // ...
4279 // ###### Header 6
4280 //
4281 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
4282
4283 text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
4284 var hText = m2;
4285 if (options.customizedHeaderId) {
4286 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
4287 }
4288
4289 var span = showdown.subParser('spanGamut')(hText, options, globals),
4290 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
4291 hLevel = headerLevelStart - 1 + m1.length,
4292 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
4293
4294 return showdown.subParser('hashBlock')(header, options, globals);
4295 });
4296
4297 function headerId (m) {
4298 var title,
4299 prefix;
4300
4301 // It is separate from other options to allow combining prefix and customized
4302 if (options.customizedHeaderId) {
4303 var match = m.match(/\{([^{]+?)}\s*$/);
4304 if (match && match[1]) {
4305 m = match[1];
4306 }
4307 }
4308
4309 title = m;
4310
4311 // Prefix id to prevent causing inadvertent pre-existing style matches.
4312 if (showdown.helper.isString(options.prefixHeaderId)) {
4313 prefix = options.prefixHeaderId;
4314 } else if (options.prefixHeaderId === true) {
4315 prefix = 'section-';
4316 } else {
4317 prefix = '';
4318 }
4319
4320 if (!options.rawPrefixHeaderId) {
4321 title = prefix + title;
4322 }
4323
4324 if (options.ghCompatibleHeaderId) {
4325 title = title
4326 .replace(/ /g, '-')
4327 // replace previously escaped chars (&, ¨ and $)
4328 .replace(/&amp;/g, '')
4329 .replace(/¨T/g, '')
4330 .replace(/¨D/g, '')
4331 // replace rest of the chars (&~$ are repeated as they might have been escaped)
4332 // borrowed from github's redcarpet (some they should produce similar results)
4333 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
4334 .toLowerCase();
4335 } else if (options.rawHeaderId) {
4336 title = title
4337 .replace(/ /g, '-')
4338 // replace previously escaped chars (&, ¨ and $)
4339 .replace(/&amp;/g, '&')
4340 .replace(/¨T/g, '¨')
4341 .replace(/¨D/g, '$')
4342 // replace " and '
4343 .replace(/["']/g, '-')
4344 .toLowerCase();
4345 } else {
4346 title = title
4347 .replace(/[^\w]/g, '')
4348 .toLowerCase();
4349 }
4350
4351 if (options.rawPrefixHeaderId) {
4352 title = prefix + title;
4353 }
4354
4355 if (globals.hashLinkCounts[title]) {
4356 title = title + '-' + (globals.hashLinkCounts[title]++);
4357 } else {
4358 globals.hashLinkCounts[title] = 1;
4359 }
4360 return title;
4361 }
4362
4363 text = globals.converter._dispatch('headers.after', text, options, globals);
4364 return text;
4365 });
4366
4367 /**
4368 * Turn Markdown link shortcuts into XHTML <a> tags.
4369 */
4370 showdown.subParser('horizontalRule', function (text, options, globals) {
4371 'use strict';
4372 text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
4373
4374 var key = showdown.subParser('hashBlock')('<hr />', options, globals);
4375 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
4376 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
4377 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
4378
4379 text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
4380 return text;
4381 });
4382
4383 /**
4384 * Turn Markdown image shortcuts into <img> tags.
4385 */
4386 showdown.subParser('images', function (text, options, globals) {
4387 'use strict';
4388
4389 text = globals.converter._dispatch('images.before', text, options, globals);
4390
4391 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
4392 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
4393 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,
4394 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
4395 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
4396
4397 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
4398 url = url.replace(/\s/g, '');
4399 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
4400 }
4401
4402 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
4403
4404 var gUrls = globals.gUrls,
4405 gTitles = globals.gTitles,
4406 gDims = globals.gDimensions;
4407
4408 linkId = linkId.toLowerCase();
4409
4410 if (!title) {
4411 title = '';
4412 }
4413 // Special case for explicit empty url
4414 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
4415 url = '';
4416
4417 } else if (url === '' || url === null) {
4418 if (linkId === '' || linkId === null) {
4419 // lower-case and turn embedded newlines into spaces
4420 linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
4421 }
4422 url = '#' + linkId;
4423
4424 if (!showdown.helper.isUndefined(gUrls[linkId])) {
4425 url = gUrls[linkId];
4426 if (!showdown.helper.isUndefined(gTitles[linkId])) {
4427 title = gTitles[linkId];
4428 }
4429 if (!showdown.helper.isUndefined(gDims[linkId])) {
4430 width = gDims[linkId].width;
4431 height = gDims[linkId].height;
4432 }
4433 } else {
4434 return wholeMatch;
4435 }
4436 }
4437
4438 altText = altText
4439 .replace(/"/g, '&quot;')
4440 //altText = showdown.helper.escapeCharacters(altText, '*_', false);
4441 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4442 //url = showdown.helper.escapeCharacters(url, '*_', false);
4443 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4444 var result = '<img src="' + url + '" alt="' + altText + '"';
4445
4446 if (title && showdown.helper.isString(title)) {
4447 title = title
4448 .replace(/"/g, '&quot;')
4449 //title = showdown.helper.escapeCharacters(title, '*_', false);
4450 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4451 result += ' title="' + title + '"';
4452 }
4453
4454 if (width && height) {
4455 width = (width === '*') ? 'auto' : width;
4456 height = (height === '*') ? 'auto' : height;
4457
4458 result += ' width="' + width + '"';
4459 result += ' height="' + height + '"';
4460 }
4461
4462 result += ' />';
4463
4464 return result;
4465 }
4466
4467 // First, handle reference-style labeled images: ![alt text][id]
4468 text = text.replace(referenceRegExp, writeImageTag);
4469
4470 // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
4471
4472 // base64 encoded images
4473 text = text.replace(base64RegExp, writeImageTagBase64);
4474
4475 // cases with crazy urls like ./image/cat1).png
4476 text = text.replace(crazyRegExp, writeImageTag);
4477
4478 // normal cases
4479 text = text.replace(inlineRegExp, writeImageTag);
4480
4481 // handle reference-style shortcuts: ![img text]
4482 text = text.replace(refShortcutRegExp, writeImageTag);
4483
4484 text = globals.converter._dispatch('images.after', text, options, globals);
4485 return text;
4486 });
4487
4488 showdown.subParser('italicsAndBold', function (text, options, globals) {
4489 'use strict';
4490
4491 text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
4492
4493 // it's faster to have 3 separate regexes for each case than have just one
4494 // because of backtracing, in some cases, it could lead to an exponential effect
4495 // called "catastrophic backtrace". Ominous!
4496
4497 function parseInside (txt, left, right) {
4498 /*
4499 if (options.simplifiedAutoLink) {
4500 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4501 }
4502 */
4503 return left + txt + right;
4504 }
4505
4506 // Parse underscores
4507 if (options.literalMidWordUnderscores) {
4508 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4509 return parseInside (txt, '<strong><em>', '</em></strong>');
4510 });
4511 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4512 return parseInside (txt, '<strong>', '</strong>');
4513 });
4514 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
4515 return parseInside (txt, '<em>', '</em>');
4516 });
4517 } else {
4518 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4519 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4520 });
4521 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4522 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4523 });
4524 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
4525 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
4526 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4527 });
4528 }
4529
4530 // Now parse asterisks
4531 if (options.literalMidWordAsterisks) {
4532 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
4533 return parseInside (txt, lead + '<strong><em>', '</em></strong>');
4534 });
4535 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
4536 return parseInside (txt, lead + '<strong>', '</strong>');
4537 });
4538 text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
4539 return parseInside (txt, lead + '<em>', '</em>');
4540 });
4541 } else {
4542 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
4543 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4544 });
4545 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
4546 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4547 });
4548 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
4549 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
4550 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4551 });
4552 }
4553
4554
4555 text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
4556 return text;
4557 });
4558
4559 /**
4560 * Form HTML ordered (numbered) and unordered (bulleted) lists.
4561 */
4562 showdown.subParser('lists', function (text, options, globals) {
4563 'use strict';
4564
4565 /**
4566 * Process the contents of a single ordered or unordered list, splitting it
4567 * into individual list items.
4568 * @param {string} listStr
4569 * @param {boolean} trimTrailing
4570 * @returns {string}
4571 */
4572 function processListItems (listStr, trimTrailing) {
4573 // The $g_list_level global keeps track of when we're inside a list.
4574 // Each time we enter a list, we increment it; when we leave a list,
4575 // we decrement. If it's zero, we're not in a list anymore.
4576 //
4577 // We do this because when we're not inside a list, we want to treat
4578 // something like this:
4579 //
4580 // I recommend upgrading to version
4581 // 8. Oops, now this line is treated
4582 // as a sub-list.
4583 //
4584 // As a single paragraph, despite the fact that the second line starts
4585 // with a digit-period-space sequence.
4586 //
4587 // Whereas when we're inside a list (or sub-list), that line will be
4588 // treated as the start of a sub-list. What a kludge, huh? This is
4589 // an aspect of Markdown's syntax that's hard to parse perfectly
4590 // without resorting to mind-reading. Perhaps the solution is to
4591 // change the syntax rules such that sub-lists must start with a
4592 // starting cardinal number; e.g. "1." or "a.".
4593 globals.gListLevel++;
4594
4595 // trim trailing blank lines:
4596 listStr = listStr.replace(/\n{2,}$/, '\n');
4597
4598 // attacklab: add sentinel to emulate \z
4599 listStr += '¨0';
4600
4601 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
4602 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
4603
4604 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
4605 // which is a syntax breaking change
4606 // activating this option reverts to old behavior
4607 if (options.disableForced4SpacesIndentedSublists) {
4608 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
4609 }
4610
4611 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
4612 checked = (checked && checked.trim() !== '');
4613
4614 var item = showdown.subParser('outdent')(m4, options, globals),
4615 bulletStyle = '';
4616
4617 // Support for github tasklists
4618 if (taskbtn && options.tasklists) {
4619 bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
4620 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
4621 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
4622 if (checked) {
4623 otp += ' checked';
4624 }
4625 otp += '>';
4626 return otp;
4627 });
4628 }
4629
4630 // ISSUE #312
4631 // This input: - - - a
4632 // causes trouble to the parser, since it interprets it as:
4633 // <ul><li><li><li>a</li></li></li></ul>
4634 // instead of:
4635 // <ul><li>- - a</li></ul>
4636 // So, to prevent it, we will put a marker (¨A)in the beginning of the line
4637 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
4638 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
4639 return '¨A' + wm2;
4640 });
4641
4642 // m1 - Leading line or
4643 // Has a double return (multi paragraph) or
4644 // Has sublist
4645 if (m1 || (item.search(/\n{2,}/) > -1)) {
4646 item = showdown.subParser('githubCodeBlocks')(item, options, globals);
4647 item = showdown.subParser('blockGamut')(item, options, globals);
4648 } else {
4649 // Recursion for sub-lists:
4650 item = showdown.subParser('lists')(item, options, globals);
4651 item = item.replace(/\n$/, ''); // chomp(item)
4652 item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
4653
4654 // Colapse double linebreaks
4655 item = item.replace(/\n\n+/g, '\n\n');
4656 if (isParagraphed) {
4657 item = showdown.subParser('paragraphs')(item, options, globals);
4658 } else {
4659 item = showdown.subParser('spanGamut')(item, options, globals);
4660 }
4661 }
4662
4663 // now we need to remove the marker (¨A)
4664 item = item.replace('¨A', '');
4665 // we can finally wrap the line in list item tags
4666 item = '<li' + bulletStyle + '>' + item + '</li>\n';
4667
4668 return item;
4669 });
4670
4671 // attacklab: strip sentinel
4672 listStr = listStr.replace(/¨0/g, '');
4673
4674 globals.gListLevel--;
4675
4676 if (trimTrailing) {
4677 listStr = listStr.replace(/\s+$/, '');
4678 }
4679
4680 return listStr;
4681 }
4682
4683 function styleStartNumber (list, listType) {
4684 // check if ol and starts by a number different than 1
4685 if (listType === 'ol') {
4686 var res = list.match(/^ *(\d+)\./);
4687 if (res && res[1] !== '1') {
4688 return ' start="' + res[1] + '"';
4689 }
4690 }
4691 return '';
4692 }
4693
4694 /**
4695 * Check and parse consecutive lists (better fix for issue #142)
4696 * @param {string} list
4697 * @param {string} listType
4698 * @param {boolean} trimTrailing
4699 * @returns {string}
4700 */
4701 function parseConsecutiveLists (list, listType, trimTrailing) {
4702 // check if we caught 2 or more consecutive lists by mistake
4703 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
4704 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
4705 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
4706 counterRxg = (listType === 'ul') ? olRgx : ulRgx,
4707 result = '';
4708
4709 if (list.search(counterRxg) !== -1) {
4710 (function parseCL (txt) {
4711 var pos = txt.search(counterRxg),
4712 style = styleStartNumber(list, listType);
4713 if (pos !== -1) {
4714 // slice
4715 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
4716
4717 // invert counterType and listType
4718 listType = (listType === 'ul') ? 'ol' : 'ul';
4719 counterRxg = (listType === 'ul') ? olRgx : ulRgx;
4720
4721 //recurse
4722 parseCL(txt.slice(pos));
4723 } else {
4724 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
4725 }
4726 })(list);
4727 } else {
4728 var style = styleStartNumber(list, listType);
4729 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
4730 }
4731
4732 return result;
4733 }
4734
4735 /** Start of list parsing **/
4736 text = globals.converter._dispatch('lists.before', text, options, globals);
4737 // add sentinel to hack around khtml/safari bug:
4738 // http://bugs.webkit.org/show_bug.cgi?id=11231
4739 text += '¨0';
4740
4741 if (globals.gListLevel) {
4742 text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4743 function (wholeMatch, list, m2) {
4744 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4745 return parseConsecutiveLists(list, listType, true);
4746 }
4747 );
4748 } else {
4749 text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4750 function (wholeMatch, m1, list, m3) {
4751 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4752 return parseConsecutiveLists(list, listType, false);
4753 }
4754 );
4755 }
4756
4757 // strip sentinel
4758 text = text.replace(/¨0/, '');
4759 text = globals.converter._dispatch('lists.after', text, options, globals);
4760 return text;
4761 });
4762
4763 /**
4764 * Parse metadata at the top of the document
4765 */
4766 showdown.subParser('metadata', function (text, options, globals) {
4767 'use strict';
4768
4769 if (!options.metadata) {
4770 return text;
4771 }
4772
4773 text = globals.converter._dispatch('metadata.before', text, options, globals);
4774
4775 function parseMetadataContents (content) {
4776 // raw is raw so it's not changed in any way
4777 globals.metadata.raw = content;
4778
4779 // escape chars forbidden in html attributes
4780 // double quotes
4781 content = content
4782 // ampersand first
4783 .replace(/&/g, '&amp;')
4784 // double quotes
4785 .replace(/"/g, '&quot;');
4786
4787 content = content.replace(/\n {4}/g, ' ');
4788 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
4789 globals.metadata.parsed[key] = value;
4790 return '';
4791 });
4792 }
4793
4794 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
4795 parseMetadataContents(content);
4796 return '¨M';
4797 });
4798
4799 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
4800 if (format) {
4801 globals.metadata.format = format;
4802 }
4803 parseMetadataContents(content);
4804 return '¨M';
4805 });
4806
4807 text = text.replace(/¨M/g, '');
4808
4809 text = globals.converter._dispatch('metadata.after', text, options, globals);
4810 return text;
4811 });
4812
4813 /**
4814 * Remove one level of line-leading tabs or spaces
4815 */
4816 showdown.subParser('outdent', function (text, options, globals) {
4817 'use strict';
4818 text = globals.converter._dispatch('outdent.before', text, options, globals);
4819
4820 // attacklab: hack around Konqueror 3.5.4 bug:
4821 // "----------bug".replace(/^-/g,"") == "bug"
4822 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
4823
4824 // attacklab: clean up hack
4825 text = text.replace(/¨0/g, '');
4826
4827 text = globals.converter._dispatch('outdent.after', text, options, globals);
4828 return text;
4829 });
4830
4831 /**
4832 *
4833 */
4834 showdown.subParser('paragraphs', function (text, options, globals) {
4835 'use strict';
4836
4837 text = globals.converter._dispatch('paragraphs.before', text, options, globals);
4838 // Strip leading and trailing lines:
4839 text = text.replace(/^\n+/g, '');
4840 text = text.replace(/\n+$/g, '');
4841
4842 var grafs = text.split(/\n{2,}/g),
4843 grafsOut = [],
4844 end = grafs.length; // Wrap <p> tags
4845
4846 for (var i = 0; i < end; i++) {
4847 var str = grafs[i];
4848 // if this is an HTML marker, copy it
4849 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
4850 grafsOut.push(str);
4851
4852 // test for presence of characters to prevent empty lines being parsed
4853 // as paragraphs (resulting in undesired extra empty paragraphs)
4854 } else if (str.search(/\S/) >= 0) {
4855 str = showdown.subParser('spanGamut')(str, options, globals);
4856 str = str.replace(/^([ \t]*)/g, '<p>');
4857 str += '</p>';
4858 grafsOut.push(str);
4859 }
4860 }
4861
4862 /** Unhashify HTML blocks */
4863 end = grafsOut.length;
4864 for (i = 0; i < end; i++) {
4865 var blockText = '',
4866 grafsOutIt = grafsOut[i],
4867 codeFlag = false;
4868 // if this is a marker for an html block...
4869 // use RegExp.test instead of string.search because of QML bug
4870 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
4871 var delim = RegExp.$1,
4872 num = RegExp.$2;
4873
4874 if (delim === 'K') {
4875 blockText = globals.gHtmlBlocks[num];
4876 } else {
4877 // we need to check if ghBlock is a false positive
4878 if (codeFlag) {
4879 // use encoded version of all text
4880 blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4881 } else {
4882 blockText = globals.ghCodeBlocks[num].codeblock;
4883 }
4884 }
4885 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4886
4887 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4888 // Check if grafsOutIt is a pre->code
4889 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4890 codeFlag = true;
4891 }
4892 }
4893 grafsOut[i] = grafsOutIt;
4894 }
4895 text = grafsOut.join('\n');
4896 // Strip leading and trailing lines:
4897 text = text.replace(/^\n+/g, '');
4898 text = text.replace(/\n+$/g, '');
4899 return globals.converter._dispatch('paragraphs.after', text, options, globals);
4900 });
4901
4902 /**
4903 * Run extension
4904 */
4905 showdown.subParser('runExtension', function (ext, text, options, globals) {
4906 'use strict';
4907
4908 if (ext.filter) {
4909 text = ext.filter(text, globals.converter, options);
4910
4911 } else if (ext.regex) {
4912 // TODO remove this when old extension loading mechanism is deprecated
4913 var re = ext.regex;
4914 if (!(re instanceof RegExp)) {
4915 re = new RegExp(re, 'g');
4916 }
4917 text = text.replace(re, ext.replace);
4918 }
4919
4920 return text;
4921 });
4922
4923 /**
4924 * These are all the transformations that occur *within* block-level
4925 * tags like paragraphs, headers, and list items.
4926 */
4927 showdown.subParser('spanGamut', function (text, options, globals) {
4928 'use strict';
4929
4930 text = globals.converter._dispatch('spanGamut.before', text, options, globals);
4931 text = showdown.subParser('codeSpans')(text, options, globals);
4932 text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4933 text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
4934
4935 // Process anchor and image tags. Images must come first,
4936 // because ![foo][f] looks like an anchor.
4937 text = showdown.subParser('images')(text, options, globals);
4938 text = showdown.subParser('anchors')(text, options, globals);
4939
4940 // Make links out of things like `<http://example.com/>`
4941 // Must come after anchors, because you can use < and >
4942 // delimiters in inline links like [this](<url>).
4943 text = showdown.subParser('autoLinks')(text, options, globals);
4944 text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
4945 text = showdown.subParser('emoji')(text, options, globals);
4946 text = showdown.subParser('underline')(text, options, globals);
4947 text = showdown.subParser('italicsAndBold')(text, options, globals);
4948 text = showdown.subParser('strikethrough')(text, options, globals);
4949 text = showdown.subParser('ellipsis')(text, options, globals);
4950
4951 // we need to hash HTML tags inside spans
4952 text = showdown.subParser('hashHTMLSpans')(text, options, globals);
4953
4954 // now we encode amps and angles
4955 text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
4956
4957 // Do hard breaks
4958 if (options.simpleLineBreaks) {
4959 // GFM style hard breaks
4960 // only add line breaks if the text does not contain a block (special case for lists)
4961 if (!/\n\n¨K/.test(text)) {
4962 text = text.replace(/\n+/g, '<br />\n');
4963 }
4964 } else {
4965 // Vanilla hard breaks
4966 text = text.replace(/ +\n/g, '<br />\n');
4967 }
4968
4969 text = globals.converter._dispatch('spanGamut.after', text, options, globals);
4970 return text;
4971 });
4972
4973 showdown.subParser('strikethrough', function (text, options, globals) {
4974 'use strict';
4975
4976 function parseInside (txt) {
4977 if (options.simplifiedAutoLink) {
4978 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4979 }
4980 return '<del>' + txt + '</del>';
4981 }
4982
4983 if (options.strikethrough) {
4984 text = globals.converter._dispatch('strikethrough.before', text, options, globals);
4985 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
4986 text = globals.converter._dispatch('strikethrough.after', text, options, globals);
4987 }
4988
4989 return text;
4990 });
4991
4992 /**
4993 * Strips link definitions from text, stores the URLs and titles in
4994 * hash references.
4995 * Link defs are in the form: ^[id]: url "optional title"
4996 */
4997 showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
4998 'use strict';
4999
5000 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,
5001 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;
5002
5003 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
5004 text += '¨0';
5005
5006 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
5007 linkId = linkId.toLowerCase();
5008 if (url.match(/^data:.+?\/.+?;base64,/)) {
5009 // remove newlines
5010 globals.gUrls[linkId] = url.replace(/\s/g, '');
5011 } else {
5012 globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
5013 }
5014
5015 if (blankLines) {
5016 // Oops, found blank lines, so it's not a title.
5017 // Put back the parenthetical statement we stole.
5018 return blankLines + title;
5019
5020 } else {
5021 if (title) {
5022 globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
5023 }
5024 if (options.parseImgDimensions && width && height) {
5025 globals.gDimensions[linkId] = {
5026 width: width,
5027 height: height
5028 };
5029 }
5030 }
5031 // Completely remove the definition from the text
5032 return '';
5033 };
5034
5035 // first we try to find base64 link references
5036 text = text.replace(base64Regex, replaceFunc);
5037
5038 text = text.replace(regex, replaceFunc);
5039
5040 // attacklab: strip sentinel
5041 text = text.replace(/¨0/, '');
5042
5043 return text;
5044 });
5045
5046 showdown.subParser('tables', function (text, options, globals) {
5047 'use strict';
5048
5049 if (!options.tables) {
5050 return text;
5051 }
5052
5053 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
5054 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
5055 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
5056
5057 function parseStyles (sLine) {
5058 if (/^:[ \t]*--*$/.test(sLine)) {
5059 return ' style="text-align:left;"';
5060 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
5061 return ' style="text-align:right;"';
5062 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
5063 return ' style="text-align:center;"';
5064 } else {
5065 return '';
5066 }
5067 }
5068
5069 function parseHeaders (header, style) {
5070 var id = '';
5071 header = header.trim();
5072 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
5073 if (options.tablesHeaderId || options.tableHeaderId) {
5074 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
5075 }
5076 header = showdown.subParser('spanGamut')(header, options, globals);
5077
5078 return '<th' + id + style + '>' + header + '</th>\n';
5079 }
5080
5081 function parseCells (cell, style) {
5082 var subText = showdown.subParser('spanGamut')(cell, options, globals);
5083 return '<td' + style + '>' + subText + '</td>\n';
5084 }
5085
5086 function buildTable (headers, cells) {
5087 var tb = '<table>\n<thead>\n<tr>\n',
5088 tblLgn = headers.length;
5089
5090 for (var i = 0; i < tblLgn; ++i) {
5091 tb += headers[i];
5092 }
5093 tb += '</tr>\n</thead>\n<tbody>\n';
5094
5095 for (i = 0; i < cells.length; ++i) {
5096 tb += '<tr>\n';
5097 for (var ii = 0; ii < tblLgn; ++ii) {
5098 tb += cells[i][ii];
5099 }
5100 tb += '</tr>\n';
5101 }
5102 tb += '</tbody>\n</table>\n';
5103 return tb;
5104 }
5105
5106 function parseTable (rawTable) {
5107 var i, tableLines = rawTable.split('\n');
5108
5109 for (i = 0; i < tableLines.length; ++i) {
5110 // strip wrong first and last column if wrapped tables are used
5111 if (/^ {0,3}\|/.test(tableLines[i])) {
5112 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
5113 }
5114 if (/\|[ \t]*$/.test(tableLines[i])) {
5115 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
5116 }
5117 // parse code spans first, but we only support one line code spans
5118 tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
5119 }
5120
5121 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
5122 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
5123 rawCells = [],
5124 headers = [],
5125 styles = [],
5126 cells = [];
5127
5128 tableLines.shift();
5129 tableLines.shift();
5130
5131 for (i = 0; i < tableLines.length; ++i) {
5132 if (tableLines[i].trim() === '') {
5133 continue;
5134 }
5135 rawCells.push(
5136 tableLines[i]
5137 .split('|')
5138 .map(function (s) {
5139 return s.trim();
5140 })
5141 );
5142 }
5143
5144 if (rawHeaders.length < rawStyles.length) {
5145 return rawTable;
5146 }
5147
5148 for (i = 0; i < rawStyles.length; ++i) {
5149 styles.push(parseStyles(rawStyles[i]));
5150 }
5151
5152 for (i = 0; i < rawHeaders.length; ++i) {
5153 if (showdown.helper.isUndefined(styles[i])) {
5154 styles[i] = '';
5155 }
5156 headers.push(parseHeaders(rawHeaders[i], styles[i]));
5157 }
5158
5159 for (i = 0; i < rawCells.length; ++i) {
5160 var row = [];
5161 for (var ii = 0; ii < headers.length; ++ii) {
5162 if (showdown.helper.isUndefined(rawCells[i][ii])) {
5163
5164 }
5165 row.push(parseCells(rawCells[i][ii], styles[ii]));
5166 }
5167 cells.push(row);
5168 }
5169
5170 return buildTable(headers, cells);
5171 }
5172
5173 text = globals.converter._dispatch('tables.before', text, options, globals);
5174
5175 // find escaped pipe characters
5176 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
5177
5178 // parse multi column tables
5179 text = text.replace(tableRgx, parseTable);
5180
5181 // parse one column tables
5182 text = text.replace(singeColTblRgx, parseTable);
5183
5184 text = globals.converter._dispatch('tables.after', text, options, globals);
5185
5186 return text;
5187 });
5188
5189 showdown.subParser('underline', function (text, options, globals) {
5190 'use strict';
5191
5192 if (!options.underline) {
5193 return text;
5194 }
5195
5196 text = globals.converter._dispatch('underline.before', text, options, globals);
5197
5198 if (options.literalMidWordUnderscores) {
5199 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
5200 return '<u>' + txt + '</u>';
5201 });
5202 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
5203 return '<u>' + txt + '</u>';
5204 });
5205 } else {
5206 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
5207 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5208 });
5209 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
5210 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
5211 });
5212 }
5213
5214 // escape remaining underscores to prevent them being parsed by italic and bold
5215 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
5216
5217 text = globals.converter._dispatch('underline.after', text, options, globals);
5218
5219 return text;
5220 });
5221
5222 /**
5223 * Swap back in all the special characters we've hidden.
5224 */
5225 showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
5226 'use strict';
5227 text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
5228
5229 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
5230 var charCodeToReplace = parseInt(m1);
5231 return String.fromCharCode(charCodeToReplace);
5232 });
5233
5234 text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
5235 return text;
5236 });
5237
5238 showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
5239 'use strict';
5240
5241 var txt = '';
5242 if (node.hasChildNodes()) {
5243 var children = node.childNodes,
5244 childrenLength = children.length;
5245
5246 for (var i = 0; i < childrenLength; ++i) {
5247 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
5248
5249 if (innerTxt === '') {
5250 continue;
5251 }
5252 txt += innerTxt;
5253 }
5254 }
5255 // cleanup
5256 txt = txt.trim();
5257 txt = '> ' + txt.split('\n').join('\n> ');
5258 return txt;
5259 });
5260
5261 showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
5262 'use strict';
5263
5264 var lang = node.getAttribute('language'),
5265 num = node.getAttribute('precodenum');
5266 return '```' + lang + '\n' + globals.preList[num] + '\n```';
5267 });
5268
5269 showdown.subParser('makeMarkdown.codeSpan', function (node) {
5270 'use strict';
5271
5272 return '`' + node.innerHTML + '`';
5273 });
5274
5275 showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
5276 'use strict';
5277
5278 var txt = '';
5279 if (node.hasChildNodes()) {
5280 txt += '*';
5281 var children = node.childNodes,
5282 childrenLength = children.length;
5283 for (var i = 0; i < childrenLength; ++i) {
5284 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5285 }
5286 txt += '*';
5287 }
5288 return txt;
5289 });
5290
5291 showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
5292 'use strict';
5293
5294 var headerMark = new Array(headerLevel + 1).join('#'),
5295 txt = '';
5296
5297 if (node.hasChildNodes()) {
5298 txt = headerMark + ' ';
5299 var children = node.childNodes,
5300 childrenLength = children.length;
5301
5302 for (var i = 0; i < childrenLength; ++i) {
5303 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5304 }
5305 }
5306 return txt;
5307 });
5308
5309 showdown.subParser('makeMarkdown.hr', function () {
5310 'use strict';
5311
5312 return '---';
5313 });
5314
5315 showdown.subParser('makeMarkdown.image', function (node) {
5316 'use strict';
5317
5318 var txt = '';
5319 if (node.hasAttribute('src')) {
5320 txt += '![' + node.getAttribute('alt') + '](';
5321 txt += '<' + node.getAttribute('src') + '>';
5322 if (node.hasAttribute('width') && node.hasAttribute('height')) {
5323 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
5324 }
5325
5326 if (node.hasAttribute('title')) {
5327 txt += ' "' + node.getAttribute('title') + '"';
5328 }
5329 txt += ')';
5330 }
5331 return txt;
5332 });
5333
5334 showdown.subParser('makeMarkdown.links', function (node, globals) {
5335 'use strict';
5336
5337 var txt = '';
5338 if (node.hasChildNodes() && node.hasAttribute('href')) {
5339 var children = node.childNodes,
5340 childrenLength = children.length;
5341 txt = '[';
5342 for (var i = 0; i < childrenLength; ++i) {
5343 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5344 }
5345 txt += '](';
5346 txt += '<' + node.getAttribute('href') + '>';
5347 if (node.hasAttribute('title')) {
5348 txt += ' "' + node.getAttribute('title') + '"';
5349 }
5350 txt += ')';
5351 }
5352 return txt;
5353 });
5354
5355 showdown.subParser('makeMarkdown.list', function (node, globals, type) {
5356 'use strict';
5357
5358 var txt = '';
5359 if (!node.hasChildNodes()) {
5360 return '';
5361 }
5362 var listItems = node.childNodes,
5363 listItemsLenght = listItems.length,
5364 listNum = node.getAttribute('start') || 1;
5365
5366 for (var i = 0; i < listItemsLenght; ++i) {
5367 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
5368 continue;
5369 }
5370
5371 // define the bullet to use in list
5372 var bullet = '';
5373 if (type === 'ol') {
5374 bullet = listNum.toString() + '. ';
5375 } else {
5376 bullet = '- ';
5377 }
5378
5379 // parse list item
5380 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
5381 ++listNum;
5382 }
5383
5384 // add comment at the end to prevent consecutive lists to be parsed as one
5385 txt += '\n<!-- -->\n';
5386 return txt.trim();
5387 });
5388
5389 showdown.subParser('makeMarkdown.listItem', function (node, globals) {
5390 'use strict';
5391
5392 var listItemTxt = '';
5393
5394 var children = node.childNodes,
5395 childrenLenght = children.length;
5396
5397 for (var i = 0; i < childrenLenght; ++i) {
5398 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5399 }
5400 // if it's only one liner, we need to add a newline at the end
5401 if (!/\n$/.test(listItemTxt)) {
5402 listItemTxt += '\n';
5403 } else {
5404 // it's multiparagraph, so we need to indent
5405 listItemTxt = listItemTxt
5406 .split('\n')
5407 .join('\n ')
5408 .replace(/^ {4}$/gm, '')
5409 .replace(/\n\n+/g, '\n\n');
5410 }
5411
5412 return listItemTxt;
5413 });
5414
5415
5416
5417 showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
5418 'use strict';
5419
5420 spansOnly = spansOnly || false;
5421
5422 var txt = '';
5423
5424 // edge case of text without wrapper paragraph
5425 if (node.nodeType === 3) {
5426 return showdown.subParser('makeMarkdown.txt')(node, globals);
5427 }
5428
5429 // HTML comment
5430 if (node.nodeType === 8) {
5431 return '<!--' + node.data + '-->\n\n';
5432 }
5433
5434 // process only node elements
5435 if (node.nodeType !== 1) {
5436 return '';
5437 }
5438
5439 var tagName = node.tagName.toLowerCase();
5440
5441 switch (tagName) {
5442
5443 //
5444 // BLOCKS
5445 //
5446 case 'h1':
5447 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
5448 break;
5449 case 'h2':
5450 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
5451 break;
5452 case 'h3':
5453 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
5454 break;
5455 case 'h4':
5456 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
5457 break;
5458 case 'h5':
5459 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
5460 break;
5461 case 'h6':
5462 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
5463 break;
5464
5465 case 'p':
5466 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
5467 break;
5468
5469 case 'blockquote':
5470 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
5471 break;
5472
5473 case 'hr':
5474 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
5475 break;
5476
5477 case 'ol':
5478 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
5479 break;
5480
5481 case 'ul':
5482 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
5483 break;
5484
5485 case 'precode':
5486 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
5487 break;
5488
5489 case 'pre':
5490 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
5491 break;
5492
5493 case 'table':
5494 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
5495 break;
5496
5497 //
5498 // SPANS
5499 //
5500 case 'code':
5501 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
5502 break;
5503
5504 case 'em':
5505 case 'i':
5506 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
5507 break;
5508
5509 case 'strong':
5510 case 'b':
5511 txt = showdown.subParser('makeMarkdown.strong')(node, globals);
5512 break;
5513
5514 case 'del':
5515 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
5516 break;
5517
5518 case 'a':
5519 txt = showdown.subParser('makeMarkdown.links')(node, globals);
5520 break;
5521
5522 case 'img':
5523 txt = showdown.subParser('makeMarkdown.image')(node, globals);
5524 break;
5525
5526 default:
5527 txt = node.outerHTML + '\n\n';
5528 }
5529
5530 // common normalization
5531 // TODO eventually
5532
5533 return txt;
5534 });
5535
5536 showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
5537 'use strict';
5538
5539 var txt = '';
5540 if (node.hasChildNodes()) {
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 }
5547
5548 // some text normalization
5549 txt = txt.trim();
5550
5551 return txt;
5552 });
5553
5554 showdown.subParser('makeMarkdown.pre', function (node, globals) {
5555 'use strict';
5556
5557 var num = node.getAttribute('prenum');
5558 return '<pre>' + globals.preList[num] + '</pre>';
5559 });
5560
5561 showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
5562 'use strict';
5563
5564 var txt = '';
5565 if (node.hasChildNodes()) {
5566 txt += '~~';
5567 var children = node.childNodes,
5568 childrenLength = children.length;
5569 for (var i = 0; i < childrenLength; ++i) {
5570 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5571 }
5572 txt += '~~';
5573 }
5574 return txt;
5575 });
5576
5577 showdown.subParser('makeMarkdown.strong', function (node, globals) {
5578 'use strict';
5579
5580 var txt = '';
5581 if (node.hasChildNodes()) {
5582 txt += '**';
5583 var children = node.childNodes,
5584 childrenLength = children.length;
5585 for (var i = 0; i < childrenLength; ++i) {
5586 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5587 }
5588 txt += '**';
5589 }
5590 return txt;
5591 });
5592
5593 showdown.subParser('makeMarkdown.table', function (node, globals) {
5594 'use strict';
5595
5596 var txt = '',
5597 tableArray = [[], []],
5598 headings = node.querySelectorAll('thead>tr>th'),
5599 rows = node.querySelectorAll('tbody>tr'),
5600 i, ii;
5601 for (i = 0; i < headings.length; ++i) {
5602 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
5603 allign = '---';
5604
5605 if (headings[i].hasAttribute('style')) {
5606 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
5607 switch (style) {
5608 case 'text-align:left;':
5609 allign = ':---';
5610 break;
5611 case 'text-align:right;':
5612 allign = '---:';
5613 break;
5614 case 'text-align:center;':
5615 allign = ':---:';
5616 break;
5617 }
5618 }
5619 tableArray[0][i] = headContent.trim();
5620 tableArray[1][i] = allign;
5621 }
5622
5623 for (i = 0; i < rows.length; ++i) {
5624 var r = tableArray.push([]) - 1,
5625 cols = rows[i].getElementsByTagName('td');
5626
5627 for (ii = 0; ii < headings.length; ++ii) {
5628 var cellContent = ' ';
5629 if (typeof cols[ii] !== 'undefined') {
5630 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
5631 }
5632 tableArray[r].push(cellContent);
5633 }
5634 }
5635
5636 var cellSpacesCount = 3;
5637 for (i = 0; i < tableArray.length; ++i) {
5638 for (ii = 0; ii < tableArray[i].length; ++ii) {
5639 var strLen = tableArray[i][ii].length;
5640 if (strLen > cellSpacesCount) {
5641 cellSpacesCount = strLen;
5642 }
5643 }
5644 }
5645
5646 for (i = 0; i < tableArray.length; ++i) {
5647 for (ii = 0; ii < tableArray[i].length; ++ii) {
5648 if (i === 1) {
5649 if (tableArray[i][ii].slice(-1) === ':') {
5650 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
5651 } else {
5652 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
5653 }
5654 } else {
5655 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
5656 }
5657 }
5658 txt += '| ' + tableArray[i].join(' | ') + ' |\n';
5659 }
5660
5661 return txt.trim();
5662 });
5663
5664 showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
5665 'use strict';
5666
5667 var txt = '';
5668 if (!node.hasChildNodes()) {
5669 return '';
5670 }
5671 var children = node.childNodes,
5672 childrenLength = children.length;
5673
5674 for (var i = 0; i < childrenLength; ++i) {
5675 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
5676 }
5677 return txt.trim();
5678 });
5679
5680 showdown.subParser('makeMarkdown.txt', function (node) {
5681 'use strict';
5682
5683 var txt = node.nodeValue;
5684
5685 // multiple spaces are collapsed
5686 txt = txt.replace(/ +/g, ' ');
5687
5688 // replace the custom ¨NBSP; with a space
5689 txt = txt.replace(/¨NBSP;/g, ' ');
5690
5691 // ", <, > and & should replace escaped html entities
5692 txt = showdown.helper.unescapeHTMLEntities(txt);
5693
5694 // escape markdown magic characters
5695 // emphasis, strong and strikethrough - can appear everywhere
5696 // we also escape pipe (|) because of tables
5697 // and escape ` because of code blocks and spans
5698 txt = txt.replace(/([*_~|`])/g, '\\$1');
5699
5700 // escape > because of blockquotes
5701 txt = txt.replace(/^(\s*)>/g, '\\$1>');
5702
5703 // hash character, only troublesome at the beginning of a line because of headers
5704 txt = txt.replace(/^#/gm, '\\#');
5705
5706 // horizontal rules
5707 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
5708
5709 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
5710 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
5711
5712 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
5713 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
5714
5715 // images and links, ] followed by ( is problematic, so we escape it
5716 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
5717
5718 // reference URIs must also be escaped
5719 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
5720
5721 return txt;
5722 });
5723
5724 var root = this;
5725
5726 // AMD Loader
5727 if (true) {
5728 !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {
5729 'use strict';
5730 return showdown;
5731 }).call(exports, __webpack_require__, exports, module),
5732 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5733
5734 // CommonJS/nodeJS Loader
5735 } else {}
5736 }).call(this);
5737
5738
5739
5740
5741 /***/ })
5742
5743 /******/ });
5744 /************************************************************************/
5745 /******/ // The module cache
5746 /******/ var __webpack_module_cache__ = {};
5747 /******/
5748 /******/ // The require function
5749 /******/ function __webpack_require__(moduleId) {
5750 /******/ // Check if module is in cache
5751 /******/ var cachedModule = __webpack_module_cache__[moduleId];
5752 /******/ if (cachedModule !== undefined) {
5753 /******/ return cachedModule.exports;
5754 /******/ }
5755 /******/ // Create a new module (and put it into the cache)
5756 /******/ var module = __webpack_module_cache__[moduleId] = {
5757 /******/ // no module.id needed
5758 /******/ // no module.loaded needed
5759 /******/ exports: {}
5760 /******/ };
5761 /******/
5762 /******/ // Execute the module function
5763 /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5764 /******/
5765 /******/ // Return the exports of the module
5766 /******/ return module.exports;
5767 /******/ }
5768 /******/
5769 /************************************************************************/
5770 /******/ /* webpack/runtime/compat get default export */
5771 /******/ (() => {
5772 /******/ // getDefaultExport function for compatibility with non-harmony modules
5773 /******/ __webpack_require__.n = (module) => {
5774 /******/ var getter = module && module.__esModule ?
5775 /******/ () => (module['default']) :
5776 /******/ () => (module);
5777 /******/ __webpack_require__.d(getter, { a: getter });
5778 /******/ return getter;
5779 /******/ };
5780 /******/ })();
5781 /******/
5782 /******/ /* webpack/runtime/define property getters */
5783 /******/ (() => {
5784 /******/ // define getter functions for harmony exports
5785 /******/ __webpack_require__.d = (exports, definition) => {
5786 /******/ for(var key in definition) {
5787 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
5788 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
5789 /******/ }
5790 /******/ }
5791 /******/ };
5792 /******/ })();
5793 /******/
5794 /******/ /* webpack/runtime/hasOwnProperty shorthand */
5795 /******/ (() => {
5796 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
5797 /******/ })();
5798 /******/
5799 /******/ /* webpack/runtime/make namespace object */
5800 /******/ (() => {
5801 /******/ // define __esModule on exports
5802 /******/ __webpack_require__.r = (exports) => {
5803 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
5804 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5805 /******/ }
5806 /******/ Object.defineProperty(exports, '__esModule', { value: true });
5807 /******/ };
5808 /******/ })();
5809 /******/
5810 /************************************************************************/
5811 var __webpack_exports__ = {};
5812 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
5813 (() => {
5814 "use strict";
5815 // ESM COMPAT FLAG
5816 __webpack_require__.r(__webpack_exports__);
5817
5818 // EXPORTS
5819 __webpack_require__.d(__webpack_exports__, {
5820 "__EXPERIMENTAL_ELEMENTS": () => (/* reexport */ __EXPERIMENTAL_ELEMENTS),
5821 "__EXPERIMENTAL_PATHS_WITH_MERGE": () => (/* reexport */ __EXPERIMENTAL_PATHS_WITH_MERGE),
5822 "__EXPERIMENTAL_STYLE_PROPERTY": () => (/* reexport */ __EXPERIMENTAL_STYLE_PROPERTY),
5823 "__experimentalCloneSanitizedBlock": () => (/* reexport */ __experimentalCloneSanitizedBlock),
5824 "__experimentalGetAccessibleBlockLabel": () => (/* reexport */ getAccessibleBlockLabel),
5825 "__experimentalGetBlockAttributesNamesByRole": () => (/* reexport */ __experimentalGetBlockAttributesNamesByRole),
5826 "__experimentalGetBlockLabel": () => (/* reexport */ getBlockLabel),
5827 "__experimentalSanitizeBlockAttributes": () => (/* reexport */ __experimentalSanitizeBlockAttributes),
5828 "__unstableGetBlockProps": () => (/* reexport */ getBlockProps),
5829 "__unstableGetInnerBlocksProps": () => (/* reexport */ getInnerBlocksProps),
5830 "__unstableSerializeAndClean": () => (/* reexport */ __unstableSerializeAndClean),
5831 "children": () => (/* reexport */ children),
5832 "cloneBlock": () => (/* reexport */ cloneBlock),
5833 "createBlock": () => (/* reexport */ createBlock),
5834 "createBlocksFromInnerBlocksTemplate": () => (/* reexport */ createBlocksFromInnerBlocksTemplate),
5835 "doBlocksMatchTemplate": () => (/* reexport */ doBlocksMatchTemplate),
5836 "findTransform": () => (/* reexport */ findTransform),
5837 "getBlockAttributes": () => (/* reexport */ getBlockAttributes),
5838 "getBlockContent": () => (/* reexport */ getBlockInnerHTML),
5839 "getBlockDefaultClassName": () => (/* reexport */ getBlockDefaultClassName),
5840 "getBlockFromExample": () => (/* reexport */ getBlockFromExample),
5841 "getBlockMenuDefaultClassName": () => (/* reexport */ getBlockMenuDefaultClassName),
5842 "getBlockSupport": () => (/* reexport */ registration_getBlockSupport),
5843 "getBlockTransforms": () => (/* reexport */ getBlockTransforms),
5844 "getBlockType": () => (/* reexport */ registration_getBlockType),
5845 "getBlockTypes": () => (/* reexport */ registration_getBlockTypes),
5846 "getBlockVariations": () => (/* reexport */ registration_getBlockVariations),
5847 "getCategories": () => (/* reexport */ categories_getCategories),
5848 "getChildBlockNames": () => (/* reexport */ registration_getChildBlockNames),
5849 "getDefaultBlockName": () => (/* reexport */ registration_getDefaultBlockName),
5850 "getFreeformContentHandlerName": () => (/* reexport */ getFreeformContentHandlerName),
5851 "getGroupingBlockName": () => (/* reexport */ registration_getGroupingBlockName),
5852 "getPhrasingContentSchema": () => (/* reexport */ deprecatedGetPhrasingContentSchema),
5853 "getPossibleBlockTransformations": () => (/* reexport */ getPossibleBlockTransformations),
5854 "getSaveContent": () => (/* reexport */ getSaveContent),
5855 "getSaveElement": () => (/* reexport */ getSaveElement),
5856 "getUnregisteredTypeHandlerName": () => (/* reexport */ getUnregisteredTypeHandlerName),
5857 "hasBlockSupport": () => (/* reexport */ registration_hasBlockSupport),
5858 "hasChildBlocks": () => (/* reexport */ registration_hasChildBlocks),
5859 "hasChildBlocksWithInserterSupport": () => (/* reexport */ registration_hasChildBlocksWithInserterSupport),
5860 "isReusableBlock": () => (/* reexport */ isReusableBlock),
5861 "isTemplatePart": () => (/* reexport */ isTemplatePart),
5862 "isUnmodifiedDefaultBlock": () => (/* reexport */ isUnmodifiedDefaultBlock),
5863 "isValidBlockContent": () => (/* reexport */ isValidBlockContent),
5864 "isValidIcon": () => (/* reexport */ isValidIcon),
5865 "node": () => (/* reexport */ node),
5866 "normalizeIconObject": () => (/* reexport */ normalizeIconObject),
5867 "parse": () => (/* reexport */ parser_parse),
5868 "parseWithAttributeSchema": () => (/* reexport */ parseWithAttributeSchema),
5869 "pasteHandler": () => (/* reexport */ pasteHandler),
5870 "rawHandler": () => (/* reexport */ rawHandler),
5871 "registerBlockCollection": () => (/* reexport */ registerBlockCollection),
5872 "registerBlockStyle": () => (/* reexport */ registerBlockStyle),
5873 "registerBlockType": () => (/* reexport */ registerBlockType),
5874 "registerBlockVariation": () => (/* reexport */ registerBlockVariation),
5875 "serialize": () => (/* reexport */ serialize),
5876 "serializeRawBlock": () => (/* reexport */ serializeRawBlock),
5877 "setCategories": () => (/* reexport */ categories_setCategories),
5878 "setDefaultBlockName": () => (/* reexport */ setDefaultBlockName),
5879 "setFreeformContentHandlerName": () => (/* reexport */ setFreeformContentHandlerName),
5880 "setGroupingBlockName": () => (/* reexport */ setGroupingBlockName),
5881 "setUnregisteredTypeHandlerName": () => (/* reexport */ setUnregisteredTypeHandlerName),
5882 "store": () => (/* reexport */ store),
5883 "switchToBlockType": () => (/* reexport */ switchToBlockType),
5884 "synchronizeBlocksWithTemplate": () => (/* reexport */ synchronizeBlocksWithTemplate),
5885 "unregisterBlockStyle": () => (/* reexport */ unregisterBlockStyle),
5886 "unregisterBlockType": () => (/* reexport */ unregisterBlockType),
5887 "unregisterBlockVariation": () => (/* reexport */ unregisterBlockVariation),
5888 "unstable__bootstrapServerSideBlockDefinitions": () => (/* reexport */ unstable__bootstrapServerSideBlockDefinitions),
5889 "updateCategory": () => (/* reexport */ categories_updateCategory),
5890 "validateBlock": () => (/* reexport */ validateBlock),
5891 "withBlockContentContext": () => (/* reexport */ withBlockContentContext)
5892 });
5893
5894 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/selectors.js
5895 var selectors_namespaceObject = {};
5896 __webpack_require__.r(selectors_namespaceObject);
5897 __webpack_require__.d(selectors_namespaceObject, {
5898 "__experimentalGetUnprocessedBlockTypes": () => (__experimentalGetUnprocessedBlockTypes),
5899 "getActiveBlockVariation": () => (getActiveBlockVariation),
5900 "getBlockStyles": () => (getBlockStyles),
5901 "getBlockSupport": () => (getBlockSupport),
5902 "getBlockType": () => (getBlockType),
5903 "getBlockTypes": () => (getBlockTypes),
5904 "getBlockVariations": () => (getBlockVariations),
5905 "getCategories": () => (getCategories),
5906 "getChildBlockNames": () => (getChildBlockNames),
5907 "getCollections": () => (getCollections),
5908 "getDefaultBlockName": () => (getDefaultBlockName),
5909 "getDefaultBlockVariation": () => (getDefaultBlockVariation),
5910 "getFreeformFallbackBlockName": () => (getFreeformFallbackBlockName),
5911 "getGroupingBlockName": () => (getGroupingBlockName),
5912 "getUnregisteredFallbackBlockName": () => (getUnregisteredFallbackBlockName),
5913 "hasBlockSupport": () => (hasBlockSupport),
5914 "hasChildBlocks": () => (hasChildBlocks),
5915 "hasChildBlocksWithInserterSupport": () => (hasChildBlocksWithInserterSupport),
5916 "isMatchingSearchTerm": () => (isMatchingSearchTerm)
5917 });
5918
5919 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/actions.js
5920 var actions_namespaceObject = {};
5921 __webpack_require__.r(actions_namespaceObject);
5922 __webpack_require__.d(actions_namespaceObject, {
5923 "__experimentalReapplyBlockTypeFilters": () => (__experimentalReapplyBlockTypeFilters),
5924 "__experimentalRegisterBlockType": () => (__experimentalRegisterBlockType),
5925 "addBlockCollection": () => (addBlockCollection),
5926 "addBlockStyles": () => (addBlockStyles),
5927 "addBlockTypes": () => (addBlockTypes),
5928 "addBlockVariations": () => (addBlockVariations),
5929 "removeBlockCollection": () => (removeBlockCollection),
5930 "removeBlockStyles": () => (removeBlockStyles),
5931 "removeBlockTypes": () => (removeBlockTypes),
5932 "removeBlockVariations": () => (removeBlockVariations),
5933 "setCategories": () => (setCategories),
5934 "setDefaultBlockName": () => (actions_setDefaultBlockName),
5935 "setFreeformFallbackBlockName": () => (setFreeformFallbackBlockName),
5936 "setGroupingBlockName": () => (actions_setGroupingBlockName),
5937 "setUnregisteredFallbackBlockName": () => (setUnregisteredFallbackBlockName),
5938 "updateCategory": () => (updateCategory)
5939 });
5940
5941 ;// CONCATENATED MODULE: external ["wp","data"]
5942 const external_wp_data_namespaceObject = window["wp"]["data"];
5943 ;// CONCATENATED MODULE: external "lodash"
5944 const external_lodash_namespaceObject = window["lodash"];
5945 ;// CONCATENATED MODULE: external ["wp","i18n"]
5946 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
5947 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/reducer.js
5948 /**
5949 * External dependencies
5950 */
5951
5952 /**
5953 * WordPress dependencies
5954 */
5955
5956
5957
5958 /**
5959 * @typedef {Object} WPBlockCategory
5960 *
5961 * @property {string} slug Unique category slug.
5962 * @property {string} title Category label, for display in user interface.
5963 */
5964
5965 /**
5966 * Default set of categories.
5967 *
5968 * @type {WPBlockCategory[]}
5969 */
5970
5971 const DEFAULT_CATEGORIES = [{
5972 slug: 'text',
5973 title: (0,external_wp_i18n_namespaceObject.__)('Text')
5974 }, {
5975 slug: 'media',
5976 title: (0,external_wp_i18n_namespaceObject.__)('Media')
5977 }, {
5978 slug: 'design',
5979 title: (0,external_wp_i18n_namespaceObject.__)('Design')
5980 }, {
5981 slug: 'widgets',
5982 title: (0,external_wp_i18n_namespaceObject.__)('Widgets')
5983 }, {
5984 slug: 'theme',
5985 title: (0,external_wp_i18n_namespaceObject.__)('Theme')
5986 }, {
5987 slug: 'embed',
5988 title: (0,external_wp_i18n_namespaceObject.__)('Embeds')
5989 }, {
5990 slug: 'reusable',
5991 title: (0,external_wp_i18n_namespaceObject.__)('Reusable blocks')
5992 }]; // Key block types by their name.
5993
5994 function keyBlockTypesByName(types) {
5995 return types.reduce((newBlockTypes, block) => ({ ...newBlockTypes,
5996 [block.name]: block
5997 }), {});
5998 } // Filter items to ensure they're unique by their name.
5999
6000
6001 function getUniqueItemsByName(items) {
6002 return items.reduce((acc, currentItem) => {
6003 if (!acc.some(item => item.name === currentItem.name)) {
6004 acc.push(currentItem);
6005 }
6006
6007 return acc;
6008 }, []);
6009 }
6010 /**
6011 * Reducer managing the unprocessed block types in a form passed when registering the by block.
6012 * It's for internal use only. It allows recomputing the processed block types on-demand after block type filters
6013 * get added or removed.
6014 *
6015 * @param {Object} state Current state.
6016 * @param {Object} action Dispatched action.
6017 *
6018 * @return {Object} Updated state.
6019 */
6020
6021
6022 function unprocessedBlockTypes() {
6023 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6024 let action = arguments.length > 1 ? arguments[1] : undefined;
6025
6026 switch (action.type) {
6027 case 'ADD_UNPROCESSED_BLOCK_TYPE':
6028 return { ...state,
6029 [action.blockType.name]: action.blockType
6030 };
6031
6032 case 'REMOVE_BLOCK_TYPES':
6033 return (0,external_lodash_namespaceObject.omit)(state, action.names);
6034 }
6035
6036 return state;
6037 }
6038 /**
6039 * Reducer managing the processed block types with all filters applied.
6040 * The state is derived from the `unprocessedBlockTypes` reducer.
6041 *
6042 * @param {Object} state Current state.
6043 * @param {Object} action Dispatched action.
6044 *
6045 * @return {Object} Updated state.
6046 */
6047
6048 function blockTypes() {
6049 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6050 let action = arguments.length > 1 ? arguments[1] : undefined;
6051
6052 switch (action.type) {
6053 case 'ADD_BLOCK_TYPES':
6054 return { ...state,
6055 ...keyBlockTypesByName(action.blockTypes)
6056 };
6057
6058 case 'REMOVE_BLOCK_TYPES':
6059 return (0,external_lodash_namespaceObject.omit)(state, action.names);
6060 }
6061
6062 return state;
6063 }
6064 /**
6065 * Reducer managing the block style variations.
6066 *
6067 * @param {Object} state Current state.
6068 * @param {Object} action Dispatched action.
6069 *
6070 * @return {Object} Updated state.
6071 */
6072
6073 function blockStyles() {
6074 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6075 let action = arguments.length > 1 ? arguments[1] : undefined;
6076
6077 switch (action.type) {
6078 case 'ADD_BLOCK_TYPES':
6079 return { ...state,
6080 ...(0,external_lodash_namespaceObject.mapValues)(keyBlockTypesByName(action.blockTypes), blockType => getUniqueItemsByName([...(0,external_lodash_namespaceObject.get)(blockType, ['styles'], []).map(style => ({ ...style,
6081 source: 'block'
6082 })), ...(0,external_lodash_namespaceObject.get)(state, [blockType.name], []).filter(_ref => {
6083 let {
6084 source
6085 } = _ref;
6086 return 'block' !== source;
6087 })]))
6088 };
6089
6090 case 'ADD_BLOCK_STYLES':
6091 return { ...state,
6092 [action.blockName]: getUniqueItemsByName([...(0,external_lodash_namespaceObject.get)(state, [action.blockName], []), ...action.styles])
6093 };
6094
6095 case 'REMOVE_BLOCK_STYLES':
6096 return { ...state,
6097 [action.blockName]: (0,external_lodash_namespaceObject.filter)((0,external_lodash_namespaceObject.get)(state, [action.blockName], []), style => action.styleNames.indexOf(style.name) === -1)
6098 };
6099 }
6100
6101 return state;
6102 }
6103 /**
6104 * Reducer managing the block variations.
6105 *
6106 * @param {Object} state Current state.
6107 * @param {Object} action Dispatched action.
6108 *
6109 * @return {Object} Updated state.
6110 */
6111
6112 function blockVariations() {
6113 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6114 let action = arguments.length > 1 ? arguments[1] : undefined;
6115
6116 switch (action.type) {
6117 case 'ADD_BLOCK_TYPES':
6118 return { ...state,
6119 ...(0,external_lodash_namespaceObject.mapValues)(keyBlockTypesByName(action.blockTypes), blockType => {
6120 return getUniqueItemsByName([...(0,external_lodash_namespaceObject.get)(blockType, ['variations'], []).map(variation => ({ ...variation,
6121 source: 'block'
6122 })), ...(0,external_lodash_namespaceObject.get)(state, [blockType.name], []).filter(_ref2 => {
6123 let {
6124 source
6125 } = _ref2;
6126 return 'block' !== source;
6127 })]);
6128 })
6129 };
6130
6131 case 'ADD_BLOCK_VARIATIONS':
6132 return { ...state,
6133 [action.blockName]: getUniqueItemsByName([...(0,external_lodash_namespaceObject.get)(state, [action.blockName], []), ...action.variations])
6134 };
6135
6136 case 'REMOVE_BLOCK_VARIATIONS':
6137 return { ...state,
6138 [action.blockName]: (0,external_lodash_namespaceObject.filter)((0,external_lodash_namespaceObject.get)(state, [action.blockName], []), variation => action.variationNames.indexOf(variation.name) === -1)
6139 };
6140 }
6141
6142 return state;
6143 }
6144 /**
6145 * Higher-order Reducer creating a reducer keeping track of given block name.
6146 *
6147 * @param {string} setActionType Action type.
6148 *
6149 * @return {Function} Reducer.
6150 */
6151
6152 function createBlockNameSetterReducer(setActionType) {
6153 return function () {
6154 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
6155 let action = arguments.length > 1 ? arguments[1] : undefined;
6156
6157 switch (action.type) {
6158 case 'REMOVE_BLOCK_TYPES':
6159 if (action.names.indexOf(state) !== -1) {
6160 return null;
6161 }
6162
6163 return state;
6164
6165 case setActionType:
6166 return action.name || null;
6167 }
6168
6169 return state;
6170 };
6171 }
6172 const defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
6173 const freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
6174 const unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
6175 const groupingBlockName = createBlockNameSetterReducer('SET_GROUPING_BLOCK_NAME');
6176 /**
6177 * Reducer managing the categories
6178 *
6179 * @param {WPBlockCategory[]} state Current state.
6180 * @param {Object} action Dispatched action.
6181 *
6182 * @return {WPBlockCategory[]} Updated state.
6183 */
6184
6185 function categories() {
6186 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_CATEGORIES;
6187 let action = arguments.length > 1 ? arguments[1] : undefined;
6188
6189 switch (action.type) {
6190 case 'SET_CATEGORIES':
6191 return action.categories || [];
6192
6193 case 'UPDATE_CATEGORY':
6194 {
6195 if (!action.category || (0,external_lodash_namespaceObject.isEmpty)(action.category)) {
6196 return state;
6197 }
6198
6199 const categoryToChange = (0,external_lodash_namespaceObject.find)(state, ['slug', action.slug]);
6200
6201 if (categoryToChange) {
6202 return (0,external_lodash_namespaceObject.map)(state, category => {
6203 if (category.slug === action.slug) {
6204 return { ...category,
6205 ...action.category
6206 };
6207 }
6208
6209 return category;
6210 });
6211 }
6212 }
6213 }
6214
6215 return state;
6216 }
6217 function collections() {
6218 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6219 let action = arguments.length > 1 ? arguments[1] : undefined;
6220
6221 switch (action.type) {
6222 case 'ADD_BLOCK_COLLECTION':
6223 return { ...state,
6224 [action.namespace]: {
6225 title: action.title,
6226 icon: action.icon
6227 }
6228 };
6229
6230 case 'REMOVE_BLOCK_COLLECTION':
6231 return (0,external_lodash_namespaceObject.omit)(state, action.namespace);
6232 }
6233
6234 return state;
6235 }
6236 /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
6237 unprocessedBlockTypes,
6238 blockTypes,
6239 blockStyles,
6240 blockVariations,
6241 defaultBlockName,
6242 freeformFallbackBlockName,
6243 unregisteredFallbackBlockName,
6244 groupingBlockName,
6245 categories,
6246 collections
6247 }));
6248
6249 ;// CONCATENATED MODULE: ./node_modules/rememo/es/rememo.js
6250
6251
6252 /** @typedef {(...args: any[]) => *[]} GetDependants */
6253
6254 /** @typedef {() => void} Clear */
6255
6256 /**
6257 * @typedef {{
6258 * getDependants: GetDependants,
6259 * clear: Clear
6260 * }} EnhancedSelector
6261 */
6262
6263 /**
6264 * Internal cache entry.
6265 *
6266 * @typedef CacheNode
6267 *
6268 * @property {?CacheNode|undefined} [prev] Previous node.
6269 * @property {?CacheNode|undefined} [next] Next node.
6270 * @property {*[]} args Function arguments for cache entry.
6271 * @property {*} val Function result.
6272 */
6273
6274 /**
6275 * @typedef Cache
6276 *
6277 * @property {Clear} clear Function to clear cache.
6278 * @property {boolean} [isUniqueByDependants] Whether dependants are valid in
6279 * considering cache uniqueness. A cache is unique if dependents are all arrays
6280 * or objects.
6281 * @property {CacheNode?} [head] Cache head.
6282 * @property {*[]} [lastDependants] Dependants from previous invocation.
6283 */
6284
6285 /**
6286 * Arbitrary value used as key for referencing cache object in WeakMap tree.
6287 *
6288 * @type {{}}
6289 */
6290 var LEAF_KEY = {};
6291
6292 /**
6293 * Returns the first argument as the sole entry in an array.
6294 *
6295 * @template T
6296 *
6297 * @param {T} value Value to return.
6298 *
6299 * @return {[T]} Value returned as entry in array.
6300 */
6301 function arrayOf(value) {
6302 return [value];
6303 }
6304
6305 /**
6306 * Returns true if the value passed is object-like, or false otherwise. A value
6307 * is object-like if it can support property assignment, e.g. object or array.
6308 *
6309 * @param {*} value Value to test.
6310 *
6311 * @return {boolean} Whether value is object-like.
6312 */
6313 function isObjectLike(value) {
6314 return !!value && 'object' === typeof value;
6315 }
6316
6317 /**
6318 * Creates and returns a new cache object.
6319 *
6320 * @return {Cache} Cache object.
6321 */
6322 function createCache() {
6323 /** @type {Cache} */
6324 var cache = {
6325 clear: function () {
6326 cache.head = null;
6327 },
6328 };
6329
6330 return cache;
6331 }
6332
6333 /**
6334 * Returns true if entries within the two arrays are strictly equal by
6335 * reference from a starting index.
6336 *
6337 * @param {*[]} a First array.
6338 * @param {*[]} b Second array.
6339 * @param {number} fromIndex Index from which to start comparison.
6340 *
6341 * @return {boolean} Whether arrays are shallowly equal.
6342 */
6343 function isShallowEqual(a, b, fromIndex) {
6344 var i;
6345
6346 if (a.length !== b.length) {
6347 return false;
6348 }
6349
6350 for (i = fromIndex; i < a.length; i++) {
6351 if (a[i] !== b[i]) {
6352 return false;
6353 }
6354 }
6355
6356 return true;
6357 }
6358
6359 /**
6360 * Returns a memoized selector function. The getDependants function argument is
6361 * called before the memoized selector and is expected to return an immutable
6362 * reference or array of references on which the selector depends for computing
6363 * its own return value. The memoize cache is preserved only as long as those
6364 * dependant references remain the same. If getDependants returns a different
6365 * reference(s), the cache is cleared and the selector value regenerated.
6366 *
6367 * @template {(...args: *[]) => *} S
6368 *
6369 * @param {S} selector Selector function.
6370 * @param {GetDependants=} getDependants Dependant getter returning an array of
6371 * references used in cache bust consideration.
6372 */
6373 /* harmony default export */ function rememo(selector, getDependants) {
6374 /** @type {WeakMap<*,*>} */
6375 var rootCache;
6376
6377 /** @type {GetDependants} */
6378 var normalizedGetDependants = getDependants ? getDependants : arrayOf;
6379
6380 /**
6381 * Returns the cache for a given dependants array. When possible, a WeakMap
6382 * will be used to create a unique cache for each set of dependants. This
6383 * is feasible due to the nature of WeakMap in allowing garbage collection
6384 * to occur on entries where the key object is no longer referenced. Since
6385 * WeakMap requires the key to be an object, this is only possible when the
6386 * dependant is object-like. The root cache is created as a hierarchy where
6387 * each top-level key is the first entry in a dependants set, the value a
6388 * WeakMap where each key is the next dependant, and so on. This continues
6389 * so long as the dependants are object-like. If no dependants are object-
6390 * like, then the cache is shared across all invocations.
6391 *
6392 * @see isObjectLike
6393 *
6394 * @param {*[]} dependants Selector dependants.
6395 *
6396 * @return {Cache} Cache object.
6397 */
6398 function getCache(dependants) {
6399 var caches = rootCache,
6400 isUniqueByDependants = true,
6401 i,
6402 dependant,
6403 map,
6404 cache;
6405
6406 for (i = 0; i < dependants.length; i++) {
6407 dependant = dependants[i];
6408
6409 // Can only compose WeakMap from object-like key.
6410 if (!isObjectLike(dependant)) {
6411 isUniqueByDependants = false;
6412 break;
6413 }
6414
6415 // Does current segment of cache already have a WeakMap?
6416 if (caches.has(dependant)) {
6417 // Traverse into nested WeakMap.
6418 caches = caches.get(dependant);
6419 } else {
6420 // Create, set, and traverse into a new one.
6421 map = new WeakMap();
6422 caches.set(dependant, map);
6423 caches = map;
6424 }
6425 }
6426
6427 // We use an arbitrary (but consistent) object as key for the last item
6428 // in the WeakMap to serve as our running cache.
6429 if (!caches.has(LEAF_KEY)) {
6430 cache = createCache();
6431 cache.isUniqueByDependants = isUniqueByDependants;
6432 caches.set(LEAF_KEY, cache);
6433 }
6434
6435 return caches.get(LEAF_KEY);
6436 }
6437
6438 /**
6439 * Resets root memoization cache.
6440 */
6441 function clear() {
6442 rootCache = new WeakMap();
6443 }
6444
6445 /* eslint-disable jsdoc/check-param-names */
6446 /**
6447 * The augmented selector call, considering first whether dependants have
6448 * changed before passing it to underlying memoize function.
6449 *
6450 * @param {*} source Source object for derivation.
6451 * @param {...*} extraArgs Additional arguments to pass to selector.
6452 *
6453 * @return {*} Selector result.
6454 */
6455 /* eslint-enable jsdoc/check-param-names */
6456 function callSelector(/* source, ...extraArgs */) {
6457 var len = arguments.length,
6458 cache,
6459 node,
6460 i,
6461 args,
6462 dependants;
6463
6464 // Create copy of arguments (avoid leaking deoptimization).
6465 args = new Array(len);
6466 for (i = 0; i < len; i++) {
6467 args[i] = arguments[i];
6468 }
6469
6470 dependants = normalizedGetDependants.apply(null, args);
6471 cache = getCache(dependants);
6472
6473 // If not guaranteed uniqueness by dependants (primitive type), shallow
6474 // compare against last dependants and, if references have changed,
6475 // destroy cache to recalculate result.
6476 if (!cache.isUniqueByDependants) {
6477 if (
6478 cache.lastDependants &&
6479 !isShallowEqual(dependants, cache.lastDependants, 0)
6480 ) {
6481 cache.clear();
6482 }
6483
6484 cache.lastDependants = dependants;
6485 }
6486
6487 node = cache.head;
6488 while (node) {
6489 // Check whether node arguments match arguments
6490 if (!isShallowEqual(node.args, args, 1)) {
6491 node = node.next;
6492 continue;
6493 }
6494
6495 // At this point we can assume we've found a match
6496
6497 // Surface matched node to head if not already
6498 if (node !== cache.head) {
6499 // Adjust siblings to point to each other.
6500 /** @type {CacheNode} */ (node.prev).next = node.next;
6501 if (node.next) {
6502 node.next.prev = node.prev;
6503 }
6504
6505 node.next = cache.head;
6506 node.prev = null;
6507 /** @type {CacheNode} */ (cache.head).prev = node;
6508 cache.head = node;
6509 }
6510
6511 // Return immediately
6512 return node.val;
6513 }
6514
6515 // No cached value found. Continue to insertion phase:
6516
6517 node = /** @type {CacheNode} */ ({
6518 // Generate the result from original function
6519 val: selector.apply(null, args),
6520 });
6521
6522 // Avoid including the source object in the cache.
6523 args[0] = null;
6524 node.args = args;
6525
6526 // Don't need to check whether node is already head, since it would
6527 // have been returned above already if it was
6528
6529 // Shift existing head down list
6530 if (cache.head) {
6531 cache.head.prev = node;
6532 node.next = cache.head;
6533 }
6534
6535 cache.head = node;
6536
6537 return node.val;
6538 }
6539
6540 callSelector.getDependants = normalizedGetDependants;
6541 callSelector.clear = clear;
6542 clear();
6543
6544 return /** @type {S & EnhancedSelector} */ (callSelector);
6545 }
6546
6547 // EXTERNAL MODULE: ./node_modules/remove-accents/index.js
6548 var remove_accents = __webpack_require__(4793);
6549 var remove_accents_default = /*#__PURE__*/__webpack_require__.n(remove_accents);
6550 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/selectors.js
6551 /**
6552 * External dependencies
6553 */
6554
6555
6556
6557 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
6558
6559 /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
6560
6561 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
6562
6563 /**
6564 * Given a block name or block type object, returns the corresponding
6565 * normalized block type object.
6566 *
6567 * @param {Object} state Blocks state.
6568 * @param {(string|Object)} nameOrType Block name or type object
6569 *
6570 * @return {Object} Block type object.
6571 */
6572
6573 const getNormalizedBlockType = (state, nameOrType) => 'string' === typeof nameOrType ? getBlockType(state, nameOrType) : nameOrType;
6574 /**
6575 * Returns all the unprocessed block types as passed during the registration.
6576 *
6577 * @param {Object} state Data state.
6578 *
6579 * @return {Array} Unprocessed block types.
6580 */
6581
6582
6583 function __experimentalGetUnprocessedBlockTypes(state) {
6584 return state.unprocessedBlockTypes;
6585 }
6586 /**
6587 * Returns all the available block types.
6588 *
6589 * @param {Object} state Data state.
6590 *
6591 * @example
6592 * ```js
6593 * import { store as blocksStore } from '@wordpress/blocks';
6594 * import { useSelect } from '@wordpress/data';
6595 *
6596 * const ExampleComponent = () => {
6597 * const blockTypes = useSelect(
6598 * ( select ) => select( blocksStore ).getBlockTypes(),
6599 * []
6600 * );
6601 *
6602 * return (
6603 * <ul>
6604 * { blockTypes.map( ( block ) => (
6605 * <li key={ block.name }>{ block.title }</li>
6606 * ) ) }
6607 * </ul>
6608 * );
6609 * };
6610 * ```
6611 *
6612 * @return {Array} Block Types.
6613 */
6614
6615 const getBlockTypes = rememo(state => Object.values(state.blockTypes), state => [state.blockTypes]);
6616 /**
6617 * Returns a block type by name.
6618 *
6619 * @param {Object} state Data state.
6620 * @param {string} name Block type name.
6621 *
6622 * @example
6623 * ```js
6624 * import { store as blocksStore } from '@wordpress/blocks';
6625 * import { useSelect } from '@wordpress/data';
6626 *
6627 * const ExampleComponent = () => {
6628 * const paragraphBlock = useSelect( ( select ) =>
6629 * ( select ) => select( blocksStore ).getBlockType( 'core/paragraph' ),
6630 * []
6631 * );
6632 *
6633 * return (
6634 * <ul>
6635 * { paragraphBlock &&
6636 * Object.entries( paragraphBlock.supports ).map(
6637 * ( blockSupportsEntry ) => {
6638 * const [ propertyName, value ] = blockSupportsEntry;
6639 * return (
6640 * <li
6641 * key={ propertyName }
6642 * >{ `${ propertyName } : ${ value }` }</li>
6643 * );
6644 * }
6645 * ) }
6646 * </ul>
6647 * );
6648 * };
6649 * ```
6650 *
6651 * @return {Object?} Block Type.
6652 */
6653
6654 function getBlockType(state, name) {
6655 return state.blockTypes[name];
6656 }
6657 /**
6658 * Returns block styles by block name.
6659 *
6660 * @param {Object} state Data state.
6661 * @param {string} name Block type name.
6662 *
6663 * @example
6664 * ```js
6665 * import { store as blocksStore } from '@wordpress/blocks';
6666 * import { useSelect } from '@wordpress/data';
6667 *
6668 * const ExampleComponent = () => {
6669 * const buttonBlockStyles = useSelect( ( select ) =>
6670 * select( blocksStore ).getBlockStyles( 'core/button' ),
6671 * []
6672 * );
6673 *
6674 * return (
6675 * <ul>
6676 * { buttonBlockStyles &&
6677 * buttonBlockStyles.map( ( style ) => (
6678 * <li key={ style.name }>{ style.label }</li>
6679 * ) ) }
6680 * </ul>
6681 * );
6682 * };
6683 * ```
6684 *
6685 * @return {Array?} Block Styles.
6686 */
6687
6688 function getBlockStyles(state, name) {
6689 return state.blockStyles[name];
6690 }
6691 /**
6692 * Returns block variations by block name.
6693 *
6694 * @param {Object} state Data state.
6695 * @param {string} blockName Block type name.
6696 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6697 *
6698 * @example
6699 * ```js
6700 * import { store as blocksStore } from '@wordpress/blocks';
6701 * import { useSelect } from '@wordpress/data';
6702 *
6703 * const ExampleComponent = () => {
6704 * const socialLinkVariations = useSelect( ( select ) =>
6705 * select( blocksStore ).getBlockVariations( 'core/social-link' ),
6706 * []
6707 * );
6708 *
6709 * return (
6710 * <ul>
6711 * { socialLinkVariations &&
6712 * socialLinkVariations.map( ( variation ) => (
6713 * <li key={ variation.name }>{ variation.title }</li>
6714 * ) ) }
6715 * </ul>
6716 * );
6717 * };
6718 * ```
6719 *
6720 * @return {(WPBlockVariation[]|void)} Block variations.
6721 */
6722
6723 const getBlockVariations = rememo((state, blockName, scope) => {
6724 const variations = state.blockVariations[blockName];
6725
6726 if (!variations || !scope) {
6727 return variations;
6728 }
6729
6730 return variations.filter(variation => {
6731 // For backward compatibility reasons, variation's scope defaults to
6732 // `block` and `inserter` when not set.
6733 return (variation.scope || ['block', 'inserter']).includes(scope);
6734 });
6735 }, (state, blockName) => [state.blockVariations[blockName]]);
6736 /**
6737 * Returns the active block variation for a given block based on its attributes.
6738 * Variations are determined by their `isActive` property.
6739 * Which is either an array of block attribute keys or a function.
6740 *
6741 * In case of an array of block attribute keys, the `attributes` are compared
6742 * to the variation's attributes using strict equality check.
6743 *
6744 * In case of function type, the function should accept a block's attributes
6745 * and the variation's attributes and determines if a variation is active.
6746 * A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
6747 *
6748 * @param {Object} state Data state.
6749 * @param {string} blockName Name of block (example: “core/columns”).
6750 * @param {Object} attributes Block attributes used to determine active variation.
6751 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6752 *
6753 * @example
6754 * ```js
6755 * import { __ } from '@wordpress/i18n';
6756 * import { store as blocksStore } from '@wordpress/blocks';
6757 * import { store as blockEditorStore } from '@wordpress/block-editor';
6758 * import { useSelect } from '@wordpress/data';
6759 *
6760 * const ExampleComponent = () => {
6761 * // This example assumes that a core/embed block is the first block in the Block Editor.
6762 * const activeBlockVariation = useSelect( ( select ) => {
6763 * // Retrieve the list of blocks.
6764 * const [ firstBlock ] = select( blockEditorStore ).getBlocks()
6765 *
6766 * // Return the active block variation for the first block.
6767 * return select( blocksStore ).getActiveBlockVariation(
6768 * firstBlock.name,
6769 * firstBlock.attributes
6770 * );
6771 * }, [] );
6772 *
6773 * return activeBlockVariation && activeBlockVariation.name === 'spotify' ? (
6774 * <p>{ __( 'Spotify variation' ) }</p>
6775 * ) : (
6776 * <p>{ __( 'Other variation' ) }</p>
6777 * );
6778 * };
6779 * ```
6780 *
6781 * @return {(WPBlockVariation|undefined)} Active block variation.
6782 */
6783
6784 function getActiveBlockVariation(state, blockName, attributes, scope) {
6785 const variations = getBlockVariations(state, blockName, scope);
6786 const match = variations === null || variations === void 0 ? void 0 : variations.find(variation => {
6787 var _variation$isActive;
6788
6789 if (Array.isArray(variation.isActive)) {
6790 const blockType = getBlockType(state, blockName);
6791 const attributeKeys = Object.keys((blockType === null || blockType === void 0 ? void 0 : blockType.attributes) || {});
6792 const definedAttributes = variation.isActive.filter(attribute => attributeKeys.includes(attribute));
6793
6794 if (definedAttributes.length === 0) {
6795 return false;
6796 }
6797
6798 return definedAttributes.every(attribute => attributes[attribute] === variation.attributes[attribute]);
6799 }
6800
6801 return (_variation$isActive = variation.isActive) === null || _variation$isActive === void 0 ? void 0 : _variation$isActive.call(variation, attributes, variation.attributes);
6802 });
6803 return match;
6804 }
6805 /**
6806 * Returns the default block variation for the given block type.
6807 * When there are multiple variations annotated as the default one,
6808 * the last added item is picked. This simplifies registering overrides.
6809 * When there is no default variation set, it returns the first item.
6810 *
6811 * @param {Object} state Data state.
6812 * @param {string} blockName Block type name.
6813 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6814 *
6815 * @example
6816 * ```js
6817 * import { __, sprintf } from '@wordpress/i18n';
6818 * import { store as blocksStore } from '@wordpress/blocks';
6819 * import { useSelect } from '@wordpress/data';
6820 *
6821 * const ExampleComponent = () => {
6822 * const defaultEmbedBlockVariation = useSelect( ( select ) =>
6823 * select( blocksStore ).getDefaultBlockVariation( 'core/embed' ),
6824 * []
6825 * );
6826 *
6827 * return (
6828 * defaultEmbedBlockVariation && (
6829 * <p>
6830 * { sprintf(
6831 * __( 'core/embed default variation: %s' ),
6832 * defaultEmbedBlockVariation.title
6833 * ) }
6834 * </p>
6835 * )
6836 * );
6837 * };
6838 * ```
6839 *
6840 * @return {?WPBlockVariation} The default block variation.
6841 */
6842
6843 function getDefaultBlockVariation(state, blockName, scope) {
6844 const variations = getBlockVariations(state, blockName, scope);
6845 const defaultVariation = [...variations].reverse().find(_ref => {
6846 let {
6847 isDefault
6848 } = _ref;
6849 return !!isDefault;
6850 });
6851 return defaultVariation || variations[0];
6852 }
6853 /**
6854 * Returns all the available block categories.
6855 *
6856 * @param {Object} state Data state.
6857 *
6858 * @example
6859 * ```js
6860 * import { store as blocksStore } from '@wordpress/blocks';
6861 * import { useSelect, } from '@wordpress/data';
6862 *
6863 * const ExampleComponent = () => {
6864 * const blockCategories = useSelect( ( select ) =>
6865 * select( blocksStore ).getCategories(),
6866 * []
6867 * );
6868 *
6869 * return (
6870 * <ul>
6871 * { blockCategories.map( ( category ) => (
6872 * <li key={ category.slug }>{ category.title }</li>
6873 * ) ) }
6874 * </ul>
6875 * );
6876 * };
6877 * ```
6878 *
6879 * @return {WPBlockCategory[]} Categories list.
6880 */
6881
6882 function getCategories(state) {
6883 return state.categories;
6884 }
6885 /**
6886 * Returns all the available collections.
6887 *
6888 * @param {Object} state Data state.
6889 *
6890 * @example
6891 * ```js
6892 * import { store as blocksStore } from '@wordpress/blocks';
6893 * import { useSelect } from '@wordpress/data';
6894 *
6895 * const ExampleComponent = () => {
6896 * const blockCollections = useSelect( ( select ) =>
6897 * select( blocksStore ).getCollections(),
6898 * []
6899 * );
6900 *
6901 * return (
6902 * <ul>
6903 * { Object.values( blockCollections ).length > 0 &&
6904 * Object.values( blockCollections ).map( ( collection ) => (
6905 * <li key={ collection.title }>{ collection.title }</li>
6906 * ) ) }
6907 * </ul>
6908 * );
6909 * };
6910 * ```
6911 *
6912 * @return {Object} Collections list.
6913 */
6914
6915 function getCollections(state) {
6916 return state.collections;
6917 }
6918 /**
6919 * Returns the name of the default block name.
6920 *
6921 * @param {Object} state Data state.
6922 *
6923 * @example
6924 * ```js
6925 * import { __, sprintf } from '@wordpress/i18n';
6926 * import { store as blocksStore } from '@wordpress/blocks';
6927 * import { useSelect } from '@wordpress/data';
6928 *
6929 * const ExampleComponent = () => {
6930 * const defaultBlockName = useSelect( ( select ) =>
6931 * select( blocksStore ).getDefaultBlockName(),
6932 * []
6933 * );
6934 *
6935 * return (
6936 * defaultBlockName && (
6937 * <p>
6938 * { sprintf( __( 'Default block name: %s' ), defaultBlockName ) }
6939 * </p>
6940 * )
6941 * );
6942 * };
6943 * ```
6944 *
6945 * @return {string?} Default block name.
6946 */
6947
6948 function getDefaultBlockName(state) {
6949 return state.defaultBlockName;
6950 }
6951 /**
6952 * Returns the name of the block for handling non-block content.
6953 *
6954 * @param {Object} state Data state.
6955 *
6956 * @example
6957 * ```js
6958 * import { __, sprintf } from '@wordpress/i18n';
6959 * import { store as blocksStore } from '@wordpress/blocks';
6960 * import { useSelect } from '@wordpress/data';
6961 *
6962 * const ExampleComponent = () => {
6963 * const freeformFallbackBlockName = useSelect( ( select ) =>
6964 * select( blocksStore ).getFreeformFallbackBlockName(),
6965 * []
6966 * );
6967 *
6968 * return (
6969 * freeformFallbackBlockName && (
6970 * <p>
6971 * { sprintf( __(
6972 * 'Freeform fallback block name: %s' ),
6973 * freeformFallbackBlockName
6974 * ) }
6975 * </p>
6976 * )
6977 * );
6978 * };
6979 * ```
6980 *
6981 * @return {string?} Name of the block for handling non-block content.
6982 */
6983
6984 function getFreeformFallbackBlockName(state) {
6985 return state.freeformFallbackBlockName;
6986 }
6987 /**
6988 * Returns the name of the block for handling unregistered blocks.
6989 *
6990 * @param {Object} state Data state.
6991 *
6992 * @example
6993 * ```js
6994 * import { __, sprintf } from '@wordpress/i18n';
6995 * import { store as blocksStore } from '@wordpress/blocks';
6996 * import { useSelect } from '@wordpress/data';
6997 *
6998 * const ExampleComponent = () => {
6999 * const unregisteredFallbackBlockName = useSelect( ( select ) =>
7000 * select( blocksStore ).getUnregisteredFallbackBlockName(),
7001 * []
7002 * );
7003 *
7004 * return (
7005 * unregisteredFallbackBlockName && (
7006 * <p>
7007 * { sprintf( __(
7008 * 'Unregistered fallback block name: %s' ),
7009 * unregisteredFallbackBlockName
7010 * ) }
7011 * </p>
7012 * )
7013 * );
7014 * };
7015 * ```
7016 *
7017 * @return {string?} Name of the block for handling unregistered blocks.
7018 */
7019
7020 function getUnregisteredFallbackBlockName(state) {
7021 return state.unregisteredFallbackBlockName;
7022 }
7023 /**
7024 * Returns the name of the block for handling the grouping of blocks.
7025 *
7026 * @param {Object} state Data state.
7027 *
7028 * @example
7029 * ```js
7030 * import { __, sprintf } from '@wordpress/i18n';
7031 * import { store as blocksStore } from '@wordpress/blocks';
7032 * import { useSelect } from '@wordpress/data';
7033 *
7034 * const ExampleComponent = () => {
7035 * const groupingBlockName = useSelect( ( select ) =>
7036 * select( blocksStore ).getGroupingBlockName(),
7037 * []
7038 * );
7039 *
7040 * return (
7041 * groupingBlockName && (
7042 * <p>
7043 * { sprintf(
7044 * __( 'Default grouping block name: %s' ),
7045 * groupingBlockName
7046 * ) }
7047 * </p>
7048 * )
7049 * );
7050 * };
7051 * ```
7052 *
7053 * @return {string?} Name of the block for handling the grouping of blocks.
7054 */
7055
7056 function getGroupingBlockName(state) {
7057 return state.groupingBlockName;
7058 }
7059 /**
7060 * Returns an array with the child blocks of a given block.
7061 *
7062 * @param {Object} state Data state.
7063 * @param {string} blockName Block type name.
7064 *
7065 * @example
7066 * ```js
7067 * import { store as blocksStore } from '@wordpress/blocks';
7068 * import { useSelect } from '@wordpress/data';
7069 *
7070 * const ExampleComponent = () => {
7071 * const childBlockNames = useSelect( ( select ) =>
7072 * select( blocksStore ).getChildBlockNames( 'core/navigation' ),
7073 * []
7074 * );
7075 *
7076 * return (
7077 * <ul>
7078 * { childBlockNames &&
7079 * childBlockNames.map( ( child ) => (
7080 * <li key={ child }>{ child }</li>
7081 * ) ) }
7082 * </ul>
7083 * );
7084 * };
7085 * ```
7086 *
7087 * @return {Array} Array of child block names.
7088 */
7089
7090 const getChildBlockNames = rememo((state, blockName) => {
7091 return (0,external_lodash_namespaceObject.map)((0,external_lodash_namespaceObject.filter)(state.blockTypes, blockType => {
7092 return (0,external_lodash_namespaceObject.includes)(blockType.parent, blockName);
7093 }), _ref2 => {
7094 let {
7095 name
7096 } = _ref2;
7097 return name;
7098 });
7099 }, state => [state.blockTypes]);
7100 /**
7101 * Returns the block support value for a feature, if defined.
7102 *
7103 * @param {Object} state Data state.
7104 * @param {(string|Object)} nameOrType Block name or type object
7105 * @param {Array|string} feature Feature to retrieve
7106 * @param {*} defaultSupports Default value to return if not
7107 * explicitly defined
7108 *
7109 * @example
7110 * ```js
7111 * import { __, sprintf } from '@wordpress/i18n';
7112 * import { store as blocksStore } from '@wordpress/blocks';
7113 * import { useSelect } from '@wordpress/data';
7114 *
7115 * const ExampleComponent = () => {
7116 * const paragraphBlockSupportValue = useSelect( ( select ) =>
7117 * select( blocksStore ).getBlockSupport( 'core/paragraph', 'anchor' ),
7118 * []
7119 * );
7120 *
7121 * return (
7122 * <p>
7123 * { sprintf(
7124 * __( 'core/paragraph supports.anchor value: %s' ),
7125 * paragraphBlockSupportValue
7126 * ) }
7127 * </p>
7128 * );
7129 * };
7130 * ```
7131 *
7132 * @return {?*} Block support value
7133 */
7134
7135 const getBlockSupport = (state, nameOrType, feature, defaultSupports) => {
7136 const blockType = getNormalizedBlockType(state, nameOrType);
7137
7138 if (!(blockType !== null && blockType !== void 0 && blockType.supports)) {
7139 return defaultSupports;
7140 }
7141
7142 return (0,external_lodash_namespaceObject.get)(blockType.supports, feature, defaultSupports);
7143 };
7144 /**
7145 * Returns true if the block defines support for a feature, or false otherwise.
7146 *
7147 * @param {Object} state Data state.
7148 * @param {(string|Object)} nameOrType Block name or type object.
7149 * @param {string} feature Feature to test.
7150 * @param {boolean} defaultSupports Whether feature is supported by
7151 * default if not explicitly defined.
7152 *
7153 * @example
7154 * ```js
7155 * import { __, sprintf } from '@wordpress/i18n';
7156 * import { store as blocksStore } from '@wordpress/blocks';
7157 * import { useSelect } from '@wordpress/data';
7158 *
7159 * const ExampleComponent = () => {
7160 * const paragraphBlockSupportClassName = useSelect( ( select ) =>
7161 * select( blocksStore ).hasBlockSupport( 'core/paragraph', 'className' ),
7162 * []
7163 * );
7164 *
7165 * return (
7166 * <p>
7167 * { sprintf(
7168 * __( 'core/paragraph supports custom class name?: %s' ),
7169 * paragraphBlockSupportClassName
7170 * ) }
7171 * /p>
7172 * );
7173 * };
7174 * ```
7175 *
7176 * @return {boolean} Whether block supports feature.
7177 */
7178
7179 function hasBlockSupport(state, nameOrType, feature, defaultSupports) {
7180 return !!getBlockSupport(state, nameOrType, feature, defaultSupports);
7181 }
7182 /**
7183 * Returns true if the block type by the given name or object value matches a
7184 * search term, or false otherwise.
7185 *
7186 * @param {Object} state Blocks state.
7187 * @param {(string|Object)} nameOrType Block name or type object.
7188 * @param {string} searchTerm Search term by which to filter.
7189 *
7190 * @example
7191 * ```js
7192 * import { __, sprintf } from '@wordpress/i18n';
7193 * import { store as blocksStore } from '@wordpress/blocks';
7194 * import { useSelect } from '@wordpress/data';
7195 *
7196 * const ExampleComponent = () => {
7197 * const termFound = useSelect(
7198 * ( select ) =>
7199 * select( blocksStore ).isMatchingSearchTerm(
7200 * 'core/navigation',
7201 * 'theme'
7202 * ),
7203 * []
7204 * );
7205 *
7206 * return (
7207 * <p>
7208 * { sprintf(
7209 * __(
7210 * 'Search term was found in the title, keywords, category or description in block.json: %s'
7211 * ),
7212 * termFound
7213 * ) }
7214 * </p>
7215 * );
7216 * };
7217 * ```
7218 *
7219 * @return {Object[]} Whether block type matches search term.
7220 */
7221
7222 function isMatchingSearchTerm(state, nameOrType, searchTerm) {
7223 const blockType = getNormalizedBlockType(state, nameOrType);
7224 const getNormalizedSearchTerm = (0,external_lodash_namespaceObject.flow)([// Disregard diacritics.
7225 // Input: "média"
7226 term => remove_accents_default()(term !== null && term !== void 0 ? term : ''), // Lowercase.
7227 // Input: "MEDIA"
7228 term => term.toLowerCase(), // Strip leading and trailing whitespace.
7229 // Input: " media "
7230 term => term.trim()]);
7231 const normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
7232 const isSearchMatch = (0,external_lodash_namespaceObject.flow)([getNormalizedSearchTerm, normalizedCandidate => (0,external_lodash_namespaceObject.includes)(normalizedCandidate, normalizedSearchTerm)]);
7233 return isSearchMatch(blockType.title) || (0,external_lodash_namespaceObject.some)(blockType.keywords, isSearchMatch) || isSearchMatch(blockType.category) || isSearchMatch(blockType.description);
7234 }
7235 /**
7236 * Returns a boolean indicating if a block has child blocks or not.
7237 *
7238 * @param {Object} state Data state.
7239 * @param {string} blockName Block type name.
7240 *
7241 * @example
7242 * ```js
7243 * import { __, sprintf } from '@wordpress/i18n';
7244 * import { store as blocksStore } from '@wordpress/blocks';
7245 * import { useSelect } from '@wordpress/data';
7246 *
7247 * const ExampleComponent = () => {
7248 * const navigationBlockHasChildBlocks = useSelect( ( select ) =>
7249 * select( blocksStore ).hasChildBlocks( 'core/navigation' ),
7250 * []
7251 * );
7252 *
7253 * return (
7254 * <p>
7255 * { sprintf(
7256 * __( 'core/navigation has child blocks: %s' ),
7257 * navigationBlockHasChildBlocks
7258 * ) }
7259 * </p>
7260 * );
7261 * };
7262 * ```
7263 *
7264 * @return {boolean} True if a block contains child blocks and false otherwise.
7265 */
7266
7267 const hasChildBlocks = (state, blockName) => {
7268 return getChildBlockNames(state, blockName).length > 0;
7269 };
7270 /**
7271 * Returns a boolean indicating if a block has at least one child block with inserter support.
7272 *
7273 * @param {Object} state Data state.
7274 * @param {string} blockName Block type name.
7275 *
7276 * @example
7277 * ```js
7278 * import { __, sprintf } from '@wordpress/i18n';
7279 * import { store as blocksStore } from '@wordpress/blocks';
7280 * import { useSelect } from '@wordpress/data';
7281 *
7282 * const ExampleComponent = () => {
7283 * const navigationBlockHasChildBlocksWithInserterSupport = useSelect( ( select ) =>
7284 * select( blocksStore ).hasChildBlocksWithInserterSupport(
7285 * 'core/navigation'
7286 * ),
7287 * []
7288 * );
7289 *
7290 * return (
7291 * <p>
7292 * { sprintf(
7293 * __( 'core/navigation has child blocks with inserter support: %s' ),
7294 * navigationBlockHasChildBlocksWithInserterSupport
7295 * ) }
7296 * </p>
7297 * );
7298 * };
7299 * ```
7300 *
7301 * @return {boolean} True if a block contains at least one child blocks with inserter support
7302 * and false otherwise.
7303 */
7304
7305 const hasChildBlocksWithInserterSupport = (state, blockName) => {
7306 return (0,external_lodash_namespaceObject.some)(getChildBlockNames(state, blockName), childBlockName => {
7307 return hasBlockSupport(state, childBlockName, 'inserter', true);
7308 });
7309 };
7310
7311 ;// CONCATENATED MODULE: ./node_modules/is-plain-object/dist/is-plain-object.mjs
7312 /*!
7313 * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
7314 *
7315 * Copyright (c) 2014-2017, Jon Schlinkert.
7316 * Released under the MIT License.
7317 */
7318
7319 function isObject(o) {
7320 return Object.prototype.toString.call(o) === '[object Object]';
7321 }
7322
7323 function isPlainObject(o) {
7324 var ctor,prot;
7325
7326 if (isObject(o) === false) return false;
7327
7328 // If has modified constructor
7329 ctor = o.constructor;
7330 if (ctor === undefined) return true;
7331
7332 // If has modified prototype
7333 prot = ctor.prototype;
7334 if (isObject(prot) === false) return false;
7335
7336 // If constructor does not have an Object-specific method
7337 if (prot.hasOwnProperty('isPrototypeOf') === false) {
7338 return false;
7339 }
7340
7341 // Most likely a plain Object
7342 return true;
7343 }
7344
7345
7346
7347 ;// CONCATENATED MODULE: external ["wp","hooks"]
7348 const external_wp_hooks_namespaceObject = window["wp"]["hooks"];
7349 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/index.mjs
7350 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()})};
7351
7352 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/plugins/names.mjs
7353 /* 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"])}
7354
7355 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/plugins/a11y.mjs
7356 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}}
7357
7358 ;// CONCATENATED MODULE: external ["wp","element"]
7359 const external_wp_element_namespaceObject = window["wp"]["element"];
7360 ;// CONCATENATED MODULE: external ["wp","dom"]
7361 const external_wp_dom_namespaceObject = window["wp"]["dom"];
7362 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/constants.js
7363 const BLOCK_ICON_DEFAULT = 'block-default';
7364 /**
7365 * Array of valid keys in a block type settings deprecation object.
7366 *
7367 * @type {string[]}
7368 */
7369
7370 const DEPRECATED_ENTRY_KEYS = ['attributes', 'supports', 'save', 'migrate', 'isEligible', 'apiVersion'];
7371 const __EXPERIMENTAL_STYLE_PROPERTY = {
7372 // Kept for back-compatibility purposes.
7373 '--wp--style--color--link': {
7374 value: ['color', 'link'],
7375 support: ['color', 'link']
7376 },
7377 background: {
7378 value: ['color', 'gradient'],
7379 support: ['color', 'gradients'],
7380 useEngine: true
7381 },
7382 backgroundColor: {
7383 value: ['color', 'background'],
7384 support: ['color', 'background'],
7385 requiresOptOut: true,
7386 useEngine: true
7387 },
7388 borderColor: {
7389 value: ['border', 'color'],
7390 support: ['__experimentalBorder', 'color'],
7391 useEngine: true
7392 },
7393 borderRadius: {
7394 value: ['border', 'radius'],
7395 support: ['__experimentalBorder', 'radius'],
7396 properties: {
7397 borderTopLeftRadius: 'topLeft',
7398 borderTopRightRadius: 'topRight',
7399 borderBottomLeftRadius: 'bottomLeft',
7400 borderBottomRightRadius: 'bottomRight'
7401 },
7402 useEngine: true
7403 },
7404 borderStyle: {
7405 value: ['border', 'style'],
7406 support: ['__experimentalBorder', 'style'],
7407 useEngine: true
7408 },
7409 borderWidth: {
7410 value: ['border', 'width'],
7411 support: ['__experimentalBorder', 'width'],
7412 useEngine: true
7413 },
7414 borderTopColor: {
7415 value: ['border', 'top', 'color'],
7416 support: ['__experimentalBorder', 'color'],
7417 useEngine: true
7418 },
7419 borderTopStyle: {
7420 value: ['border', 'top', 'style'],
7421 support: ['__experimentalBorder', 'style'],
7422 useEngine: true
7423 },
7424 borderTopWidth: {
7425 value: ['border', 'top', 'width'],
7426 support: ['__experimentalBorder', 'width'],
7427 useEngine: true
7428 },
7429 borderRightColor: {
7430 value: ['border', 'right', 'color'],
7431 support: ['__experimentalBorder', 'color'],
7432 useEngine: true
7433 },
7434 borderRightStyle: {
7435 value: ['border', 'right', 'style'],
7436 support: ['__experimentalBorder', 'style'],
7437 useEngine: true
7438 },
7439 borderRightWidth: {
7440 value: ['border', 'right', 'width'],
7441 support: ['__experimentalBorder', 'width'],
7442 useEngine: true
7443 },
7444 borderBottomColor: {
7445 value: ['border', 'bottom', 'color'],
7446 support: ['__experimentalBorder', 'color'],
7447 useEngine: true
7448 },
7449 borderBottomStyle: {
7450 value: ['border', 'bottom', 'style'],
7451 support: ['__experimentalBorder', 'style'],
7452 useEngine: true
7453 },
7454 borderBottomWidth: {
7455 value: ['border', 'bottom', 'width'],
7456 support: ['__experimentalBorder', 'width'],
7457 useEngine: true
7458 },
7459 borderLeftColor: {
7460 value: ['border', 'left', 'color'],
7461 support: ['__experimentalBorder', 'color'],
7462 useEngine: true
7463 },
7464 borderLeftStyle: {
7465 value: ['border', 'left', 'style'],
7466 support: ['__experimentalBorder', 'style'],
7467 useEngine: true
7468 },
7469 borderLeftWidth: {
7470 value: ['border', 'left', 'width'],
7471 support: ['__experimentalBorder', 'width'],
7472 useEngine: true
7473 },
7474 color: {
7475 value: ['color', 'text'],
7476 support: ['color', 'text'],
7477 requiresOptOut: true,
7478 useEngine: true
7479 },
7480 filter: {
7481 value: ['filter', 'duotone'],
7482 support: ['color', '__experimentalDuotone']
7483 },
7484 linkColor: {
7485 value: ['elements', 'link', 'color', 'text'],
7486 support: ['color', 'link']
7487 },
7488 buttonColor: {
7489 value: ['elements', 'button', 'color', 'text'],
7490 support: ['color', 'button']
7491 },
7492 buttonBackgroundColor: {
7493 value: ['elements', 'button', 'color', 'background'],
7494 support: ['color', 'button']
7495 },
7496 fontFamily: {
7497 value: ['typography', 'fontFamily'],
7498 support: ['typography', '__experimentalFontFamily'],
7499 useEngine: true
7500 },
7501 fontSize: {
7502 value: ['typography', 'fontSize'],
7503 support: ['typography', 'fontSize'],
7504 useEngine: true
7505 },
7506 fontStyle: {
7507 value: ['typography', 'fontStyle'],
7508 support: ['typography', '__experimentalFontStyle'],
7509 useEngine: true
7510 },
7511 fontWeight: {
7512 value: ['typography', 'fontWeight'],
7513 support: ['typography', '__experimentalFontWeight'],
7514 useEngine: true
7515 },
7516 lineHeight: {
7517 value: ['typography', 'lineHeight'],
7518 support: ['typography', 'lineHeight'],
7519 useEngine: true
7520 },
7521 margin: {
7522 value: ['spacing', 'margin'],
7523 support: ['spacing', 'margin'],
7524 properties: {
7525 marginTop: 'top',
7526 marginRight: 'right',
7527 marginBottom: 'bottom',
7528 marginLeft: 'left'
7529 },
7530 useEngine: true
7531 },
7532 padding: {
7533 value: ['spacing', 'padding'],
7534 support: ['spacing', 'padding'],
7535 properties: {
7536 paddingTop: 'top',
7537 paddingRight: 'right',
7538 paddingBottom: 'bottom',
7539 paddingLeft: 'left'
7540 },
7541 useEngine: true
7542 },
7543 textDecoration: {
7544 value: ['typography', 'textDecoration'],
7545 support: ['typography', '__experimentalTextDecoration'],
7546 useEngine: true
7547 },
7548 textTransform: {
7549 value: ['typography', 'textTransform'],
7550 support: ['typography', '__experimentalTextTransform'],
7551 useEngine: true
7552 },
7553 letterSpacing: {
7554 value: ['typography', 'letterSpacing'],
7555 support: ['typography', '__experimentalLetterSpacing'],
7556 useEngine: true
7557 },
7558 '--wp--style--root--padding': {
7559 value: ['spacing', 'padding'],
7560 support: ['spacing', 'padding'],
7561 properties: {
7562 '--wp--style--root--padding-top': 'top',
7563 '--wp--style--root--padding-right': 'right',
7564 '--wp--style--root--padding-bottom': 'bottom',
7565 '--wp--style--root--padding-left': 'left'
7566 },
7567 rootOnly: true
7568 }
7569 };
7570 const __EXPERIMENTAL_ELEMENTS = {
7571 link: 'a',
7572 heading: 'h1, h2, h3, h4, h5, h6',
7573 h1: 'h1',
7574 h2: 'h2',
7575 h3: 'h3',
7576 h4: 'h4',
7577 h5: 'h5',
7578 h6: 'h6',
7579 button: '.wp-element-button, .wp-block-button__link',
7580 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'
7581 };
7582 const __EXPERIMENTAL_PATHS_WITH_MERGE = {
7583 'color.duotone': true,
7584 'color.gradients': true,
7585 'color.palette': true,
7586 'typography.fontFamilies': true,
7587 'typography.fontSizes': true,
7588 'spacing.spacingSizes': true
7589 };
7590
7591 ;// CONCATENATED MODULE: ./node_modules/tslib/tslib.es6.js
7592 /*! *****************************************************************************
7593 Copyright (c) Microsoft Corporation.
7594
7595 Permission to use, copy, modify, and/or distribute this software for any
7596 purpose with or without fee is hereby granted.
7597
7598 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7599 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
7600 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
7601 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
7602 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
7603 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
7604 PERFORMANCE OF THIS SOFTWARE.
7605 ***************************************************************************** */
7606 /* global Reflect, Promise */
7607
7608 var extendStatics = function(d, b) {
7609 extendStatics = Object.setPrototypeOf ||
7610 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
7611 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7612 return extendStatics(d, b);
7613 };
7614
7615 function __extends(d, b) {
7616 if (typeof b !== "function" && b !== null)
7617 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
7618 extendStatics(d, b);
7619 function __() { this.constructor = d; }
7620 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
7621 }
7622
7623 var __assign = function() {
7624 __assign = Object.assign || function __assign(t) {
7625 for (var s, i = 1, n = arguments.length; i < n; i++) {
7626 s = arguments[i];
7627 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
7628 }
7629 return t;
7630 }
7631 return __assign.apply(this, arguments);
7632 }
7633
7634 function __rest(s, e) {
7635 var t = {};
7636 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
7637 t[p] = s[p];
7638 if (s != null && typeof Object.getOwnPropertySymbols === "function")
7639 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7640 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
7641 t[p[i]] = s[p[i]];
7642 }
7643 return t;
7644 }
7645
7646 function __decorate(decorators, target, key, desc) {
7647 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7648 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
7649 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;
7650 return c > 3 && r && Object.defineProperty(target, key, r), r;
7651 }
7652
7653 function __param(paramIndex, decorator) {
7654 return function (target, key) { decorator(target, key, paramIndex); }
7655 }
7656
7657 function __metadata(metadataKey, metadataValue) {
7658 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
7659 }
7660
7661 function __awaiter(thisArg, _arguments, P, generator) {
7662 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7663 return new (P || (P = Promise))(function (resolve, reject) {
7664 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7665 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7666 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7667 step((generator = generator.apply(thisArg, _arguments || [])).next());
7668 });
7669 }
7670
7671 function __generator(thisArg, body) {
7672 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
7673 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
7674 function verb(n) { return function (v) { return step([n, v]); }; }
7675 function step(op) {
7676 if (f) throw new TypeError("Generator is already executing.");
7677 while (_) try {
7678 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;
7679 if (y = 0, t) op = [op[0] & 2, t.value];
7680 switch (op[0]) {
7681 case 0: case 1: t = op; break;
7682 case 4: _.label++; return { value: op[1], done: false };
7683 case 5: _.label++; y = op[1]; op = [0]; continue;
7684 case 7: op = _.ops.pop(); _.trys.pop(); continue;
7685 default:
7686 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
7687 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
7688 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
7689 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
7690 if (t[2]) _.ops.pop();
7691 _.trys.pop(); continue;
7692 }
7693 op = body.call(thisArg, _);
7694 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
7695 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
7696 }
7697 }
7698
7699 var __createBinding = Object.create ? (function(o, m, k, k2) {
7700 if (k2 === undefined) k2 = k;
7701 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
7702 }) : (function(o, m, k, k2) {
7703 if (k2 === undefined) k2 = k;
7704 o[k2] = m[k];
7705 });
7706
7707 function __exportStar(m, o) {
7708 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
7709 }
7710
7711 function __values(o) {
7712 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
7713 if (m) return m.call(o);
7714 if (o && typeof o.length === "number") return {
7715 next: function () {
7716 if (o && i >= o.length) o = void 0;
7717 return { value: o && o[i++], done: !o };
7718 }
7719 };
7720 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
7721 }
7722
7723 function __read(o, n) {
7724 var m = typeof Symbol === "function" && o[Symbol.iterator];
7725 if (!m) return o;
7726 var i = m.call(o), r, ar = [], e;
7727 try {
7728 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
7729 }
7730 catch (error) { e = { error: error }; }
7731 finally {
7732 try {
7733 if (r && !r.done && (m = i["return"])) m.call(i);
7734 }
7735 finally { if (e) throw e.error; }
7736 }
7737 return ar;
7738 }
7739
7740 /** @deprecated */
7741 function __spread() {
7742 for (var ar = [], i = 0; i < arguments.length; i++)
7743 ar = ar.concat(__read(arguments[i]));
7744 return ar;
7745 }
7746
7747 /** @deprecated */
7748 function __spreadArrays() {
7749 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
7750 for (var r = Array(s), k = 0, i = 0; i < il; i++)
7751 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
7752 r[k] = a[j];
7753 return r;
7754 }
7755
7756 function __spreadArray(to, from, pack) {
7757 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
7758 if (ar || !(i in from)) {
7759 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
7760 ar[i] = from[i];
7761 }
7762 }
7763 return to.concat(ar || from);
7764 }
7765
7766 function __await(v) {
7767 return this instanceof __await ? (this.v = v, this) : new __await(v);
7768 }
7769
7770 function __asyncGenerator(thisArg, _arguments, generator) {
7771 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
7772 var g = generator.apply(thisArg, _arguments || []), i, q = [];
7773 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
7774 function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
7775 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
7776 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
7777 function fulfill(value) { resume("next", value); }
7778 function reject(value) { resume("throw", value); }
7779 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
7780 }
7781
7782 function __asyncDelegator(o) {
7783 var i, p;
7784 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
7785 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
7786 }
7787
7788 function __asyncValues(o) {
7789 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
7790 var m = o[Symbol.asyncIterator], i;
7791 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);
7792 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); }); }; }
7793 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
7794 }
7795
7796 function __makeTemplateObject(cooked, raw) {
7797 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
7798 return cooked;
7799 };
7800
7801 var __setModuleDefault = Object.create ? (function(o, v) {
7802 Object.defineProperty(o, "default", { enumerable: true, value: v });
7803 }) : function(o, v) {
7804 o["default"] = v;
7805 };
7806
7807 function __importStar(mod) {
7808 if (mod && mod.__esModule) return mod;
7809 var result = {};
7810 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
7811 __setModuleDefault(result, mod);
7812 return result;
7813 }
7814
7815 function __importDefault(mod) {
7816 return (mod && mod.__esModule) ? mod : { default: mod };
7817 }
7818
7819 function __classPrivateFieldGet(receiver, state, kind, f) {
7820 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
7821 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");
7822 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
7823 }
7824
7825 function __classPrivateFieldSet(receiver, state, value, kind, f) {
7826 if (kind === "m") throw new TypeError("Private method is not writable");
7827 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
7828 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");
7829 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7830 }
7831
7832 ;// CONCATENATED MODULE: ./node_modules/lower-case/dist.es2015/index.js
7833 /**
7834 * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
7835 */
7836 var SUPPORTED_LOCALE = {
7837 tr: {
7838 regexp: /\u0130|\u0049|\u0049\u0307/g,
7839 map: {
7840 İ: "\u0069",
7841 I: "\u0131",
7842 İ: "\u0069",
7843 },
7844 },
7845 az: {
7846 regexp: /\u0130/g,
7847 map: {
7848 İ: "\u0069",
7849 I: "\u0131",
7850 İ: "\u0069",
7851 },
7852 },
7853 lt: {
7854 regexp: /\u0049|\u004A|\u012E|\u00CC|\u00CD|\u0128/g,
7855 map: {
7856 I: "\u0069\u0307",
7857 J: "\u006A\u0307",
7858 Į: "\u012F\u0307",
7859 Ì: "\u0069\u0307\u0300",
7860 Í: "\u0069\u0307\u0301",
7861 Ĩ: "\u0069\u0307\u0303",
7862 },
7863 },
7864 };
7865 /**
7866 * Localized lower case.
7867 */
7868 function localeLowerCase(str, locale) {
7869 var lang = SUPPORTED_LOCALE[locale.toLowerCase()];
7870 if (lang)
7871 return lowerCase(str.replace(lang.regexp, function (m) { return lang.map[m]; }));
7872 return lowerCase(str);
7873 }
7874 /**
7875 * Lower case as a function.
7876 */
7877 function lowerCase(str) {
7878 return str.toLowerCase();
7879 }
7880
7881 ;// CONCATENATED MODULE: ./node_modules/no-case/dist.es2015/index.js
7882
7883 // Support camel case ("camelCase" -> "camel Case" and "CAMELCase" -> "CAMEL Case").
7884 var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
7885 // Remove all non-word characters.
7886 var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
7887 /**
7888 * Normalize the string into something other libraries can manipulate easier.
7889 */
7890 function noCase(input, options) {
7891 if (options === void 0) { options = {}; }
7892 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;
7893 var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
7894 var start = 0;
7895 var end = result.length;
7896 // Trim the delimiter from around the output string.
7897 while (result.charAt(start) === "\0")
7898 start++;
7899 while (result.charAt(end - 1) === "\0")
7900 end--;
7901 // Transform each token independently.
7902 return result.slice(start, end).split("\0").map(transform).join(delimiter);
7903 }
7904 /**
7905 * Replace `re` in the input string with the replacement value.
7906 */
7907 function replace(input, re, value) {
7908 if (re instanceof RegExp)
7909 return input.replace(re, value);
7910 return re.reduce(function (input, re) { return input.replace(re, value); }, input);
7911 }
7912
7913 ;// CONCATENATED MODULE: ./node_modules/pascal-case/dist.es2015/index.js
7914
7915
7916 function pascalCaseTransform(input, index) {
7917 var firstChar = input.charAt(0);
7918 var lowerChars = input.substr(1).toLowerCase();
7919 if (index > 0 && firstChar >= "0" && firstChar <= "9") {
7920 return "_" + firstChar + lowerChars;
7921 }
7922 return "" + firstChar.toUpperCase() + lowerChars;
7923 }
7924 function dist_es2015_pascalCaseTransformMerge(input) {
7925 return input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
7926 }
7927 function pascalCase(input, options) {
7928 if (options === void 0) { options = {}; }
7929 return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
7930 }
7931
7932 ;// CONCATENATED MODULE: ./node_modules/camel-case/dist.es2015/index.js
7933
7934
7935 function camelCaseTransform(input, index) {
7936 if (index === 0)
7937 return input.toLowerCase();
7938 return pascalCaseTransform(input, index);
7939 }
7940 function camelCaseTransformMerge(input, index) {
7941 if (index === 0)
7942 return input.toLowerCase();
7943 return pascalCaseTransformMerge(input);
7944 }
7945 function camelCase(input, options) {
7946 if (options === void 0) { options = {}; }
7947 return pascalCase(input, __assign({ transform: camelCaseTransform }, options));
7948 }
7949
7950 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/registration.js
7951 /* eslint no-console: [ 'error', { allow: [ 'error', 'warn' ] } ] */
7952
7953 /**
7954 * External dependencies
7955 */
7956
7957
7958 /**
7959 * WordPress dependencies
7960 */
7961
7962
7963
7964 /**
7965 * Internal dependencies
7966 */
7967
7968 const i18nBlockSchema = {
7969 title: "block title",
7970 description: "block description",
7971 keywords: ["block keyword"],
7972 styles: [{
7973 label: "block style label"
7974 }],
7975 variations: [{
7976 title: "block variation title",
7977 description: "block variation description",
7978 keywords: ["block variation keyword"]
7979 }]
7980 };
7981
7982
7983 /**
7984 * An icon type definition. One of a Dashicon slug, an element,
7985 * or a component.
7986 *
7987 * @typedef {(string|WPElement|WPComponent)} WPIcon
7988 *
7989 * @see https://developer.wordpress.org/resource/dashicons/
7990 */
7991
7992 /**
7993 * Render behavior of a block type icon; one of a Dashicon slug, an element,
7994 * or a component.
7995 *
7996 * @typedef {WPIcon} WPBlockTypeIconRender
7997 */
7998
7999 /**
8000 * An object describing a normalized block type icon.
8001 *
8002 * @typedef {Object} WPBlockTypeIconDescriptor
8003 *
8004 * @property {WPBlockTypeIconRender} src Render behavior of the icon,
8005 * one of a Dashicon slug, an
8006 * element, or a component.
8007 * @property {string} background Optimal background hex string
8008 * color when displaying icon.
8009 * @property {string} foreground Optimal foreground hex string
8010 * color when displaying icon.
8011 * @property {string} shadowColor Optimal shadow hex string
8012 * color when displaying icon.
8013 */
8014
8015 /**
8016 * Value to use to render the icon for a block type in an editor interface,
8017 * either a Dashicon slug, an element, a component, or an object describing
8018 * the icon.
8019 *
8020 * @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
8021 */
8022
8023 /**
8024 * Named block variation scopes.
8025 *
8026 * @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
8027 */
8028
8029 /**
8030 * An object describing a variation defined for the block type.
8031 *
8032 * @typedef {Object} WPBlockVariation
8033 *
8034 * @property {string} name The unique and machine-readable name.
8035 * @property {string} title A human-readable variation title.
8036 * @property {string} [description] A detailed variation description.
8037 * @property {string} [category] Block type category classification,
8038 * used in search interfaces to arrange
8039 * block types by category.
8040 * @property {WPIcon} [icon] An icon helping to visualize the variation.
8041 * @property {boolean} [isDefault] Indicates whether the current variation is
8042 * the default one. Defaults to `false`.
8043 * @property {Object} [attributes] Values which override block attributes.
8044 * @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
8045 * @property {Object} [example] Example provides structured data for
8046 * the block preview. You can set to
8047 * `undefined` to disable the preview shown
8048 * for the block type.
8049 * @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
8050 * is applicable. When not provided, it
8051 * assumes all available scopes.
8052 * @property {string[]} [keywords] An array of terms (which can be translated)
8053 * that help users discover the variation
8054 * while searching.
8055 * @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
8056 * Function that accepts a block's attributes and the
8057 * variation's attributes and determines if a variation is active.
8058 * This function doesn't try to find a match dynamically based
8059 * on all block's attributes, as in many cases some attributes are irrelevant.
8060 * An example would be for `embed` block where we only care
8061 * about `providerNameSlug` attribute's value.
8062 * We can also use a `string[]` to tell which attributes
8063 * should be compared as a shorthand. Each attributes will
8064 * be matched and the variation will be active if all of them are matching.
8065 */
8066
8067 /**
8068 * Defined behavior of a block type.
8069 *
8070 * @typedef {Object} WPBlockType
8071 *
8072 * @property {string} name Block type's namespaced name.
8073 * @property {string} title Human-readable block type label.
8074 * @property {string} [description] A detailed block type description.
8075 * @property {string} [category] Block type category classification,
8076 * used in search interfaces to arrange
8077 * block types by category.
8078 * @property {WPBlockTypeIcon} [icon] Block type icon.
8079 * @property {string[]} [keywords] Additional keywords to produce block
8080 * type as result in search interfaces.
8081 * @property {Object} [attributes] Block type attributes.
8082 * @property {WPComponent} [save] Optional component describing
8083 * serialized markup structure of a
8084 * block type.
8085 * @property {WPComponent} edit Component rendering an element to
8086 * manipulate the attributes of a block
8087 * in the context of an editor.
8088 * @property {WPBlockVariation[]} [variations] The list of block variations.
8089 * @property {Object} [example] Example provides structured data for
8090 * the block preview. When not defined
8091 * then no preview is shown.
8092 */
8093
8094 const serverSideBlockDefinitions = {};
8095
8096 function registration_isObject(object) {
8097 return object !== null && typeof object === 'object';
8098 }
8099 /**
8100 * Sets the server side block definition of blocks.
8101 *
8102 * @param {Object} definitions Server-side block definitions
8103 */
8104 // eslint-disable-next-line camelcase
8105
8106
8107 function unstable__bootstrapServerSideBlockDefinitions(definitions) {
8108 for (const blockName of Object.keys(definitions)) {
8109 // Don't overwrite if already set. It covers the case when metadata
8110 // was initialized from the server.
8111 if (serverSideBlockDefinitions[blockName]) {
8112 // We still need to polyfill `apiVersion` for WordPress version
8113 // lower than 5.7. If it isn't present in the definition shared
8114 // from the server, we try to fallback to the definition passed.
8115 // @see https://github.com/WordPress/gutenberg/pull/29279
8116 if (serverSideBlockDefinitions[blockName].apiVersion === undefined && definitions[blockName].apiVersion) {
8117 serverSideBlockDefinitions[blockName].apiVersion = definitions[blockName].apiVersion;
8118 } // The `ancestor` prop is not included in the definitions shared
8119 // from the server yet, so it needs to be polyfilled as well.
8120 // @see https://github.com/WordPress/gutenberg/pull/39894
8121
8122
8123 if (serverSideBlockDefinitions[blockName].ancestor === undefined && definitions[blockName].ancestor) {
8124 serverSideBlockDefinitions[blockName].ancestor = definitions[blockName].ancestor;
8125 }
8126
8127 continue;
8128 }
8129
8130 serverSideBlockDefinitions[blockName] = Object.fromEntries(Object.entries((0,external_lodash_namespaceObject.pickBy)(definitions[blockName], value => value !== null && value !== undefined)).map(_ref => {
8131 let [key, value] = _ref;
8132 return [camelCase(key), value];
8133 }));
8134 }
8135 }
8136 /**
8137 * Gets block settings from metadata loaded from `block.json` file.
8138 *
8139 * @param {Object} metadata Block metadata loaded from `block.json`.
8140 * @param {string} metadata.textdomain Textdomain to use with translations.
8141 *
8142 * @return {Object} Block settings.
8143 */
8144
8145 function getBlockSettingsFromMetadata(_ref2) {
8146 let {
8147 textdomain,
8148 ...metadata
8149 } = _ref2;
8150 const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'supports', 'styles', 'example', 'variations'];
8151 const settings = (0,external_lodash_namespaceObject.pick)(metadata, allowedFields);
8152
8153 if (textdomain) {
8154 Object.keys(i18nBlockSchema).forEach(key => {
8155 if (!settings[key]) {
8156 return;
8157 }
8158
8159 settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
8160 });
8161 }
8162
8163 return settings;
8164 }
8165 /**
8166 * Registers a new block provided a unique name and an object defining its
8167 * behavior. Once registered, the block is made available as an option to any
8168 * editor interface where blocks are implemented.
8169 *
8170 * For more in-depth information on registering a custom block see the [Create a block tutorial](docs/how-to-guides/block-tutorial/README.md)
8171 *
8172 * @param {string|Object} blockNameOrMetadata Block type name or its metadata.
8173 * @param {Object} settings Block settings.
8174 *
8175 * @example
8176 * ```js
8177 * import { __ } from '@wordpress/i18n';
8178 * import { registerBlockType } from '@wordpress/blocks'
8179 *
8180 * registerBlockType( 'namespace/block-name', {
8181 * title: __( 'My First Block' ),
8182 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
8183 * save: () => <div>Hello from the saved content!</div>,
8184 * } );
8185 * ```
8186 *
8187 * @return {?WPBlockType} The block, if it has been successfully registered;
8188 * otherwise `undefined`.
8189 */
8190
8191
8192 function registerBlockType(blockNameOrMetadata, settings) {
8193 const name = registration_isObject(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
8194
8195 if (typeof name !== 'string') {
8196 console.error('Block names must be strings.');
8197 return;
8198 }
8199
8200 if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
8201 console.error('Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block');
8202 return;
8203 }
8204
8205 if ((0,external_wp_data_namespaceObject.select)(store).getBlockType(name)) {
8206 console.error('Block "' + name + '" is already registered.');
8207 return;
8208 }
8209
8210 if (registration_isObject(blockNameOrMetadata)) {
8211 unstable__bootstrapServerSideBlockDefinitions({
8212 [name]: getBlockSettingsFromMetadata(blockNameOrMetadata)
8213 });
8214 }
8215
8216 const blockType = {
8217 name,
8218 icon: BLOCK_ICON_DEFAULT,
8219 keywords: [],
8220 attributes: {},
8221 providesContext: {},
8222 usesContext: [],
8223 supports: {},
8224 styles: [],
8225 variations: [],
8226 save: () => null,
8227 ...(serverSideBlockDefinitions === null || serverSideBlockDefinitions === void 0 ? void 0 : serverSideBlockDefinitions[name]),
8228 ...settings
8229 };
8230
8231 (0,external_wp_data_namespaceObject.dispatch)(store).__experimentalRegisterBlockType(blockType);
8232
8233 return (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
8234 }
8235 /**
8236 * Translates block settings provided with metadata using the i18n schema.
8237 *
8238 * @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
8239 * @param {string|string[]|Object[]} settingValue Value for the block setting.
8240 * @param {string} textdomain Textdomain to use with translations.
8241 *
8242 * @return {string|string[]|Object[]} Translated setting.
8243 */
8244
8245 function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
8246 if (typeof i18nSchema === 'string' && typeof settingValue === 'string') {
8247 // eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
8248 return (0,external_wp_i18n_namespaceObject._x)(settingValue, i18nSchema, textdomain);
8249 }
8250
8251 if (Array.isArray(i18nSchema) && !(0,external_lodash_namespaceObject.isEmpty)(i18nSchema) && Array.isArray(settingValue)) {
8252 return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
8253 }
8254
8255 if (registration_isObject(i18nSchema) && !(0,external_lodash_namespaceObject.isEmpty)(i18nSchema) && registration_isObject(settingValue)) {
8256 return Object.keys(settingValue).reduce((accumulator, key) => {
8257 if (!i18nSchema[key]) {
8258 accumulator[key] = settingValue[key];
8259 return accumulator;
8260 }
8261
8262 accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
8263 return accumulator;
8264 }, {});
8265 }
8266
8267 return settingValue;
8268 }
8269 /**
8270 * Registers a new block collection to group blocks in the same namespace in the inserter.
8271 *
8272 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
8273 * @param {Object} settings The block collection settings.
8274 * @param {string} settings.title The title to display in the block inserter.
8275 * @param {Object} [settings.icon] The icon to display in the block inserter.
8276 *
8277 * @example
8278 * ```js
8279 * import { __ } from '@wordpress/i18n';
8280 * import { registerBlockCollection, registerBlockType } from '@wordpress/blocks';
8281 *
8282 * // Register the collection.
8283 * registerBlockCollection( 'my-collection', {
8284 * title: __( 'Custom Collection' ),
8285 * } );
8286 *
8287 * // Register a block in the same namespace to add it to the collection.
8288 * registerBlockType( 'my-collection/block-name', {
8289 * title: __( 'My First Block' ),
8290 * edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
8291 * save: () => <div>'Hello from the saved content!</div>,
8292 * } );
8293 * ```
8294 */
8295
8296
8297 function registerBlockCollection(namespace, _ref3) {
8298 let {
8299 title,
8300 icon
8301 } = _ref3;
8302 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockCollection(namespace, title, icon);
8303 }
8304 /**
8305 * Unregisters a block collection
8306 *
8307 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
8308 *
8309 * @example
8310 * ```js
8311 * import { unregisterBlockCollection } from '@wordpress/blocks';
8312 *
8313 * unregisterBlockCollection( 'my-collection' );
8314 * ```
8315 */
8316
8317 function unregisterBlockCollection(namespace) {
8318 dispatch(blocksStore).removeBlockCollection(namespace);
8319 }
8320 /**
8321 * Unregisters a block.
8322 *
8323 * @param {string} name Block name.
8324 *
8325 * @example
8326 * ```js
8327 * import { __ } from '@wordpress/i18n';
8328 * import { unregisterBlockType } from '@wordpress/blocks';
8329 *
8330 * const ExampleComponent = () => {
8331 * return (
8332 * <Button
8333 * onClick={ () =>
8334 * unregisterBlockType( 'my-collection/block-name' )
8335 * }
8336 * >
8337 * { __( 'Unregister my custom block.' ) }
8338 * </Button>
8339 * );
8340 * };
8341 * ```
8342 *
8343 * @return {?WPBlockType} The previous block value, if it has been successfully
8344 * unregistered; otherwise `undefined`.
8345 */
8346
8347 function unregisterBlockType(name) {
8348 const oldBlock = (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
8349
8350 if (!oldBlock) {
8351 console.error('Block "' + name + '" is not registered.');
8352 return;
8353 }
8354
8355 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockTypes(name);
8356 return oldBlock;
8357 }
8358 /**
8359 * Assigns name of block for handling non-block content.
8360 *
8361 * @param {string} blockName Block name.
8362 */
8363
8364 function setFreeformContentHandlerName(blockName) {
8365 (0,external_wp_data_namespaceObject.dispatch)(store).setFreeformFallbackBlockName(blockName);
8366 }
8367 /**
8368 * Retrieves name of block handling non-block content, or undefined if no
8369 * handler has been defined.
8370 *
8371 * @return {?string} Block name.
8372 */
8373
8374 function getFreeformContentHandlerName() {
8375 return (0,external_wp_data_namespaceObject.select)(store).getFreeformFallbackBlockName();
8376 }
8377 /**
8378 * Retrieves name of block used for handling grouping interactions.
8379 *
8380 * @return {?string} Block name.
8381 */
8382
8383 function registration_getGroupingBlockName() {
8384 return (0,external_wp_data_namespaceObject.select)(store).getGroupingBlockName();
8385 }
8386 /**
8387 * Assigns name of block handling unregistered block types.
8388 *
8389 * @param {string} blockName Block name.
8390 */
8391
8392 function setUnregisteredTypeHandlerName(blockName) {
8393 (0,external_wp_data_namespaceObject.dispatch)(store).setUnregisteredFallbackBlockName(blockName);
8394 }
8395 /**
8396 * Retrieves name of block handling unregistered block types, or undefined if no
8397 * handler has been defined.
8398 *
8399 * @return {?string} Block name.
8400 */
8401
8402 function getUnregisteredTypeHandlerName() {
8403 return (0,external_wp_data_namespaceObject.select)(store).getUnregisteredFallbackBlockName();
8404 }
8405 /**
8406 * Assigns the default block name.
8407 *
8408 * @param {string} name Block name.
8409 *
8410 * @example
8411 * ```js
8412 * import { setDefaultBlockName } from '@wordpress/blocks';
8413 *
8414 * const ExampleComponent = () => {
8415 *
8416 * return (
8417 * <Button onClick={ () => setDefaultBlockName( 'core/heading' ) }>
8418 * { __( 'Set the default block to Heading' ) }
8419 * </Button>
8420 * );
8421 * };
8422 * ```
8423 */
8424
8425 function setDefaultBlockName(name) {
8426 (0,external_wp_data_namespaceObject.dispatch)(store).setDefaultBlockName(name);
8427 }
8428 /**
8429 * Assigns name of block for handling block grouping interactions.
8430 *
8431 * @param {string} name Block name.
8432 *
8433 * @example
8434 * ```js
8435 * import { setGroupingBlockName } from '@wordpress/blocks';
8436 *
8437 * const ExampleComponent = () => {
8438 *
8439 * return (
8440 * <Button onClick={ () => setGroupingBlockName( 'core/columns' ) }>
8441 * { __( 'Set the default block to Heading' ) }
8442 * </Button>
8443 * );
8444 * };
8445 * ```
8446 */
8447
8448 function setGroupingBlockName(name) {
8449 (0,external_wp_data_namespaceObject.dispatch)(store).setGroupingBlockName(name);
8450 }
8451 /**
8452 * Retrieves the default block name.
8453 *
8454 * @return {?string} Block name.
8455 */
8456
8457 function registration_getDefaultBlockName() {
8458 return (0,external_wp_data_namespaceObject.select)(store).getDefaultBlockName();
8459 }
8460 /**
8461 * Returns a registered block type.
8462 *
8463 * @param {string} name Block name.
8464 *
8465 * @return {?Object} Block type.
8466 */
8467
8468 function registration_getBlockType(name) {
8469 var _select;
8470
8471 return (_select = (0,external_wp_data_namespaceObject.select)(store)) === null || _select === void 0 ? void 0 : _select.getBlockType(name);
8472 }
8473 /**
8474 * Returns all registered blocks.
8475 *
8476 * @return {Array} Block settings.
8477 */
8478
8479 function registration_getBlockTypes() {
8480 return (0,external_wp_data_namespaceObject.select)(store).getBlockTypes();
8481 }
8482 /**
8483 * Returns the block support value for a feature, if defined.
8484 *
8485 * @param {(string|Object)} nameOrType Block name or type object
8486 * @param {string} feature Feature to retrieve
8487 * @param {*} defaultSupports Default value to return if not
8488 * explicitly defined
8489 *
8490 * @return {?*} Block support value
8491 */
8492
8493 function registration_getBlockSupport(nameOrType, feature, defaultSupports) {
8494 return (0,external_wp_data_namespaceObject.select)(store).getBlockSupport(nameOrType, feature, defaultSupports);
8495 }
8496 /**
8497 * Returns true if the block defines support for a feature, or false otherwise.
8498 *
8499 * @param {(string|Object)} nameOrType Block name or type object.
8500 * @param {string} feature Feature to test.
8501 * @param {boolean} defaultSupports Whether feature is supported by
8502 * default if not explicitly defined.
8503 *
8504 * @return {boolean} Whether block supports feature.
8505 */
8506
8507 function registration_hasBlockSupport(nameOrType, feature, defaultSupports) {
8508 return (0,external_wp_data_namespaceObject.select)(store).hasBlockSupport(nameOrType, feature, defaultSupports);
8509 }
8510 /**
8511 * Determines whether or not the given block is a reusable block. This is a
8512 * special block type that is used to point to a global block stored via the
8513 * API.
8514 *
8515 * @param {Object} blockOrType Block or Block Type to test.
8516 *
8517 * @return {boolean} Whether the given block is a reusable block.
8518 */
8519
8520 function isReusableBlock(blockOrType) {
8521 return (blockOrType === null || blockOrType === void 0 ? void 0 : blockOrType.name) === 'core/block';
8522 }
8523 /**
8524 * Determines whether or not the given block is a template part. This is a
8525 * special block type that allows composing a page template out of reusable
8526 * design elements.
8527 *
8528 * @param {Object} blockOrType Block or Block Type to test.
8529 *
8530 * @return {boolean} Whether the given block is a template part.
8531 */
8532
8533 function isTemplatePart(blockOrType) {
8534 return blockOrType.name === 'core/template-part';
8535 }
8536 /**
8537 * Returns an array with the child blocks of a given block.
8538 *
8539 * @param {string} blockName Name of block (example: “latest-posts”).
8540 *
8541 * @return {Array} Array of child block names.
8542 */
8543
8544 const registration_getChildBlockNames = blockName => {
8545 return (0,external_wp_data_namespaceObject.select)(store).getChildBlockNames(blockName);
8546 };
8547 /**
8548 * Returns a boolean indicating if a block has child blocks or not.
8549 *
8550 * @param {string} blockName Name of block (example: “latest-posts”).
8551 *
8552 * @return {boolean} True if a block contains child blocks and false otherwise.
8553 */
8554
8555 const registration_hasChildBlocks = blockName => {
8556 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocks(blockName);
8557 };
8558 /**
8559 * Returns a boolean indicating if a block has at least one child block with inserter support.
8560 *
8561 * @param {string} blockName Block type name.
8562 *
8563 * @return {boolean} True if a block contains at least one child blocks with inserter support
8564 * and false otherwise.
8565 */
8566
8567 const registration_hasChildBlocksWithInserterSupport = blockName => {
8568 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocksWithInserterSupport(blockName);
8569 };
8570 /**
8571 * Registers a new block style variation for the given block.
8572 *
8573 * For more information on connecting the styles with CSS [the official documentation](/docs/reference-guides/block-api/block-styles.md#styles)
8574 *
8575 * @param {string} blockName Name of block (example: “core/latest-posts”).
8576 * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
8577 *
8578 * @example
8579 * ```js
8580 * import { __ } from '@wordpress/i18n';
8581 * import { registerBlockStyle } from '@wordpress/blocks';
8582 * import { Button } from '@wordpress/components';
8583 *
8584 *
8585 * const ExampleComponent = () => {
8586 * return (
8587 * <Button
8588 * onClick={ () => {
8589 * registerBlockStyle( 'core/quote', {
8590 * name: 'fancy-quote',
8591 * label: __( 'Fancy Quote' ),
8592 * } );
8593 * } }
8594 * >
8595 * { __( 'Add a new block style for core/quote' ) }
8596 * </Button>
8597 * );
8598 * };
8599 * ```
8600 */
8601
8602 const registerBlockStyle = (blockName, styleVariation) => {
8603 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockStyles(blockName, styleVariation);
8604 };
8605 /**
8606 * Unregisters a block style variation for the given block.
8607 *
8608 * @param {string} blockName Name of block (example: “core/latest-posts”).
8609 * @param {string} styleVariationName Name of class applied to the block.
8610 *
8611 * @example
8612 * ```js
8613 * import { __ } from '@wordpress/i18n';
8614 * import { unregisterBlockStyle } from '@wordpress/blocks';
8615 * import { Button } from '@wordpress/components';
8616 *
8617 * const ExampleComponent = () => {
8618 * return (
8619 * <Button
8620 * onClick={ () => {
8621 * unregisterBlockStyle( 'core/quote', 'plain' );
8622 * } }
8623 * >
8624 * { __( 'Remove the "Plain" block style for core/quote' ) }
8625 * </Button>
8626 * );
8627 * };
8628 * ```
8629 */
8630
8631 const unregisterBlockStyle = (blockName, styleVariationName) => {
8632 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockStyles(blockName, styleVariationName);
8633 };
8634 /**
8635 * Returns an array with the variations of a given block type.
8636 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
8637 *
8638 * @ignore
8639 *
8640 * @param {string} blockName Name of block (example: “core/columns”).
8641 * @param {WPBlockVariationScope} [scope] Block variation scope name.
8642 *
8643 * @return {(WPBlockVariation[]|void)} Block variations.
8644 */
8645
8646 const registration_getBlockVariations = (blockName, scope) => {
8647 return (0,external_wp_data_namespaceObject.select)(store).getBlockVariations(blockName, scope);
8648 };
8649 /**
8650 * Registers a new block variation for the given block type.
8651 *
8652 * For more information on block variations see [the official documentation ](/docs/reference-guides/block-api/block-variations.md)
8653 *
8654 * @param {string} blockName Name of the block (example: “core/columns”).
8655 * @param {WPBlockVariation} variation Object describing a block variation.
8656 *
8657 * @example
8658 * ```js
8659 * import { __ } from '@wordpress/i18n';
8660 * import { registerBlockVariation } from '@wordpress/blocks';
8661 * import { Button } from '@wordpress/components';
8662 *
8663 * const ExampleComponent = () => {
8664 * return (
8665 * <Button
8666 * onClick={ () => {
8667 * registerBlockVariation( 'core/embed', {
8668 * name: 'custom',
8669 * title: __( 'My Custom Embed' ),
8670 * attributes: { providerNameSlug: 'custom' },
8671 * } );
8672 * } }
8673 * >
8674 * __( 'Add a custom variation for core/embed' ) }
8675 * </Button>
8676 * );
8677 * };
8678 * ```
8679 */
8680
8681 const registerBlockVariation = (blockName, variation) => {
8682 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockVariations(blockName, variation);
8683 };
8684 /**
8685 * Unregisters a block variation defined for the given block type.
8686 *
8687 * @param {string} blockName Name of the block (example: “core/columns”).
8688 * @param {string} variationName Name of the variation defined for the block.
8689 *
8690 * @example
8691 * ```js
8692 * import { __ } from '@wordpress/i18n';
8693 * import { unregisterBlockVariation } from '@wordpress/blocks';
8694 * import { Button } from '@wordpress/components';
8695 *
8696 * const ExampleComponent = () => {
8697 * return (
8698 * <Button
8699 * onClick={ () => {
8700 * unregisterBlockVariation( 'core/embed', 'youtube' );
8701 * } }
8702 * >
8703 * { __( 'Remove the YouTube variation from core/embed' ) }
8704 * </Button>
8705 * );
8706 * };
8707 * ```
8708 */
8709
8710 const unregisterBlockVariation = (blockName, variationName) => {
8711 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockVariations(blockName, variationName);
8712 };
8713
8714 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/rng.js
8715 // Unique ID creation requires a high quality random # generator. In the browser we therefore
8716 // require the crypto API and do not support built-in fallback to lower quality random number
8717 // generators (like Math.random()).
8718 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
8719 // find the complete implementation of crypto (msCrypto) on IE11.
8720 var getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
8721 var rnds8 = new Uint8Array(16);
8722 function rng() {
8723 if (!getRandomValues) {
8724 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
8725 }
8726
8727 return getRandomValues(rnds8);
8728 }
8729 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/regex.js
8730 /* 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);
8731 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/validate.js
8732
8733
8734 function validate(uuid) {
8735 return typeof uuid === 'string' && regex.test(uuid);
8736 }
8737
8738 /* harmony default export */ const esm_browser_validate = (validate);
8739 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/stringify.js
8740
8741 /**
8742 * Convert array of 16 byte values to UUID string format of the form:
8743 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
8744 */
8745
8746 var byteToHex = [];
8747
8748 for (var stringify_i = 0; stringify_i < 256; ++stringify_i) {
8749 byteToHex.push((stringify_i + 0x100).toString(16).substr(1));
8750 }
8751
8752 function stringify(arr) {
8753 var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
8754 // Note: Be careful editing this code! It's been tuned for performance
8755 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
8756 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
8757 // of the following:
8758 // - One or more input array values don't map to a hex octet (leading to
8759 // "undefined" in the uuid)
8760 // - Invalid input values for the RFC `version` or `variant` fields
8761
8762 if (!esm_browser_validate(uuid)) {
8763 throw TypeError('Stringified UUID is invalid');
8764 }
8765
8766 return uuid;
8767 }
8768
8769 /* harmony default export */ const esm_browser_stringify = (stringify);
8770 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/v4.js
8771
8772
8773
8774 function v4(options, buf, offset) {
8775 options = options || {};
8776 var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
8777
8778 rnds[6] = rnds[6] & 0x0f | 0x40;
8779 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
8780
8781 if (buf) {
8782 offset = offset || 0;
8783
8784 for (var i = 0; i < 16; ++i) {
8785 buf[offset + i] = rnds[i];
8786 }
8787
8788 return buf;
8789 }
8790
8791 return esm_browser_stringify(rnds);
8792 }
8793
8794 /* harmony default export */ const esm_browser_v4 = (v4);
8795 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/factory.js
8796 /**
8797 * External dependencies
8798 */
8799
8800
8801 /**
8802 * WordPress dependencies
8803 */
8804
8805
8806 /**
8807 * Internal dependencies
8808 */
8809
8810
8811
8812 /**
8813 * Returns a block object given its type and attributes.
8814 *
8815 * @param {string} name Block name.
8816 * @param {Object} attributes Block attributes.
8817 * @param {?Array} innerBlocks Nested blocks.
8818 *
8819 * @return {Object} Block object.
8820 */
8821
8822 function createBlock(name) {
8823 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8824 let innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
8825
8826 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, attributes);
8827
8828 const clientId = esm_browser_v4(); // Blocks are stored with a unique ID, the assigned type name, the block
8829 // attributes, and their inner blocks.
8830
8831 return {
8832 clientId,
8833 name,
8834 isValid: true,
8835 attributes: sanitizedAttributes,
8836 innerBlocks
8837 };
8838 }
8839 /**
8840 * Given an array of InnerBlocks templates or Block Objects,
8841 * returns an array of created Blocks from them.
8842 * It handles the case of having InnerBlocks as Blocks by
8843 * converting them to the proper format to continue recursively.
8844 *
8845 * @param {Array} innerBlocksOrTemplate Nested blocks or InnerBlocks templates.
8846 *
8847 * @return {Object[]} Array of Block objects.
8848 */
8849
8850 function createBlocksFromInnerBlocksTemplate() {
8851 let innerBlocksOrTemplate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
8852 return innerBlocksOrTemplate.map(innerBlock => {
8853 const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [innerBlock.name, innerBlock.attributes, innerBlock.innerBlocks];
8854 const [name, attributes, innerBlocks = []] = innerBlockTemplate;
8855 return createBlock(name, attributes, createBlocksFromInnerBlocksTemplate(innerBlocks));
8856 });
8857 }
8858 /**
8859 * Given a block object, returns a copy of the block object while sanitizing its attributes,
8860 * optionally merging new attributes and/or replacing its inner blocks.
8861 *
8862 * @param {Object} block Block instance.
8863 * @param {Object} mergeAttributes Block attributes.
8864 * @param {?Array} newInnerBlocks Nested blocks.
8865 *
8866 * @return {Object} A cloned block.
8867 */
8868
8869 function __experimentalCloneSanitizedBlock(block) {
8870 let mergeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8871 let newInnerBlocks = arguments.length > 2 ? arguments[2] : undefined;
8872 const clientId = esm_browser_v4();
8873
8874 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(block.name, { ...block.attributes,
8875 ...mergeAttributes
8876 });
8877
8878 return { ...block,
8879 clientId,
8880 attributes: sanitizedAttributes,
8881 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => __experimentalCloneSanitizedBlock(innerBlock))
8882 };
8883 }
8884 /**
8885 * Given a block object, returns a copy of the block object,
8886 * optionally merging new attributes and/or replacing its inner blocks.
8887 *
8888 * @param {Object} block Block instance.
8889 * @param {Object} mergeAttributes Block attributes.
8890 * @param {?Array} newInnerBlocks Nested blocks.
8891 *
8892 * @return {Object} A cloned block.
8893 */
8894
8895 function cloneBlock(block) {
8896 let mergeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8897 let newInnerBlocks = arguments.length > 2 ? arguments[2] : undefined;
8898 const clientId = esm_browser_v4();
8899 return { ...block,
8900 clientId,
8901 attributes: { ...block.attributes,
8902 ...mergeAttributes
8903 },
8904 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => cloneBlock(innerBlock))
8905 };
8906 }
8907 /**
8908 * Returns a boolean indicating whether a transform is possible based on
8909 * various bits of context.
8910 *
8911 * @param {Object} transform The transform object to validate.
8912 * @param {string} direction Is this a 'from' or 'to' transform.
8913 * @param {Array} blocks The blocks to transform from.
8914 *
8915 * @return {boolean} Is the transform possible?
8916 */
8917
8918 const isPossibleTransformForSource = (transform, direction, blocks) => {
8919 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
8920 return false;
8921 } // If multiple blocks are selected, only multi block transforms
8922 // or wildcard transforms are allowed.
8923
8924
8925 const isMultiBlock = blocks.length > 1;
8926 const firstBlockName = (0,external_lodash_namespaceObject.first)(blocks).name;
8927 const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
8928
8929 if (!isValidForMultiBlocks) {
8930 return false;
8931 } // Check non-wildcard transforms to ensure that transform is valid
8932 // for a block selection of multiple blocks of different types.
8933
8934
8935 if (!isWildcardBlockTransform(transform) && !(0,external_lodash_namespaceObject.every)(blocks, {
8936 name: firstBlockName
8937 })) {
8938 return false;
8939 } // Only consider 'block' type transforms as valid.
8940
8941
8942 const isBlockType = transform.type === 'block';
8943
8944 if (!isBlockType) {
8945 return false;
8946 } // Check if the transform's block name matches the source block (or is a wildcard)
8947 // only if this is a transform 'from'.
8948
8949
8950 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
8951 const hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
8952
8953 if (!hasMatchingName) {
8954 return false;
8955 } // Don't allow single Grouping blocks to be transformed into
8956 // a Grouping block.
8957
8958
8959 if (!isMultiBlock && direction === 'from' && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
8960 return false;
8961 } // If the transform has a `isMatch` function specified, check that it returns true.
8962
8963
8964 if (!maybeCheckTransformIsMatch(transform, blocks)) {
8965 return false;
8966 }
8967
8968 if (transform.usingMobileTransformations && isWildcardBlockTransform(transform) && !isContainerGroupBlock(sourceBlock.name)) {
8969 return false;
8970 }
8971
8972 return true;
8973 };
8974 /**
8975 * Returns block types that the 'blocks' can be transformed into, based on
8976 * 'from' transforms on other blocks.
8977 *
8978 * @param {Array} blocks The blocks to transform from.
8979 *
8980 * @return {Array} Block types that the blocks can be transformed into.
8981 */
8982
8983
8984 const getBlockTypesForPossibleFromTransforms = blocks => {
8985 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
8986 return [];
8987 }
8988
8989 const allBlockTypes = registration_getBlockTypes(); // filter all blocks to find those with a 'from' transform.
8990
8991 const blockTypesWithPossibleFromTransforms = (0,external_lodash_namespaceObject.filter)(allBlockTypes, blockType => {
8992 const fromTransforms = getBlockTransforms('from', blockType.name);
8993 return !!findTransform(fromTransforms, transform => {
8994 return isPossibleTransformForSource(transform, 'from', blocks);
8995 });
8996 });
8997 return blockTypesWithPossibleFromTransforms;
8998 };
8999 /**
9000 * Returns block types that the 'blocks' can be transformed into, based on
9001 * the source block's own 'to' transforms.
9002 *
9003 * @param {Array} blocks The blocks to transform from.
9004 *
9005 * @return {Array} Block types that the source can be transformed into.
9006 */
9007
9008
9009 const getBlockTypesForPossibleToTransforms = blocks => {
9010 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
9011 return [];
9012 }
9013
9014 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
9015 const blockType = registration_getBlockType(sourceBlock.name);
9016 const transformsTo = blockType ? getBlockTransforms('to', blockType.name) : []; // filter all 'to' transforms to find those that are possible.
9017
9018 const possibleTransforms = (0,external_lodash_namespaceObject.filter)(transformsTo, transform => {
9019 return transform && isPossibleTransformForSource(transform, 'to', blocks);
9020 }); // Build a list of block names using the possible 'to' transforms.
9021
9022 const blockNames = possibleTransforms.map(transformation => transformation.blocks).flat(); // Map block names to block types.
9023
9024 return blockNames.map(name => name === '*' ? name : registration_getBlockType(name));
9025 };
9026 /**
9027 * Determines whether transform is a "block" type
9028 * and if so whether it is a "wildcard" transform
9029 * ie: targets "any" block type
9030 *
9031 * @param {Object} t the Block transform object
9032 *
9033 * @return {boolean} whether transform is a wildcard transform
9034 */
9035
9036
9037 const isWildcardBlockTransform = t => t && t.type === 'block' && Array.isArray(t.blocks) && t.blocks.includes('*');
9038 /**
9039 * Determines whether the given Block is the core Block which
9040 * acts as a container Block for other Blocks as part of the
9041 * Grouping mechanics
9042 *
9043 * @param {string} name the name of the Block to test against
9044 *
9045 * @return {boolean} whether or not the Block is the container Block type
9046 */
9047
9048 const isContainerGroupBlock = name => name === registration_getGroupingBlockName();
9049 /**
9050 * Returns an array of block types that the set of blocks received as argument
9051 * can be transformed into.
9052 *
9053 * @param {Array} blocks Blocks array.
9054 *
9055 * @return {Array} Block types that the blocks argument can be transformed to.
9056 */
9057
9058 function getPossibleBlockTransformations(blocks) {
9059 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
9060 return [];
9061 }
9062
9063 const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
9064 const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
9065 return [...new Set([...blockTypesForFromTransforms, ...blockTypesForToTransforms])];
9066 }
9067 /**
9068 * Given an array of transforms, returns the highest-priority transform where
9069 * the predicate function returns a truthy value. A higher-priority transform
9070 * is one with a lower priority value (i.e. first in priority order). Returns
9071 * null if the transforms set is empty or the predicate function returns a
9072 * falsey value for all entries.
9073 *
9074 * @param {Object[]} transforms Transforms to search.
9075 * @param {Function} predicate Function returning true on matching transform.
9076 *
9077 * @return {?Object} Highest-priority transform candidate.
9078 */
9079
9080 function findTransform(transforms, predicate) {
9081 // The hooks library already has built-in mechanisms for managing priority
9082 // queue, so leverage via locally-defined instance.
9083 const hooks = (0,external_wp_hooks_namespaceObject.createHooks)();
9084
9085 for (let i = 0; i < transforms.length; i++) {
9086 const candidate = transforms[i];
9087
9088 if (predicate(candidate)) {
9089 hooks.addFilter('transform', 'transform/' + i.toString(), result => result ? result : candidate, candidate.priority);
9090 }
9091 } // Filter name is arbitrarily chosen but consistent with above aggregation.
9092
9093
9094 return hooks.applyFilters('transform', null);
9095 }
9096 /**
9097 * Returns normal block transforms for a given transform direction, optionally
9098 * for a specific block by name, or an empty array if there are no transforms.
9099 * If no block name is provided, returns transforms for all blocks. A normal
9100 * transform object includes `blockName` as a property.
9101 *
9102 * @param {string} direction Transform direction ("to", "from").
9103 * @param {string|Object} blockTypeOrName Block type or name.
9104 *
9105 * @return {Array} Block transforms for direction.
9106 */
9107
9108 function getBlockTransforms(direction, blockTypeOrName) {
9109 // When retrieving transforms for all block types, recurse into self.
9110 if (blockTypeOrName === undefined) {
9111 return registration_getBlockTypes().map(_ref => {
9112 let {
9113 name
9114 } = _ref;
9115 return getBlockTransforms(direction, name);
9116 }).flat();
9117 } // Validate that block type exists and has array of direction.
9118
9119
9120 const blockType = normalizeBlockType(blockTypeOrName);
9121 const {
9122 name: blockName,
9123 transforms
9124 } = blockType || {};
9125
9126 if (!transforms || !Array.isArray(transforms[direction])) {
9127 return [];
9128 }
9129
9130 const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
9131 const filteredTransforms = usingMobileTransformations ? (0,external_lodash_namespaceObject.filter)(transforms[direction], t => {
9132 if (t.type === 'raw') {
9133 return true;
9134 }
9135
9136 if (!t.blocks || !t.blocks.length) {
9137 return false;
9138 }
9139
9140 if (isWildcardBlockTransform(t)) {
9141 return true;
9142 }
9143
9144 return (0,external_lodash_namespaceObject.every)(t.blocks, transformBlockName => transforms.supportedMobileTransforms.includes(transformBlockName));
9145 }) : transforms[direction]; // Map transforms to normal form.
9146
9147 return filteredTransforms.map(transform => ({ ...transform,
9148 blockName,
9149 usingMobileTransformations
9150 }));
9151 }
9152 /**
9153 * Checks that a given transforms isMatch method passes for given source blocks.
9154 *
9155 * @param {Object} transform A transform object.
9156 * @param {Array} blocks Blocks array.
9157 *
9158 * @return {boolean} True if given blocks are a match for the transform.
9159 */
9160
9161 function maybeCheckTransformIsMatch(transform, blocks) {
9162 if (typeof transform.isMatch !== 'function') {
9163 return true;
9164 }
9165
9166 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
9167 const attributes = transform.isMultiBlock ? blocks.map(block => block.attributes) : sourceBlock.attributes;
9168 const block = transform.isMultiBlock ? blocks : sourceBlock;
9169 return transform.isMatch(attributes, block);
9170 }
9171 /**
9172 * Switch one or more blocks into one or more blocks of the new block type.
9173 *
9174 * @param {Array|Object} blocks Blocks array or block object.
9175 * @param {string} name Block name.
9176 *
9177 * @return {?Array} Array of blocks or null.
9178 */
9179
9180
9181 function switchToBlockType(blocks, name) {
9182 const blocksArray = (0,external_lodash_namespaceObject.castArray)(blocks);
9183 const isMultiBlock = blocksArray.length > 1;
9184 const firstBlock = blocksArray[0];
9185 const sourceName = firstBlock.name; // Find the right transformation by giving priority to the "to"
9186 // transformation.
9187
9188 const transformationsFrom = getBlockTransforms('from', name);
9189 const transformationsTo = getBlockTransforms('to', sourceName);
9190 const transformation = findTransform(transformationsTo, t => t.type === 'block' && t.blocks.indexOf(name) !== -1 && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)) || findTransform(transformationsFrom, t => t.type === 'block' && (isWildcardBlockTransform(t) || t.blocks.indexOf(sourceName) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)); // Stop if there is no valid transformation.
9191
9192 if (!transformation) {
9193 return null;
9194 }
9195
9196 let transformationResults;
9197
9198 if (transformation.isMultiBlock) {
9199 if ((0,external_lodash_namespaceObject.has)(transformation, '__experimentalConvert')) {
9200 transformationResults = transformation.__experimentalConvert(blocksArray);
9201 } else {
9202 transformationResults = transformation.transform(blocksArray.map(currentBlock => currentBlock.attributes), blocksArray.map(currentBlock => currentBlock.innerBlocks));
9203 }
9204 } else if ((0,external_lodash_namespaceObject.has)(transformation, '__experimentalConvert')) {
9205 transformationResults = transformation.__experimentalConvert(firstBlock);
9206 } else {
9207 transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
9208 } // Ensure that the transformation function returned an object or an array
9209 // of objects.
9210
9211
9212 if (transformationResults === null || typeof transformationResults !== 'object') {
9213 return null;
9214 } // If the transformation function returned a single object, we want to work
9215 // with an array instead.
9216
9217
9218 transformationResults = (0,external_lodash_namespaceObject.castArray)(transformationResults); // Ensure that every block object returned by the transformation has a
9219 // valid block type.
9220
9221 if (transformationResults.some(result => !registration_getBlockType(result.name))) {
9222 return null;
9223 } // When unwrapping blocks (`switchToBlockType( wrapperblocks, '*' )`), do
9224 // not run filters on the unwrapped blocks. They shoud remain as they are.
9225
9226
9227 if (name === '*') {
9228 return transformationResults;
9229 }
9230
9231 const hasSwitchedBlock = (0,external_lodash_namespaceObject.some)(transformationResults, result => result.name === name); // Ensure that at least one block object returned by the transformation has
9232 // the expected "destination" block type.
9233
9234 if (!hasSwitchedBlock) {
9235 return null;
9236 }
9237
9238 const ret = transformationResults.map((result, index, results) => {
9239 /**
9240 * Filters an individual transform result from block transformation.
9241 * All of the original blocks are passed, since transformations are
9242 * many-to-many, not one-to-one.
9243 *
9244 * @param {Object} transformedBlock The transformed block.
9245 * @param {Object[]} blocks Original blocks transformed.
9246 * @param {Object[]} index Index of the transformed block on the array of results.
9247 * @param {Object[]} results An array all the blocks that resulted from the transformation.
9248 */
9249 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.switchToBlockType.transformedBlock', result, blocks, index, results);
9250 });
9251 return ret;
9252 }
9253 /**
9254 * Create a block object from the example API.
9255 *
9256 * @param {string} name
9257 * @param {Object} example
9258 *
9259 * @return {Object} block.
9260 */
9261
9262 const getBlockFromExample = (name, example) => {
9263 return createBlock(name, example.attributes, (0,external_lodash_namespaceObject.map)(example.innerBlocks, innerBlock => getBlockFromExample(innerBlock.name, innerBlock)));
9264 };
9265
9266 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/utils.js
9267 /**
9268 * External dependencies
9269 */
9270
9271
9272
9273
9274 /**
9275 * WordPress dependencies
9276 */
9277
9278
9279
9280
9281 /**
9282 * Internal dependencies
9283 */
9284
9285
9286
9287
9288 k([names, a11y]);
9289 /**
9290 * Array of icon colors containing a color to be used if the icon color
9291 * was not explicitly set but the icon background color was.
9292 *
9293 * @type {Object}
9294 */
9295
9296 const ICON_COLORS = ['#191e23', '#f8f9f9'];
9297 /**
9298 * Determines whether the block is a default block
9299 * and its attributes are equal to the default attributes
9300 * which means the block is unmodified.
9301 *
9302 * @param {WPBlock} block Block Object
9303 *
9304 * @return {boolean} Whether the block is an unmodified default block
9305 */
9306
9307 function isUnmodifiedDefaultBlock(block) {
9308 const defaultBlockName = registration_getDefaultBlockName();
9309
9310 if (block.name !== defaultBlockName) {
9311 return false;
9312 } // Cache a created default block if no cache exists or the default block
9313 // name changed.
9314
9315
9316 if (!isUnmodifiedDefaultBlock.block || isUnmodifiedDefaultBlock.block.name !== defaultBlockName) {
9317 isUnmodifiedDefaultBlock.block = createBlock(defaultBlockName);
9318 }
9319
9320 const newDefaultBlock = isUnmodifiedDefaultBlock.block;
9321 const blockType = registration_getBlockType(defaultBlockName);
9322 return (0,external_lodash_namespaceObject.every)(blockType === null || blockType === void 0 ? void 0 : blockType.attributes, (value, key) => newDefaultBlock.attributes[key] === block.attributes[key]);
9323 }
9324 /**
9325 * Function that checks if the parameter is a valid icon.
9326 *
9327 * @param {*} icon Parameter to be checked.
9328 *
9329 * @return {boolean} True if the parameter is a valid icon and false otherwise.
9330 */
9331
9332 function isValidIcon(icon) {
9333 return !!icon && (typeof icon === 'string' || (0,external_wp_element_namespaceObject.isValidElement)(icon) || typeof icon === 'function' || icon instanceof external_wp_element_namespaceObject.Component);
9334 }
9335 /**
9336 * Function that receives an icon as set by the blocks during the registration
9337 * and returns a new icon object that is normalized so we can rely on just on possible icon structure
9338 * in the codebase.
9339 *
9340 * @param {WPBlockTypeIconRender} icon Render behavior of a block type icon;
9341 * one of a Dashicon slug, an element, or a
9342 * component.
9343 *
9344 * @return {WPBlockTypeIconDescriptor} Object describing the icon.
9345 */
9346
9347 function normalizeIconObject(icon) {
9348 icon = icon || BLOCK_ICON_DEFAULT;
9349
9350 if (isValidIcon(icon)) {
9351 return {
9352 src: icon
9353 };
9354 }
9355
9356 if ((0,external_lodash_namespaceObject.has)(icon, ['background'])) {
9357 const colordBgColor = w(icon.background);
9358
9359 const getColorContrast = iconColor => colordBgColor.contrast(iconColor);
9360
9361 const maxContrast = Math.max(...ICON_COLORS.map(getColorContrast));
9362 return { ...icon,
9363 foreground: icon.foreground ? icon.foreground : ICON_COLORS.find(iconColor => getColorContrast(iconColor) === maxContrast),
9364 shadowColor: colordBgColor.alpha(0.3).toRgbString()
9365 };
9366 }
9367
9368 return icon;
9369 }
9370 /**
9371 * Normalizes block type passed as param. When string is passed then
9372 * it converts it to the matching block type object.
9373 * It passes the original object otherwise.
9374 *
9375 * @param {string|Object} blockTypeOrName Block type or name.
9376 *
9377 * @return {?Object} Block type.
9378 */
9379
9380 function normalizeBlockType(blockTypeOrName) {
9381 if (typeof blockTypeOrName === 'string') {
9382 return registration_getBlockType(blockTypeOrName);
9383 }
9384
9385 return blockTypeOrName;
9386 }
9387 /**
9388 * Get the label for the block, usually this is either the block title,
9389 * or the value of the block's `label` function when that's specified.
9390 *
9391 * @param {Object} blockType The block type.
9392 * @param {Object} attributes The values of the block's attributes.
9393 * @param {Object} context The intended use for the label.
9394 *
9395 * @return {string} The block label.
9396 */
9397
9398 function getBlockLabel(blockType, attributes) {
9399 let context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'visual';
9400 const {
9401 __experimentalLabel: getLabel,
9402 title
9403 } = blockType;
9404 const label = getLabel && getLabel(attributes, {
9405 context
9406 });
9407
9408 if (!label) {
9409 return title;
9410 } // Strip any HTML (i.e. RichText formatting) before returning.
9411
9412
9413 return (0,external_wp_dom_namespaceObject.__unstableStripHTML)(label);
9414 }
9415 /**
9416 * Get a label for the block for use by screenreaders, this is more descriptive
9417 * than the visual label and includes the block title and the value of the
9418 * `getLabel` function if it's specified.
9419 *
9420 * @param {?Object} blockType The block type.
9421 * @param {Object} attributes The values of the block's attributes.
9422 * @param {?number} position The position of the block in the block list.
9423 * @param {string} [direction='vertical'] The direction of the block layout.
9424 *
9425 * @return {string} The block label.
9426 */
9427
9428 function getAccessibleBlockLabel(blockType, attributes, position) {
9429 let direction = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'vertical';
9430 // `title` is already localized, `label` is a user-supplied value.
9431 const title = blockType === null || blockType === void 0 ? void 0 : blockType.title;
9432 const label = blockType ? getBlockLabel(blockType, attributes, 'accessibility') : '';
9433 const hasPosition = position !== undefined; // getBlockLabel returns the block title as a fallback when there's no label,
9434 // if it did return the title, this function needs to avoid adding the
9435 // title twice within the accessible label. Use this `hasLabel` boolean to
9436 // handle that.
9437
9438 const hasLabel = label && label !== title;
9439
9440 if (hasPosition && direction === 'vertical') {
9441 if (hasLabel) {
9442 return (0,external_wp_i18n_namespaceObject.sprintf)(
9443 /* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */
9444 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d. %3$s'), title, position, label);
9445 }
9446
9447 return (0,external_wp_i18n_namespaceObject.sprintf)(
9448 /* translators: accessibility text. 1: The block title. 2: The block row number. */
9449 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d'), title, position);
9450 } else if (hasPosition && direction === 'horizontal') {
9451 if (hasLabel) {
9452 return (0,external_wp_i18n_namespaceObject.sprintf)(
9453 /* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */
9454 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d. %3$s'), title, position, label);
9455 }
9456
9457 return (0,external_wp_i18n_namespaceObject.sprintf)(
9458 /* translators: accessibility text. 1: The block title. 2: The block column number. */
9459 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d'), title, position);
9460 }
9461
9462 if (hasLabel) {
9463 return (0,external_wp_i18n_namespaceObject.sprintf)(
9464 /* translators: accessibility text. %1: The block title. %2: The block label. */
9465 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. %2$s'), title, label);
9466 }
9467
9468 return (0,external_wp_i18n_namespaceObject.sprintf)(
9469 /* translators: accessibility text. %s: The block title. */
9470 (0,external_wp_i18n_namespaceObject.__)('%s Block'), title);
9471 }
9472 /**
9473 * Ensure attributes contains only values defined by block type, and merge
9474 * default values for missing attributes.
9475 *
9476 * @param {string} name The block's name.
9477 * @param {Object} attributes The block's attributes.
9478 * @return {Object} The sanitized attributes.
9479 */
9480
9481 function __experimentalSanitizeBlockAttributes(name, attributes) {
9482 // Get the type definition associated with a registered block.
9483 const blockType = registration_getBlockType(name);
9484
9485 if (undefined === blockType) {
9486 throw new Error(`Block type '${name}' is not registered.`);
9487 }
9488
9489 return (0,external_lodash_namespaceObject.reduce)(blockType.attributes, (accumulator, schema, key) => {
9490 const value = attributes[key];
9491
9492 if (undefined !== value) {
9493 accumulator[key] = value;
9494 } else if (schema.hasOwnProperty('default')) {
9495 accumulator[key] = schema.default;
9496 }
9497
9498 if (['node', 'children'].indexOf(schema.source) !== -1) {
9499 // Ensure value passed is always an array, which we're expecting in
9500 // the RichText component to handle the deprecated value.
9501 if (typeof accumulator[key] === 'string') {
9502 accumulator[key] = [accumulator[key]];
9503 } else if (!Array.isArray(accumulator[key])) {
9504 accumulator[key] = [];
9505 }
9506 }
9507
9508 return accumulator;
9509 }, {});
9510 }
9511 /**
9512 * Filter block attributes by `role` and return their names.
9513 *
9514 * @param {string} name Block attribute's name.
9515 * @param {string} role The role of a block attribute.
9516 *
9517 * @return {string[]} The attribute names that have the provided role.
9518 */
9519
9520 function __experimentalGetBlockAttributesNamesByRole(name, role) {
9521 var _getBlockType;
9522
9523 const attributes = (_getBlockType = registration_getBlockType(name)) === null || _getBlockType === void 0 ? void 0 : _getBlockType.attributes;
9524 if (!attributes) return [];
9525 const attributesNames = Object.keys(attributes);
9526 if (!role) return attributesNames;
9527 return attributesNames.filter(attributeName => {
9528 var _attributes$attribute;
9529
9530 return ((_attributes$attribute = attributes[attributeName]) === null || _attributes$attribute === void 0 ? void 0 : _attributes$attribute.__experimentalRole) === role;
9531 });
9532 }
9533
9534 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/actions.js
9535 /**
9536 * External dependencies
9537 */
9538
9539
9540 /**
9541 * WordPress dependencies
9542 */
9543
9544
9545 /**
9546 * Internal dependencies
9547 */
9548
9549
9550
9551 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
9552
9553 /** @typedef {import('../api/registration').WPBlockType} WPBlockType */
9554
9555 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
9556
9557 const {
9558 error,
9559 warn
9560 } = window.console;
9561 /**
9562 * Mapping of legacy category slugs to their latest normal values, used to
9563 * accommodate updates of the default set of block categories.
9564 *
9565 * @type {Record<string,string>}
9566 */
9567
9568 const LEGACY_CATEGORY_MAPPING = {
9569 common: 'text',
9570 formatting: 'text',
9571 layout: 'design'
9572 };
9573 /**
9574 * Whether the argument is a function.
9575 *
9576 * @param {*} maybeFunc The argument to check.
9577 * @return {boolean} True if the argument is a function, false otherwise.
9578 */
9579
9580 function isFunction(maybeFunc) {
9581 return typeof maybeFunc === 'function';
9582 }
9583 /**
9584 * Takes the unprocessed block type data and applies all the existing filters for the registered block type.
9585 * Next, it validates all the settings and performs additional processing to the block type definition.
9586 *
9587 * @param {WPBlockType} blockType Unprocessed block type settings.
9588 * @param {Object} thunkArgs Argument object for the thunk middleware.
9589 * @param {Function} thunkArgs.select Function to select from the store.
9590 *
9591 * @return {?WPBlockType} The block, if it has been successfully registered; otherwise `undefined`.
9592 */
9593
9594
9595 const processBlockType = (blockType, _ref) => {
9596 let {
9597 select
9598 } = _ref;
9599 const {
9600 name
9601 } = blockType;
9602 const settings = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', { ...blockType
9603 }, name, null);
9604
9605 if (settings.deprecated) {
9606 settings.deprecated = settings.deprecated.map(deprecation => (0,external_lodash_namespaceObject.pick)( // Only keep valid deprecation keys.
9607 (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', // Merge deprecation keys with pre-filter settings
9608 // so that filters that depend on specific keys being
9609 // present don't fail.
9610 { // Omit deprecation keys here so that deprecations
9611 // can opt out of specific keys like "supports".
9612 ...(0,external_lodash_namespaceObject.omit)(blockType, DEPRECATED_ENTRY_KEYS),
9613 ...deprecation
9614 }, name, deprecation), DEPRECATED_ENTRY_KEYS));
9615 }
9616
9617 if (!isPlainObject(settings)) {
9618 error('Block settings must be a valid object.');
9619 return;
9620 }
9621
9622 if (!isFunction(settings.save)) {
9623 error('The "save" property must be a valid function.');
9624 return;
9625 }
9626
9627 if ('edit' in settings && !isFunction(settings.edit)) {
9628 error('The "edit" property must be a valid function.');
9629 return;
9630 } // Canonicalize legacy categories to equivalent fallback.
9631
9632
9633 if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) {
9634 settings.category = LEGACY_CATEGORY_MAPPING[settings.category];
9635 }
9636
9637 if ('category' in settings && !(0,external_lodash_namespaceObject.some)(select.getCategories(), {
9638 slug: settings.category
9639 })) {
9640 warn('The block "' + name + '" is registered with an invalid category "' + settings.category + '".');
9641 delete settings.category;
9642 }
9643
9644 if (!('title' in settings) || settings.title === '') {
9645 error('The block "' + name + '" must have a title.');
9646 return;
9647 }
9648
9649 if (typeof settings.title !== 'string') {
9650 error('Block titles must be strings.');
9651 return;
9652 }
9653
9654 settings.icon = normalizeIconObject(settings.icon);
9655
9656 if (!isValidIcon(settings.icon.src)) {
9657 error('The icon passed is invalid. ' + 'The icon should be a string, an element, a function, or an object following the specifications documented in https://developer.wordpress.org/block-editor/developers/block-api/block-registration/#icon-optional');
9658 return;
9659 }
9660
9661 return settings;
9662 };
9663 /**
9664 * Returns an action object used in signalling that block types have been added.
9665 * Ignored from documentation as the recommended usage for this action through registerBlockType from @wordpress/blocks.
9666 *
9667 * @ignore
9668 *
9669 * @param {WPBlockType|WPBlockType[]} blockTypes Object or array of objects representing blocks to added.
9670 *
9671 *
9672 * @return {Object} Action object.
9673 */
9674
9675
9676 function addBlockTypes(blockTypes) {
9677 return {
9678 type: 'ADD_BLOCK_TYPES',
9679 blockTypes: (0,external_lodash_namespaceObject.castArray)(blockTypes)
9680 };
9681 }
9682 /**
9683 * Signals that the passed block type's settings should be stored in the state.
9684 *
9685 * @param {WPBlockType} blockType Unprocessed block type settings.
9686 */
9687
9688 const __experimentalRegisterBlockType = blockType => _ref2 => {
9689 let {
9690 dispatch,
9691 select
9692 } = _ref2;
9693 dispatch({
9694 type: 'ADD_UNPROCESSED_BLOCK_TYPE',
9695 blockType
9696 });
9697 const processedBlockType = processBlockType(blockType, {
9698 select
9699 });
9700
9701 if (!processedBlockType) {
9702 return;
9703 }
9704
9705 dispatch.addBlockTypes(processedBlockType);
9706 };
9707 /**
9708 * Signals that all block types should be computed again.
9709 * It uses stored unprocessed block types and all the most recent list of registered filters.
9710 *
9711 * It addresses the issue where third party block filters get registered after third party blocks. A sample sequence:
9712 * 1. Filter A.
9713 * 2. Block B.
9714 * 3. Block C.
9715 * 4. Filter D.
9716 * 5. Filter E.
9717 * 6. Block F.
9718 * 7. Filter G.
9719 * In this scenario some filters would not get applied for all blocks because they are registered too late.
9720 */
9721
9722 const __experimentalReapplyBlockTypeFilters = () => _ref3 => {
9723 let {
9724 dispatch,
9725 select
9726 } = _ref3;
9727
9728 const unprocessedBlockTypes = select.__experimentalGetUnprocessedBlockTypes();
9729
9730 const processedBlockTypes = Object.keys(unprocessedBlockTypes).reduce((accumulator, blockName) => {
9731 const result = processBlockType(unprocessedBlockTypes[blockName], {
9732 select
9733 });
9734
9735 if (result) {
9736 accumulator.push(result);
9737 }
9738
9739 return accumulator;
9740 }, []);
9741
9742 if (!processedBlockTypes.length) {
9743 return;
9744 }
9745
9746 dispatch.addBlockTypes(processedBlockTypes);
9747 };
9748 /**
9749 * Returns an action object used to remove a registered block type.
9750 * Ignored from documentation as the recommended usage for this action through unregisterBlockType from @wordpress/blocks.
9751 *
9752 * @ignore
9753 *
9754 * @param {string|string[]} names Block name or array of block names to be removed.
9755 *
9756 *
9757 * @return {Object} Action object.
9758 */
9759
9760 function removeBlockTypes(names) {
9761 return {
9762 type: 'REMOVE_BLOCK_TYPES',
9763 names: (0,external_lodash_namespaceObject.castArray)(names)
9764 };
9765 }
9766 /**
9767 * Returns an action object used in signalling that new block styles have been added.
9768 * Ignored from documentation as the recommended usage for this action through registerBlockStyle from @wordpress/blocks.
9769 *
9770 * @param {string} blockName Block name.
9771 * @param {Array|Object} styles Block style object or array of block style objects.
9772 *
9773 * @ignore
9774 *
9775 * @return {Object} Action object.
9776 */
9777
9778 function addBlockStyles(blockName, styles) {
9779 return {
9780 type: 'ADD_BLOCK_STYLES',
9781 styles: (0,external_lodash_namespaceObject.castArray)(styles),
9782 blockName
9783 };
9784 }
9785 /**
9786 * Returns an action object used in signalling that block styles have been removed.
9787 * Ignored from documentation as the recommended usage for this action through unregisterBlockStyle from @wordpress/blocks.
9788 *
9789 * @ignore
9790 *
9791 * @param {string} blockName Block name.
9792 * @param {Array|string} styleNames Block style names or array of block style names.
9793 *
9794 * @return {Object} Action object.
9795 */
9796
9797 function removeBlockStyles(blockName, styleNames) {
9798 return {
9799 type: 'REMOVE_BLOCK_STYLES',
9800 styleNames: (0,external_lodash_namespaceObject.castArray)(styleNames),
9801 blockName
9802 };
9803 }
9804 /**
9805 * Returns an action object used in signalling that new block variations have been added.
9806 * Ignored from documentation as the recommended usage for this action through registerBlockVariation from @wordpress/blocks.
9807 *
9808 * @ignore
9809 *
9810 * @param {string} blockName Block name.
9811 * @param {WPBlockVariation|WPBlockVariation[]} variations Block variations.
9812 *
9813 * @return {Object} Action object.
9814 */
9815
9816 function addBlockVariations(blockName, variations) {
9817 return {
9818 type: 'ADD_BLOCK_VARIATIONS',
9819 variations: (0,external_lodash_namespaceObject.castArray)(variations),
9820 blockName
9821 };
9822 }
9823 /**
9824 * Returns an action object used in signalling that block variations have been removed.
9825 * Ignored from documentation as the recommended usage for this action through unregisterBlockVariation from @wordpress/blocks.
9826 *
9827 * @ignore
9828 *
9829 * @param {string} blockName Block name.
9830 * @param {string|string[]} variationNames Block variation names.
9831 *
9832 * @return {Object} Action object.
9833 */
9834
9835 function removeBlockVariations(blockName, variationNames) {
9836 return {
9837 type: 'REMOVE_BLOCK_VARIATIONS',
9838 variationNames: (0,external_lodash_namespaceObject.castArray)(variationNames),
9839 blockName
9840 };
9841 }
9842 /**
9843 * Returns an action object used to set the default block name.
9844 * Ignored from documentation as the recommended usage for this action through setDefaultBlockName from @wordpress/blocks.
9845 *
9846 * @ignore
9847 *
9848 * @param {string} name Block name.
9849 *
9850 * @return {Object} Action object.
9851 */
9852
9853 function actions_setDefaultBlockName(name) {
9854 return {
9855 type: 'SET_DEFAULT_BLOCK_NAME',
9856 name
9857 };
9858 }
9859 /**
9860 * Returns an action object used to set the name of the block used as a fallback
9861 * for non-block content.
9862 * Ignored from documentation as the recommended usage for this action through setFreeformContentHandlerName from @wordpress/blocks.
9863 *
9864 * @ignore
9865 *
9866 * @param {string} name Block name.
9867 *
9868 * @return {Object} Action object.
9869 */
9870
9871 function setFreeformFallbackBlockName(name) {
9872 return {
9873 type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
9874 name
9875 };
9876 }
9877 /**
9878 * Returns an action object used to set the name of the block used as a fallback
9879 * for unregistered blocks.
9880 * Ignored from documentation as the recommended usage for this action through setUnregisteredTypeHandlerName from @wordpress/blocks.
9881 *
9882 * @ignore
9883 *
9884 * @param {string} name Block name.
9885 *
9886 * @return {Object} Action object.
9887 */
9888
9889 function setUnregisteredFallbackBlockName(name) {
9890 return {
9891 type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
9892 name
9893 };
9894 }
9895 /**
9896 * Returns an action object used to set the name of the block used
9897 * when grouping other blocks
9898 * eg: in "Group/Ungroup" interactions
9899 * Ignored from documentation as the recommended usage for this action through setGroupingBlockName from @wordpress/blocks.
9900 *
9901 * @ignore
9902 *
9903 * @param {string} name Block name.
9904 *
9905 * @return {Object} Action object.
9906 */
9907
9908 function actions_setGroupingBlockName(name) {
9909 return {
9910 type: 'SET_GROUPING_BLOCK_NAME',
9911 name
9912 };
9913 }
9914 /**
9915 * Returns an action object used to set block categories.
9916 * Ignored from documentation as the recommended usage for this action through setCategories from @wordpress/blocks.
9917 *
9918 * @ignore
9919 *
9920 * @param {WPBlockCategory[]} categories Block categories.
9921 *
9922 * @return {Object} Action object.
9923 */
9924
9925 function setCategories(categories) {
9926 return {
9927 type: 'SET_CATEGORIES',
9928 categories
9929 };
9930 }
9931 /**
9932 * Returns an action object used to update a category.
9933 * Ignored from documentation as the recommended usage for this action through updateCategory from @wordpress/blocks.
9934 *
9935 * @ignore
9936 *
9937 * @param {string} slug Block category slug.
9938 * @param {Object} category Object containing the category properties that should be updated.
9939 *
9940 * @return {Object} Action object.
9941 */
9942
9943 function updateCategory(slug, category) {
9944 return {
9945 type: 'UPDATE_CATEGORY',
9946 slug,
9947 category
9948 };
9949 }
9950 /**
9951 * Returns an action object used to add block collections
9952 * Ignored from documentation as the recommended usage for this action through registerBlockCollection from @wordpress/blocks.
9953 *
9954 * @ignore
9955 *
9956 * @param {string} namespace The namespace of the blocks to put in the collection
9957 * @param {string} title The title to display in the block inserter
9958 * @param {Object} icon (optional) The icon to display in the block inserter
9959 *
9960 * @return {Object} Action object.
9961 */
9962
9963 function addBlockCollection(namespace, title, icon) {
9964 return {
9965 type: 'ADD_BLOCK_COLLECTION',
9966 namespace,
9967 title,
9968 icon
9969 };
9970 }
9971 /**
9972 * Returns an action object used to remove block collections
9973 * Ignored from documentation as the recommended usage for this action through unregisterBlockCollection from @wordpress/blocks.
9974 *
9975 * @ignore
9976 *
9977 * @param {string} namespace The namespace of the blocks to put in the collection
9978 *
9979 * @return {Object} Action object.
9980 */
9981
9982 function removeBlockCollection(namespace) {
9983 return {
9984 type: 'REMOVE_BLOCK_COLLECTION',
9985 namespace
9986 };
9987 }
9988
9989 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/constants.js
9990 const STORE_NAME = 'core/blocks';
9991
9992 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/index.js
9993 /**
9994 * WordPress dependencies
9995 */
9996
9997 /**
9998 * Internal dependencies
9999 */
10000
10001
10002
10003
10004
10005 /**
10006 * Store definition for the blocks namespace.
10007 *
10008 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
10009 *
10010 * @type {Object}
10011 */
10012
10013 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
10014 reducer: reducer,
10015 selectors: selectors_namespaceObject,
10016 actions: actions_namespaceObject
10017 });
10018 (0,external_wp_data_namespaceObject.register)(store);
10019
10020 ;// CONCATENATED MODULE: external ["wp","blockSerializationDefaultParser"]
10021 const external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
10022 ;// CONCATENATED MODULE: external ["wp","autop"]
10023 const external_wp_autop_namespaceObject = window["wp"]["autop"];
10024 ;// CONCATENATED MODULE: external ["wp","isShallowEqual"]
10025 const external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"];
10026 var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject);
10027 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/serialize-raw-block.js
10028 /**
10029 * Internal dependencies
10030 */
10031
10032 /**
10033 * @typedef {Object} Options Serialization options.
10034 * @property {boolean} [isCommentDelimited=true] Whether to output HTML comments around blocks.
10035 */
10036
10037 /** @typedef {import("./").WPRawBlock} WPRawBlock */
10038
10039 /**
10040 * Serializes a block node into the native HTML-comment-powered block format.
10041 * CAVEAT: This function is intended for re-serializing blocks as parsed by
10042 * valid parsers and skips any validation steps. This is NOT a generic
10043 * serialization function for in-memory blocks. For most purposes, see the
10044 * following functions available in the `@wordpress/blocks` package:
10045 *
10046 * @see serializeBlock
10047 * @see serialize
10048 *
10049 * For more on the format of block nodes as returned by valid parsers:
10050 *
10051 * @see `@wordpress/block-serialization-default-parser` package
10052 * @see `@wordpress/block-serialization-spec-parser` package
10053 *
10054 * @param {WPRawBlock} rawBlock A block node as returned by a valid parser.
10055 * @param {Options} [options={}] Serialization options.
10056 *
10057 * @return {string} An HTML string representing a block.
10058 */
10059
10060 function serializeRawBlock(rawBlock) {
10061 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10062 const {
10063 isCommentDelimited = true
10064 } = options;
10065 const {
10066 blockName,
10067 attrs = {},
10068 innerBlocks = [],
10069 innerContent = []
10070 } = rawBlock;
10071 let childIndex = 0;
10072 const content = innerContent.map(item => // `null` denotes a nested block, otherwise we have an HTML fragment.
10073 item !== null ? item : serializeRawBlock(innerBlocks[childIndex++], options)).join('\n').replace(/\n+/g, '\n').trim();
10074 return isCommentDelimited ? getCommentDelimitedContent(blockName, attrs, content) : content;
10075 }
10076
10077 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/serializer.js
10078
10079
10080 /**
10081 * External dependencies
10082 */
10083
10084 /**
10085 * WordPress dependencies
10086 */
10087
10088
10089
10090
10091
10092 /**
10093 * Internal dependencies
10094 */
10095
10096
10097
10098
10099 /** @typedef {import('./parser').WPBlock} WPBlock */
10100
10101 /**
10102 * @typedef {Object} WPBlockSerializationOptions Serialization Options.
10103 *
10104 * @property {boolean} isInnerBlocks Whether we are serializing inner blocks.
10105 */
10106
10107 /**
10108 * Returns the block's default classname from its name.
10109 *
10110 * @param {string} blockName The block name.
10111 *
10112 * @return {string} The block's default class.
10113 */
10114
10115 function getBlockDefaultClassName(blockName) {
10116 // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
10117 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10118 const className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10119 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockDefaultClassName', className, blockName);
10120 }
10121 /**
10122 * Returns the block's default menu item classname from its name.
10123 *
10124 * @param {string} blockName The block name.
10125 *
10126 * @return {string} The block's default menu item class.
10127 */
10128
10129 function getBlockMenuDefaultClassName(blockName) {
10130 // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
10131 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
10132 const className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
10133 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockMenuDefaultClassName', className, blockName);
10134 }
10135 const blockPropsProvider = {};
10136 const innerBlocksPropsProvider = {};
10137 /**
10138 * Call within a save function to get the props for the block wrapper.
10139 *
10140 * @param {Object} props Optional. Props to pass to the element.
10141 */
10142
10143 function getBlockProps() {
10144 let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
10145 const {
10146 blockType,
10147 attributes
10148 } = blockPropsProvider;
10149 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...props
10150 }, blockType, attributes);
10151 }
10152 /**
10153 * Call within a save function to get the props for the inner blocks wrapper.
10154 *
10155 * @param {Object} props Optional. Props to pass to the element.
10156 */
10157
10158 function getInnerBlocksProps() {
10159 let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
10160 const {
10161 innerBlocks
10162 } = innerBlocksPropsProvider; // Value is an array of blocks, so defer to block serializer.
10163
10164 const html = serialize(innerBlocks, {
10165 isInnerBlocks: true
10166 }); // Use special-cased raw HTML tag to avoid default escaping.
10167
10168 const children = (0,external_wp_element_namespaceObject.createElement)(external_wp_element_namespaceObject.RawHTML, null, html);
10169 return { ...props,
10170 children
10171 };
10172 }
10173 /**
10174 * Given a block type containing a save render implementation and attributes, returns the
10175 * enhanced element to be saved or string when raw HTML expected.
10176 *
10177 * @param {string|Object} blockTypeOrName Block type or name.
10178 * @param {Object} attributes Block attributes.
10179 * @param {?Array} innerBlocks Nested blocks.
10180 *
10181 * @return {Object|string} Save element or raw HTML string.
10182 */
10183
10184 function getSaveElement(blockTypeOrName, attributes) {
10185 let innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
10186 const blockType = normalizeBlockType(blockTypeOrName);
10187 let {
10188 save
10189 } = blockType; // Component classes are unsupported for save since serialization must
10190 // occur synchronously. For improved interoperability with higher-order
10191 // components which often return component class, emulate basic support.
10192
10193 if (save.prototype instanceof external_wp_element_namespaceObject.Component) {
10194 const instance = new save({
10195 attributes
10196 });
10197 save = instance.render.bind(instance);
10198 }
10199
10200 blockPropsProvider.blockType = blockType;
10201 blockPropsProvider.attributes = attributes;
10202 innerBlocksPropsProvider.innerBlocks = innerBlocks;
10203 let element = save({
10204 attributes,
10205 innerBlocks
10206 });
10207
10208 if (element !== null && typeof element === 'object' && (0,external_wp_hooks_namespaceObject.hasFilter)('blocks.getSaveContent.extraProps') && !(blockType.apiVersion > 1)) {
10209 /**
10210 * Filters the props applied to the block save result element.
10211 *
10212 * @param {Object} props Props applied to save element.
10213 * @param {WPBlock} blockType Block type definition.
10214 * @param {Object} attributes Block attributes.
10215 */
10216 const props = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...element.props
10217 }, blockType, attributes);
10218
10219 if (!external_wp_isShallowEqual_default()(props, element.props)) {
10220 element = (0,external_wp_element_namespaceObject.cloneElement)(element, props);
10221 }
10222 }
10223 /**
10224 * Filters the save result of a block during serialization.
10225 *
10226 * @param {WPElement} element Block save result.
10227 * @param {WPBlock} blockType Block type definition.
10228 * @param {Object} attributes Block attributes.
10229 */
10230
10231
10232 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveElement', element, blockType, attributes);
10233 }
10234 /**
10235 * Given a block type containing a save render implementation and attributes, returns the
10236 * static markup to be saved.
10237 *
10238 * @param {string|Object} blockTypeOrName Block type or name.
10239 * @param {Object} attributes Block attributes.
10240 * @param {?Array} innerBlocks Nested blocks.
10241 *
10242 * @return {string} Save content.
10243 */
10244
10245 function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
10246 const blockType = normalizeBlockType(blockTypeOrName);
10247 return (0,external_wp_element_namespaceObject.renderToString)(getSaveElement(blockType, attributes, innerBlocks));
10248 }
10249 /**
10250 * Returns attributes which are to be saved and serialized into the block
10251 * comment delimiter.
10252 *
10253 * When a block exists in memory it contains as its attributes both those
10254 * parsed the block comment delimiter _and_ those which matched from the
10255 * contents of the block.
10256 *
10257 * This function returns only those attributes which are needed to persist and
10258 * which cannot be matched from the block content.
10259 *
10260 * @param {Object<string,*>} blockType Block type.
10261 * @param {Object<string,*>} attributes Attributes from in-memory block data.
10262 *
10263 * @return {Object<string,*>} Subset of attributes for comment serialization.
10264 */
10265
10266 function getCommentAttributes(blockType, attributes) {
10267 return (0,external_lodash_namespaceObject.reduce)(blockType.attributes, (accumulator, attributeSchema, key) => {
10268 const value = attributes[key]; // Ignore undefined values.
10269
10270 if (undefined === value) {
10271 return accumulator;
10272 } // Ignore all attributes but the ones with an "undefined" source
10273 // "undefined" source refers to attributes saved in the block comment.
10274
10275
10276 if (attributeSchema.source !== undefined) {
10277 return accumulator;
10278 } // Ignore default value.
10279
10280
10281 if ('default' in attributeSchema && attributeSchema.default === value) {
10282 return accumulator;
10283 } // Otherwise, include in comment set.
10284
10285
10286 accumulator[key] = value;
10287 return accumulator;
10288 }, {});
10289 }
10290 /**
10291 * Given an attributes object, returns a string in the serialized attributes
10292 * format prepared for post content.
10293 *
10294 * @param {Object} attributes Attributes object.
10295 *
10296 * @return {string} Serialized attributes.
10297 */
10298
10299 function serializeAttributes(attributes) {
10300 return JSON.stringify(attributes) // Don't break HTML comments.
10301 .replace(/--/g, '\\u002d\\u002d') // Don't break non-standard-compliant tools.
10302 .replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026') // Bypass server stripslashes behavior which would unescape stringify's
10303 // escaping of quotation mark.
10304 //
10305 // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
10306 .replace(/\\"/g, '\\u0022');
10307 }
10308 /**
10309 * Given a block object, returns the Block's Inner HTML markup.
10310 *
10311 * @param {Object} block Block instance.
10312 *
10313 * @return {string} HTML.
10314 */
10315
10316 function getBlockInnerHTML(block) {
10317 // If block was parsed as invalid or encounters an error while generating
10318 // save content, use original content instead to avoid content loss. If a
10319 // block contains nested content, exempt it from this condition because we
10320 // otherwise have no access to its original content and content loss would
10321 // still occur.
10322 let saveContent = block.originalContent;
10323
10324 if (block.isValid || block.innerBlocks.length) {
10325 try {
10326 saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
10327 } catch (error) {}
10328 }
10329
10330 return saveContent;
10331 }
10332 /**
10333 * Returns the content of a block, including comment delimiters.
10334 *
10335 * @param {string} rawBlockName Block name.
10336 * @param {Object} attributes Block attributes.
10337 * @param {string} content Block save content.
10338 *
10339 * @return {string} Comment-delimited block content.
10340 */
10341
10342 function getCommentDelimitedContent(rawBlockName, attributes, content) {
10343 const serializedAttributes = !(0,external_lodash_namespaceObject.isEmpty)(attributes) ? serializeAttributes(attributes) + ' ' : ''; // Strip core blocks of their namespace prefix.
10344
10345 const blockName = rawBlockName !== null && rawBlockName !== void 0 && rawBlockName.startsWith('core/') ? rawBlockName.slice(5) : rawBlockName; // @todo make the `wp:` prefix potentially configurable.
10346
10347 if (!content) {
10348 return `<!-- wp:${blockName} ${serializedAttributes}/-->`;
10349 }
10350
10351 return `<!-- wp:${blockName} ${serializedAttributes}-->\n` + content + `\n<!-- /wp:${blockName} -->`;
10352 }
10353 /**
10354 * Returns the content of a block, including comment delimiters, determining
10355 * serialized attributes and content form from the current state of the block.
10356 *
10357 * @param {WPBlock} block Block instance.
10358 * @param {WPBlockSerializationOptions} options Serialization options.
10359 *
10360 * @return {string} Serialized block.
10361 */
10362
10363 function serializeBlock(block) {
10364 let {
10365 isInnerBlocks = false
10366 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10367
10368 if (!block.isValid && block.__unstableBlockSource) {
10369 return serializeRawBlock(block.__unstableBlockSource);
10370 }
10371
10372 const blockName = block.name;
10373 const saveContent = getBlockInnerHTML(block);
10374
10375 if (blockName === getUnregisteredTypeHandlerName() || !isInnerBlocks && blockName === getFreeformContentHandlerName()) {
10376 return saveContent;
10377 }
10378
10379 const blockType = registration_getBlockType(blockName);
10380
10381 if (!blockType) {
10382 return saveContent;
10383 }
10384
10385 const saveAttributes = getCommentAttributes(blockType, block.attributes);
10386 return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
10387 }
10388 function __unstableSerializeAndClean(blocks) {
10389 // A single unmodified default block is assumed to
10390 // be equivalent to an empty post.
10391 if (blocks.length === 1 && isUnmodifiedDefaultBlock(blocks[0])) {
10392 blocks = [];
10393 }
10394
10395 let content = serialize(blocks); // For compatibility, treat a post consisting of a
10396 // single freeform block as legacy content and apply
10397 // pre-block-editor removep'd content formatting.
10398
10399 if (blocks.length === 1 && blocks[0].name === getFreeformContentHandlerName()) {
10400 content = (0,external_wp_autop_namespaceObject.removep)(content);
10401 }
10402
10403 return content;
10404 }
10405 /**
10406 * Takes a block or set of blocks and returns the serialized post content.
10407 *
10408 * @param {Array} blocks Block(s) to serialize.
10409 * @param {WPBlockSerializationOptions} options Serialization options.
10410 *
10411 * @return {string} The post content.
10412 */
10413
10414 function serialize(blocks, options) {
10415 return (0,external_lodash_namespaceObject.castArray)(blocks).map(block => serializeBlock(block, options)).join('\n\n');
10416 }
10417
10418 ;// CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/index.js
10419 /**
10420 * generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
10421 * do not edit
10422 */
10423 var namedCharRefs = {
10424 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"
10425 };
10426
10427 var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
10428 var CHARCODE = /^#([0-9]+)$/;
10429 var NAMED = /^([A-Za-z0-9]+)$/;
10430 var EntityParser = /** @class */ (function () {
10431 function EntityParser(named) {
10432 this.named = named;
10433 }
10434 EntityParser.prototype.parse = function (entity) {
10435 if (!entity) {
10436 return;
10437 }
10438 var matches = entity.match(HEXCHARCODE);
10439 if (matches) {
10440 return String.fromCharCode(parseInt(matches[1], 16));
10441 }
10442 matches = entity.match(CHARCODE);
10443 if (matches) {
10444 return String.fromCharCode(parseInt(matches[1], 10));
10445 }
10446 matches = entity.match(NAMED);
10447 if (matches) {
10448 return this.named[matches[1]];
10449 }
10450 };
10451 return EntityParser;
10452 }());
10453
10454 var WSP = /[\t\n\f ]/;
10455 var ALPHA = /[A-Za-z]/;
10456 var CRLF = /\r\n?/g;
10457 function isSpace(char) {
10458 return WSP.test(char);
10459 }
10460 function isAlpha(char) {
10461 return ALPHA.test(char);
10462 }
10463 function preprocessInput(input) {
10464 return input.replace(CRLF, '\n');
10465 }
10466
10467 var EventedTokenizer = /** @class */ (function () {
10468 function EventedTokenizer(delegate, entityParser) {
10469 this.delegate = delegate;
10470 this.entityParser = entityParser;
10471 this.state = "beforeData" /* beforeData */;
10472 this.line = -1;
10473 this.column = -1;
10474 this.input = '';
10475 this.index = -1;
10476 this.tagNameBuffer = '';
10477 this.states = {
10478 beforeData: function () {
10479 var char = this.peek();
10480 if (char === '<') {
10481 this.transitionTo("tagOpen" /* tagOpen */);
10482 this.markTagStart();
10483 this.consume();
10484 }
10485 else {
10486 if (char === '\n') {
10487 var tag = this.tagNameBuffer.toLowerCase();
10488 if (tag === 'pre' || tag === 'textarea') {
10489 this.consume();
10490 }
10491 }
10492 this.transitionTo("data" /* data */);
10493 this.delegate.beginData();
10494 }
10495 },
10496 data: function () {
10497 var char = this.peek();
10498 if (char === '<') {
10499 this.delegate.finishData();
10500 this.transitionTo("tagOpen" /* tagOpen */);
10501 this.markTagStart();
10502 this.consume();
10503 }
10504 else if (char === '&') {
10505 this.consume();
10506 this.delegate.appendToData(this.consumeCharRef() || '&');
10507 }
10508 else {
10509 this.consume();
10510 this.delegate.appendToData(char);
10511 }
10512 },
10513 tagOpen: function () {
10514 var char = this.consume();
10515 if (char === '!') {
10516 this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
10517 }
10518 else if (char === '/') {
10519 this.transitionTo("endTagOpen" /* endTagOpen */);
10520 }
10521 else if (char === '@' || char === ':' || isAlpha(char)) {
10522 this.transitionTo("tagName" /* tagName */);
10523 this.tagNameBuffer = '';
10524 this.delegate.beginStartTag();
10525 this.appendToTagName(char);
10526 }
10527 },
10528 markupDeclarationOpen: function () {
10529 var char = this.consume();
10530 if (char === '-' && this.input.charAt(this.index) === '-') {
10531 this.consume();
10532 this.transitionTo("commentStart" /* commentStart */);
10533 this.delegate.beginComment();
10534 }
10535 },
10536 commentStart: function () {
10537 var char = this.consume();
10538 if (char === '-') {
10539 this.transitionTo("commentStartDash" /* commentStartDash */);
10540 }
10541 else if (char === '>') {
10542 this.delegate.finishComment();
10543 this.transitionTo("beforeData" /* beforeData */);
10544 }
10545 else {
10546 this.delegate.appendToCommentData(char);
10547 this.transitionTo("comment" /* comment */);
10548 }
10549 },
10550 commentStartDash: function () {
10551 var char = this.consume();
10552 if (char === '-') {
10553 this.transitionTo("commentEnd" /* commentEnd */);
10554 }
10555 else if (char === '>') {
10556 this.delegate.finishComment();
10557 this.transitionTo("beforeData" /* beforeData */);
10558 }
10559 else {
10560 this.delegate.appendToCommentData('-');
10561 this.transitionTo("comment" /* comment */);
10562 }
10563 },
10564 comment: function () {
10565 var char = this.consume();
10566 if (char === '-') {
10567 this.transitionTo("commentEndDash" /* commentEndDash */);
10568 }
10569 else {
10570 this.delegate.appendToCommentData(char);
10571 }
10572 },
10573 commentEndDash: function () {
10574 var char = this.consume();
10575 if (char === '-') {
10576 this.transitionTo("commentEnd" /* commentEnd */);
10577 }
10578 else {
10579 this.delegate.appendToCommentData('-' + char);
10580 this.transitionTo("comment" /* comment */);
10581 }
10582 },
10583 commentEnd: function () {
10584 var char = this.consume();
10585 if (char === '>') {
10586 this.delegate.finishComment();
10587 this.transitionTo("beforeData" /* beforeData */);
10588 }
10589 else {
10590 this.delegate.appendToCommentData('--' + char);
10591 this.transitionTo("comment" /* comment */);
10592 }
10593 },
10594 tagName: function () {
10595 var char = this.consume();
10596 if (isSpace(char)) {
10597 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10598 }
10599 else if (char === '/') {
10600 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10601 }
10602 else if (char === '>') {
10603 this.delegate.finishTag();
10604 this.transitionTo("beforeData" /* beforeData */);
10605 }
10606 else {
10607 this.appendToTagName(char);
10608 }
10609 },
10610 beforeAttributeName: function () {
10611 var char = this.peek();
10612 if (isSpace(char)) {
10613 this.consume();
10614 return;
10615 }
10616 else if (char === '/') {
10617 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10618 this.consume();
10619 }
10620 else if (char === '>') {
10621 this.consume();
10622 this.delegate.finishTag();
10623 this.transitionTo("beforeData" /* beforeData */);
10624 }
10625 else if (char === '=') {
10626 this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
10627 this.transitionTo("attributeName" /* attributeName */);
10628 this.delegate.beginAttribute();
10629 this.consume();
10630 this.delegate.appendToAttributeName(char);
10631 }
10632 else {
10633 this.transitionTo("attributeName" /* attributeName */);
10634 this.delegate.beginAttribute();
10635 }
10636 },
10637 attributeName: function () {
10638 var char = this.peek();
10639 if (isSpace(char)) {
10640 this.transitionTo("afterAttributeName" /* afterAttributeName */);
10641 this.consume();
10642 }
10643 else if (char === '/') {
10644 this.delegate.beginAttributeValue(false);
10645 this.delegate.finishAttributeValue();
10646 this.consume();
10647 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10648 }
10649 else if (char === '=') {
10650 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
10651 this.consume();
10652 }
10653 else if (char === '>') {
10654 this.delegate.beginAttributeValue(false);
10655 this.delegate.finishAttributeValue();
10656 this.consume();
10657 this.delegate.finishTag();
10658 this.transitionTo("beforeData" /* beforeData */);
10659 }
10660 else if (char === '"' || char === "'" || char === '<') {
10661 this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
10662 this.consume();
10663 this.delegate.appendToAttributeName(char);
10664 }
10665 else {
10666 this.consume();
10667 this.delegate.appendToAttributeName(char);
10668 }
10669 },
10670 afterAttributeName: function () {
10671 var char = this.peek();
10672 if (isSpace(char)) {
10673 this.consume();
10674 return;
10675 }
10676 else if (char === '/') {
10677 this.delegate.beginAttributeValue(false);
10678 this.delegate.finishAttributeValue();
10679 this.consume();
10680 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10681 }
10682 else if (char === '=') {
10683 this.consume();
10684 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
10685 }
10686 else if (char === '>') {
10687 this.delegate.beginAttributeValue(false);
10688 this.delegate.finishAttributeValue();
10689 this.consume();
10690 this.delegate.finishTag();
10691 this.transitionTo("beforeData" /* beforeData */);
10692 }
10693 else {
10694 this.delegate.beginAttributeValue(false);
10695 this.delegate.finishAttributeValue();
10696 this.transitionTo("attributeName" /* attributeName */);
10697 this.delegate.beginAttribute();
10698 this.consume();
10699 this.delegate.appendToAttributeName(char);
10700 }
10701 },
10702 beforeAttributeValue: function () {
10703 var char = this.peek();
10704 if (isSpace(char)) {
10705 this.consume();
10706 }
10707 else if (char === '"') {
10708 this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
10709 this.delegate.beginAttributeValue(true);
10710 this.consume();
10711 }
10712 else if (char === "'") {
10713 this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
10714 this.delegate.beginAttributeValue(true);
10715 this.consume();
10716 }
10717 else if (char === '>') {
10718 this.delegate.beginAttributeValue(false);
10719 this.delegate.finishAttributeValue();
10720 this.consume();
10721 this.delegate.finishTag();
10722 this.transitionTo("beforeData" /* beforeData */);
10723 }
10724 else {
10725 this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
10726 this.delegate.beginAttributeValue(false);
10727 this.consume();
10728 this.delegate.appendToAttributeValue(char);
10729 }
10730 },
10731 attributeValueDoubleQuoted: function () {
10732 var char = this.consume();
10733 if (char === '"') {
10734 this.delegate.finishAttributeValue();
10735 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
10736 }
10737 else if (char === '&') {
10738 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
10739 }
10740 else {
10741 this.delegate.appendToAttributeValue(char);
10742 }
10743 },
10744 attributeValueSingleQuoted: function () {
10745 var char = this.consume();
10746 if (char === "'") {
10747 this.delegate.finishAttributeValue();
10748 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
10749 }
10750 else if (char === '&') {
10751 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
10752 }
10753 else {
10754 this.delegate.appendToAttributeValue(char);
10755 }
10756 },
10757 attributeValueUnquoted: function () {
10758 var char = this.peek();
10759 if (isSpace(char)) {
10760 this.delegate.finishAttributeValue();
10761 this.consume();
10762 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10763 }
10764 else if (char === '/') {
10765 this.delegate.finishAttributeValue();
10766 this.consume();
10767 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10768 }
10769 else if (char === '&') {
10770 this.consume();
10771 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
10772 }
10773 else if (char === '>') {
10774 this.delegate.finishAttributeValue();
10775 this.consume();
10776 this.delegate.finishTag();
10777 this.transitionTo("beforeData" /* beforeData */);
10778 }
10779 else {
10780 this.consume();
10781 this.delegate.appendToAttributeValue(char);
10782 }
10783 },
10784 afterAttributeValueQuoted: function () {
10785 var char = this.peek();
10786 if (isSpace(char)) {
10787 this.consume();
10788 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10789 }
10790 else if (char === '/') {
10791 this.consume();
10792 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
10793 }
10794 else if (char === '>') {
10795 this.consume();
10796 this.delegate.finishTag();
10797 this.transitionTo("beforeData" /* beforeData */);
10798 }
10799 else {
10800 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10801 }
10802 },
10803 selfClosingStartTag: function () {
10804 var char = this.peek();
10805 if (char === '>') {
10806 this.consume();
10807 this.delegate.markTagAsSelfClosing();
10808 this.delegate.finishTag();
10809 this.transitionTo("beforeData" /* beforeData */);
10810 }
10811 else {
10812 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
10813 }
10814 },
10815 endTagOpen: function () {
10816 var char = this.consume();
10817 if (char === '@' || char === ':' || isAlpha(char)) {
10818 this.transitionTo("tagName" /* tagName */);
10819 this.tagNameBuffer = '';
10820 this.delegate.beginEndTag();
10821 this.appendToTagName(char);
10822 }
10823 }
10824 };
10825 this.reset();
10826 }
10827 EventedTokenizer.prototype.reset = function () {
10828 this.transitionTo("beforeData" /* beforeData */);
10829 this.input = '';
10830 this.index = 0;
10831 this.line = 1;
10832 this.column = 0;
10833 this.delegate.reset();
10834 };
10835 EventedTokenizer.prototype.transitionTo = function (state) {
10836 this.state = state;
10837 };
10838 EventedTokenizer.prototype.tokenize = function (input) {
10839 this.reset();
10840 this.tokenizePart(input);
10841 this.tokenizeEOF();
10842 };
10843 EventedTokenizer.prototype.tokenizePart = function (input) {
10844 this.input += preprocessInput(input);
10845 while (this.index < this.input.length) {
10846 var handler = this.states[this.state];
10847 if (handler !== undefined) {
10848 handler.call(this);
10849 }
10850 else {
10851 throw new Error("unhandled state " + this.state);
10852 }
10853 }
10854 };
10855 EventedTokenizer.prototype.tokenizeEOF = function () {
10856 this.flushData();
10857 };
10858 EventedTokenizer.prototype.flushData = function () {
10859 if (this.state === 'data') {
10860 this.delegate.finishData();
10861 this.transitionTo("beforeData" /* beforeData */);
10862 }
10863 };
10864 EventedTokenizer.prototype.peek = function () {
10865 return this.input.charAt(this.index);
10866 };
10867 EventedTokenizer.prototype.consume = function () {
10868 var char = this.peek();
10869 this.index++;
10870 if (char === '\n') {
10871 this.line++;
10872 this.column = 0;
10873 }
10874 else {
10875 this.column++;
10876 }
10877 return char;
10878 };
10879 EventedTokenizer.prototype.consumeCharRef = function () {
10880 var endIndex = this.input.indexOf(';', this.index);
10881 if (endIndex === -1) {
10882 return;
10883 }
10884 var entity = this.input.slice(this.index, endIndex);
10885 var chars = this.entityParser.parse(entity);
10886 if (chars) {
10887 var count = entity.length;
10888 // consume the entity chars
10889 while (count) {
10890 this.consume();
10891 count--;
10892 }
10893 // consume the `;`
10894 this.consume();
10895 return chars;
10896 }
10897 };
10898 EventedTokenizer.prototype.markTagStart = function () {
10899 this.delegate.tagOpen();
10900 };
10901 EventedTokenizer.prototype.appendToTagName = function (char) {
10902 this.tagNameBuffer += char;
10903 this.delegate.appendToTagName(char);
10904 };
10905 return EventedTokenizer;
10906 }());
10907
10908 var Tokenizer = /** @class */ (function () {
10909 function Tokenizer(entityParser, options) {
10910 if (options === void 0) { options = {}; }
10911 this.options = options;
10912 this.token = null;
10913 this.startLine = 1;
10914 this.startColumn = 0;
10915 this.tokens = [];
10916 this.tokenizer = new EventedTokenizer(this, entityParser);
10917 this._currentAttribute = undefined;
10918 }
10919 Tokenizer.prototype.tokenize = function (input) {
10920 this.tokens = [];
10921 this.tokenizer.tokenize(input);
10922 return this.tokens;
10923 };
10924 Tokenizer.prototype.tokenizePart = function (input) {
10925 this.tokens = [];
10926 this.tokenizer.tokenizePart(input);
10927 return this.tokens;
10928 };
10929 Tokenizer.prototype.tokenizeEOF = function () {
10930 this.tokens = [];
10931 this.tokenizer.tokenizeEOF();
10932 return this.tokens[0];
10933 };
10934 Tokenizer.prototype.reset = function () {
10935 this.token = null;
10936 this.startLine = 1;
10937 this.startColumn = 0;
10938 };
10939 Tokenizer.prototype.current = function () {
10940 var token = this.token;
10941 if (token === null) {
10942 throw new Error('token was unexpectedly null');
10943 }
10944 if (arguments.length === 0) {
10945 return token;
10946 }
10947 for (var i = 0; i < arguments.length; i++) {
10948 if (token.type === arguments[i]) {
10949 return token;
10950 }
10951 }
10952 throw new Error("token type was unexpectedly " + token.type);
10953 };
10954 Tokenizer.prototype.push = function (token) {
10955 this.token = token;
10956 this.tokens.push(token);
10957 };
10958 Tokenizer.prototype.currentAttribute = function () {
10959 return this._currentAttribute;
10960 };
10961 Tokenizer.prototype.addLocInfo = function () {
10962 if (this.options.loc) {
10963 this.current().loc = {
10964 start: {
10965 line: this.startLine,
10966 column: this.startColumn
10967 },
10968 end: {
10969 line: this.tokenizer.line,
10970 column: this.tokenizer.column
10971 }
10972 };
10973 }
10974 this.startLine = this.tokenizer.line;
10975 this.startColumn = this.tokenizer.column;
10976 };
10977 // Data
10978 Tokenizer.prototype.beginData = function () {
10979 this.push({
10980 type: "Chars" /* Chars */,
10981 chars: ''
10982 });
10983 };
10984 Tokenizer.prototype.appendToData = function (char) {
10985 this.current("Chars" /* Chars */).chars += char;
10986 };
10987 Tokenizer.prototype.finishData = function () {
10988 this.addLocInfo();
10989 };
10990 // Comment
10991 Tokenizer.prototype.beginComment = function () {
10992 this.push({
10993 type: "Comment" /* Comment */,
10994 chars: ''
10995 });
10996 };
10997 Tokenizer.prototype.appendToCommentData = function (char) {
10998 this.current("Comment" /* Comment */).chars += char;
10999 };
11000 Tokenizer.prototype.finishComment = function () {
11001 this.addLocInfo();
11002 };
11003 // Tags - basic
11004 Tokenizer.prototype.tagOpen = function () { };
11005 Tokenizer.prototype.beginStartTag = function () {
11006 this.push({
11007 type: "StartTag" /* StartTag */,
11008 tagName: '',
11009 attributes: [],
11010 selfClosing: false
11011 });
11012 };
11013 Tokenizer.prototype.beginEndTag = function () {
11014 this.push({
11015 type: "EndTag" /* EndTag */,
11016 tagName: ''
11017 });
11018 };
11019 Tokenizer.prototype.finishTag = function () {
11020 this.addLocInfo();
11021 };
11022 Tokenizer.prototype.markTagAsSelfClosing = function () {
11023 this.current("StartTag" /* StartTag */).selfClosing = true;
11024 };
11025 // Tags - name
11026 Tokenizer.prototype.appendToTagName = function (char) {
11027 this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
11028 };
11029 // Tags - attributes
11030 Tokenizer.prototype.beginAttribute = function () {
11031 this._currentAttribute = ['', '', false];
11032 };
11033 Tokenizer.prototype.appendToAttributeName = function (char) {
11034 this.currentAttribute()[0] += char;
11035 };
11036 Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
11037 this.currentAttribute()[2] = isQuoted;
11038 };
11039 Tokenizer.prototype.appendToAttributeValue = function (char) {
11040 this.currentAttribute()[1] += char;
11041 };
11042 Tokenizer.prototype.finishAttributeValue = function () {
11043 this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
11044 };
11045 Tokenizer.prototype.reportSyntaxError = function (message) {
11046 this.current().syntaxError = message;
11047 };
11048 return Tokenizer;
11049 }());
11050
11051 function tokenize(input, options) {
11052 var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);
11053 return tokenizer.tokenize(input);
11054 }
11055
11056
11057
11058 ;// CONCATENATED MODULE: external ["wp","deprecated"]
11059 const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
11060 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
11061 ;// CONCATENATED MODULE: external ["wp","htmlEntities"]
11062 const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
11063 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/logger.js
11064 /**
11065 * @typedef LoggerItem
11066 * @property {Function} log Which logger recorded the message
11067 * @property {Array<any>} args White arguments were supplied to the logger
11068 */
11069 function createLogger() {
11070 /**
11071 * Creates a log handler with block validation prefix.
11072 *
11073 * @param {Function} logger Original logger function.
11074 *
11075 * @return {Function} Augmented logger function.
11076 */
11077 function createLogHandler(logger) {
11078 let log = function (message) {
11079 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
11080 args[_key - 1] = arguments[_key];
11081 }
11082
11083 return logger('Block validation: ' + message, ...args);
11084 }; // In test environments, pre-process string substitutions to improve
11085 // readability of error messages. We'd prefer to avoid pulling in this
11086 // dependency in runtime environments, and it can be dropped by a combo
11087 // of Webpack env substitution + UglifyJS dead code elimination.
11088
11089
11090 if (false) {}
11091
11092 return log;
11093 }
11094
11095 return {
11096 // eslint-disable-next-line no-console
11097 error: createLogHandler(console.error),
11098 // eslint-disable-next-line no-console
11099 warning: createLogHandler(console.warn),
11100
11101 getItems() {
11102 return [];
11103 }
11104
11105 };
11106 }
11107 function createQueuedLogger() {
11108 /**
11109 * The list of enqueued log actions to print.
11110 *
11111 * @type {Array<LoggerItem>}
11112 */
11113 const queue = [];
11114 const logger = createLogger();
11115 return {
11116 error() {
11117 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
11118 args[_key2] = arguments[_key2];
11119 }
11120
11121 queue.push({
11122 log: logger.error,
11123 args
11124 });
11125 },
11126
11127 warning() {
11128 for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
11129 args[_key3] = arguments[_key3];
11130 }
11131
11132 queue.push({
11133 log: logger.warning,
11134 args
11135 });
11136 },
11137
11138 getItems() {
11139 return queue;
11140 }
11141
11142 };
11143 }
11144
11145 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/index.js
11146 /**
11147 * External dependencies
11148 */
11149
11150
11151 /**
11152 * WordPress dependencies
11153 */
11154
11155
11156
11157 /**
11158 * Internal dependencies
11159 */
11160
11161
11162
11163
11164
11165 /** @typedef {import('../parser').WPBlock} WPBlock */
11166
11167 /** @typedef {import('../registration').WPBlockType} WPBlockType */
11168
11169 /** @typedef {import('./logger').LoggerItem} LoggerItem */
11170
11171 const identity = x => x;
11172 /**
11173 * Globally matches any consecutive whitespace
11174 *
11175 * @type {RegExp}
11176 */
11177
11178
11179 const REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
11180 /**
11181 * Matches a string containing only whitespace
11182 *
11183 * @type {RegExp}
11184 */
11185
11186 const REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
11187 /**
11188 * Matches a CSS URL type value
11189 *
11190 * @type {RegExp}
11191 */
11192
11193 const REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
11194 /**
11195 * Boolean attributes are attributes whose presence as being assigned is
11196 * meaningful, even if only empty.
11197 *
11198 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
11199 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11200 *
11201 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11202 * .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
11203 * .reduce( ( result, tr ) => Object.assign( result, {
11204 * [ tr.firstChild.textContent.trim() ]: true
11205 * } ), {} ) ).sort();
11206 *
11207 * @type {Array}
11208 */
11209
11210 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'];
11211 /**
11212 * Enumerated attributes are attributes which must be of a specific value form.
11213 * Like boolean attributes, these are meaningful if specified, even if not of a
11214 * valid enumerated value.
11215 *
11216 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
11217 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
11218 *
11219 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
11220 * .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
11221 * .reduce( ( result, tr ) => Object.assign( result, {
11222 * [ tr.firstChild.textContent.trim() ]: true
11223 * } ), {} ) ).sort();
11224 *
11225 * @type {Array}
11226 */
11227
11228 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'];
11229 /**
11230 * Meaningful attributes are those who cannot be safely ignored when omitted in
11231 * one HTML markup string and not another.
11232 *
11233 * @type {Array}
11234 */
11235
11236 const MEANINGFUL_ATTRIBUTES = [...BOOLEAN_ATTRIBUTES, ...ENUMERATED_ATTRIBUTES];
11237 /**
11238 * Array of functions which receive a text string on which to apply normalizing
11239 * behavior for consideration in text token equivalence, carefully ordered from
11240 * least-to-most expensive operations.
11241 *
11242 * @type {Array}
11243 */
11244
11245 const TEXT_NORMALIZATIONS = [identity, getTextWithCollapsedWhitespace];
11246 /**
11247 * Regular expression matching a named character reference. In lieu of bundling
11248 * a full set of references, the pattern covers the minimal necessary to test
11249 * positively against the full set.
11250 *
11251 * "The ampersand must be followed by one of the names given in the named
11252 * character references section, using the same case."
11253 *
11254 * Tested aginst "12.5 Named character references":
11255 *
11256 * ```
11257 * const references = Array.from( document.querySelectorAll(
11258 * '#named-character-references-table tr[id^=entity-] td:first-child'
11259 * ) ).map( ( code ) => code.textContent )
11260 * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
11261 * ```
11262 *
11263 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11264 * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
11265 *
11266 * @type {RegExp}
11267 */
11268
11269 const REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
11270 /**
11271 * Regular expression matching a decimal character reference.
11272 *
11273 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
11274 * followed by one or more ASCII digits, representing a base-ten integer"
11275 *
11276 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11277 *
11278 * @type {RegExp}
11279 */
11280
11281 const REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
11282 /**
11283 * Regular expression matching a hexadecimal character reference.
11284 *
11285 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
11286 * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
11287 * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
11288 * one or more ASCII hex digits, representing a hexadecimal integer"
11289 *
11290 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
11291 *
11292 * @type {RegExp}
11293 */
11294
11295 const REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
11296 /**
11297 * Returns true if the given string is a valid character reference segment, or
11298 * false otherwise. The text should be stripped of `&` and `;` demarcations.
11299 *
11300 * @param {string} text Text to test.
11301 *
11302 * @return {boolean} Whether text is valid character reference.
11303 */
11304
11305 function isValidCharacterReference(text) {
11306 return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
11307 }
11308 /**
11309 * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
11310 * implementation of `decodeEntities` from `html-entities`, in order to avoid
11311 * bundling a massive named character reference.
11312 *
11313 * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts
11314 */
11315
11316 class DecodeEntityParser {
11317 /**
11318 * Returns a substitute string for an entity string sequence between `&`
11319 * and `;`, or undefined if no substitution should occur.
11320 *
11321 * @param {string} entity Entity fragment discovered in HTML.
11322 *
11323 * @return {?string} Entity substitute value.
11324 */
11325 parse(entity) {
11326 if (isValidCharacterReference(entity)) {
11327 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)('&' + entity + ';');
11328 }
11329 }
11330
11331 }
11332 /**
11333 * Given a specified string, returns an array of strings split by consecutive
11334 * whitespace, ignoring leading or trailing whitespace.
11335 *
11336 * @param {string} text Original text.
11337 *
11338 * @return {string[]} Text pieces split on whitespace.
11339 */
11340
11341 function getTextPiecesSplitOnWhitespace(text) {
11342 return text.trim().split(REGEXP_WHITESPACE);
11343 }
11344 /**
11345 * Given a specified string, returns a new trimmed string where all consecutive
11346 * whitespace is collapsed to a single space.
11347 *
11348 * @param {string} text Original text.
11349 *
11350 * @return {string} Trimmed text with consecutive whitespace collapsed.
11351 */
11352
11353 function getTextWithCollapsedWhitespace(text) {
11354 // This is an overly simplified whitespace comparison. The specification is
11355 // more prescriptive of whitespace behavior in inline and block contexts.
11356 //
11357 // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
11358 return getTextPiecesSplitOnWhitespace(text).join(' ');
11359 }
11360 /**
11361 * Returns attribute pairs of the given StartTag token, including only pairs
11362 * where the value is non-empty or the attribute is a boolean attribute, an
11363 * enumerated attribute, or a custom data- attribute.
11364 *
11365 * @see MEANINGFUL_ATTRIBUTES
11366 *
11367 * @param {Object} token StartTag token.
11368 *
11369 * @return {Array[]} Attribute pairs.
11370 */
11371
11372 function getMeaningfulAttributePairs(token) {
11373 return token.attributes.filter(pair => {
11374 const [key, value] = pair;
11375 return value || key.indexOf('data-') === 0 || (0,external_lodash_namespaceObject.includes)(MEANINGFUL_ATTRIBUTES, key);
11376 });
11377 }
11378 /**
11379 * Returns true if two text tokens (with `chars` property) are equivalent, or
11380 * false otherwise.
11381 *
11382 * @param {Object} actual Actual token.
11383 * @param {Object} expected Expected token.
11384 * @param {Object} logger Validation logger object.
11385 *
11386 * @return {boolean} Whether two text tokens are equivalent.
11387 */
11388
11389 function isEquivalentTextTokens(actual, expected) {
11390 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
11391 // This function is intentionally written as syntactically "ugly" as a hot
11392 // path optimization. Text is progressively normalized in order from least-
11393 // to-most operationally expensive, until the earliest point at which text
11394 // can be confidently inferred as being equal.
11395 let actualChars = actual.chars;
11396 let expectedChars = expected.chars;
11397
11398 for (let i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
11399 const normalize = TEXT_NORMALIZATIONS[i];
11400 actualChars = normalize(actualChars);
11401 expectedChars = normalize(expectedChars);
11402
11403 if (actualChars === expectedChars) {
11404 return true;
11405 }
11406 }
11407
11408 logger.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
11409 return false;
11410 }
11411 /**
11412 * Given a CSS length value, returns a normalized CSS length value for strict equality
11413 * comparison.
11414 *
11415 * @param {string} value CSS length value.
11416 *
11417 * @return {string} Normalized CSS length value.
11418 */
11419
11420 function getNormalizedLength(value) {
11421 if (0 === parseFloat(value)) {
11422 return '0';
11423 } // Normalize strings with floats to always include a leading zero.
11424
11425
11426 if (value.indexOf('.') === 0) {
11427 return '0' + value;
11428 }
11429
11430 return value;
11431 }
11432 /**
11433 * Given a style value, returns a normalized style value for strict equality
11434 * comparison.
11435 *
11436 * @param {string} value Style value.
11437 *
11438 * @return {string} Normalized style value.
11439 */
11440
11441 function getNormalizedStyleValue(value) {
11442 const textPieces = getTextPiecesSplitOnWhitespace(value);
11443 const normalizedPieces = textPieces.map(getNormalizedLength);
11444 const result = normalizedPieces.join(' ');
11445 return result // Normalize URL type to omit whitespace or quotes.
11446 .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
11447 }
11448 /**
11449 * Given a style attribute string, returns an object of style properties.
11450 *
11451 * @param {string} text Style attribute.
11452 *
11453 * @return {Object} Style properties.
11454 */
11455
11456 function getStyleProperties(text) {
11457 const pairs = text // Trim ending semicolon (avoid including in split)
11458 .replace(/;?\s*$/, '') // Split on property assignment.
11459 .split(';') // For each property assignment...
11460 .map(style => {
11461 // ...split further into key-value pairs.
11462 const [key, ...valueParts] = style.split(':');
11463 const value = valueParts.join(':');
11464 return [key.trim(), getNormalizedStyleValue(value.trim())];
11465 });
11466 return Object.fromEntries(pairs);
11467 }
11468 /**
11469 * Attribute-specific equality handlers
11470 *
11471 * @type {Object}
11472 */
11473
11474 const isEqualAttributesOfName = {
11475 class: (actual, expected) => {
11476 // Class matches if members are the same, even if out of order or
11477 // superfluous whitespace between.
11478 const [actualPieces, expectedPieces] = [actual, expected].map(getTextPiecesSplitOnWhitespace);
11479 const actualDiff = actualPieces.filter(c => !expectedPieces.includes(c));
11480 const expectedDiff = expectedPieces.filter(c => !actualPieces.includes(c));
11481 return actualDiff.length === 0 && expectedDiff.length === 0;
11482 },
11483 style: (actual, expected) => {
11484 return (0,external_lodash_namespaceObject.isEqual)(...[actual, expected].map(getStyleProperties));
11485 },
11486 // For each boolean attribute, mere presence of attribute in both is enough
11487 // to assume equivalence.
11488 ...Object.fromEntries(BOOLEAN_ATTRIBUTES.map(attribute => [attribute, () => true]))
11489 };
11490 /**
11491 * Given two sets of attribute tuples, returns true if the attribute sets are
11492 * equivalent.
11493 *
11494 * @param {Array[]} actual Actual attributes tuples.
11495 * @param {Array[]} expected Expected attributes tuples.
11496 * @param {Object} logger Validation logger object.
11497 *
11498 * @return {boolean} Whether attributes are equivalent.
11499 */
11500
11501 function isEqualTagAttributePairs(actual, expected) {
11502 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
11503
11504 // Attributes is tokenized as tuples. Their lengths should match. This also
11505 // avoids us needing to check both attributes sets, since if A has any keys
11506 // which do not exist in B, we know the sets to be different.
11507 if (actual.length !== expected.length) {
11508 logger.warning('Expected attributes %o, instead saw %o.', expected, actual);
11509 return false;
11510 } // Attributes are not guaranteed to occur in the same order. For validating
11511 // actual attributes, first convert the set of expected attribute values to
11512 // an object, for lookup by key.
11513
11514
11515 const expectedAttributes = {};
11516
11517 for (let i = 0; i < expected.length; i++) {
11518 expectedAttributes[expected[i][0].toLowerCase()] = expected[i][1];
11519 }
11520
11521 for (let i = 0; i < actual.length; i++) {
11522 const [name, actualValue] = actual[i];
11523 const nameLower = name.toLowerCase(); // As noted above, if missing member in B, assume different.
11524
11525 if (!expectedAttributes.hasOwnProperty(nameLower)) {
11526 logger.warning('Encountered unexpected attribute `%s`.', name);
11527 return false;
11528 }
11529
11530 const expectedValue = expectedAttributes[nameLower];
11531 const isEqualAttributes = isEqualAttributesOfName[nameLower];
11532
11533 if (isEqualAttributes) {
11534 // Defer custom attribute equality handling.
11535 if (!isEqualAttributes(actualValue, expectedValue)) {
11536 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11537 return false;
11538 }
11539 } else if (actualValue !== expectedValue) {
11540 // Otherwise strict inequality should bail.
11541 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
11542 return false;
11543 }
11544 }
11545
11546 return true;
11547 }
11548 /**
11549 * Token-type-specific equality handlers
11550 *
11551 * @type {Object}
11552 */
11553
11554 const isEqualTokensOfType = {
11555 StartTag: function (actual, expected) {
11556 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
11557
11558 if (actual.tagName !== expected.tagName && // Optimization: Use short-circuit evaluation to defer case-
11559 // insensitive check on the assumption that the majority case will
11560 // have exactly equal tag names.
11561 actual.tagName.toLowerCase() !== expected.tagName.toLowerCase()) {
11562 logger.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
11563 return false;
11564 }
11565
11566 return isEqualTagAttributePairs(...[actual, expected].map(getMeaningfulAttributePairs), logger);
11567 },
11568 Chars: isEquivalentTextTokens,
11569 Comment: isEquivalentTextTokens
11570 };
11571 /**
11572 * Given an array of tokens, returns the first token which is not purely
11573 * whitespace.
11574 *
11575 * Mutates the tokens array.
11576 *
11577 * @param {Object[]} tokens Set of tokens to search.
11578 *
11579 * @return {Object} Next non-whitespace token.
11580 */
11581
11582 function getNextNonWhitespaceToken(tokens) {
11583 let token;
11584
11585 while (token = tokens.shift()) {
11586 if (token.type !== 'Chars') {
11587 return token;
11588 }
11589
11590 if (!REGEXP_ONLY_WHITESPACE.test(token.chars)) {
11591 return token;
11592 }
11593 }
11594 }
11595 /**
11596 * Tokenize an HTML string, gracefully handling any errors thrown during
11597 * underlying tokenization.
11598 *
11599 * @param {string} html HTML string to tokenize.
11600 * @param {Object} logger Validation logger object.
11601 *
11602 * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error
11603 */
11604
11605 function getHTMLTokens(html) {
11606 let logger = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : createLogger();
11607
11608 try {
11609 return new Tokenizer(new DecodeEntityParser()).tokenize(html);
11610 } catch (e) {
11611 logger.warning('Malformed HTML detected: %s', html);
11612 }
11613
11614 return null;
11615 }
11616 /**
11617 * Returns true if the next HTML token closes the current token.
11618 *
11619 * @param {Object} currentToken Current token to compare with.
11620 * @param {Object|undefined} nextToken Next token to compare against.
11621 *
11622 * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise
11623 */
11624
11625
11626 function isClosedByToken(currentToken, nextToken) {
11627 // Ensure this is a self closed token.
11628 if (!currentToken.selfClosing) {
11629 return false;
11630 } // Check token names and determine if nextToken is the closing tag for currentToken.
11631
11632
11633 if (nextToken && nextToken.tagName === currentToken.tagName && nextToken.type === 'EndTag') {
11634 return true;
11635 }
11636
11637 return false;
11638 }
11639 /**
11640 * Returns true if the given HTML strings are effectively equivalent, or
11641 * false otherwise. Invalid HTML is not considered equivalent, even if the
11642 * strings directly match.
11643 *
11644 * @param {string} actual Actual HTML string.
11645 * @param {string} expected Expected HTML string.
11646 * @param {Object} logger Validation logger object.
11647 *
11648 * @return {boolean} Whether HTML strings are equivalent.
11649 */
11650
11651 function isEquivalentHTML(actual, expected) {
11652 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
11653
11654 // Short-circuit if markup is identical.
11655 if (actual === expected) {
11656 return true;
11657 } // Tokenize input content and reserialized save content.
11658
11659
11660 const [actualTokens, expectedTokens] = [actual, expected].map(html => getHTMLTokens(html, logger)); // If either is malformed then stop comparing - the strings are not equivalent.
11661
11662 if (!actualTokens || !expectedTokens) {
11663 return false;
11664 }
11665
11666 let actualToken, expectedToken;
11667
11668 while (actualToken = getNextNonWhitespaceToken(actualTokens)) {
11669 expectedToken = getNextNonWhitespaceToken(expectedTokens); // Inequal if exhausted all expected tokens.
11670
11671 if (!expectedToken) {
11672 logger.warning('Expected end of content, instead saw %o.', actualToken);
11673 return false;
11674 } // Inequal if next non-whitespace token of each set are not same type.
11675
11676
11677 if (actualToken.type !== expectedToken.type) {
11678 logger.warning('Expected token of type `%s` (%o), instead saw `%s` (%o).', expectedToken.type, expectedToken, actualToken.type, actualToken);
11679 return false;
11680 } // Defer custom token type equality handling, otherwise continue and
11681 // assume as equal.
11682
11683
11684 const isEqualTokens = isEqualTokensOfType[actualToken.type];
11685
11686 if (isEqualTokens && !isEqualTokens(actualToken, expectedToken, logger)) {
11687 return false;
11688 } // Peek at the next tokens (actual and expected) to see if they close
11689 // a self-closing tag.
11690
11691
11692 if (isClosedByToken(actualToken, expectedTokens[0])) {
11693 // Consume the next expected token that closes the current actual
11694 // self-closing token.
11695 getNextNonWhitespaceToken(expectedTokens);
11696 } else if (isClosedByToken(expectedToken, actualTokens[0])) {
11697 // Consume the next actual token that closes the current expected
11698 // self-closing token.
11699 getNextNonWhitespaceToken(actualTokens);
11700 }
11701 }
11702
11703 if (expectedToken = getNextNonWhitespaceToken(expectedTokens)) {
11704 // If any non-whitespace tokens remain in expected token set, this
11705 // indicates inequality.
11706 logger.warning('Expected %o, instead saw end of content.', expectedToken);
11707 return false;
11708 }
11709
11710 return true;
11711 }
11712 /**
11713 * Returns an object with `isValid` property set to `true` if the parsed block
11714 * is valid given the input content. A block is considered valid if, when serialized
11715 * with assumed attributes, the content matches the original value. If block is
11716 * invalid, this function returns all validations issues as well.
11717 *
11718 * @param {string|Object} blockTypeOrName Block type.
11719 * @param {Object} attributes Parsed block attributes.
11720 * @param {string} originalBlockContent Original block content.
11721 * @param {Object} logger Validation logger object.
11722 *
11723 * @return {Object} Whether block is valid and contains validation messages.
11724 */
11725
11726 /**
11727 * Returns an object with `isValid` property set to `true` if the parsed block
11728 * is valid given the input content. A block is considered valid if, when serialized
11729 * with assumed attributes, the content matches the original value. If block is
11730 * invalid, this function returns all validations issues as well.
11731 *
11732 * @param {WPBlock} block block object.
11733 * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.
11734 *
11735 * @return {[boolean,Array<LoggerItem>]} validation results.
11736 */
11737
11738 function validateBlock(block) {
11739 let blockTypeOrName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : block.name;
11740 const isFallbackBlock = block.name === getFreeformContentHandlerName() || block.name === getUnregisteredTypeHandlerName(); // Shortcut to avoid costly validation.
11741
11742 if (isFallbackBlock) {
11743 return [true, []];
11744 }
11745
11746 const logger = createQueuedLogger();
11747 const blockType = normalizeBlockType(blockTypeOrName);
11748 let generatedBlockContent;
11749
11750 try {
11751 generatedBlockContent = getSaveContent(blockType, block.attributes);
11752 } catch (error) {
11753 logger.error('Block validation failed because an error occurred while generating block content:\n\n%s', error.toString());
11754 return [false, logger.getItems()];
11755 }
11756
11757 const isValid = isEquivalentHTML(block.originalContent, generatedBlockContent, logger);
11758
11759 if (!isValid) {
11760 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);
11761 }
11762
11763 return [isValid, logger.getItems()];
11764 }
11765 /**
11766 * Returns true if the parsed block is valid given the input content. A block
11767 * is considered valid if, when serialized with assumed attributes, the content
11768 * matches the original value.
11769 *
11770 * Logs to console in development environments when invalid.
11771 *
11772 * @deprecated Use validateBlock instead to avoid data loss.
11773 *
11774 * @param {string|Object} blockTypeOrName Block type.
11775 * @param {Object} attributes Parsed block attributes.
11776 * @param {string} originalBlockContent Original block content.
11777 *
11778 * @return {boolean} Whether block is valid.
11779 */
11780
11781 function isValidBlockContent(blockTypeOrName, attributes, originalBlockContent) {
11782 external_wp_deprecated_default()('isValidBlockContent introduces opportunity for data loss', {
11783 since: '12.6',
11784 plugin: 'Gutenberg',
11785 alternative: 'validateBlock'
11786 });
11787 const blockType = normalizeBlockType(blockTypeOrName);
11788 const block = {
11789 name: blockType.name,
11790 attributes,
11791 innerBlocks: [],
11792 originalContent: originalBlockContent
11793 };
11794 const [isValid] = validateBlock(block, blockType);
11795 return isValid;
11796 }
11797
11798 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/convert-legacy-block.js
11799 /**
11800 * Convert legacy blocks to their canonical form. This function is used
11801 * both in the parser level for previous content and to convert such blocks
11802 * used in Custom Post Types templates.
11803 *
11804 * @param {string} name The block's name
11805 * @param {Object} attributes The block's attributes
11806 *
11807 * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found
11808 */
11809 function convertLegacyBlockNameAndAttributes(name, attributes) {
11810 const newAttributes = { ...attributes
11811 }; // Convert 'core/cover-image' block in existing content to 'core/cover'.
11812
11813 if ('core/cover-image' === name) {
11814 name = 'core/cover';
11815 } // Convert 'core/text' blocks in existing content to 'core/paragraph'.
11816
11817
11818 if ('core/text' === name || 'core/cover-text' === name) {
11819 name = 'core/paragraph';
11820 } // Convert derivative blocks such as 'core/social-link-wordpress' to the
11821 // canonical form 'core/social-link'.
11822
11823
11824 if (name && name.indexOf('core/social-link-') === 0) {
11825 // Capture `social-link-wordpress` into `{"service":"wordpress"}`
11826 newAttributes.service = name.substring(17);
11827 name = 'core/social-link';
11828 } // Convert derivative blocks such as 'core-embed/instagram' to the
11829 // canonical form 'core/embed'.
11830
11831
11832 if (name && name.indexOf('core-embed/') === 0) {
11833 // Capture `core-embed/instagram` into `{"providerNameSlug":"instagram"}`
11834 const providerSlug = name.substring(11);
11835 const deprecated = {
11836 speaker: 'speaker-deck',
11837 polldaddy: 'crowdsignal'
11838 };
11839 newAttributes.providerNameSlug = providerSlug in deprecated ? deprecated[providerSlug] : providerSlug; // This is needed as the `responsive` attribute was passed
11840 // in a different way before the refactoring to block variations.
11841
11842 if (!['amazon-kindle', 'wordpress'].includes(providerSlug)) {
11843 newAttributes.responsive = true;
11844 }
11845
11846 name = 'core/embed';
11847 } // Convert Post Comment blocks in existing content to Comment blocks.
11848 // TODO: Remove these checks when WordPress 6.0 is released.
11849
11850
11851 if (name === 'core/post-comment-author') {
11852 name = 'core/comment-author-name';
11853 }
11854
11855 if (name === 'core/post-comment-content') {
11856 name = 'core/comment-content';
11857 }
11858
11859 if (name === 'core/post-comment-date') {
11860 name = 'core/comment-date';
11861 }
11862
11863 if (name === 'core/comments-query-loop') {
11864 name = 'core/comments';
11865 const {
11866 className = ''
11867 } = newAttributes;
11868
11869 if (!className.includes('wp-block-comments-query-loop')) {
11870 newAttributes.className = ['wp-block-comments-query-loop', className].join(' ');
11871 } // Note that we also had to add a deprecation to the block in order
11872 // for the ID change to work.
11873
11874 }
11875
11876 if (name === 'core/post-comments') {
11877 name = 'core/comments';
11878 newAttributes.legacy = true;
11879 }
11880
11881 return [name, newAttributes];
11882 }
11883
11884 ;// CONCATENATED MODULE: ./node_modules/hpq/es/get-path.js
11885 /**
11886 * Given object and string of dot-delimited path segments, returns value at
11887 * path or undefined if path cannot be resolved.
11888 *
11889 * @param {Object} object Lookup object
11890 * @param {string} path Path to resolve
11891 * @return {?*} Resolved value
11892 */
11893 function getPath(object, path) {
11894 var segments = path.split('.');
11895 var segment;
11896
11897 while (segment = segments.shift()) {
11898 if (!(segment in object)) {
11899 return;
11900 }
11901
11902 object = object[segment];
11903 }
11904
11905 return object;
11906 }
11907 ;// CONCATENATED MODULE: ./node_modules/hpq/es/index.js
11908 /**
11909 * Internal dependencies
11910 */
11911
11912 /**
11913 * Function returning a DOM document created by `createHTMLDocument`. The same
11914 * document is returned between invocations.
11915 *
11916 * @return {Document} DOM document.
11917 */
11918
11919 var getDocument = function () {
11920 var doc;
11921 return function () {
11922 if (!doc) {
11923 doc = document.implementation.createHTMLDocument('');
11924 }
11925
11926 return doc;
11927 };
11928 }();
11929 /**
11930 * Given a markup string or DOM element, creates an object aligning with the
11931 * shape of the matchers object, or the value returned by the matcher.
11932 *
11933 * @param {(string|Element)} source Source content
11934 * @param {(Object|Function)} matchers Matcher function or object of matchers
11935 * @return {(Object|*)} Matched value(s), shaped by object
11936 */
11937
11938
11939 function parse(source, matchers) {
11940 if (!matchers) {
11941 return;
11942 } // Coerce to element
11943
11944
11945 if ('string' === typeof source) {
11946 var doc = getDocument();
11947 doc.body.innerHTML = source;
11948 source = doc.body;
11949 } // Return singular value
11950
11951
11952 if ('function' === typeof matchers) {
11953 return matchers(source);
11954 } // Bail if we can't handle matchers
11955
11956
11957 if (Object !== matchers.constructor) {
11958 return;
11959 } // Shape result by matcher object
11960
11961
11962 return Object.keys(matchers).reduce(function (memo, key) {
11963 memo[key] = parse(source, matchers[key]);
11964 return memo;
11965 }, {});
11966 }
11967 /**
11968 * Generates a function which matches node of type selector, returning an
11969 * attribute by property if the attribute exists. If no selector is passed,
11970 * returns property of the query element.
11971 *
11972 * @param {?string} selector Optional selector
11973 * @param {string} name Property name
11974 * @return {*} Property value
11975 */
11976
11977 function prop(selector, name) {
11978 if (1 === arguments.length) {
11979 name = selector;
11980 selector = undefined;
11981 }
11982
11983 return function (node) {
11984 var match = node;
11985
11986 if (selector) {
11987 match = node.querySelector(selector);
11988 }
11989
11990 if (match) {
11991 return getPath(match, name);
11992 }
11993 };
11994 }
11995 /**
11996 * Generates a function which matches node of type selector, returning an
11997 * attribute by name if the attribute exists. If no selector is passed,
11998 * returns attribute of the query element.
11999 *
12000 * @param {?string} selector Optional selector
12001 * @param {string} name Attribute name
12002 * @return {?string} Attribute value
12003 */
12004
12005 function attr(selector, name) {
12006 if (1 === arguments.length) {
12007 name = selector;
12008 selector = undefined;
12009 }
12010
12011 return function (node) {
12012 var attributes = prop(selector, 'attributes')(node);
12013
12014 if (attributes && attributes.hasOwnProperty(name)) {
12015 return attributes[name].value;
12016 }
12017 };
12018 }
12019 /**
12020 * Convenience for `prop( selector, 'innerHTML' )`.
12021 *
12022 * @see prop()
12023 *
12024 * @param {?string} selector Optional selector
12025 * @return {string} Inner HTML
12026 */
12027
12028 function html(selector) {
12029 return prop(selector, 'innerHTML');
12030 }
12031 /**
12032 * Convenience for `prop( selector, 'textContent' )`.
12033 *
12034 * @see prop()
12035 *
12036 * @param {?string} selector Optional selector
12037 * @return {string} Text content
12038 */
12039
12040 function es_text(selector) {
12041 return prop(selector, 'textContent');
12042 }
12043 /**
12044 * Creates a new matching context by first finding elements matching selector
12045 * using querySelectorAll before then running another `parse` on `matchers`
12046 * scoped to the matched elements.
12047 *
12048 * @see parse()
12049 *
12050 * @param {string} selector Selector to match
12051 * @param {(Object|Function)} matchers Matcher function or object of matchers
12052 * @return {Array.<*,Object>} Array of matched value(s)
12053 */
12054
12055 function query(selector, matchers) {
12056 return function (node) {
12057 var matches = node.querySelectorAll(selector);
12058 return [].map.call(matches, function (match) {
12059 return parse(match, matchers);
12060 });
12061 };
12062 }
12063 // EXTERNAL MODULE: ./node_modules/memize/index.js
12064 var memize = __webpack_require__(9756);
12065 var memize_default = /*#__PURE__*/__webpack_require__.n(memize);
12066 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/matchers.js
12067 /**
12068 * External dependencies
12069 */
12070
12071 /**
12072 * Internal dependencies
12073 */
12074
12075
12076
12077 function matchers_html(selector, multilineTag) {
12078 return domNode => {
12079 let match = domNode;
12080
12081 if (selector) {
12082 match = domNode.querySelector(selector);
12083 }
12084
12085 if (!match) {
12086 return '';
12087 }
12088
12089 if (multilineTag) {
12090 let value = '';
12091 const length = match.children.length;
12092
12093 for (let index = 0; index < length; index++) {
12094 const child = match.children[index];
12095
12096 if (child.nodeName.toLowerCase() !== multilineTag) {
12097 continue;
12098 }
12099
12100 value += child.outerHTML;
12101 }
12102
12103 return value;
12104 }
12105
12106 return match.innerHTML;
12107 };
12108 }
12109
12110 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/node.js
12111 /**
12112 * Internal dependencies
12113 */
12114
12115 /**
12116 * A representation of a single node within a block's rich text value. If
12117 * representing a text node, the value is simply a string of the node value.
12118 * As representing an element node, it is an object of:
12119 *
12120 * 1. `type` (string): Tag name.
12121 * 2. `props` (object): Attributes and children array of WPBlockNode.
12122 *
12123 * @typedef {string|Object} WPBlockNode
12124 */
12125
12126 /**
12127 * Given a single node and a node type (e.g. `'br'`), returns true if the node
12128 * corresponds to that type, false otherwise.
12129 *
12130 * @param {WPBlockNode} node Block node to test
12131 * @param {string} type Node to type to test against.
12132 *
12133 * @return {boolean} Whether node is of intended type.
12134 */
12135
12136 function isNodeOfType(node, type) {
12137 return node && node.type === type;
12138 }
12139 /**
12140 * Given an object implementing the NamedNodeMap interface, returns a plain
12141 * object equivalent value of name, value key-value pairs.
12142 *
12143 * @see https://dom.spec.whatwg.org/#interface-namednodemap
12144 *
12145 * @param {NamedNodeMap} nodeMap NamedNodeMap to convert to object.
12146 *
12147 * @return {Object} Object equivalent value of NamedNodeMap.
12148 */
12149
12150
12151 function getNamedNodeMapAsObject(nodeMap) {
12152 const result = {};
12153
12154 for (let i = 0; i < nodeMap.length; i++) {
12155 const {
12156 name,
12157 value
12158 } = nodeMap[i];
12159 result[name] = value;
12160 }
12161
12162 return result;
12163 }
12164 /**
12165 * Given a DOM Element or Text node, returns an equivalent block node. Throws
12166 * if passed any node type other than element or text.
12167 *
12168 * @throws {TypeError} If non-element/text node is passed.
12169 *
12170 * @param {Node} domNode DOM node to convert.
12171 *
12172 * @return {WPBlockNode} Block node equivalent to DOM node.
12173 */
12174
12175 function fromDOM(domNode) {
12176 if (domNode.nodeType === domNode.TEXT_NODE) {
12177 return domNode.nodeValue;
12178 }
12179
12180 if (domNode.nodeType !== domNode.ELEMENT_NODE) {
12181 throw new TypeError('A block node can only be created from a node of type text or ' + 'element.');
12182 }
12183
12184 return {
12185 type: domNode.nodeName.toLowerCase(),
12186 props: { ...getNamedNodeMapAsObject(domNode.attributes),
12187 children: children_fromDOM(domNode.childNodes)
12188 }
12189 };
12190 }
12191 /**
12192 * Given a block node, returns its HTML string representation.
12193 *
12194 * @param {WPBlockNode} node Block node to convert to string.
12195 *
12196 * @return {string} String HTML representation of block node.
12197 */
12198
12199 function toHTML(node) {
12200 return children_toHTML([node]);
12201 }
12202 /**
12203 * Given a selector, returns an hpq matcher generating a WPBlockNode value
12204 * matching the selector result.
12205 *
12206 * @param {string} selector DOM selector.
12207 *
12208 * @return {Function} hpq matcher.
12209 */
12210
12211 function node_matcher(selector) {
12212 return domNode => {
12213 let match = domNode;
12214
12215 if (selector) {
12216 match = domNode.querySelector(selector);
12217 }
12218
12219 try {
12220 return fromDOM(match);
12221 } catch (error) {
12222 return null;
12223 }
12224 };
12225 }
12226 /**
12227 * Object of utility functions used in managing block attribute values of
12228 * source `node`.
12229 *
12230 * @see https://github.com/WordPress/gutenberg/pull/10439
12231 *
12232 * @deprecated since 4.0. The `node` source should not be used, and can be
12233 * replaced by the `html` source.
12234 *
12235 * @private
12236 */
12237
12238 /* harmony default export */ const node = ({
12239 isNodeOfType,
12240 fromDOM,
12241 toHTML,
12242 matcher: node_matcher
12243 });
12244
12245 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/children.js
12246 /**
12247 * External dependencies
12248 */
12249
12250 /**
12251 * WordPress dependencies
12252 */
12253
12254
12255 /**
12256 * Internal dependencies
12257 */
12258
12259
12260 /**
12261 * A representation of a block's rich text value.
12262 *
12263 * @typedef {WPBlockNode[]} WPBlockChildren
12264 */
12265
12266 /**
12267 * Given block children, returns a serialize-capable WordPress element.
12268 *
12269 * @param {WPBlockChildren} children Block children object to convert.
12270 *
12271 * @return {WPElement} A serialize-capable element.
12272 */
12273
12274 function getSerializeCapableElement(children) {
12275 // The fact that block children are compatible with the element serializer is
12276 // merely an implementation detail that currently serves to be true, but
12277 // should not be mistaken as being a guarantee on the external API. The
12278 // public API only offers guarantees to work with strings (toHTML) and DOM
12279 // elements (fromDOM), and should provide utilities to manipulate the value
12280 // rather than expect consumers to inspect or construct its shape (concat).
12281 return children;
12282 }
12283 /**
12284 * Given block children, returns an array of block nodes.
12285 *
12286 * @param {WPBlockChildren} children Block children object to convert.
12287 *
12288 * @return {Array<WPBlockNode>} An array of individual block nodes.
12289 */
12290
12291 function getChildrenArray(children) {
12292 // The fact that block children are compatible with the element serializer
12293 // is merely an implementation detail that currently serves to be true, but
12294 // should not be mistaken as being a guarantee on the external API.
12295 return children;
12296 }
12297 /**
12298 * Given two or more block nodes, returns a new block node representing a
12299 * concatenation of its values.
12300 *
12301 * @param {...WPBlockChildren} blockNodes Block nodes to concatenate.
12302 *
12303 * @return {WPBlockChildren} Concatenated block node.
12304 */
12305
12306
12307 function concat() {
12308 const result = [];
12309
12310 for (let i = 0; i < arguments.length; i++) {
12311 const blockNode = (0,external_lodash_namespaceObject.castArray)(i < 0 || arguments.length <= i ? undefined : arguments[i]);
12312
12313 for (let j = 0; j < blockNode.length; j++) {
12314 const child = blockNode[j];
12315 const canConcatToPreviousString = typeof child === 'string' && typeof result[result.length - 1] === 'string';
12316
12317 if (canConcatToPreviousString) {
12318 result[result.length - 1] += child;
12319 } else {
12320 result.push(child);
12321 }
12322 }
12323 }
12324
12325 return result;
12326 }
12327 /**
12328 * Given an iterable set of DOM nodes, returns equivalent block children.
12329 * Ignores any non-element/text nodes included in set.
12330 *
12331 * @param {Iterable.<Node>} domNodes Iterable set of DOM nodes to convert.
12332 *
12333 * @return {WPBlockChildren} Block children equivalent to DOM nodes.
12334 */
12335
12336 function children_fromDOM(domNodes) {
12337 const result = [];
12338
12339 for (let i = 0; i < domNodes.length; i++) {
12340 try {
12341 result.push(fromDOM(domNodes[i]));
12342 } catch (error) {// Simply ignore if DOM node could not be converted.
12343 }
12344 }
12345
12346 return result;
12347 }
12348 /**
12349 * Given a block node, returns its HTML string representation.
12350 *
12351 * @param {WPBlockChildren} children Block node(s) to convert to string.
12352 *
12353 * @return {string} String HTML representation of block node.
12354 */
12355
12356 function children_toHTML(children) {
12357 const element = getSerializeCapableElement(children);
12358 return (0,external_wp_element_namespaceObject.renderToString)(element);
12359 }
12360 /**
12361 * Given a selector, returns an hpq matcher generating a WPBlockChildren value
12362 * matching the selector result.
12363 *
12364 * @param {string} selector DOM selector.
12365 *
12366 * @return {Function} hpq matcher.
12367 */
12368
12369 function children_matcher(selector) {
12370 return domNode => {
12371 let match = domNode;
12372
12373 if (selector) {
12374 match = domNode.querySelector(selector);
12375 }
12376
12377 if (match) {
12378 return children_fromDOM(match.childNodes);
12379 }
12380
12381 return [];
12382 };
12383 }
12384 /**
12385 * Object of utility functions used in managing block attribute values of
12386 * source `children`.
12387 *
12388 * @see https://github.com/WordPress/gutenberg/pull/10439
12389 *
12390 * @deprecated since 4.0. The `children` source should not be used, and can be
12391 * replaced by the `html` source.
12392 *
12393 * @private
12394 */
12395
12396 /* harmony default export */ const children = ({
12397 concat,
12398 getChildrenArray,
12399 fromDOM: children_fromDOM,
12400 toHTML: children_toHTML,
12401 matcher: children_matcher
12402 });
12403
12404 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/get-block-attributes.js
12405 /**
12406 * External dependencies
12407 */
12408
12409
12410
12411 /**
12412 * WordPress dependencies
12413 */
12414
12415
12416 /**
12417 * Internal dependencies
12418 */
12419
12420
12421
12422 /**
12423 * Higher-order hpq matcher which enhances an attribute matcher to return true
12424 * or false depending on whether the original matcher returns undefined. This
12425 * is useful for boolean attributes (e.g. disabled) whose attribute values may
12426 * be technically falsey (empty string), though their mere presence should be
12427 * enough to infer as true.
12428 *
12429 * @param {Function} matcher Original hpq matcher.
12430 *
12431 * @return {Function} Enhanced hpq matcher.
12432 */
12433
12434 const toBooleanAttributeMatcher = matcher => (0,external_lodash_namespaceObject.flow)([matcher, // Expected values from `attr( 'disabled' )`:
12435 //
12436 // <input>
12437 // - Value: `undefined`
12438 // - Transformed: `false`
12439 //
12440 // <input disabled>
12441 // - Value: `''`
12442 // - Transformed: `true`
12443 //
12444 // <input disabled="disabled">
12445 // - Value: `'disabled'`
12446 // - Transformed: `true`
12447 value => value !== undefined]);
12448 /**
12449 * Returns true if value is of the given JSON schema type, or false otherwise.
12450 *
12451 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
12452 *
12453 * @param {*} value Value to test.
12454 * @param {string} type Type to test.
12455 *
12456 * @return {boolean} Whether value is of type.
12457 */
12458
12459 function isOfType(value, type) {
12460 switch (type) {
12461 case 'string':
12462 return typeof value === 'string';
12463
12464 case 'boolean':
12465 return typeof value === 'boolean';
12466
12467 case 'object':
12468 return !!value && value.constructor === Object;
12469
12470 case 'null':
12471 return value === null;
12472
12473 case 'array':
12474 return Array.isArray(value);
12475
12476 case 'integer':
12477 case 'number':
12478 return typeof value === 'number';
12479 }
12480
12481 return true;
12482 }
12483 /**
12484 * Returns true if value is of an array of given JSON schema types, or false
12485 * otherwise.
12486 *
12487 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
12488 *
12489 * @param {*} value Value to test.
12490 * @param {string[]} types Types to test.
12491 *
12492 * @return {boolean} Whether value is of types.
12493 */
12494
12495 function isOfTypes(value, types) {
12496 return types.some(type => isOfType(value, type));
12497 }
12498 /**
12499 * Given an attribute key, an attribute's schema, a block's raw content and the
12500 * commentAttributes returns the attribute value depending on its source
12501 * definition of the given attribute key.
12502 *
12503 * @param {string} attributeKey Attribute key.
12504 * @param {Object} attributeSchema Attribute's schema.
12505 * @param {string|Node} innerHTML Block's raw content.
12506 * @param {Object} commentAttributes Block's comment attributes.
12507 *
12508 * @return {*} Attribute value.
12509 */
12510
12511 function getBlockAttribute(attributeKey, attributeSchema, innerHTML, commentAttributes) {
12512 let value;
12513
12514 switch (attributeSchema.source) {
12515 // An undefined source means that it's an attribute serialized to the
12516 // block's "comment".
12517 case undefined:
12518 value = commentAttributes ? commentAttributes[attributeKey] : undefined;
12519 break;
12520
12521 case 'attribute':
12522 case 'property':
12523 case 'html':
12524 case 'text':
12525 case 'children':
12526 case 'node':
12527 case 'query':
12528 case 'tag':
12529 value = parseWithAttributeSchema(innerHTML, attributeSchema);
12530 break;
12531 }
12532
12533 if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) {
12534 // Reject the value if it is not valid. Reverting to the undefined
12535 // value ensures the default is respected, if applicable.
12536 value = undefined;
12537 }
12538
12539 if (value === undefined) {
12540 value = attributeSchema.default;
12541 }
12542
12543 return value;
12544 }
12545 /**
12546 * Returns true if value is valid per the given block attribute schema type
12547 * definition, or false otherwise.
12548 *
12549 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1
12550 *
12551 * @param {*} value Value to test.
12552 * @param {?(Array<string>|string)} type Block attribute schema type.
12553 *
12554 * @return {boolean} Whether value is valid.
12555 */
12556
12557 function isValidByType(value, type) {
12558 return type === undefined || isOfTypes(value, (0,external_lodash_namespaceObject.castArray)(type));
12559 }
12560 /**
12561 * Returns true if value is valid per the given block attribute schema enum
12562 * definition, or false otherwise.
12563 *
12564 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2
12565 *
12566 * @param {*} value Value to test.
12567 * @param {?Array} enumSet Block attribute schema enum.
12568 *
12569 * @return {boolean} Whether value is valid.
12570 */
12571
12572 function isValidByEnum(value, enumSet) {
12573 return !Array.isArray(enumSet) || enumSet.includes(value);
12574 }
12575 /**
12576 * Returns an hpq matcher given a source object.
12577 *
12578 * @param {Object} sourceConfig Attribute Source object.
12579 *
12580 * @return {Function} A hpq Matcher.
12581 */
12582
12583 const matcherFromSource = memize_default()(sourceConfig => {
12584 switch (sourceConfig.source) {
12585 case 'attribute':
12586 let matcher = attr(sourceConfig.selector, sourceConfig.attribute);
12587
12588 if (sourceConfig.type === 'boolean') {
12589 matcher = toBooleanAttributeMatcher(matcher);
12590 }
12591
12592 return matcher;
12593
12594 case 'html':
12595 return matchers_html(sourceConfig.selector, sourceConfig.multiline);
12596
12597 case 'text':
12598 return es_text(sourceConfig.selector);
12599
12600 case 'children':
12601 return children_matcher(sourceConfig.selector);
12602
12603 case 'node':
12604 return node_matcher(sourceConfig.selector);
12605
12606 case 'query':
12607 const subMatchers = (0,external_lodash_namespaceObject.mapValues)(sourceConfig.query, matcherFromSource);
12608 return query(sourceConfig.selector, subMatchers);
12609
12610 case 'tag':
12611 return (0,external_lodash_namespaceObject.flow)([prop(sourceConfig.selector, 'nodeName'), nodeName => nodeName ? nodeName.toLowerCase() : undefined]);
12612
12613 default:
12614 // eslint-disable-next-line no-console
12615 console.error(`Unknown source type "${sourceConfig.source}"`);
12616 }
12617 });
12618 /**
12619 * Parse a HTML string into DOM tree.
12620 *
12621 * @param {string|Node} innerHTML HTML string or already parsed DOM node.
12622 *
12623 * @return {Node} Parsed DOM node.
12624 */
12625
12626 function parseHtml(innerHTML) {
12627 return parse(innerHTML, h => h);
12628 }
12629 /**
12630 * Given a block's raw content and an attribute's schema returns the attribute's
12631 * value depending on its source.
12632 *
12633 * @param {string|Node} innerHTML Block's raw content.
12634 * @param {Object} attributeSchema Attribute's schema.
12635 *
12636 * @return {*} Attribute value.
12637 */
12638
12639
12640 function parseWithAttributeSchema(innerHTML, attributeSchema) {
12641 return matcherFromSource(attributeSchema)(parseHtml(innerHTML));
12642 }
12643 /**
12644 * Returns the block attributes of a registered block node given its type.
12645 *
12646 * @param {string|Object} blockTypeOrName Block type or name.
12647 * @param {string|Node} innerHTML Raw block content.
12648 * @param {?Object} attributes Known block attributes (from delimiters).
12649 *
12650 * @return {Object} All block attributes.
12651 */
12652
12653 function getBlockAttributes(blockTypeOrName, innerHTML) {
12654 let attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
12655 const doc = parseHtml(innerHTML);
12656 const blockType = normalizeBlockType(blockTypeOrName);
12657 const blockAttributes = (0,external_lodash_namespaceObject.mapValues)(blockType.attributes, (schema, key) => getBlockAttribute(key, schema, doc, attributes));
12658 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockAttributes', blockAttributes, blockType, innerHTML, attributes);
12659 }
12660
12661 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/fix-custom-classname.js
12662 /**
12663 * External dependencies
12664 */
12665
12666 /**
12667 * Internal dependencies
12668 */
12669
12670
12671
12672
12673 const CLASS_ATTR_SCHEMA = {
12674 type: 'string',
12675 source: 'attribute',
12676 selector: '[data-custom-class-name] > *',
12677 attribute: 'class'
12678 };
12679 /**
12680 * Given an HTML string, returns an array of class names assigned to the root
12681 * element in the markup.
12682 *
12683 * @param {string} innerHTML Markup string from which to extract classes.
12684 *
12685 * @return {string[]} Array of class names assigned to the root element.
12686 */
12687
12688 function getHTMLRootElementClasses(innerHTML) {
12689 const parsed = parseWithAttributeSchema(`<div data-custom-class-name>${innerHTML}</div>`, CLASS_ATTR_SCHEMA);
12690 return parsed ? parsed.trim().split(/\s+/) : [];
12691 }
12692 /**
12693 * Given a parsed set of block attributes, if the block supports custom class
12694 * names and an unknown class (per the block's serialization behavior) is
12695 * found, the unknown classes are treated as custom classes. This prevents the
12696 * block from being considered as invalid.
12697 *
12698 * @param {Object} blockAttributes Original block attributes.
12699 * @param {Object} blockType Block type settings.
12700 * @param {string} innerHTML Original block markup.
12701 *
12702 * @return {Object} Filtered block attributes.
12703 */
12704
12705 function fixCustomClassname(blockAttributes, blockType, innerHTML) {
12706 if (registration_hasBlockSupport(blockType, 'customClassName', true)) {
12707 // To determine difference, serialize block given the known set of
12708 // attributes, with the exception of `className`. This will determine
12709 // the default set of classes. From there, any difference in innerHTML
12710 // can be considered as custom classes.
12711 const attributesSansClassName = (0,external_lodash_namespaceObject.omit)(blockAttributes, ['className']);
12712 const serialized = getSaveContent(blockType, attributesSansClassName);
12713 const defaultClasses = getHTMLRootElementClasses(serialized);
12714 const actualClasses = getHTMLRootElementClasses(innerHTML);
12715 const customClasses = actualClasses.filter(className => !defaultClasses.includes(className));
12716
12717 if (customClasses.length) {
12718 blockAttributes.className = customClasses.join(' ');
12719 } else if (serialized) {
12720 delete blockAttributes.className;
12721 }
12722 }
12723
12724 return blockAttributes;
12725 }
12726
12727 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-built-in-validation-fixes.js
12728 /**
12729 * Internal dependencies
12730 */
12731
12732 /**
12733 * Attempts to fix block invalidation by applying build-in validation fixes
12734 * like moving all extra classNames to the className attribute.
12735 *
12736 * @param {WPBlock} block block object.
12737 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
12738 * can be inferred from the block name,
12739 * but it's here for performance reasons.
12740 *
12741 * @return {WPBlock} Fixed block object
12742 */
12743
12744 function applyBuiltInValidationFixes(block, blockType) {
12745 const updatedBlockAttributes = fixCustomClassname(block.attributes, blockType, block.originalContent);
12746 return { ...block,
12747 attributes: updatedBlockAttributes
12748 };
12749 }
12750
12751 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-block-deprecated-versions.js
12752 /**
12753 * External dependencies
12754 */
12755
12756 /**
12757 * Internal dependencies
12758 */
12759
12760
12761
12762
12763
12764 /**
12765 * Function that takes no arguments and always returns false.
12766 *
12767 * @return {boolean} Always returns false.
12768 */
12769
12770 function stubFalse() {
12771 return false;
12772 }
12773 /**
12774 * Given a block object, returns a new copy of the block with any applicable
12775 * deprecated migrations applied, or the original block if it was both valid
12776 * and no eligible migrations exist.
12777 *
12778 * @param {import(".").WPBlock} block Parsed and invalid block object.
12779 * @param {import(".").WPRawBlock} rawBlock Raw block object.
12780 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
12781 * can be inferred from the block name,
12782 * but it's here for performance reasons.
12783 *
12784 * @return {import(".").WPBlock} Migrated block object.
12785 */
12786
12787
12788 function applyBlockDeprecatedVersions(block, rawBlock, blockType) {
12789 const parsedAttributes = rawBlock.attrs;
12790 const {
12791 deprecated: deprecatedDefinitions
12792 } = blockType; // Bail early if there are no registered deprecations to be handled.
12793
12794 if (!deprecatedDefinitions || !deprecatedDefinitions.length) {
12795 return block;
12796 } // By design, blocks lack any sort of version tracking. Instead, to process
12797 // outdated content the system operates a queue out of all the defined
12798 // attribute shapes and tries each definition until the input produces a
12799 // valid result. This mechanism seeks to avoid polluting the user-space with
12800 // machine-specific code. An invalid block is thus a block that could not be
12801 // matched successfully with any of the registered deprecation definitions.
12802
12803
12804 for (let i = 0; i < deprecatedDefinitions.length; i++) {
12805 // A block can opt into a migration even if the block is valid by
12806 // defining `isEligible` on its deprecation. If the block is both valid
12807 // and does not opt to migrate, skip.
12808 const {
12809 isEligible = stubFalse
12810 } = deprecatedDefinitions[i];
12811
12812 if (block.isValid && !isEligible(parsedAttributes, block.innerBlocks)) {
12813 continue;
12814 } // Block type properties which could impact either serialization or
12815 // parsing are not considered in the deprecated block type by default,
12816 // and must be explicitly provided.
12817
12818
12819 const deprecatedBlockType = Object.assign((0,external_lodash_namespaceObject.omit)(blockType, DEPRECATED_ENTRY_KEYS), deprecatedDefinitions[i]);
12820 let migratedBlock = { ...block,
12821 attributes: getBlockAttributes(deprecatedBlockType, block.originalContent, parsedAttributes)
12822 }; // Ignore the deprecation if it produces a block which is not valid.
12823
12824 let [isValid] = validateBlock(migratedBlock, deprecatedBlockType); // If the migrated block is not valid initially, try the built-in fixes.
12825
12826 if (!isValid) {
12827 migratedBlock = applyBuiltInValidationFixes(migratedBlock, deprecatedBlockType);
12828 [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
12829 } // An invalid block does not imply incorrect HTML but the fact block
12830 // source information could be lost on re-serialization.
12831
12832
12833 if (!isValid) {
12834 continue;
12835 }
12836
12837 let migratedInnerBlocks = migratedBlock.innerBlocks;
12838 let migratedAttributes = migratedBlock.attributes; // A block may provide custom behavior to assign new attributes and/or
12839 // inner blocks.
12840
12841 const {
12842 migrate
12843 } = deprecatedBlockType;
12844
12845 if (migrate) {
12846 [migratedAttributes = parsedAttributes, migratedInnerBlocks = block.innerBlocks] = (0,external_lodash_namespaceObject.castArray)(migrate(migratedAttributes, block.innerBlocks));
12847 }
12848
12849 block = { ...block,
12850 attributes: migratedAttributes,
12851 innerBlocks: migratedInnerBlocks,
12852 isValid: true,
12853 validationIssues: []
12854 };
12855 }
12856
12857 return block;
12858 }
12859
12860 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/index.js
12861 /**
12862 * WordPress dependencies
12863 */
12864
12865
12866 /**
12867 * Internal dependencies
12868 */
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879 /**
12880 * The raw structure of a block includes its attributes, inner
12881 * blocks, and inner HTML. It is important to distinguish inner blocks from
12882 * the HTML content of the block as only the latter is relevant for block
12883 * validation and edit operations.
12884 *
12885 * @typedef WPRawBlock
12886 *
12887 * @property {string=} blockName Block name
12888 * @property {Object=} attrs Block raw or comment attributes.
12889 * @property {string} innerHTML HTML content of the block.
12890 * @property {(string|null)[]} innerContent Content without inner blocks.
12891 * @property {WPRawBlock[]} innerBlocks Inner Blocks.
12892 */
12893
12894 /**
12895 * Fully parsed block object.
12896 *
12897 * @typedef WPBlock
12898 *
12899 * @property {string} name Block name
12900 * @property {Object} attributes Block raw or comment attributes.
12901 * @property {WPBlock[]} innerBlocks Inner Blocks.
12902 * @property {string} originalContent Original content of the block before validation fixes.
12903 * @property {boolean} isValid Whether the block is valid.
12904 * @property {Object[]} validationIssues Validation issues.
12905 * @property {WPRawBlock} [__unstableBlockSource] Un-processed original copy of block if created through parser.
12906 */
12907
12908 /**
12909 * @typedef {Object} ParseOptions
12910 * @property {boolean?} __unstableSkipMigrationLogs If a block is migrated from a deprecated version, skip logging the migration details.
12911 * @property {boolean?} __unstableSkipAutop Whether to skip autop when processing freeform content.
12912 */
12913
12914 /**
12915 * Convert legacy blocks to their canonical form. This function is used
12916 * both in the parser level for previous content and to convert such blocks
12917 * used in Custom Post Types templates.
12918 *
12919 * @param {WPRawBlock} rawBlock
12920 *
12921 * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found
12922 */
12923
12924 function convertLegacyBlocks(rawBlock) {
12925 const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(rawBlock.blockName, rawBlock.attrs);
12926 return { ...rawBlock,
12927 blockName: correctName,
12928 attrs: correctedAttributes
12929 };
12930 }
12931 /**
12932 * Normalize the raw block by applying the fallback block name if none given,
12933 * sanitize the parsed HTML...
12934 *
12935 * @param {WPRawBlock} rawBlock The raw block object.
12936 * @param {ParseOptions?} options Extra options for handling block parsing.
12937 *
12938 * @return {WPRawBlock} The normalized block object.
12939 */
12940
12941
12942 function normalizeRawBlock(rawBlock, options) {
12943 const fallbackBlockName = getFreeformContentHandlerName(); // If the grammar parsing don't produce any block name, use the freeform block.
12944
12945 const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
12946 const rawAttributes = rawBlock.attrs || {};
12947 const rawInnerBlocks = rawBlock.innerBlocks || [];
12948 let rawInnerHTML = rawBlock.innerHTML.trim(); // Fallback content may be upgraded from classic content expecting implicit
12949 // automatic paragraphs, so preserve them. Assumes wpautop is idempotent,
12950 // meaning there are no negative consequences to repeated autop calls.
12951
12952 if (rawBlockName === fallbackBlockName && !(options !== null && options !== void 0 && options.__unstableSkipAutop)) {
12953 rawInnerHTML = (0,external_wp_autop_namespaceObject.autop)(rawInnerHTML).trim();
12954 }
12955
12956 return { ...rawBlock,
12957 blockName: rawBlockName,
12958 attrs: rawAttributes,
12959 innerHTML: rawInnerHTML,
12960 innerBlocks: rawInnerBlocks
12961 };
12962 }
12963 /**
12964 * Uses the "unregistered blockType" to create a block object.
12965 *
12966 * @param {WPRawBlock} rawBlock block.
12967 *
12968 * @return {WPRawBlock} The unregistered block object.
12969 */
12970
12971 function createMissingBlockType(rawBlock) {
12972 const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName(); // Preserve undelimited content for use by the unregistered type
12973 // handler. A block node's `innerHTML` isn't enough, as that field only
12974 // carries the block's own HTML and not its nested blocks.
12975
12976 const originalUndelimitedContent = serializeRawBlock(rawBlock, {
12977 isCommentDelimited: false
12978 }); // Preserve full block content for use by the unregistered type
12979 // handler, block boundaries included.
12980
12981 const originalContent = serializeRawBlock(rawBlock, {
12982 isCommentDelimited: true
12983 });
12984 return {
12985 blockName: unregisteredFallbackBlock,
12986 attrs: {
12987 originalName: rawBlock.blockName,
12988 originalContent,
12989 originalUndelimitedContent
12990 },
12991 innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
12992 innerBlocks: rawBlock.innerBlocks,
12993 innerContent: rawBlock.innerContent
12994 };
12995 }
12996 /**
12997 * Validates a block and wraps with validation meta.
12998 *
12999 * The name here is regrettable but `validateBlock` is already taken.
13000 *
13001 * @param {WPBlock} unvalidatedBlock
13002 * @param {import('../registration').WPBlockType} blockType
13003 * @return {WPBlock} validated block, with auto-fixes if initially invalid
13004 */
13005
13006
13007 function applyBlockValidation(unvalidatedBlock, blockType) {
13008 // Attempt to validate the block.
13009 const [isValid] = validateBlock(unvalidatedBlock, blockType);
13010
13011 if (isValid) {
13012 return { ...unvalidatedBlock,
13013 isValid,
13014 validationIssues: []
13015 };
13016 } // If the block is invalid, attempt some built-in fixes
13017 // like custom classNames handling.
13018
13019
13020 const fixedBlock = applyBuiltInValidationFixes(unvalidatedBlock, blockType); // Attempt to validate the block once again after the built-in fixes.
13021
13022 const [isFixedValid, validationIssues] = validateBlock(unvalidatedBlock, blockType);
13023 return { ...fixedBlock,
13024 isValid: isFixedValid,
13025 validationIssues
13026 };
13027 }
13028 /**
13029 * Given a raw block returned by grammar parsing, returns a fully parsed block.
13030 *
13031 * @param {WPRawBlock} rawBlock The raw block object.
13032 * @param {ParseOptions} options Extra options for handling block parsing.
13033 *
13034 * @return {WPBlock} Fully parsed block.
13035 */
13036
13037
13038 function parseRawBlock(rawBlock, options) {
13039 let normalizedBlock = normalizeRawBlock(rawBlock, options); // During the lifecycle of the project, we renamed some old blocks
13040 // and transformed others to new blocks. To avoid breaking existing content,
13041 // we added this function to properly parse the old content.
13042
13043 normalizedBlock = convertLegacyBlocks(normalizedBlock); // Try finding the type for known block name.
13044
13045 let blockType = registration_getBlockType(normalizedBlock.blockName); // If not blockType is found for the specified name, fallback to the "unregistedBlockType".
13046
13047 if (!blockType) {
13048 normalizedBlock = createMissingBlockType(normalizedBlock);
13049 blockType = registration_getBlockType(normalizedBlock.blockName);
13050 } // If it's an empty freeform block or there's no blockType (no missing block handler)
13051 // Then, just ignore the block.
13052 // It might be a good idea to throw a warning here.
13053 // TODO: I'm unsure about the unregisteredFallbackBlock check,
13054 // it might ignore some dynamic unregistered third party blocks wrongly.
13055
13056
13057 const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
13058
13059 if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
13060 return;
13061 } // Parse inner blocks recursively.
13062
13063
13064 const parsedInnerBlocks = normalizedBlock.innerBlocks.map(innerBlock => parseRawBlock(innerBlock, options)) // See https://github.com/WordPress/gutenberg/pull/17164.
13065 .filter(innerBlock => !!innerBlock); // Get the fully parsed block.
13066
13067 const parsedBlock = createBlock(normalizedBlock.blockName, getBlockAttributes(blockType, normalizedBlock.innerHTML, normalizedBlock.attrs), parsedInnerBlocks);
13068 parsedBlock.originalContent = normalizedBlock.innerHTML;
13069 const validatedBlock = applyBlockValidation(parsedBlock, blockType);
13070 const {
13071 validationIssues
13072 } = validatedBlock; // Run the block deprecation and migrations.
13073 // This is performed on both invalid and valid blocks because
13074 // migration using the `migrate` functions should run even
13075 // if the output is deemed valid.
13076
13077 const updatedBlock = applyBlockDeprecatedVersions(validatedBlock, normalizedBlock, blockType);
13078
13079 if (!updatedBlock.isValid) {
13080 // Preserve the original unprocessed version of the block
13081 // that we received (no fixes, no deprecations) so that
13082 // we can save it as close to exactly the same way as
13083 // we loaded it. This is important to avoid corruption
13084 // and data loss caused by block implementations trying
13085 // to process data that isn't fully recognized.
13086 updatedBlock.__unstableBlockSource = rawBlock;
13087 }
13088
13089 if (!validatedBlock.isValid && updatedBlock.isValid && !(options !== null && options !== void 0 && options.__unstableSkipMigrationLogs)) {
13090 /* eslint-disable no-console */
13091 console.groupCollapsed('Updated Block: %s', blockType.name);
13092 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);
13093 console.groupEnd();
13094 /* eslint-enable no-console */
13095 } else if (!validatedBlock.isValid && !updatedBlock.isValid) {
13096 validationIssues.forEach(_ref => {
13097 let {
13098 log,
13099 args
13100 } = _ref;
13101 return log(...args);
13102 });
13103 }
13104
13105 return updatedBlock;
13106 }
13107 /**
13108 * Utilizes an optimized token-driven parser based on the Gutenberg grammar spec
13109 * defined through a parsing expression grammar to take advantage of the regular
13110 * cadence provided by block delimiters -- composed syntactically through HTML
13111 * comments -- which, given a general HTML document as an input, returns a block
13112 * list array representation.
13113 *
13114 * This is a recursive-descent parser that scans linearly once through the input
13115 * document. Instead of directly recursing it utilizes a trampoline mechanism to
13116 * prevent stack overflow. This initial pass is mainly interested in separating
13117 * and isolating the blocks serialized in the document and manifestly not in the
13118 * content within the blocks.
13119 *
13120 * @see
13121 * https://developer.wordpress.org/block-editor/packages/packages-block-serialization-default-parser/
13122 *
13123 * @param {string} content The post content.
13124 * @param {ParseOptions} options Extra options for handling block parsing.
13125 *
13126 * @return {Array} Block list.
13127 */
13128
13129 function parser_parse(content, options) {
13130 return (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(content).reduce((accumulator, rawBlock) => {
13131 const block = parseRawBlock(rawBlock, options);
13132
13133 if (block) {
13134 accumulator.push(block);
13135 }
13136
13137 return accumulator;
13138 }, []);
13139 }
13140
13141 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/get-raw-transforms.js
13142 /**
13143 * External dependencies
13144 */
13145
13146 /**
13147 * Internal dependencies
13148 */
13149
13150
13151 function getRawTransforms() {
13152 return (0,external_lodash_namespaceObject.filter)(getBlockTransforms('from'), {
13153 type: 'raw'
13154 }).map(transform => {
13155 return transform.isMatch ? transform : { ...transform,
13156 isMatch: node => transform.selector && node.matches(transform.selector)
13157 };
13158 });
13159 }
13160
13161 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-to-blocks.js
13162 /**
13163 * Internal dependencies
13164 */
13165
13166
13167
13168 /**
13169 * Converts HTML directly to blocks. Looks for a matching transform for each
13170 * top-level tag. The HTML should be filtered to not have any text between
13171 * top-level tags and formatted in a way that blocks can handle the HTML.
13172 *
13173 * @param {string} html HTML to convert.
13174 * @param {Function} handler The handler calling htmlToBlocks: either rawHandler
13175 * or pasteHandler.
13176 *
13177 * @return {Array} An array of blocks.
13178 */
13179
13180 function htmlToBlocks(html, handler) {
13181 const doc = document.implementation.createHTMLDocument('');
13182 doc.body.innerHTML = html;
13183 return Array.from(doc.body.children).flatMap(node => {
13184 const rawTransform = findTransform(getRawTransforms(), _ref => {
13185 let {
13186 isMatch
13187 } = _ref;
13188 return isMatch(node);
13189 });
13190
13191 if (!rawTransform) {
13192 return createBlock( // Should not be hardcoded.
13193 'core/html', getBlockAttributes('core/html', node.outerHTML));
13194 }
13195
13196 const {
13197 transform,
13198 blockName
13199 } = rawTransform;
13200
13201 if (transform) {
13202 return transform(node, handler);
13203 }
13204
13205 return createBlock(blockName, getBlockAttributes(blockName, node.outerHTML));
13206 });
13207 }
13208
13209 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/normalise-blocks.js
13210 /**
13211 * WordPress dependencies
13212 */
13213
13214 function normaliseBlocks(HTML) {
13215 const decuDoc = document.implementation.createHTMLDocument('');
13216 const accuDoc = document.implementation.createHTMLDocument('');
13217 const decu = decuDoc.body;
13218 const accu = accuDoc.body;
13219 decu.innerHTML = HTML;
13220
13221 while (decu.firstChild) {
13222 const node = decu.firstChild; // Text nodes: wrap in a paragraph, or append to previous.
13223
13224 if (node.nodeType === node.TEXT_NODE) {
13225 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
13226 decu.removeChild(node);
13227 } else {
13228 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13229 accu.appendChild(accuDoc.createElement('P'));
13230 }
13231
13232 accu.lastChild.appendChild(node);
13233 } // Element nodes.
13234
13235 } else if (node.nodeType === node.ELEMENT_NODE) {
13236 // BR nodes: create a new paragraph on double, or append to previous.
13237 if (node.nodeName === 'BR') {
13238 if (node.nextSibling && node.nextSibling.nodeName === 'BR') {
13239 accu.appendChild(accuDoc.createElement('P'));
13240 decu.removeChild(node.nextSibling);
13241 } // Don't append to an empty paragraph.
13242
13243
13244 if (accu.lastChild && accu.lastChild.nodeName === 'P' && accu.lastChild.hasChildNodes()) {
13245 accu.lastChild.appendChild(node);
13246 } else {
13247 decu.removeChild(node);
13248 }
13249 } else if (node.nodeName === 'P') {
13250 // Only append non-empty paragraph nodes.
13251 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
13252 decu.removeChild(node);
13253 } else {
13254 accu.appendChild(node);
13255 }
13256 } else if ((0,external_wp_dom_namespaceObject.isPhrasingContent)(node)) {
13257 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
13258 accu.appendChild(accuDoc.createElement('P'));
13259 }
13260
13261 accu.lastChild.appendChild(node);
13262 } else {
13263 accu.appendChild(node);
13264 }
13265 } else {
13266 decu.removeChild(node);
13267 }
13268 }
13269
13270 return accu.innerHTML;
13271 }
13272
13273 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/special-comment-converter.js
13274 /**
13275 * WordPress dependencies
13276 */
13277
13278 /**
13279 * Looks for `<!--nextpage-->` and `<!--more-->` comments and
13280 * replaces them with a custom element representing a future block.
13281 *
13282 * The custom element is a way to bypass the rest of the `raw-handling`
13283 * transforms, which would eliminate other kinds of node with which to carry
13284 * `<!--more-->`'s data: nodes with `data` attributes, empty paragraphs, etc.
13285 *
13286 * The custom element is then expected to be recognized by any registered
13287 * block's `raw` transform.
13288 *
13289 * @param {Node} node The node to be processed.
13290 * @param {Document} doc The document of the node.
13291 * @return {void}
13292 */
13293
13294 function specialCommentConverter(node, doc) {
13295 if (node.nodeType !== node.COMMENT_NODE) {
13296 return;
13297 }
13298
13299 if (node.nodeValue === 'nextpage') {
13300 (0,external_wp_dom_namespaceObject.replace)(node, createNextpage(doc));
13301 return;
13302 }
13303
13304 if (node.nodeValue.indexOf('more') === 0) {
13305 moreCommentConverter(node, doc);
13306 }
13307 }
13308 /**
13309 * Convert `<!--more-->` as well as the `<!--more Some text-->` variant
13310 * and its `<!--noteaser-->` companion into the custom element
13311 * described in `specialCommentConverter()`.
13312 *
13313 * @param {Node} node The node to be processed.
13314 * @param {Document} doc The document of the node.
13315 * @return {void}
13316 */
13317
13318 function moreCommentConverter(node, doc) {
13319 // Grab any custom text in the comment.
13320 const customText = node.nodeValue.slice(4).trim();
13321 /*
13322 * When a `<!--more-->` comment is found, we need to look for any
13323 * `<!--noteaser-->` sibling, but it may not be a direct sibling
13324 * (whitespace typically lies in between)
13325 */
13326
13327 let sibling = node;
13328 let noTeaser = false;
13329
13330 while (sibling = sibling.nextSibling) {
13331 if (sibling.nodeType === sibling.COMMENT_NODE && sibling.nodeValue === 'noteaser') {
13332 noTeaser = true;
13333 (0,external_wp_dom_namespaceObject.remove)(sibling);
13334 break;
13335 }
13336 }
13337
13338 const moreBlock = createMore(customText, noTeaser, doc); // If our `<!--more-->` comment is in the middle of a paragraph, we should
13339 // split the paragraph in two and insert the more block in between. If not,
13340 // the more block will eventually end up being inserted after the paragraph.
13341
13342 if (!node.parentNode || node.parentNode.nodeName !== 'P' || node.parentNode.childNodes.length === 1) {
13343 (0,external_wp_dom_namespaceObject.replace)(node, moreBlock);
13344 } else {
13345 const childNodes = Array.from(node.parentNode.childNodes);
13346 const nodeIndex = childNodes.indexOf(node);
13347 const wrapperNode = node.parentNode.parentNode || doc.body;
13348
13349 const paragraphBuilder = (acc, child) => {
13350 if (!acc) {
13351 acc = doc.createElement('p');
13352 }
13353
13354 acc.appendChild(child);
13355 return acc;
13356 }; // Split the original parent node and insert our more block
13357
13358
13359 [childNodes.slice(0, nodeIndex).reduce(paragraphBuilder, null), moreBlock, childNodes.slice(nodeIndex + 1).reduce(paragraphBuilder, null)].forEach(element => element && wrapperNode.insertBefore(element, node.parentNode)); // Remove the old parent paragraph
13360
13361 (0,external_wp_dom_namespaceObject.remove)(node.parentNode);
13362 }
13363 }
13364
13365 function createMore(customText, noTeaser, doc) {
13366 const node = doc.createElement('wp-block');
13367 node.dataset.block = 'core/more';
13368
13369 if (customText) {
13370 node.dataset.customText = customText;
13371 }
13372
13373 if (noTeaser) {
13374 // "Boolean" data attribute.
13375 node.dataset.noTeaser = '';
13376 }
13377
13378 return node;
13379 }
13380
13381 function createNextpage(doc) {
13382 const node = doc.createElement('wp-block');
13383 node.dataset.block = 'core/nextpage';
13384 return node;
13385 }
13386
13387 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/list-reducer.js
13388 /**
13389 * WordPress dependencies
13390 */
13391
13392
13393 function isList(node) {
13394 return node.nodeName === 'OL' || node.nodeName === 'UL';
13395 }
13396
13397 function shallowTextContent(element) {
13398 return Array.from(element.childNodes).map(_ref => {
13399 let {
13400 nodeValue = ''
13401 } = _ref;
13402 return nodeValue;
13403 }).join('');
13404 }
13405
13406 function listReducer(node) {
13407 if (!isList(node)) {
13408 return;
13409 }
13410
13411 const list = node;
13412 const prevElement = node.previousElementSibling; // Merge with previous list if:
13413 // * There is a previous list of the same type.
13414 // * There is only one list item.
13415
13416 if (prevElement && prevElement.nodeName === node.nodeName && list.children.length === 1) {
13417 // Move all child nodes, including any text nodes, if any.
13418 while (list.firstChild) {
13419 prevElement.appendChild(list.firstChild);
13420 }
13421
13422 list.parentNode.removeChild(list);
13423 }
13424
13425 const parentElement = node.parentNode; // Nested list with empty parent item.
13426
13427 if (parentElement && parentElement.nodeName === 'LI' && parentElement.children.length === 1 && !/\S/.test(shallowTextContent(parentElement))) {
13428 const parentListItem = parentElement;
13429 const prevListItem = parentListItem.previousElementSibling;
13430 const parentList = parentListItem.parentNode;
13431
13432 if (prevListItem) {
13433 prevListItem.appendChild(list);
13434 parentList.removeChild(parentListItem);
13435 } else {
13436 parentList.parentNode.insertBefore(list, parentList);
13437 parentList.parentNode.removeChild(parentList);
13438 }
13439 } // Invalid: OL/UL > OL/UL.
13440
13441
13442 if (parentElement && isList(parentElement)) {
13443 const prevListItem = node.previousElementSibling;
13444
13445 if (prevListItem) {
13446 prevListItem.appendChild(node);
13447 } else {
13448 (0,external_wp_dom_namespaceObject.unwrap)(node);
13449 }
13450 }
13451 }
13452
13453 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/blockquote-normaliser.js
13454 /**
13455 * Internal dependencies
13456 */
13457
13458 function blockquoteNormaliser(node) {
13459 if (node.nodeName !== 'BLOCKQUOTE') {
13460 return;
13461 }
13462
13463 node.innerHTML = normaliseBlocks(node.innerHTML);
13464 }
13465
13466 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/figure-content-reducer.js
13467 /**
13468 * External dependencies
13469 */
13470
13471 /**
13472 * WordPress dependencies
13473 */
13474
13475
13476 /**
13477 * Whether or not the given node is figure content.
13478 *
13479 * @param {Node} node The node to check.
13480 * @param {Object} schema The schema to use.
13481 *
13482 * @return {boolean} True if figure content, false if not.
13483 */
13484
13485 function isFigureContent(node, schema) {
13486 const tag = node.nodeName.toLowerCase(); // We are looking for tags that can be a child of the figure tag, excluding
13487 // `figcaption` and any phrasing content.
13488
13489 if (tag === 'figcaption' || (0,external_wp_dom_namespaceObject.isTextContent)(node)) {
13490 return false;
13491 }
13492
13493 return (0,external_lodash_namespaceObject.has)(schema, ['figure', 'children', tag]);
13494 }
13495 /**
13496 * Whether or not the given node can have an anchor.
13497 *
13498 * @param {Node} node The node to check.
13499 * @param {Object} schema The schema to use.
13500 *
13501 * @return {boolean} True if it can, false if not.
13502 */
13503
13504
13505 function canHaveAnchor(node, schema) {
13506 const tag = node.nodeName.toLowerCase();
13507 return (0,external_lodash_namespaceObject.has)(schema, ['figure', 'children', 'a', 'children', tag]);
13508 }
13509 /**
13510 * Wraps the given element in a figure element.
13511 *
13512 * @param {Element} element The element to wrap.
13513 * @param {Element} beforeElement The element before which to place the figure.
13514 */
13515
13516
13517 function wrapFigureContent(element) {
13518 let beforeElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element;
13519 const figure = element.ownerDocument.createElement('figure');
13520 beforeElement.parentNode.insertBefore(figure, beforeElement);
13521 figure.appendChild(element);
13522 }
13523 /**
13524 * This filter takes figure content out of paragraphs, wraps it in a figure
13525 * element, and moves any anchors with it if needed.
13526 *
13527 * @param {Node} node The node to filter.
13528 * @param {Document} doc The document of the node.
13529 * @param {Object} schema The schema to use.
13530 *
13531 * @return {void}
13532 */
13533
13534
13535 function figureContentReducer(node, doc, schema) {
13536 if (!isFigureContent(node, schema)) {
13537 return;
13538 }
13539
13540 let nodeToInsert = node;
13541 const parentNode = node.parentNode; // If the figure content can have an anchor and its parent is an anchor with
13542 // only the figure content, take the anchor out instead of just the content.
13543
13544 if (canHaveAnchor(node, schema) && parentNode.nodeName === 'A' && parentNode.childNodes.length === 1) {
13545 nodeToInsert = node.parentNode;
13546 }
13547
13548 const wrapper = nodeToInsert.closest('p,div'); // If wrapped in a paragraph or div, only extract if it's aligned or if
13549 // there is no text content.
13550 // Otherwise, if directly at the root, wrap in a figure element.
13551
13552 if (wrapper) {
13553 // In jsdom-jscore, 'node.classList' can be undefined.
13554 // In this case, default to extract as it offers a better UI experience on mobile.
13555 if (!node.classList) {
13556 wrapFigureContent(nodeToInsert, wrapper);
13557 } else if (node.classList.contains('alignright') || node.classList.contains('alignleft') || node.classList.contains('aligncenter') || !wrapper.textContent.trim()) {
13558 wrapFigureContent(nodeToInsert, wrapper);
13559 }
13560 } else if (nodeToInsert.parentNode.nodeName === 'BODY') {
13561 wrapFigureContent(nodeToInsert);
13562 }
13563 }
13564
13565 ;// CONCATENATED MODULE: external ["wp","shortcode"]
13566 const external_wp_shortcode_namespaceObject = window["wp"]["shortcode"];
13567 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/shortcode-converter.js
13568 /**
13569 * External dependencies
13570 */
13571
13572 /**
13573 * WordPress dependencies
13574 */
13575
13576
13577 /**
13578 * Internal dependencies
13579 */
13580
13581
13582
13583
13584
13585
13586 function segmentHTMLToShortcodeBlock(HTML) {
13587 let lastIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
13588 let excludedBlockNames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
13589 // Get all matches.
13590 const transformsFrom = getBlockTransforms('from');
13591 const transformation = findTransform(transformsFrom, transform => excludedBlockNames.indexOf(transform.blockName) === -1 && transform.type === 'shortcode' && (0,external_lodash_namespaceObject.some)((0,external_lodash_namespaceObject.castArray)(transform.tag), tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML)));
13592
13593 if (!transformation) {
13594 return [HTML];
13595 }
13596
13597 const transformTags = (0,external_lodash_namespaceObject.castArray)(transformation.tag);
13598 const transformTag = (0,external_lodash_namespaceObject.find)(transformTags, tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML));
13599 let match;
13600 const previousIndex = lastIndex;
13601
13602 if (match = (0,external_wp_shortcode_namespaceObject.next)(transformTag, HTML, lastIndex)) {
13603 lastIndex = match.index + match.content.length;
13604 const beforeHTML = HTML.substr(0, match.index);
13605 const afterHTML = HTML.substr(lastIndex); // If the shortcode content does not contain HTML and the shortcode is
13606 // not on a new line (or in paragraph from Markdown converter),
13607 // consider the shortcode as inline text, and thus skip conversion for
13608 // this segment.
13609
13610 if (!(0,external_lodash_namespaceObject.includes)(match.shortcode.content || '', '<') && !(/(\n|<p>)\s*$/.test(beforeHTML) && /^\s*(\n|<\/p>)/.test(afterHTML))) {
13611 return segmentHTMLToShortcodeBlock(HTML, lastIndex);
13612 } // If a transformation's `isMatch` predicate fails for the inbound
13613 // shortcode, try again by excluding the current block type.
13614 //
13615 // This is the only call to `segmentHTMLToShortcodeBlock` that should
13616 // ever carry over `excludedBlockNames`. Other calls in the module
13617 // should skip that argument as a way to reset the exclusion state, so
13618 // that one `isMatch` fail in an HTML fragment doesn't prevent any
13619 // valid matches in subsequent fragments.
13620
13621
13622 if (transformation.isMatch && !transformation.isMatch(match.shortcode.attrs)) {
13623 return segmentHTMLToShortcodeBlock(HTML, previousIndex, [...excludedBlockNames, transformation.blockName]);
13624 }
13625
13626 let blocks = [];
13627
13628 if (typeof transformation.transform === 'function') {
13629 // Passing all of `match` as second argument is intentionally broad
13630 // but shouldn't be too relied upon.
13631 //
13632 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
13633 blocks = [].concat(transformation.transform(match.shortcode.attrs, match)); // Applying the built-in fixes can enhance the attributes with missing content like "className".
13634
13635 blocks = blocks.map(block => {
13636 block.originalContent = match.shortcode.content;
13637 return applyBuiltInValidationFixes(block, registration_getBlockType(block.name));
13638 });
13639 } else {
13640 const attributes = (0,external_lodash_namespaceObject.mapValues)((0,external_lodash_namespaceObject.pickBy)(transformation.attributes, schema => schema.shortcode), // Passing all of `match` as second argument is intentionally broad
13641 // but shouldn't be too relied upon.
13642 //
13643 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
13644 schema => schema.shortcode(match.shortcode.attrs, match));
13645 const blockType = registration_getBlockType(transformation.blockName);
13646
13647 if (!blockType) {
13648 return [HTML];
13649 }
13650
13651 const transformationBlockType = { ...blockType,
13652 attributes: transformation.attributes
13653 };
13654 let block = createBlock(transformation.blockName, getBlockAttributes(transformationBlockType, match.shortcode.content, attributes)); // Applying the built-in fixes can enhance the attributes with missing content like "className".
13655
13656 block.originalContent = match.shortcode.content;
13657 block = applyBuiltInValidationFixes(block, transformationBlockType);
13658 blocks = [block];
13659 }
13660
13661 return [...segmentHTMLToShortcodeBlock(beforeHTML), ...blocks, ...segmentHTMLToShortcodeBlock(afterHTML)];
13662 }
13663
13664 return [HTML];
13665 }
13666
13667 /* harmony default export */ const shortcode_converter = (segmentHTMLToShortcodeBlock);
13668
13669 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/utils.js
13670 /**
13671 * External dependencies
13672 */
13673
13674 /**
13675 * WordPress dependencies
13676 */
13677
13678
13679 /**
13680 * Internal dependencies
13681 */
13682
13683
13684
13685 function getBlockContentSchemaFromTransforms(transforms, context) {
13686 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
13687 const schemaArgs = {
13688 phrasingContentSchema,
13689 isPaste: context === 'paste'
13690 };
13691 const schemas = transforms.map(_ref => {
13692 let {
13693 isMatch,
13694 blockName,
13695 schema
13696 } = _ref;
13697 const hasAnchorSupport = registration_hasBlockSupport(blockName, 'anchor');
13698 schema = typeof schema === 'function' ? schema(schemaArgs) : schema; // If the block does not has anchor support and the transform does not
13699 // provides an isMatch we can return the schema right away.
13700
13701 if (!hasAnchorSupport && !isMatch) {
13702 return schema;
13703 }
13704
13705 return (0,external_lodash_namespaceObject.mapValues)(schema, value => {
13706 let attributes = value.attributes || []; // If the block supports the "anchor" functionality, it needs to keep its ID attribute.
13707
13708 if (hasAnchorSupport) {
13709 attributes = [...attributes, 'id'];
13710 }
13711
13712 return { ...value,
13713 attributes,
13714 isMatch: isMatch ? isMatch : undefined
13715 };
13716 });
13717 });
13718 return (0,external_lodash_namespaceObject.mergeWith)({}, ...schemas, (objValue, srcValue, key) => {
13719 switch (key) {
13720 case 'children':
13721 {
13722 if (objValue === '*' || srcValue === '*') {
13723 return '*';
13724 }
13725
13726 return { ...objValue,
13727 ...srcValue
13728 };
13729 }
13730
13731 case 'attributes':
13732 case 'require':
13733 {
13734 return [...(objValue || []), ...(srcValue || [])];
13735 }
13736
13737 case 'isMatch':
13738 {
13739 // If one of the values being merge is undefined (matches everything),
13740 // the result of the merge will be undefined.
13741 if (!objValue || !srcValue) {
13742 return undefined;
13743 } // When merging two isMatch functions, the result is a new function
13744 // that returns if one of the source functions returns true.
13745
13746
13747 return function () {
13748 return objValue(...arguments) || srcValue(...arguments);
13749 };
13750 }
13751 }
13752 });
13753 }
13754 /**
13755 * Gets the block content schema, which is extracted and merged from all
13756 * registered blocks with raw transfroms.
13757 *
13758 * @param {string} context Set to "paste" when in paste context, where the
13759 * schema is more strict.
13760 *
13761 * @return {Object} A complete block content schema.
13762 */
13763
13764 function getBlockContentSchema(context) {
13765 return getBlockContentSchemaFromTransforms(getRawTransforms(), context);
13766 }
13767 /**
13768 * Checks whether HTML can be considered plain text. That is, it does not contain
13769 * any elements that are not line breaks.
13770 *
13771 * @param {string} HTML The HTML to check.
13772 *
13773 * @return {boolean} Whether the HTML can be considered plain text.
13774 */
13775
13776 function isPlain(HTML) {
13777 return !/<(?!br[ />])/i.test(HTML);
13778 }
13779 /**
13780 * Given node filters, deeply filters and mutates a NodeList.
13781 *
13782 * @param {NodeList} nodeList The nodeList to filter.
13783 * @param {Array} filters An array of functions that can mutate with the provided node.
13784 * @param {Document} doc The document of the nodeList.
13785 * @param {Object} schema The schema to use.
13786 */
13787
13788 function deepFilterNodeList(nodeList, filters, doc, schema) {
13789 Array.from(nodeList).forEach(node => {
13790 deepFilterNodeList(node.childNodes, filters, doc, schema);
13791 filters.forEach(item => {
13792 // Make sure the node is still attached to the document.
13793 if (!doc.contains(node)) {
13794 return;
13795 }
13796
13797 item(node, doc, schema);
13798 });
13799 });
13800 }
13801 /**
13802 * Given node filters, deeply filters HTML tags.
13803 * Filters from the deepest nodes to the top.
13804 *
13805 * @param {string} HTML The HTML to filter.
13806 * @param {Array} filters An array of functions that can mutate with the provided node.
13807 * @param {Object} schema The schema to use.
13808 *
13809 * @return {string} The filtered HTML.
13810 */
13811
13812 function deepFilterHTML(HTML) {
13813 let filters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
13814 let schema = arguments.length > 2 ? arguments[2] : undefined;
13815 const doc = document.implementation.createHTMLDocument('');
13816 doc.body.innerHTML = HTML;
13817 deepFilterNodeList(doc.body.childNodes, filters, doc, schema);
13818 return doc.body.innerHTML;
13819 }
13820 /**
13821 * Gets a sibling within text-level context.
13822 *
13823 * @param {Element} node The subject node.
13824 * @param {string} which "next" or "previous".
13825 */
13826
13827 function getSibling(node, which) {
13828 const sibling = node[`${which}Sibling`];
13829
13830 if (sibling && (0,external_wp_dom_namespaceObject.isPhrasingContent)(sibling)) {
13831 return sibling;
13832 }
13833
13834 const {
13835 parentNode
13836 } = node;
13837
13838 if (!parentNode || !(0,external_wp_dom_namespaceObject.isPhrasingContent)(parentNode)) {
13839 return;
13840 }
13841
13842 return getSibling(parentNode, which);
13843 }
13844
13845 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/index.js
13846 /**
13847 * WordPress dependencies
13848 */
13849
13850
13851 /**
13852 * Internal dependencies
13853 */
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863
13864
13865 function deprecatedGetPhrasingContentSchema(context) {
13866 external_wp_deprecated_default()('wp.blocks.getPhrasingContentSchema', {
13867 since: '5.6',
13868 alternative: 'wp.dom.getPhrasingContentSchema'
13869 });
13870 return (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
13871 }
13872 /**
13873 * Converts an HTML string to known blocks.
13874 *
13875 * @param {Object} $1
13876 * @param {string} $1.HTML The HTML to convert.
13877 *
13878 * @return {Array} A list of blocks.
13879 */
13880
13881 function rawHandler(_ref) {
13882 let {
13883 HTML = ''
13884 } = _ref;
13885
13886 // If we detect block delimiters, parse entirely as blocks.
13887 if (HTML.indexOf('<!-- wp:') !== -1) {
13888 return parser_parse(HTML);
13889 } // An array of HTML strings and block objects. The blocks replace matched
13890 // shortcodes.
13891
13892
13893 const pieces = shortcode_converter(HTML);
13894 const blockContentSchema = getBlockContentSchema();
13895 return pieces.map(piece => {
13896 // Already a block from shortcode.
13897 if (typeof piece !== 'string') {
13898 return piece;
13899 } // These filters are essential for some blocks to be able to transform
13900 // from raw HTML. These filters move around some content or add
13901 // additional tags, they do not remove any content.
13902
13903
13904 const filters = [// Needed to adjust invalid lists.
13905 listReducer, // Needed to create more and nextpage blocks.
13906 specialCommentConverter, // Needed to create media blocks.
13907 figureContentReducer, // Needed to create the quote block, which cannot handle text
13908 // without wrapper paragraphs.
13909 blockquoteNormaliser];
13910 piece = deepFilterHTML(piece, filters, blockContentSchema);
13911 piece = normaliseBlocks(piece);
13912 return htmlToBlocks(piece, rawHandler);
13913 }).flat().filter(Boolean);
13914 }
13915
13916 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/comment-remover.js
13917 /**
13918 * WordPress dependencies
13919 */
13920
13921 /**
13922 * Looks for comments, and removes them.
13923 *
13924 * @param {Node} node The node to be processed.
13925 * @return {void}
13926 */
13927
13928 function commentRemover(node) {
13929 if (node.nodeType === node.COMMENT_NODE) {
13930 (0,external_wp_dom_namespaceObject.remove)(node);
13931 }
13932 }
13933
13934 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/is-inline-content.js
13935 /**
13936 * WordPress dependencies
13937 */
13938
13939 /**
13940 * Checks if the given node should be considered inline content, optionally
13941 * depending on a context tag.
13942 *
13943 * @param {Node} node Node name.
13944 * @param {string} contextTag Tag name.
13945 *
13946 * @return {boolean} True if the node is inline content, false if nohe.
13947 */
13948
13949 function isInline(node, contextTag) {
13950 if ((0,external_wp_dom_namespaceObject.isTextContent)(node)) {
13951 return true;
13952 }
13953
13954 if (!contextTag) {
13955 return false;
13956 }
13957
13958 const tag = node.nodeName.toLowerCase();
13959 const inlineAllowedTagGroups = [['ul', 'li', 'ol'], ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']];
13960 return inlineAllowedTagGroups.some(tagGroup => [tag, contextTag].filter(t => !tagGroup.includes(t)).length === 0);
13961 }
13962
13963 function deepCheck(nodes, contextTag) {
13964 return nodes.every(node => isInline(node, contextTag) && deepCheck(Array.from(node.children), contextTag));
13965 }
13966
13967 function isDoubleBR(node) {
13968 return node.nodeName === 'BR' && node.previousSibling && node.previousSibling.nodeName === 'BR';
13969 }
13970
13971 function isInlineContent(HTML, contextTag) {
13972 const doc = document.implementation.createHTMLDocument('');
13973 doc.body.innerHTML = HTML;
13974 const nodes = Array.from(doc.body.children);
13975 return !nodes.some(isDoubleBR) && deepCheck(nodes, contextTag);
13976 }
13977
13978 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/phrasing-content-reducer.js
13979 /**
13980 * External dependencies
13981 */
13982
13983 /**
13984 * WordPress dependencies
13985 */
13986
13987
13988 function phrasingContentReducer(node, doc) {
13989 // In jsdom-jscore, 'node.style' can be null.
13990 // TODO: Explore fixing this by patching jsdom-jscore.
13991 if (node.nodeName === 'SPAN' && node.style) {
13992 const {
13993 fontWeight,
13994 fontStyle,
13995 textDecorationLine,
13996 textDecoration,
13997 verticalAlign
13998 } = node.style;
13999
14000 if (fontWeight === 'bold' || fontWeight === '700') {
14001 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('strong'), node);
14002 }
14003
14004 if (fontStyle === 'italic') {
14005 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('em'), node);
14006 } // Some DOM implementations (Safari, JSDom) don't support
14007 // style.textDecorationLine, so we check style.textDecoration as a
14008 // fallback.
14009
14010
14011 if (textDecorationLine === 'line-through' || (0,external_lodash_namespaceObject.includes)(textDecoration, 'line-through')) {
14012 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('s'), node);
14013 }
14014
14015 if (verticalAlign === 'super') {
14016 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sup'), node);
14017 } else if (verticalAlign === 'sub') {
14018 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sub'), node);
14019 }
14020 } else if (node.nodeName === 'B') {
14021 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'strong');
14022 } else if (node.nodeName === 'I') {
14023 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'em');
14024 } else if (node.nodeName === 'A') {
14025 // In jsdom-jscore, 'node.target' can be null.
14026 // TODO: Explore fixing this by patching jsdom-jscore.
14027 if (node.target && node.target.toLowerCase() === '_blank') {
14028 node.rel = 'noreferrer noopener';
14029 } else {
14030 node.removeAttribute('target');
14031 node.removeAttribute('rel');
14032 } // Saves anchor elements name attribute as id
14033
14034
14035 if (node.name && !node.id) {
14036 node.id = node.name;
14037 } // Keeps id only if there is an internal link pointing to it
14038
14039
14040 if (node.id && !node.ownerDocument.querySelector(`[href="#${node.id}"]`)) {
14041 node.removeAttribute('id');
14042 }
14043 }
14044 }
14045
14046 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/head-remover.js
14047 function headRemover(node) {
14048 if (node.nodeName !== 'SCRIPT' && node.nodeName !== 'NOSCRIPT' && node.nodeName !== 'TEMPLATE' && node.nodeName !== 'STYLE') {
14049 return;
14050 }
14051
14052 node.parentNode.removeChild(node);
14053 }
14054
14055 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/ms-list-converter.js
14056 /**
14057 * Browser dependencies
14058 */
14059 const {
14060 parseInt: ms_list_converter_parseInt
14061 } = window;
14062
14063 function ms_list_converter_isList(node) {
14064 return node.nodeName === 'OL' || node.nodeName === 'UL';
14065 }
14066
14067 function msListConverter(node, doc) {
14068 if (node.nodeName !== 'P') {
14069 return;
14070 }
14071
14072 const style = node.getAttribute('style');
14073
14074 if (!style) {
14075 return;
14076 } // Quick check.
14077
14078
14079 if (style.indexOf('mso-list') === -1) {
14080 return;
14081 }
14082
14083 const matches = /mso-list\s*:[^;]+level([0-9]+)/i.exec(style);
14084
14085 if (!matches) {
14086 return;
14087 }
14088
14089 let level = ms_list_converter_parseInt(matches[1], 10) - 1 || 0;
14090 const prevNode = node.previousElementSibling; // Add new list if no previous.
14091
14092 if (!prevNode || !ms_list_converter_isList(prevNode)) {
14093 // See https://html.spec.whatwg.org/multipage/grouping-content.html#attr-ol-type.
14094 const type = node.textContent.trim().slice(0, 1);
14095 const isNumeric = /[1iIaA]/.test(type);
14096 const newListNode = doc.createElement(isNumeric ? 'ol' : 'ul');
14097
14098 if (isNumeric) {
14099 newListNode.setAttribute('type', type);
14100 }
14101
14102 node.parentNode.insertBefore(newListNode, node);
14103 }
14104
14105 const listNode = node.previousElementSibling;
14106 const listType = listNode.nodeName;
14107 const listItem = doc.createElement('li');
14108 let receivingNode = listNode; // Remove the first span with list info.
14109
14110 node.removeChild(node.firstChild); // Add content.
14111
14112 while (node.firstChild) {
14113 listItem.appendChild(node.firstChild);
14114 } // Change pointer depending on indentation level.
14115
14116
14117 while (level--) {
14118 receivingNode = receivingNode.lastChild || receivingNode; // If it's a list, move pointer to the last item.
14119
14120 if (ms_list_converter_isList(receivingNode)) {
14121 receivingNode = receivingNode.lastChild || receivingNode;
14122 }
14123 } // Make sure we append to a list.
14124
14125
14126 if (!ms_list_converter_isList(receivingNode)) {
14127 receivingNode = receivingNode.appendChild(doc.createElement(listType));
14128 } // Append the list item to the list.
14129
14130
14131 receivingNode.appendChild(listItem); // Remove the wrapper paragraph.
14132
14133 node.parentNode.removeChild(node);
14134 }
14135
14136 ;// CONCATENATED MODULE: external ["wp","blob"]
14137 const external_wp_blob_namespaceObject = window["wp"]["blob"];
14138 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/image-corrector.js
14139 /**
14140 * WordPress dependencies
14141 */
14142
14143 /**
14144 * Browser dependencies
14145 */
14146
14147 const {
14148 atob,
14149 File
14150 } = window;
14151 function imageCorrector(node) {
14152 if (node.nodeName !== 'IMG') {
14153 return;
14154 }
14155
14156 if (node.src.indexOf('file:') === 0) {
14157 node.src = '';
14158 } // This piece cannot be tested outside a browser env.
14159
14160
14161 if (node.src.indexOf('data:') === 0) {
14162 const [properties, data] = node.src.split(',');
14163 const [type] = properties.slice(5).split(';');
14164
14165 if (!data || !type) {
14166 node.src = '';
14167 return;
14168 }
14169
14170 let decoded; // Can throw DOMException!
14171
14172 try {
14173 decoded = atob(data);
14174 } catch (e) {
14175 node.src = '';
14176 return;
14177 }
14178
14179 const uint8Array = new Uint8Array(decoded.length);
14180
14181 for (let i = 0; i < uint8Array.length; i++) {
14182 uint8Array[i] = decoded.charCodeAt(i);
14183 }
14184
14185 const name = type.replace('/', '.');
14186 const file = new File([uint8Array], name, {
14187 type
14188 });
14189 node.src = (0,external_wp_blob_namespaceObject.createBlobURL)(file);
14190 } // Remove trackers and hardly visible images.
14191
14192
14193 if (node.height === 1 || node.width === 1) {
14194 node.parentNode.removeChild(node);
14195 }
14196 }
14197
14198 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/div-normaliser.js
14199 /**
14200 * Internal dependencies
14201 */
14202
14203 function divNormaliser(node) {
14204 if (node.nodeName !== 'DIV') {
14205 return;
14206 }
14207
14208 node.innerHTML = normaliseBlocks(node.innerHTML);
14209 }
14210
14211 // EXTERNAL MODULE: ./node_modules/showdown/dist/showdown.js
14212 var showdown = __webpack_require__(7308);
14213 var showdown_default = /*#__PURE__*/__webpack_require__.n(showdown);
14214 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/markdown-converter.js
14215 /**
14216 * External dependencies
14217 */
14218 // Reuse the same showdown converter.
14219
14220 const converter = new (showdown_default()).Converter({
14221 noHeaderId: true,
14222 tables: true,
14223 literalMidWordUnderscores: true,
14224 omitExtraWLInCodeBlocks: true,
14225 simpleLineBreaks: true,
14226 strikethrough: true
14227 });
14228 /**
14229 * Corrects the Slack Markdown variant of the code block.
14230 * If uncorrected, it will be converted to inline code.
14231 *
14232 * @see https://get.slack.help/hc/en-us/articles/202288908-how-can-i-add-formatting-to-my-messages-#code-blocks
14233 *
14234 * @param {string} text The potential Markdown text to correct.
14235 *
14236 * @return {string} The corrected Markdown.
14237 */
14238
14239 function slackMarkdownVariantCorrector(text) {
14240 return text.replace(/((?:^|\n)```)([^\n`]+)(```(?:$|\n))/, (match, p1, p2, p3) => `${p1}\n${p2}\n${p3}`);
14241 }
14242 /**
14243 * Converts a piece of text into HTML based on any Markdown present.
14244 * Also decodes any encoded HTML.
14245 *
14246 * @param {string} text The plain text to convert.
14247 *
14248 * @return {string} HTML.
14249 */
14250
14251
14252 function markdownConverter(text) {
14253 return converter.makeHtml(slackMarkdownVariantCorrector(text));
14254 }
14255
14256 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/iframe-remover.js
14257 /**
14258 * Removes iframes.
14259 *
14260 * @param {Node} node The node to check.
14261 *
14262 * @return {void}
14263 */
14264 function iframeRemover(node) {
14265 if (node.nodeName === 'IFRAME') {
14266 const text = node.ownerDocument.createTextNode(node.src);
14267 node.parentNode.replaceChild(text, node);
14268 }
14269 }
14270
14271 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/google-docs-uid-remover.js
14272 /**
14273 * WordPress dependencies
14274 */
14275
14276 function googleDocsUIdRemover(node) {
14277 if (!node.id || node.id.indexOf('docs-internal-guid-') !== 0) {
14278 return;
14279 }
14280
14281 (0,external_wp_dom_namespaceObject.unwrap)(node);
14282 }
14283
14284 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-formatting-remover.js
14285 /**
14286 * Internal dependencies
14287 */
14288
14289
14290 function isFormattingSpace(character) {
14291 return character === ' ' || character === '\r' || character === '\n' || character === '\t';
14292 }
14293 /**
14294 * Removes spacing that formats HTML.
14295 *
14296 * @see https://www.w3.org/TR/css-text-3/#white-space-processing
14297 *
14298 * @param {Node} node The node to be processed.
14299 * @return {void}
14300 */
14301
14302
14303 function htmlFormattingRemover(node) {
14304 if (node.nodeType !== node.TEXT_NODE) {
14305 return;
14306 } // Ignore pre content. Note that this does not use Element#closest due to
14307 // a combination of (a) node may not be Element and (b) node.parentElement
14308 // does not have full support in all browsers (Internet Exporer).
14309 //
14310 // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility
14311
14312 /** @type {Node?} */
14313
14314
14315 let parent = node;
14316
14317 while (parent = parent.parentNode) {
14318 if (parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE') {
14319 return;
14320 }
14321 } // First, replace any sequence of HTML formatting space with a single space.
14322
14323
14324 let newData = node.data.replace(/[ \r\n\t]+/g, ' '); // Remove the leading space if the text element is at the start of a block,
14325 // is preceded by a line break element, or has a space in the previous
14326 // node.
14327
14328 if (newData[0] === ' ') {
14329 const previousSibling = getSibling(node, 'previous');
14330
14331 if (!previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice(-1) === ' ') {
14332 newData = newData.slice(1);
14333 }
14334 } // Remove the trailing space if the text element is at the end of a block,
14335 // is succeded by a line break element, or has a space in the next text
14336 // node.
14337
14338
14339 if (newData[newData.length - 1] === ' ') {
14340 const nextSibling = getSibling(node, 'next');
14341
14342 if (!nextSibling || nextSibling.nodeName === 'BR' || nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace(nextSibling.textContent[0])) {
14343 newData = newData.slice(0, -1);
14344 }
14345 } // If there's no data left, remove the node, so `previousSibling` stays
14346 // accurate. Otherwise, update the node data.
14347
14348
14349 if (!newData) {
14350 node.parentNode.removeChild(node);
14351 } else {
14352 node.data = newData;
14353 }
14354 }
14355
14356 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/br-remover.js
14357 /**
14358 * Internal dependencies
14359 */
14360
14361 /**
14362 * Removes trailing br elements from text-level content.
14363 *
14364 * @param {Element} node Node to check.
14365 */
14366
14367 function brRemover(node) {
14368 if (node.nodeName !== 'BR') {
14369 return;
14370 }
14371
14372 if (getSibling(node, 'next')) {
14373 return;
14374 }
14375
14376 node.parentNode.removeChild(node);
14377 }
14378
14379 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/empty-paragraph-remover.js
14380 /**
14381 * Removes empty paragraph elements.
14382 *
14383 * @param {Element} node Node to check.
14384 */
14385 function emptyParagraphRemover(node) {
14386 if (node.nodeName !== 'P') {
14387 return;
14388 }
14389
14390 if (node.hasChildNodes()) {
14391 return;
14392 }
14393
14394 node.parentNode.removeChild(node);
14395 }
14396
14397 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/slack-paragraph-corrector.js
14398 /**
14399 * Replaces Slack paragraph markup with a double line break (later converted to
14400 * a proper paragraph).
14401 *
14402 * @param {Element} node Node to check.
14403 */
14404 function slackParagraphCorrector(node) {
14405 if (node.nodeName !== 'SPAN') {
14406 return;
14407 }
14408
14409 if (node.getAttribute('data-stringify-type') !== 'paragraph-break') {
14410 return;
14411 }
14412
14413 const {
14414 parentNode
14415 } = node;
14416 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
14417 parentNode.insertBefore(node.ownerDocument.createElement('br'), node);
14418 parentNode.removeChild(node);
14419 }
14420
14421 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/paste-handler.js
14422 /**
14423 * WordPress dependencies
14424 */
14425
14426 /**
14427 * Internal dependencies
14428 */
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452
14453
14454
14455 /**
14456 * Browser dependencies
14457 */
14458
14459 const {
14460 console: paste_handler_console
14461 } = window;
14462 /**
14463 * Filters HTML to only contain phrasing content.
14464 *
14465 * @param {string} HTML The HTML to filter.
14466 * @param {boolean} preserveWhiteSpace Whether or not to preserve consequent white space.
14467 *
14468 * @return {string} HTML only containing phrasing content.
14469 */
14470
14471 function filterInlineHTML(HTML, preserveWhiteSpace) {
14472 HTML = deepFilterHTML(HTML, [googleDocsUIdRemover, phrasingContentReducer, commentRemover]);
14473 HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
14474 inline: true
14475 });
14476
14477 if (!preserveWhiteSpace) {
14478 HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
14479 } // Allows us to ask for this information when we get a report.
14480
14481
14482 paste_handler_console.log('Processed inline HTML:\n\n', HTML);
14483 return HTML;
14484 }
14485 /**
14486 * Converts an HTML string to known blocks. Strips everything else.
14487 *
14488 * @param {Object} options
14489 * @param {string} [options.HTML] The HTML to convert.
14490 * @param {string} [options.plainText] Plain text version.
14491 * @param {string} [options.mode] Handle content as blocks or inline content.
14492 * * 'AUTO': Decide based on the content passed.
14493 * * 'INLINE': Always handle as inline content, and return string.
14494 * * 'BLOCKS': Always handle as blocks, and return array of blocks.
14495 * @param {Array} [options.tagName] The tag into which content will be inserted.
14496 * @param {boolean} [options.preserveWhiteSpace] Whether or not to preserve consequent white space.
14497 *
14498 * @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
14499 */
14500
14501
14502 function pasteHandler(_ref) {
14503 let {
14504 HTML = '',
14505 plainText = '',
14506 mode = 'AUTO',
14507 tagName,
14508 preserveWhiteSpace
14509 } = _ref;
14510 // First of all, strip any meta tags.
14511 HTML = HTML.replace(/<meta[^>]+>/g, ''); // Strip Windows markers.
14512
14513 HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
14514 HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, ''); // If we detect block delimiters in HTML, parse entirely as blocks.
14515
14516 if (mode !== 'INLINE') {
14517 // Check plain text if there is no HTML.
14518 const content = HTML ? HTML : plainText;
14519
14520 if (content.indexOf('<!-- wp:') !== -1) {
14521 return parser_parse(content);
14522 }
14523 } // Normalize unicode to use composed characters.
14524 // This is unsupported in IE 11 but it's a nice-to-have feature, not mandatory.
14525 // Not normalizing the content will only affect older browsers and won't
14526 // entirely break the app.
14527 // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
14528 // See: https://core.trac.wordpress.org/ticket/30130
14529 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
14530
14531
14532 if (String.prototype.normalize) {
14533 HTML = HTML.normalize();
14534 } // Parse Markdown (and encoded HTML) if:
14535 // * There is a plain text version.
14536 // * There is no HTML version, or it has no formatting.
14537
14538
14539 if (plainText && (!HTML || isPlain(HTML))) {
14540 HTML = plainText; // The markdown converter (Showdown) trims whitespace.
14541
14542 if (!/^\s+$/.test(plainText)) {
14543 HTML = markdownConverter(HTML);
14544 } // Switch to inline mode if:
14545 // * The current mode is AUTO.
14546 // * The original plain text had no line breaks.
14547 // * The original plain text was not an HTML paragraph.
14548 // * The converted text is just a paragraph.
14549
14550
14551 if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
14552 mode = 'INLINE';
14553 }
14554 }
14555
14556 if (mode === 'INLINE') {
14557 return filterInlineHTML(HTML, preserveWhiteSpace);
14558 } // Must be run before checking if it's inline content.
14559
14560
14561 HTML = deepFilterHTML(HTML, [slackParagraphCorrector]); // An array of HTML strings and block objects. The blocks replace matched
14562 // shortcodes.
14563
14564 const pieces = shortcode_converter(HTML); // The call to shortcodeConverter will always return more than one element
14565 // if shortcodes are matched. The reason is when shortcodes are matched
14566 // empty HTML strings are included.
14567
14568 const hasShortcodes = pieces.length > 1;
14569
14570 if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
14571 return filterInlineHTML(HTML, preserveWhiteSpace);
14572 }
14573
14574 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
14575 const blockContentSchema = getBlockContentSchema('paste');
14576 const blocks = pieces.map(piece => {
14577 // Already a block from shortcode.
14578 if (typeof piece !== 'string') {
14579 return piece;
14580 }
14581
14582 const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser, divNormaliser];
14583 const schema = { ...blockContentSchema,
14584 // Keep top-level phrasing content, normalised by `normaliseBlocks`.
14585 ...phrasingContentSchema
14586 };
14587 piece = deepFilterHTML(piece, filters, blockContentSchema);
14588 piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
14589 piece = normaliseBlocks(piece);
14590 piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema); // Allows us to ask for this information when we get a report.
14591
14592 paste_handler_console.log('Processed HTML piece:\n\n', piece);
14593 return htmlToBlocks(piece, pasteHandler);
14594 }).flat().filter(Boolean); // If we're allowed to return inline content, and there is only one
14595 // inlineable block, and the original plain text content does not have any
14596 // line breaks, then treat it as inline paste.
14597
14598 if (mode === 'AUTO' && blocks.length === 1 && registration_hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
14599 const trimRegex = /^[\n]+|[\n]+$/g; // Don't catch line breaks at the start or end.
14600
14601 const trimmedPlainText = plainText.replace(trimRegex, '');
14602
14603 if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
14604 return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema).replace(trimRegex, '');
14605 }
14606 }
14607
14608 return blocks;
14609 }
14610
14611 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/categories.js
14612 /**
14613 * WordPress dependencies
14614 */
14615
14616 /**
14617 * Internal dependencies
14618 */
14619
14620
14621 /** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
14622
14623 /**
14624 * Returns all the block categories.
14625 * Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
14626 *
14627 * @ignore
14628 *
14629 * @return {WPBlockCategory[]} Block categories.
14630 */
14631
14632 function categories_getCategories() {
14633 return (0,external_wp_data_namespaceObject.select)(store).getCategories();
14634 }
14635 /**
14636 * Sets the block categories.
14637 *
14638 * @param {WPBlockCategory[]} categories Block categories.
14639 *
14640 * @example
14641 * ```js
14642 * import { __ } from '@wordpress/i18n';
14643 * import { store as blocksStore, setCategories } from '@wordpress/blocks';
14644 * import { useSelect } from '@wordpress/data';
14645 * import { Button } from '@wordpress/components';
14646 *
14647 * const ExampleComponent = () => {
14648 * // Retrieve the list of current categories.
14649 * const blockCategories = useSelect(
14650 * ( select ) => select( blocksStore ).getCategories(),
14651 * []
14652 * );
14653 *
14654 * return (
14655 * <Button
14656 * onClick={ () => {
14657 * // Add a custom category to the existing list.
14658 * setCategories( [
14659 * ...blockCategories,
14660 * { title: 'Custom Category', slug: 'custom-category' },
14661 * ] );
14662 * } }
14663 * >
14664 * { __( 'Add a new custom block category' ) }
14665 * </Button>
14666 * );
14667 * };
14668 * ```
14669 */
14670
14671 function categories_setCategories(categories) {
14672 (0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
14673 }
14674 /**
14675 * Updates a category.
14676 *
14677 * @param {string} slug Block category slug.
14678 * @param {WPBlockCategory} category Object containing the category properties
14679 * that should be updated.
14680 *
14681 * @example
14682 * ```js
14683 * import { __ } from '@wordpress/i18n';
14684 * import { updateCategory } from '@wordpress/blocks';
14685 * import { Button } from '@wordpress/components';
14686 *
14687 * const ExampleComponent = () => {
14688 * return (
14689 * <Button
14690 * onClick={ () => {
14691 * updateCategory( 'text', { title: __( 'Written Word' ) } );
14692 * } }
14693 * >
14694 * { __( 'Update Text category title' ) }
14695 * </Button>
14696 * ) ;
14697 * };
14698 * ```
14699 */
14700
14701 function categories_updateCategory(slug, category) {
14702 (0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
14703 }
14704
14705 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/templates.js
14706 /**
14707 * External dependencies
14708 */
14709
14710 /**
14711 * WordPress dependencies
14712 */
14713
14714
14715 /**
14716 * Internal dependencies
14717 */
14718
14719
14720
14721
14722 /**
14723 * Checks whether a list of blocks matches a template by comparing the block names.
14724 *
14725 * @param {Array} blocks Block list.
14726 * @param {Array} template Block template.
14727 *
14728 * @return {boolean} Whether the list of blocks matches a templates.
14729 */
14730
14731 function doBlocksMatchTemplate() {
14732 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
14733 let template = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
14734 return blocks.length === template.length && (0,external_lodash_namespaceObject.every)(template, (_ref, index) => {
14735 let [name,, innerBlocksTemplate] = _ref;
14736 const block = blocks[index];
14737 return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
14738 });
14739 }
14740 /**
14741 * Synchronize a block list with a block template.
14742 *
14743 * Synchronizing a block list with a block template means that we loop over the blocks
14744 * keep the block as is if it matches the block at the same position in the template
14745 * (If it has the same name) and if doesn't match, we create a new block based on the template.
14746 * Extra blocks not present in the template are removed.
14747 *
14748 * @param {Array} blocks Block list.
14749 * @param {Array} template Block template.
14750 *
14751 * @return {Array} Updated Block list.
14752 */
14753
14754 function synchronizeBlocksWithTemplate() {
14755 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
14756 let template = arguments.length > 1 ? arguments[1] : undefined;
14757
14758 // If no template is provided, return blocks unmodified.
14759 if (!template) {
14760 return blocks;
14761 }
14762
14763 return (0,external_lodash_namespaceObject.map)(template, (_ref2, index) => {
14764 let [name, attributes, innerBlocksTemplate] = _ref2;
14765 const block = blocks[index];
14766
14767 if (block && block.name === name) {
14768 const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
14769 return { ...block,
14770 innerBlocks
14771 };
14772 } // To support old templates that were using the "children" format
14773 // for the attributes using "html" strings now, we normalize the template attributes
14774 // before creating the blocks.
14775
14776
14777 const blockType = registration_getBlockType(name);
14778
14779 const isHTMLAttribute = attributeDefinition => (0,external_lodash_namespaceObject.get)(attributeDefinition, ['source']) === 'html';
14780
14781 const isQueryAttribute = attributeDefinition => (0,external_lodash_namespaceObject.get)(attributeDefinition, ['source']) === 'query';
14782
14783 const normalizeAttributes = (schema, values) => {
14784 return (0,external_lodash_namespaceObject.mapValues)(values, (value, key) => {
14785 return normalizeAttribute(schema[key], value);
14786 });
14787 };
14788
14789 const normalizeAttribute = (definition, value) => {
14790 if (isHTMLAttribute(definition) && Array.isArray(value)) {
14791 // Introduce a deprecated call at this point
14792 // When we're confident that "children" format should be removed from the templates.
14793 return (0,external_wp_element_namespaceObject.renderToString)(value);
14794 }
14795
14796 if (isQueryAttribute(definition) && value) {
14797 return value.map(subValues => {
14798 return normalizeAttributes(definition.query, subValues);
14799 });
14800 }
14801
14802 return value;
14803 };
14804
14805 const normalizedAttributes = normalizeAttributes((0,external_lodash_namespaceObject.get)(blockType, ['attributes'], {}), attributes);
14806 let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes); // If a Block is undefined at this point, use the core/missing block as
14807 // a placeholder for a better user experience.
14808
14809 if (undefined === registration_getBlockType(blockName)) {
14810 blockAttributes = {
14811 originalName: name,
14812 originalContent: '',
14813 originalUndelimitedContent: ''
14814 };
14815 blockName = 'core/missing';
14816 }
14817
14818 return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
14819 });
14820 }
14821
14822 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/index.js
14823 // The blocktype is the most important concept within the block API. It defines
14824 // all aspects of the block configuration and its interfaces, including `edit`
14825 // and `save`. The transforms specification allows converting one blocktype to
14826 // another through formulas defined by either the source or the destination.
14827 // Switching a blocktype is to be considered a one-way operation implying a
14828 // transformation in the opposite way has to be handled explicitly.
14829 // The block tree is composed of a collection of block nodes. Blocks contained
14830 // within other blocks are called inner blocks. An important design
14831 // consideration is that inner blocks are -- conceptually -- not part of the
14832 // territory established by the parent block that contains them.
14833 //
14834 // This has multiple practical implications: when parsing, we can safely dispose
14835 // of any block boundary found within a block from the innerHTML property when
14836 // transfering to state. Not doing so would have a compounding effect on memory
14837 // and uncertainty over the source of truth. This can be illustrated in how,
14838 // given a tree of `n` nested blocks, the entry node would have to contain the
14839 // actual content of each block while each subsequent block node in the state
14840 // tree would replicate the entire chain `n-1`, meaning the extreme end node
14841 // would have been replicated `n` times as the tree is traversed and would
14842 // generate uncertainty as to which one is to hold the current value of the
14843 // block. For composition, it also means inner blocks can effectively be child
14844 // components whose mechanisms can be shielded from the `edit` implementation
14845 // and just passed along.
14846
14847
14848
14849 // While block transformations account for a specific surface of the API, there
14850 // are also raw transformations which handle arbitrary sources not made out of
14851 // blocks but producing block basaed on various heursitics. This includes
14852 // pasting rich text or HTML data.
14853
14854 // The process of serialization aims to deflate the internal memory of the block
14855 // editor and its state representation back into an HTML valid string. This
14856 // process restores the document integrity and inserts invisible delimiters
14857 // around each block with HTML comment boundaries which can contain any extra
14858 // attributes needed to operate with the block later on.
14859
14860 // Validation is the process of comparing a block source with its output before
14861 // there is any user input or interaction with a block. When this operation
14862 // fails -- for whatever reason -- the block is to be considered invalid. As
14863 // part of validating a block the system will attempt to run the source against
14864 // any provided deprecation definitions.
14865 //
14866 // Worth emphasizing that validation is not a case of whether the markup is
14867 // merely HTML spec-compliant but about how the editor knows to create such
14868 // markup and that its inability to create an identical result can be a strong
14869 // indicator of potential data loss (the invalidation is then a protective
14870 // measure).
14871 //
14872 // The invalidation process can also be deconstructed in phases: 1) validate the
14873 // block exists; 2) validate the source matches the output; 3) validate the
14874 // source matches deprecated outputs; 4) work through the significance of
14875 // differences. These are stacked in a way that favors performance and optimizes
14876 // for the majority of cases. That is to say, the evaluation logic can become
14877 // more sophisticated the further down it goes in the process as the cost is
14878 // accounted for. The first logic checks have to be extremely efficient since
14879 // they will be run for all valid and invalid blocks alike. However, once a
14880 // block is detected as invalid -- failing the three first steps -- it is
14881 // adequate to spend more time determining validity before throwing a conflict.
14882
14883
14884 // Blocks are inherently indifferent about where the data they operate with ends
14885 // up being saved. For example, all blocks can have a static and dynamic aspect
14886 // to them depending on the needs. The static nature of a block is the `save()`
14887 // definition that is meant to be serialized into HTML and which can be left
14888 // void. Any block can also register a `render_callback` on the server, which
14889 // makes its output dynamic either in part or in its totality.
14890 //
14891 // Child blocks are defined as a relationship that builds on top of the inner
14892 // blocks mechanism. A child block is a block node of a particular type that can
14893 // only exist within the inner block boundaries of a specific parent type. This
14894 // allows block authors to compose specific blocks that are not meant to be used
14895 // outside of a specified parent block context. Thus, child blocks extend the
14896 // concept of inner blocks to support a more direct relationship between sets of
14897 // blocks. The addition of parent–child would be a subset of the inner block
14898 // functionality under the premise that certain blocks only make sense as
14899 // children of another block.
14900
14901
14902 // Templates are, in a general sense, a basic collection of block nodes with any
14903 // given set of predefined attributes that are supplied as the initial state of
14904 // an inner blocks group. These nodes can, in turn, contain any number of nested
14905 // blocks within their definition. Templates allow both to specify a default
14906 // state for an editor session or a default set of blocks for any inner block
14907 // implementation within a specific block.
14908
14909
14910
14911
14912
14913
14914 ;// CONCATENATED MODULE: ./packages/blocks/build-module/deprecated.js
14915 /**
14916 * WordPress dependencies
14917 */
14918
14919 /**
14920 * A Higher Order Component used to inject BlockContent using context to the
14921 * wrapped component.
14922 *
14923 * @deprecated
14924 *
14925 * @param {WPComponent} OriginalComponent The component to enhance.
14926 * @return {WPComponent} The same component.
14927 */
14928
14929 function withBlockContentContext(OriginalComponent) {
14930 external_wp_deprecated_default()('wp.blocks.withBlockContentContext', {
14931 since: '6.1'
14932 });
14933 return OriginalComponent;
14934 }
14935
14936 ;// CONCATENATED MODULE: ./packages/blocks/build-module/index.js
14937 // A "block" is the abstract term used to describe units of markup that,
14938 // when composed together, form the content or layout of a page.
14939 // The API for blocks is exposed via `wp.blocks`.
14940 //
14941 // Supported blocks are registered by calling `registerBlockType`. Once registered,
14942 // the block is made available as an option to the editor interface.
14943 //
14944 // Blocks are inferred from the HTML source of a post through a parsing mechanism
14945 // and then stored as objects in state, from which it is then rendered for editing.
14946
14947
14948
14949
14950 })();
14951
14952 (window.wp = window.wp || {}).blocks = __webpack_exports__;
14953 /******/ })()
14954 ;