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

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

13,296 lines 464.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (function() { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ 9756:
5 /***/ (function(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 /***/ 7308:
173 /***/ (function(module, exports, __webpack_require__) {
174
175 var __WEBPACK_AMD_DEFINE_RESULT__;;/*! showdown v 1.9.1 - 02-11-2019 */
176 (function(){
177 /**
178 * Created by Tivie on 13-07-2015.
179 */
180
181 function getDefaultOpts (simple) {
182 'use strict';
183
184 var defaultOptions = {
185 omitExtraWLInCodeBlocks: {
186 defaultValue: false,
187 describe: 'Omit the default extra whiteline added to code blocks',
188 type: 'boolean'
189 },
190 noHeaderId: {
191 defaultValue: false,
192 describe: 'Turn on/off generated header id',
193 type: 'boolean'
194 },
195 prefixHeaderId: {
196 defaultValue: false,
197 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',
198 type: 'string'
199 },
200 rawPrefixHeaderId: {
201 defaultValue: false,
202 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)',
203 type: 'boolean'
204 },
205 ghCompatibleHeaderId: {
206 defaultValue: false,
207 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
208 type: 'boolean'
209 },
210 rawHeaderId: {
211 defaultValue: false,
212 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
213 type: 'boolean'
214 },
215 headerLevelStart: {
216 defaultValue: false,
217 describe: 'The header blocks level start',
218 type: 'integer'
219 },
220 parseImgDimensions: {
221 defaultValue: false,
222 describe: 'Turn on/off image dimension parsing',
223 type: 'boolean'
224 },
225 simplifiedAutoLink: {
226 defaultValue: false,
227 describe: 'Turn on/off GFM autolink style',
228 type: 'boolean'
229 },
230 excludeTrailingPunctuationFromURLs: {
231 defaultValue: false,
232 describe: 'Excludes trailing punctuation from links generated with autoLinking',
233 type: 'boolean'
234 },
235 literalMidWordUnderscores: {
236 defaultValue: false,
237 describe: 'Parse midword underscores as literal underscores',
238 type: 'boolean'
239 },
240 literalMidWordAsterisks: {
241 defaultValue: false,
242 describe: 'Parse midword asterisks as literal asterisks',
243 type: 'boolean'
244 },
245 strikethrough: {
246 defaultValue: false,
247 describe: 'Turn on/off strikethrough support',
248 type: 'boolean'
249 },
250 tables: {
251 defaultValue: false,
252 describe: 'Turn on/off tables support',
253 type: 'boolean'
254 },
255 tablesHeaderId: {
256 defaultValue: false,
257 describe: 'Add an id to table headers',
258 type: 'boolean'
259 },
260 ghCodeBlocks: {
261 defaultValue: true,
262 describe: 'Turn on/off GFM fenced code blocks support',
263 type: 'boolean'
264 },
265 tasklists: {
266 defaultValue: false,
267 describe: 'Turn on/off GFM tasklist support',
268 type: 'boolean'
269 },
270 smoothLivePreview: {
271 defaultValue: false,
272 describe: 'Prevents weird effects in live previews due to incomplete input',
273 type: 'boolean'
274 },
275 smartIndentationFix: {
276 defaultValue: false,
277 description: 'Tries to smartly fix indentation in es6 strings',
278 type: 'boolean'
279 },
280 disableForced4SpacesIndentedSublists: {
281 defaultValue: false,
282 description: 'Disables the requirement of indenting nested sublists by 4 spaces',
283 type: 'boolean'
284 },
285 simpleLineBreaks: {
286 defaultValue: false,
287 description: 'Parses simple line breaks as <br> (GFM Style)',
288 type: 'boolean'
289 },
290 requireSpaceBeforeHeadingText: {
291 defaultValue: false,
292 description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
293 type: 'boolean'
294 },
295 ghMentions: {
296 defaultValue: false,
297 description: 'Enables github @mentions',
298 type: 'boolean'
299 },
300 ghMentionsLink: {
301 defaultValue: 'https://github.com/{u}',
302 description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
303 type: 'string'
304 },
305 encodeEmails: {
306 defaultValue: true,
307 description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
308 type: 'boolean'
309 },
310 openLinksInNewWindow: {
311 defaultValue: false,
312 description: 'Open all links in new windows',
313 type: 'boolean'
314 },
315 backslashEscapesHTMLTags: {
316 defaultValue: false,
317 description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
318 type: 'boolean'
319 },
320 emoji: {
321 defaultValue: false,
322 description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
323 type: 'boolean'
324 },
325 underline: {
326 defaultValue: false,
327 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>`',
328 type: 'boolean'
329 },
330 completeHTMLDocument: {
331 defaultValue: false,
332 description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
333 type: 'boolean'
334 },
335 metadata: {
336 defaultValue: false,
337 description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
338 type: 'boolean'
339 },
340 splitAdjacentBlockquotes: {
341 defaultValue: false,
342 description: 'Split adjacent blockquote blocks',
343 type: 'boolean'
344 }
345 };
346 if (simple === false) {
347 return JSON.parse(JSON.stringify(defaultOptions));
348 }
349 var ret = {};
350 for (var opt in defaultOptions) {
351 if (defaultOptions.hasOwnProperty(opt)) {
352 ret[opt] = defaultOptions[opt].defaultValue;
353 }
354 }
355 return ret;
356 }
357
358 function allOptionsOn () {
359 'use strict';
360 var options = getDefaultOpts(true),
361 ret = {};
362 for (var opt in options) {
363 if (options.hasOwnProperty(opt)) {
364 ret[opt] = true;
365 }
366 }
367 return ret;
368 }
369
370 /**
371 * Created by Tivie on 06-01-2015.
372 */
373
374 // Private properties
375 var showdown = {},
376 parsers = {},
377 extensions = {},
378 globalOptions = getDefaultOpts(true),
379 setFlavor = 'vanilla',
380 flavor = {
381 github: {
382 omitExtraWLInCodeBlocks: true,
383 simplifiedAutoLink: true,
384 excludeTrailingPunctuationFromURLs: true,
385 literalMidWordUnderscores: true,
386 strikethrough: true,
387 tables: true,
388 tablesHeaderId: true,
389 ghCodeBlocks: true,
390 tasklists: true,
391 disableForced4SpacesIndentedSublists: true,
392 simpleLineBreaks: true,
393 requireSpaceBeforeHeadingText: true,
394 ghCompatibleHeaderId: true,
395 ghMentions: true,
396 backslashEscapesHTMLTags: true,
397 emoji: true,
398 splitAdjacentBlockquotes: true
399 },
400 original: {
401 noHeaderId: true,
402 ghCodeBlocks: false
403 },
404 ghost: {
405 omitExtraWLInCodeBlocks: true,
406 parseImgDimensions: true,
407 simplifiedAutoLink: true,
408 excludeTrailingPunctuationFromURLs: true,
409 literalMidWordUnderscores: true,
410 strikethrough: true,
411 tables: true,
412 tablesHeaderId: true,
413 ghCodeBlocks: true,
414 tasklists: true,
415 smoothLivePreview: true,
416 simpleLineBreaks: true,
417 requireSpaceBeforeHeadingText: true,
418 ghMentions: false,
419 encodeEmails: true
420 },
421 vanilla: getDefaultOpts(true),
422 allOn: allOptionsOn()
423 };
424
425 /**
426 * helper namespace
427 * @type {{}}
428 */
429 showdown.helper = {};
430
431 /**
432 * TODO LEGACY SUPPORT CODE
433 * @type {{}}
434 */
435 showdown.extensions = {};
436
437 /**
438 * Set a global option
439 * @static
440 * @param {string} key
441 * @param {*} value
442 * @returns {showdown}
443 */
444 showdown.setOption = function (key, value) {
445 'use strict';
446 globalOptions[key] = value;
447 return this;
448 };
449
450 /**
451 * Get a global option
452 * @static
453 * @param {string} key
454 * @returns {*}
455 */
456 showdown.getOption = function (key) {
457 'use strict';
458 return globalOptions[key];
459 };
460
461 /**
462 * Get the global options
463 * @static
464 * @returns {{}}
465 */
466 showdown.getOptions = function () {
467 'use strict';
468 return globalOptions;
469 };
470
471 /**
472 * Reset global options to the default values
473 * @static
474 */
475 showdown.resetOptions = function () {
476 'use strict';
477 globalOptions = getDefaultOpts(true);
478 };
479
480 /**
481 * Set the flavor showdown should use as default
482 * @param {string} name
483 */
484 showdown.setFlavor = function (name) {
485 'use strict';
486 if (!flavor.hasOwnProperty(name)) {
487 throw Error(name + ' flavor was not found');
488 }
489 showdown.resetOptions();
490 var preset = flavor[name];
491 setFlavor = name;
492 for (var option in preset) {
493 if (preset.hasOwnProperty(option)) {
494 globalOptions[option] = preset[option];
495 }
496 }
497 };
498
499 /**
500 * Get the currently set flavor
501 * @returns {string}
502 */
503 showdown.getFlavor = function () {
504 'use strict';
505 return setFlavor;
506 };
507
508 /**
509 * Get the options of a specified flavor. Returns undefined if the flavor was not found
510 * @param {string} name Name of the flavor
511 * @returns {{}|undefined}
512 */
513 showdown.getFlavorOptions = function (name) {
514 'use strict';
515 if (flavor.hasOwnProperty(name)) {
516 return flavor[name];
517 }
518 };
519
520 /**
521 * Get the default options
522 * @static
523 * @param {boolean} [simple=true]
524 * @returns {{}}
525 */
526 showdown.getDefaultOptions = function (simple) {
527 'use strict';
528 return getDefaultOpts(simple);
529 };
530
531 /**
532 * Get or set a subParser
533 *
534 * subParser(name) - Get a registered subParser
535 * subParser(name, func) - Register a subParser
536 * @static
537 * @param {string} name
538 * @param {function} [func]
539 * @returns {*}
540 */
541 showdown.subParser = function (name, func) {
542 'use strict';
543 if (showdown.helper.isString(name)) {
544 if (typeof func !== 'undefined') {
545 parsers[name] = func;
546 } else {
547 if (parsers.hasOwnProperty(name)) {
548 return parsers[name];
549 } else {
550 throw Error('SubParser named ' + name + ' not registered!');
551 }
552 }
553 }
554 };
555
556 /**
557 * Gets or registers an extension
558 * @static
559 * @param {string} name
560 * @param {object|function=} ext
561 * @returns {*}
562 */
563 showdown.extension = function (name, ext) {
564 'use strict';
565
566 if (!showdown.helper.isString(name)) {
567 throw Error('Extension \'name\' must be a string');
568 }
569
570 name = showdown.helper.stdExtName(name);
571
572 // Getter
573 if (showdown.helper.isUndefined(ext)) {
574 if (!extensions.hasOwnProperty(name)) {
575 throw Error('Extension named ' + name + ' is not registered!');
576 }
577 return extensions[name];
578
579 // Setter
580 } else {
581 // Expand extension if it's wrapped in a function
582 if (typeof ext === 'function') {
583 ext = ext();
584 }
585
586 // Ensure extension is an array
587 if (!showdown.helper.isArray(ext)) {
588 ext = [ext];
589 }
590
591 var validExtension = validate(ext, name);
592
593 if (validExtension.valid) {
594 extensions[name] = ext;
595 } else {
596 throw Error(validExtension.error);
597 }
598 }
599 };
600
601 /**
602 * Gets all extensions registered
603 * @returns {{}}
604 */
605 showdown.getAllExtensions = function () {
606 'use strict';
607 return extensions;
608 };
609
610 /**
611 * Remove an extension
612 * @param {string} name
613 */
614 showdown.removeExtension = function (name) {
615 'use strict';
616 delete extensions[name];
617 };
618
619 /**
620 * Removes all extensions
621 */
622 showdown.resetExtensions = function () {
623 'use strict';
624 extensions = {};
625 };
626
627 /**
628 * Validate extension
629 * @param {array} extension
630 * @param {string} name
631 * @returns {{valid: boolean, error: string}}
632 */
633 function validate (extension, name) {
634 'use strict';
635
636 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
637 ret = {
638 valid: true,
639 error: ''
640 };
641
642 if (!showdown.helper.isArray(extension)) {
643 extension = [extension];
644 }
645
646 for (var i = 0; i < extension.length; ++i) {
647 var baseMsg = errMsg + ' sub-extension ' + i + ': ',
648 ext = extension[i];
649 if (typeof ext !== 'object') {
650 ret.valid = false;
651 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
652 return ret;
653 }
654
655 if (!showdown.helper.isString(ext.type)) {
656 ret.valid = false;
657 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
658 return ret;
659 }
660
661 var type = ext.type = ext.type.toLowerCase();
662
663 // normalize extension type
664 if (type === 'language') {
665 type = ext.type = 'lang';
666 }
667
668 if (type === 'html') {
669 type = ext.type = 'output';
670 }
671
672 if (type !== 'lang' && type !== 'output' && type !== 'listener') {
673 ret.valid = false;
674 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
675 return ret;
676 }
677
678 if (type === 'listener') {
679 if (showdown.helper.isUndefined(ext.listeners)) {
680 ret.valid = false;
681 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
682 return ret;
683 }
684 } else {
685 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
686 ret.valid = false;
687 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
688 return ret;
689 }
690 }
691
692 if (ext.listeners) {
693 if (typeof ext.listeners !== 'object') {
694 ret.valid = false;
695 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
696 return ret;
697 }
698 for (var ln in ext.listeners) {
699 if (ext.listeners.hasOwnProperty(ln)) {
700 if (typeof ext.listeners[ln] !== 'function') {
701 ret.valid = false;
702 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
703 ' must be a function but ' + typeof ext.listeners[ln] + ' given';
704 return ret;
705 }
706 }
707 }
708 }
709
710 if (ext.filter) {
711 if (typeof ext.filter !== 'function') {
712 ret.valid = false;
713 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
714 return ret;
715 }
716 } else if (ext.regex) {
717 if (showdown.helper.isString(ext.regex)) {
718 ext.regex = new RegExp(ext.regex, 'g');
719 }
720 if (!(ext.regex instanceof RegExp)) {
721 ret.valid = false;
722 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
723 return ret;
724 }
725 if (showdown.helper.isUndefined(ext.replace)) {
726 ret.valid = false;
727 ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
728 return ret;
729 }
730 }
731 }
732 return ret;
733 }
734
735 /**
736 * Validate extension
737 * @param {object} ext
738 * @returns {boolean}
739 */
740 showdown.validateExtension = function (ext) {
741 'use strict';
742
743 var validateExtension = validate(ext, null);
744 if (!validateExtension.valid) {
745 console.warn(validateExtension.error);
746 return false;
747 }
748 return true;
749 };
750
751 /**
752 * showdownjs helper functions
753 */
754
755 if (!showdown.hasOwnProperty('helper')) {
756 showdown.helper = {};
757 }
758
759 /**
760 * Check if var is string
761 * @static
762 * @param {string} a
763 * @returns {boolean}
764 */
765 showdown.helper.isString = function (a) {
766 'use strict';
767 return (typeof a === 'string' || a instanceof String);
768 };
769
770 /**
771 * Check if var is a function
772 * @static
773 * @param {*} a
774 * @returns {boolean}
775 */
776 showdown.helper.isFunction = function (a) {
777 'use strict';
778 var getType = {};
779 return a && getType.toString.call(a) === '[object Function]';
780 };
781
782 /**
783 * isArray helper function
784 * @static
785 * @param {*} a
786 * @returns {boolean}
787 */
788 showdown.helper.isArray = function (a) {
789 'use strict';
790 return Array.isArray(a);
791 };
792
793 /**
794 * Check if value is undefined
795 * @static
796 * @param {*} value The value to check.
797 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
798 */
799 showdown.helper.isUndefined = function (value) {
800 'use strict';
801 return typeof value === 'undefined';
802 };
803
804 /**
805 * ForEach helper function
806 * Iterates over Arrays and Objects (own properties only)
807 * @static
808 * @param {*} obj
809 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
810 */
811 showdown.helper.forEach = function (obj, callback) {
812 'use strict';
813 // check if obj is defined
814 if (showdown.helper.isUndefined(obj)) {
815 throw new Error('obj param is required');
816 }
817
818 if (showdown.helper.isUndefined(callback)) {
819 throw new Error('callback param is required');
820 }
821
822 if (!showdown.helper.isFunction(callback)) {
823 throw new Error('callback param must be a function/closure');
824 }
825
826 if (typeof obj.forEach === 'function') {
827 obj.forEach(callback);
828 } else if (showdown.helper.isArray(obj)) {
829 for (var i = 0; i < obj.length; i++) {
830 callback(obj[i], i, obj);
831 }
832 } else if (typeof (obj) === 'object') {
833 for (var prop in obj) {
834 if (obj.hasOwnProperty(prop)) {
835 callback(obj[prop], prop, obj);
836 }
837 }
838 } else {
839 throw new Error('obj does not seem to be an array or an iterable object');
840 }
841 };
842
843 /**
844 * Standardidize extension name
845 * @static
846 * @param {string} s extension name
847 * @returns {string}
848 */
849 showdown.helper.stdExtName = function (s) {
850 'use strict';
851 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
852 };
853
854 function escapeCharactersCallback (wholeMatch, m1) {
855 'use strict';
856 var charCodeToEscape = m1.charCodeAt(0);
857 return '¨E' + charCodeToEscape + 'E';
858 }
859
860 /**
861 * Callback used to escape characters when passing through String.replace
862 * @static
863 * @param {string} wholeMatch
864 * @param {string} m1
865 * @returns {string}
866 */
867 showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
868
869 /**
870 * Escape characters in a string
871 * @static
872 * @param {string} text
873 * @param {string} charsToEscape
874 * @param {boolean} afterBackslash
875 * @returns {XML|string|void|*}
876 */
877 showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
878 'use strict';
879 // First we have to escape the escape characters so that
880 // we can build a character class out of them
881 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
882
883 if (afterBackslash) {
884 regexString = '\\\\' + regexString;
885 }
886
887 var regex = new RegExp(regexString, 'g');
888 text = text.replace(regex, escapeCharactersCallback);
889
890 return text;
891 };
892
893 /**
894 * Unescape HTML entities
895 * @param txt
896 * @returns {string}
897 */
898 showdown.helper.unescapeHTMLEntities = function (txt) {
899 'use strict';
900
901 return txt
902 .replace(/&quot;/g, '"')
903 .replace(/&lt;/g, '<')
904 .replace(/&gt;/g, '>')
905 .replace(/&amp;/g, '&');
906 };
907
908 var rgxFindMatchPos = function (str, left, right, flags) {
909 'use strict';
910 var f = flags || '',
911 g = f.indexOf('g') > -1,
912 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
913 l = new RegExp(left, f.replace(/g/g, '')),
914 pos = [],
915 t, s, m, start, end;
916
917 do {
918 t = 0;
919 while ((m = x.exec(str))) {
920 if (l.test(m[0])) {
921 if (!(t++)) {
922 s = x.lastIndex;
923 start = s - m[0].length;
924 }
925 } else if (t) {
926 if (!--t) {
927 end = m.index + m[0].length;
928 var obj = {
929 left: {start: start, end: s},
930 match: {start: s, end: m.index},
931 right: {start: m.index, end: end},
932 wholeMatch: {start: start, end: end}
933 };
934 pos.push(obj);
935 if (!g) {
936 return pos;
937 }
938 }
939 }
940 }
941 } while (t && (x.lastIndex = s));
942
943 return pos;
944 };
945
946 /**
947 * matchRecursiveRegExp
948 *
949 * (c) 2007 Steven Levithan <stevenlevithan.com>
950 * MIT License
951 *
952 * Accepts a string to search, a left and right format delimiter
953 * as regex patterns, and optional regex flags. Returns an array
954 * of matches, allowing nested instances of left/right delimiters.
955 * Use the "g" flag to return all matches, otherwise only the
956 * first is returned. Be careful to ensure that the left and
957 * right format delimiters produce mutually exclusive matches.
958 * Backreferences are not supported within the right delimiter
959 * due to how it is internally combined with the left delimiter.
960 * When matching strings whose format delimiters are unbalanced
961 * to the left or right, the output is intentionally as a
962 * conventional regex library with recursion support would
963 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
964 * "<" and ">" as the delimiters (both strings contain a single,
965 * balanced instance of "<x>").
966 *
967 * examples:
968 * matchRecursiveRegExp("test", "\\(", "\\)")
969 * returns: []
970 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
971 * returns: ["t<<e>><s>", ""]
972 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
973 * returns: ["test"]
974 */
975 showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
976 'use strict';
977
978 var matchPos = rgxFindMatchPos (str, left, right, flags),
979 results = [];
980
981 for (var i = 0; i < matchPos.length; ++i) {
982 results.push([
983 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
984 str.slice(matchPos[i].match.start, matchPos[i].match.end),
985 str.slice(matchPos[i].left.start, matchPos[i].left.end),
986 str.slice(matchPos[i].right.start, matchPos[i].right.end)
987 ]);
988 }
989 return results;
990 };
991
992 /**
993 *
994 * @param {string} str
995 * @param {string|function} replacement
996 * @param {string} left
997 * @param {string} right
998 * @param {string} flags
999 * @returns {string}
1000 */
1001 showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
1002 'use strict';
1003
1004 if (!showdown.helper.isFunction(replacement)) {
1005 var repStr = replacement;
1006 replacement = function () {
1007 return repStr;
1008 };
1009 }
1010
1011 var matchPos = rgxFindMatchPos(str, left, right, flags),
1012 finalStr = str,
1013 lng = matchPos.length;
1014
1015 if (lng > 0) {
1016 var bits = [];
1017 if (matchPos[0].wholeMatch.start !== 0) {
1018 bits.push(str.slice(0, matchPos[0].wholeMatch.start));
1019 }
1020 for (var i = 0; i < lng; ++i) {
1021 bits.push(
1022 replacement(
1023 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1024 str.slice(matchPos[i].match.start, matchPos[i].match.end),
1025 str.slice(matchPos[i].left.start, matchPos[i].left.end),
1026 str.slice(matchPos[i].right.start, matchPos[i].right.end)
1027 )
1028 );
1029 if (i < lng - 1) {
1030 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
1031 }
1032 }
1033 if (matchPos[lng - 1].wholeMatch.end < str.length) {
1034 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
1035 }
1036 finalStr = bits.join('');
1037 }
1038 return finalStr;
1039 };
1040
1041 /**
1042 * Returns the index within the passed String object of the first occurrence of the specified regex,
1043 * starting the search at fromIndex. Returns -1 if the value is not found.
1044 *
1045 * @param {string} str string to search
1046 * @param {RegExp} regex Regular expression to search
1047 * @param {int} [fromIndex = 0] Index to start the search
1048 * @returns {Number}
1049 * @throws InvalidArgumentError
1050 */
1051 showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
1052 'use strict';
1053 if (!showdown.helper.isString(str)) {
1054 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1055 }
1056 if (regex instanceof RegExp === false) {
1057 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
1058 }
1059 var indexOf = str.substring(fromIndex || 0).search(regex);
1060 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
1061 };
1062
1063 /**
1064 * Splits the passed string object at the defined index, and returns an array composed of the two substrings
1065 * @param {string} str string to split
1066 * @param {int} index index to split string at
1067 * @returns {[string,string]}
1068 * @throws InvalidArgumentError
1069 */
1070 showdown.helper.splitAtIndex = function (str, index) {
1071 'use strict';
1072 if (!showdown.helper.isString(str)) {
1073 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1074 }
1075 return [str.substring(0, index), str.substring(index)];
1076 };
1077
1078 /**
1079 * Obfuscate an e-mail address through the use of Character Entities,
1080 * transforming ASCII characters into their equivalent decimal or hex entities.
1081 *
1082 * Since it has a random component, subsequent calls to this function produce different results
1083 *
1084 * @param {string} mail
1085 * @returns {string}
1086 */
1087 showdown.helper.encodeEmailAddress = function (mail) {
1088 'use strict';
1089 var encode = [
1090 function (ch) {
1091 return '&#' + ch.charCodeAt(0) + ';';
1092 },
1093 function (ch) {
1094 return '&#x' + ch.charCodeAt(0).toString(16) + ';';
1095 },
1096 function (ch) {
1097 return ch;
1098 }
1099 ];
1100
1101 mail = mail.replace(/./g, function (ch) {
1102 if (ch === '@') {
1103 // this *must* be encoded. I insist.
1104 ch = encode[Math.floor(Math.random() * 2)](ch);
1105 } else {
1106 var r = Math.random();
1107 // roughly 10% raw, 45% hex, 45% dec
1108 ch = (
1109 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1110 );
1111 }
1112 return ch;
1113 });
1114
1115 return mail;
1116 };
1117
1118 /**
1119 *
1120 * @param str
1121 * @param targetLength
1122 * @param padString
1123 * @returns {string}
1124 */
1125 showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
1126 'use strict';
1127 /*jshint bitwise: false*/
1128 // eslint-disable-next-line space-infix-ops
1129 targetLength = targetLength>>0; //floor if number or convert non-number to 0;
1130 /*jshint bitwise: true*/
1131 padString = String(padString || ' ');
1132 if (str.length > targetLength) {
1133 return String(str);
1134 } else {
1135 targetLength = targetLength - str.length;
1136 if (targetLength > padString.length) {
1137 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
1138 }
1139 return String(str) + padString.slice(0,targetLength);
1140 }
1141 };
1142
1143 /**
1144 * POLYFILLS
1145 */
1146 // use this instead of builtin is undefined for IE8 compatibility
1147 if (typeof console === 'undefined') {
1148 console = {
1149 warn: function (msg) {
1150 'use strict';
1151 alert(msg);
1152 },
1153 log: function (msg) {
1154 'use strict';
1155 alert(msg);
1156 },
1157 error: function (msg) {
1158 'use strict';
1159 throw msg;
1160 }
1161 };
1162 }
1163
1164 /**
1165 * Common regexes.
1166 * We declare some common regexes to improve performance
1167 */
1168 showdown.helper.regexes = {
1169 asteriskDashAndColon: /([*_:~])/g
1170 };
1171
1172 /**
1173 * EMOJIS LIST
1174 */
1175 showdown.helper.emojis = {
1176 '+1':'\ud83d\udc4d',
1177 '-1':'\ud83d\udc4e',
1178 '100':'\ud83d\udcaf',
1179 '1234':'\ud83d\udd22',
1180 '1st_place_medal':'\ud83e\udd47',
1181 '2nd_place_medal':'\ud83e\udd48',
1182 '3rd_place_medal':'\ud83e\udd49',
1183 '8ball':'\ud83c\udfb1',
1184 'a':'\ud83c\udd70\ufe0f',
1185 'ab':'\ud83c\udd8e',
1186 'abc':'\ud83d\udd24',
1187 'abcd':'\ud83d\udd21',
1188 'accept':'\ud83c\ude51',
1189 'aerial_tramway':'\ud83d\udea1',
1190 'airplane':'\u2708\ufe0f',
1191 'alarm_clock':'\u23f0',
1192 'alembic':'\u2697\ufe0f',
1193 'alien':'\ud83d\udc7d',
1194 'ambulance':'\ud83d\ude91',
1195 'amphora':'\ud83c\udffa',
1196 'anchor':'\u2693\ufe0f',
1197 'angel':'\ud83d\udc7c',
1198 'anger':'\ud83d\udca2',
1199 'angry':'\ud83d\ude20',
1200 'anguished':'\ud83d\ude27',
1201 'ant':'\ud83d\udc1c',
1202 'apple':'\ud83c\udf4e',
1203 'aquarius':'\u2652\ufe0f',
1204 'aries':'\u2648\ufe0f',
1205 'arrow_backward':'\u25c0\ufe0f',
1206 'arrow_double_down':'\u23ec',
1207 'arrow_double_up':'\u23eb',
1208 'arrow_down':'\u2b07\ufe0f',
1209 'arrow_down_small':'\ud83d\udd3d',
1210 'arrow_forward':'\u25b6\ufe0f',
1211 'arrow_heading_down':'\u2935\ufe0f',
1212 'arrow_heading_up':'\u2934\ufe0f',
1213 'arrow_left':'\u2b05\ufe0f',
1214 'arrow_lower_left':'\u2199\ufe0f',
1215 'arrow_lower_right':'\u2198\ufe0f',
1216 'arrow_right':'\u27a1\ufe0f',
1217 'arrow_right_hook':'\u21aa\ufe0f',
1218 'arrow_up':'\u2b06\ufe0f',
1219 'arrow_up_down':'\u2195\ufe0f',
1220 'arrow_up_small':'\ud83d\udd3c',
1221 'arrow_upper_left':'\u2196\ufe0f',
1222 'arrow_upper_right':'\u2197\ufe0f',
1223 'arrows_clockwise':'\ud83d\udd03',
1224 'arrows_counterclockwise':'\ud83d\udd04',
1225 'art':'\ud83c\udfa8',
1226 'articulated_lorry':'\ud83d\ude9b',
1227 'artificial_satellite':'\ud83d\udef0',
1228 'astonished':'\ud83d\ude32',
1229 'athletic_shoe':'\ud83d\udc5f',
1230 'atm':'\ud83c\udfe7',
1231 'atom_symbol':'\u269b\ufe0f',
1232 'avocado':'\ud83e\udd51',
1233 'b':'\ud83c\udd71\ufe0f',
1234 'baby':'\ud83d\udc76',
1235 'baby_bottle':'\ud83c\udf7c',
1236 'baby_chick':'\ud83d\udc24',
1237 'baby_symbol':'\ud83d\udebc',
1238 'back':'\ud83d\udd19',
1239 'bacon':'\ud83e\udd53',
1240 'badminton':'\ud83c\udff8',
1241 'baggage_claim':'\ud83d\udec4',
1242 'baguette_bread':'\ud83e\udd56',
1243 'balance_scale':'\u2696\ufe0f',
1244 'balloon':'\ud83c\udf88',
1245 'ballot_box':'\ud83d\uddf3',
1246 'ballot_box_with_check':'\u2611\ufe0f',
1247 'bamboo':'\ud83c\udf8d',
1248 'banana':'\ud83c\udf4c',
1249 'bangbang':'\u203c\ufe0f',
1250 'bank':'\ud83c\udfe6',
1251 'bar_chart':'\ud83d\udcca',
1252 'barber':'\ud83d\udc88',
1253 'baseball':'\u26be\ufe0f',
1254 'basketball':'\ud83c\udfc0',
1255 'basketball_man':'\u26f9\ufe0f',
1256 'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1257 'bat':'\ud83e\udd87',
1258 'bath':'\ud83d\udec0',
1259 'bathtub':'\ud83d\udec1',
1260 'battery':'\ud83d\udd0b',
1261 'beach_umbrella':'\ud83c\udfd6',
1262 'bear':'\ud83d\udc3b',
1263 'bed':'\ud83d\udecf',
1264 'bee':'\ud83d\udc1d',
1265 'beer':'\ud83c\udf7a',
1266 'beers':'\ud83c\udf7b',
1267 'beetle':'\ud83d\udc1e',
1268 'beginner':'\ud83d\udd30',
1269 'bell':'\ud83d\udd14',
1270 'bellhop_bell':'\ud83d\udece',
1271 'bento':'\ud83c\udf71',
1272 'biking_man':'\ud83d\udeb4',
1273 'bike':'\ud83d\udeb2',
1274 'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1275 'bikini':'\ud83d\udc59',
1276 'biohazard':'\u2623\ufe0f',
1277 'bird':'\ud83d\udc26',
1278 'birthday':'\ud83c\udf82',
1279 'black_circle':'\u26ab\ufe0f',
1280 'black_flag':'\ud83c\udff4',
1281 'black_heart':'\ud83d\udda4',
1282 'black_joker':'\ud83c\udccf',
1283 'black_large_square':'\u2b1b\ufe0f',
1284 'black_medium_small_square':'\u25fe\ufe0f',
1285 'black_medium_square':'\u25fc\ufe0f',
1286 'black_nib':'\u2712\ufe0f',
1287 'black_small_square':'\u25aa\ufe0f',
1288 'black_square_button':'\ud83d\udd32',
1289 'blonde_man':'\ud83d\udc71',
1290 'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1291 'blossom':'\ud83c\udf3c',
1292 'blowfish':'\ud83d\udc21',
1293 'blue_book':'\ud83d\udcd8',
1294 'blue_car':'\ud83d\ude99',
1295 'blue_heart':'\ud83d\udc99',
1296 'blush':'\ud83d\ude0a',
1297 'boar':'\ud83d\udc17',
1298 'boat':'\u26f5\ufe0f',
1299 'bomb':'\ud83d\udca3',
1300 'book':'\ud83d\udcd6',
1301 'bookmark':'\ud83d\udd16',
1302 'bookmark_tabs':'\ud83d\udcd1',
1303 'books':'\ud83d\udcda',
1304 'boom':'\ud83d\udca5',
1305 'boot':'\ud83d\udc62',
1306 'bouquet':'\ud83d\udc90',
1307 'bowing_man':'\ud83d\ude47',
1308 'bow_and_arrow':'\ud83c\udff9',
1309 'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1310 'bowling':'\ud83c\udfb3',
1311 'boxing_glove':'\ud83e\udd4a',
1312 'boy':'\ud83d\udc66',
1313 'bread':'\ud83c\udf5e',
1314 'bride_with_veil':'\ud83d\udc70',
1315 'bridge_at_night':'\ud83c\udf09',
1316 'briefcase':'\ud83d\udcbc',
1317 'broken_heart':'\ud83d\udc94',
1318 'bug':'\ud83d\udc1b',
1319 'building_construction':'\ud83c\udfd7',
1320 'bulb':'\ud83d\udca1',
1321 'bullettrain_front':'\ud83d\ude85',
1322 'bullettrain_side':'\ud83d\ude84',
1323 'burrito':'\ud83c\udf2f',
1324 'bus':'\ud83d\ude8c',
1325 'business_suit_levitating':'\ud83d\udd74',
1326 'busstop':'\ud83d\ude8f',
1327 'bust_in_silhouette':'\ud83d\udc64',
1328 'busts_in_silhouette':'\ud83d\udc65',
1329 'butterfly':'\ud83e\udd8b',
1330 'cactus':'\ud83c\udf35',
1331 'cake':'\ud83c\udf70',
1332 'calendar':'\ud83d\udcc6',
1333 'call_me_hand':'\ud83e\udd19',
1334 'calling':'\ud83d\udcf2',
1335 'camel':'\ud83d\udc2b',
1336 'camera':'\ud83d\udcf7',
1337 'camera_flash':'\ud83d\udcf8',
1338 'camping':'\ud83c\udfd5',
1339 'cancer':'\u264b\ufe0f',
1340 'candle':'\ud83d\udd6f',
1341 'candy':'\ud83c\udf6c',
1342 'canoe':'\ud83d\udef6',
1343 'capital_abcd':'\ud83d\udd20',
1344 'capricorn':'\u2651\ufe0f',
1345 'car':'\ud83d\ude97',
1346 'card_file_box':'\ud83d\uddc3',
1347 'card_index':'\ud83d\udcc7',
1348 'card_index_dividers':'\ud83d\uddc2',
1349 'carousel_horse':'\ud83c\udfa0',
1350 'carrot':'\ud83e\udd55',
1351 'cat':'\ud83d\udc31',
1352 'cat2':'\ud83d\udc08',
1353 'cd':'\ud83d\udcbf',
1354 'chains':'\u26d3',
1355 'champagne':'\ud83c\udf7e',
1356 'chart':'\ud83d\udcb9',
1357 'chart_with_downwards_trend':'\ud83d\udcc9',
1358 'chart_with_upwards_trend':'\ud83d\udcc8',
1359 'checkered_flag':'\ud83c\udfc1',
1360 'cheese':'\ud83e\uddc0',
1361 'cherries':'\ud83c\udf52',
1362 'cherry_blossom':'\ud83c\udf38',
1363 'chestnut':'\ud83c\udf30',
1364 'chicken':'\ud83d\udc14',
1365 'children_crossing':'\ud83d\udeb8',
1366 'chipmunk':'\ud83d\udc3f',
1367 'chocolate_bar':'\ud83c\udf6b',
1368 'christmas_tree':'\ud83c\udf84',
1369 'church':'\u26ea\ufe0f',
1370 'cinema':'\ud83c\udfa6',
1371 'circus_tent':'\ud83c\udfaa',
1372 'city_sunrise':'\ud83c\udf07',
1373 'city_sunset':'\ud83c\udf06',
1374 'cityscape':'\ud83c\udfd9',
1375 'cl':'\ud83c\udd91',
1376 'clamp':'\ud83d\udddc',
1377 'clap':'\ud83d\udc4f',
1378 'clapper':'\ud83c\udfac',
1379 'classical_building':'\ud83c\udfdb',
1380 'clinking_glasses':'\ud83e\udd42',
1381 'clipboard':'\ud83d\udccb',
1382 'clock1':'\ud83d\udd50',
1383 'clock10':'\ud83d\udd59',
1384 'clock1030':'\ud83d\udd65',
1385 'clock11':'\ud83d\udd5a',
1386 'clock1130':'\ud83d\udd66',
1387 'clock12':'\ud83d\udd5b',
1388 'clock1230':'\ud83d\udd67',
1389 'clock130':'\ud83d\udd5c',
1390 'clock2':'\ud83d\udd51',
1391 'clock230':'\ud83d\udd5d',
1392 'clock3':'\ud83d\udd52',
1393 'clock330':'\ud83d\udd5e',
1394 'clock4':'\ud83d\udd53',
1395 'clock430':'\ud83d\udd5f',
1396 'clock5':'\ud83d\udd54',
1397 'clock530':'\ud83d\udd60',
1398 'clock6':'\ud83d\udd55',
1399 'clock630':'\ud83d\udd61',
1400 'clock7':'\ud83d\udd56',
1401 'clock730':'\ud83d\udd62',
1402 'clock8':'\ud83d\udd57',
1403 'clock830':'\ud83d\udd63',
1404 'clock9':'\ud83d\udd58',
1405 'clock930':'\ud83d\udd64',
1406 'closed_book':'\ud83d\udcd5',
1407 'closed_lock_with_key':'\ud83d\udd10',
1408 'closed_umbrella':'\ud83c\udf02',
1409 'cloud':'\u2601\ufe0f',
1410 'cloud_with_lightning':'\ud83c\udf29',
1411 'cloud_with_lightning_and_rain':'\u26c8',
1412 'cloud_with_rain':'\ud83c\udf27',
1413 'cloud_with_snow':'\ud83c\udf28',
1414 'clown_face':'\ud83e\udd21',
1415 'clubs':'\u2663\ufe0f',
1416 'cocktail':'\ud83c\udf78',
1417 'coffee':'\u2615\ufe0f',
1418 'coffin':'\u26b0\ufe0f',
1419 'cold_sweat':'\ud83d\ude30',
1420 'comet':'\u2604\ufe0f',
1421 'computer':'\ud83d\udcbb',
1422 'computer_mouse':'\ud83d\uddb1',
1423 'confetti_ball':'\ud83c\udf8a',
1424 'confounded':'\ud83d\ude16',
1425 'confused':'\ud83d\ude15',
1426 'congratulations':'\u3297\ufe0f',
1427 'construction':'\ud83d\udea7',
1428 'construction_worker_man':'\ud83d\udc77',
1429 'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1430 'control_knobs':'\ud83c\udf9b',
1431 'convenience_store':'\ud83c\udfea',
1432 'cookie':'\ud83c\udf6a',
1433 'cool':'\ud83c\udd92',
1434 'policeman':'\ud83d\udc6e',
1435 'copyright':'\u00a9\ufe0f',
1436 'corn':'\ud83c\udf3d',
1437 'couch_and_lamp':'\ud83d\udecb',
1438 'couple':'\ud83d\udc6b',
1439 'couple_with_heart_woman_man':'\ud83d\udc91',
1440 'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1441 'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1442 'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1443 'couplekiss_man_woman':'\ud83d\udc8f',
1444 'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1445 'cow':'\ud83d\udc2e',
1446 'cow2':'\ud83d\udc04',
1447 'cowboy_hat_face':'\ud83e\udd20',
1448 'crab':'\ud83e\udd80',
1449 'crayon':'\ud83d\udd8d',
1450 'credit_card':'\ud83d\udcb3',
1451 'crescent_moon':'\ud83c\udf19',
1452 'cricket':'\ud83c\udfcf',
1453 'crocodile':'\ud83d\udc0a',
1454 'croissant':'\ud83e\udd50',
1455 'crossed_fingers':'\ud83e\udd1e',
1456 'crossed_flags':'\ud83c\udf8c',
1457 'crossed_swords':'\u2694\ufe0f',
1458 'crown':'\ud83d\udc51',
1459 'cry':'\ud83d\ude22',
1460 'crying_cat_face':'\ud83d\ude3f',
1461 'crystal_ball':'\ud83d\udd2e',
1462 'cucumber':'\ud83e\udd52',
1463 'cupid':'\ud83d\udc98',
1464 'curly_loop':'\u27b0',
1465 'currency_exchange':'\ud83d\udcb1',
1466 'curry':'\ud83c\udf5b',
1467 'custard':'\ud83c\udf6e',
1468 'customs':'\ud83d\udec3',
1469 'cyclone':'\ud83c\udf00',
1470 'dagger':'\ud83d\udde1',
1471 'dancer':'\ud83d\udc83',
1472 'dancing_women':'\ud83d\udc6f',
1473 'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1474 'dango':'\ud83c\udf61',
1475 'dark_sunglasses':'\ud83d\udd76',
1476 'dart':'\ud83c\udfaf',
1477 'dash':'\ud83d\udca8',
1478 'date':'\ud83d\udcc5',
1479 'deciduous_tree':'\ud83c\udf33',
1480 'deer':'\ud83e\udd8c',
1481 'department_store':'\ud83c\udfec',
1482 'derelict_house':'\ud83c\udfda',
1483 'desert':'\ud83c\udfdc',
1484 'desert_island':'\ud83c\udfdd',
1485 'desktop_computer':'\ud83d\udda5',
1486 'male_detective':'\ud83d\udd75\ufe0f',
1487 'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1488 'diamonds':'\u2666\ufe0f',
1489 'disappointed':'\ud83d\ude1e',
1490 'disappointed_relieved':'\ud83d\ude25',
1491 'dizzy':'\ud83d\udcab',
1492 'dizzy_face':'\ud83d\ude35',
1493 'do_not_litter':'\ud83d\udeaf',
1494 'dog':'\ud83d\udc36',
1495 'dog2':'\ud83d\udc15',
1496 'dollar':'\ud83d\udcb5',
1497 'dolls':'\ud83c\udf8e',
1498 'dolphin':'\ud83d\udc2c',
1499 'door':'\ud83d\udeaa',
1500 'doughnut':'\ud83c\udf69',
1501 'dove':'\ud83d\udd4a',
1502 'dragon':'\ud83d\udc09',
1503 'dragon_face':'\ud83d\udc32',
1504 'dress':'\ud83d\udc57',
1505 'dromedary_camel':'\ud83d\udc2a',
1506 'drooling_face':'\ud83e\udd24',
1507 'droplet':'\ud83d\udca7',
1508 'drum':'\ud83e\udd41',
1509 'duck':'\ud83e\udd86',
1510 'dvd':'\ud83d\udcc0',
1511 'e-mail':'\ud83d\udce7',
1512 'eagle':'\ud83e\udd85',
1513 'ear':'\ud83d\udc42',
1514 'ear_of_rice':'\ud83c\udf3e',
1515 'earth_africa':'\ud83c\udf0d',
1516 'earth_americas':'\ud83c\udf0e',
1517 'earth_asia':'\ud83c\udf0f',
1518 'egg':'\ud83e\udd5a',
1519 'eggplant':'\ud83c\udf46',
1520 'eight_pointed_black_star':'\u2734\ufe0f',
1521 'eight_spoked_asterisk':'\u2733\ufe0f',
1522 'electric_plug':'\ud83d\udd0c',
1523 'elephant':'\ud83d\udc18',
1524 'email':'\u2709\ufe0f',
1525 'end':'\ud83d\udd1a',
1526 'envelope_with_arrow':'\ud83d\udce9',
1527 'euro':'\ud83d\udcb6',
1528 'european_castle':'\ud83c\udff0',
1529 'european_post_office':'\ud83c\udfe4',
1530 'evergreen_tree':'\ud83c\udf32',
1531 'exclamation':'\u2757\ufe0f',
1532 'expressionless':'\ud83d\ude11',
1533 'eye':'\ud83d\udc41',
1534 'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
1535 'eyeglasses':'\ud83d\udc53',
1536 'eyes':'\ud83d\udc40',
1537 'face_with_head_bandage':'\ud83e\udd15',
1538 'face_with_thermometer':'\ud83e\udd12',
1539 'fist_oncoming':'\ud83d\udc4a',
1540 'factory':'\ud83c\udfed',
1541 'fallen_leaf':'\ud83c\udf42',
1542 'family_man_woman_boy':'\ud83d\udc6a',
1543 'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
1544 'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1545 'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1546 'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1547 'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1548 'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1549 'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1550 'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1551 'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1552 'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1553 'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1554 'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1555 'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1556 'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1557 'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1558 'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1559 'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1560 'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1561 'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1562 'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1563 'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1564 'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1565 'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1566 'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1567 'fast_forward':'\u23e9',
1568 'fax':'\ud83d\udce0',
1569 'fearful':'\ud83d\ude28',
1570 'feet':'\ud83d\udc3e',
1571 'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
1572 'ferris_wheel':'\ud83c\udfa1',
1573 'ferry':'\u26f4',
1574 'field_hockey':'\ud83c\udfd1',
1575 'file_cabinet':'\ud83d\uddc4',
1576 'file_folder':'\ud83d\udcc1',
1577 'film_projector':'\ud83d\udcfd',
1578 'film_strip':'\ud83c\udf9e',
1579 'fire':'\ud83d\udd25',
1580 'fire_engine':'\ud83d\ude92',
1581 'fireworks':'\ud83c\udf86',
1582 'first_quarter_moon':'\ud83c\udf13',
1583 'first_quarter_moon_with_face':'\ud83c\udf1b',
1584 'fish':'\ud83d\udc1f',
1585 'fish_cake':'\ud83c\udf65',
1586 'fishing_pole_and_fish':'\ud83c\udfa3',
1587 'fist_raised':'\u270a',
1588 'fist_left':'\ud83e\udd1b',
1589 'fist_right':'\ud83e\udd1c',
1590 'flags':'\ud83c\udf8f',
1591 'flashlight':'\ud83d\udd26',
1592 'fleur_de_lis':'\u269c\ufe0f',
1593 'flight_arrival':'\ud83d\udeec',
1594 'flight_departure':'\ud83d\udeeb',
1595 'floppy_disk':'\ud83d\udcbe',
1596 'flower_playing_cards':'\ud83c\udfb4',
1597 'flushed':'\ud83d\ude33',
1598 'fog':'\ud83c\udf2b',
1599 'foggy':'\ud83c\udf01',
1600 'football':'\ud83c\udfc8',
1601 'footprints':'\ud83d\udc63',
1602 'fork_and_knife':'\ud83c\udf74',
1603 'fountain':'\u26f2\ufe0f',
1604 'fountain_pen':'\ud83d\udd8b',
1605 'four_leaf_clover':'\ud83c\udf40',
1606 'fox_face':'\ud83e\udd8a',
1607 'framed_picture':'\ud83d\uddbc',
1608 'free':'\ud83c\udd93',
1609 'fried_egg':'\ud83c\udf73',
1610 'fried_shrimp':'\ud83c\udf64',
1611 'fries':'\ud83c\udf5f',
1612 'frog':'\ud83d\udc38',
1613 'frowning':'\ud83d\ude26',
1614 'frowning_face':'\u2639\ufe0f',
1615 'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
1616 'frowning_woman':'\ud83d\ude4d',
1617 'middle_finger':'\ud83d\udd95',
1618 'fuelpump':'\u26fd\ufe0f',
1619 'full_moon':'\ud83c\udf15',
1620 'full_moon_with_face':'\ud83c\udf1d',
1621 'funeral_urn':'\u26b1\ufe0f',
1622 'game_die':'\ud83c\udfb2',
1623 'gear':'\u2699\ufe0f',
1624 'gem':'\ud83d\udc8e',
1625 'gemini':'\u264a\ufe0f',
1626 'ghost':'\ud83d\udc7b',
1627 'gift':'\ud83c\udf81',
1628 'gift_heart':'\ud83d\udc9d',
1629 'girl':'\ud83d\udc67',
1630 'globe_with_meridians':'\ud83c\udf10',
1631 'goal_net':'\ud83e\udd45',
1632 'goat':'\ud83d\udc10',
1633 'golf':'\u26f3\ufe0f',
1634 'golfing_man':'\ud83c\udfcc\ufe0f',
1635 'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
1636 'gorilla':'\ud83e\udd8d',
1637 'grapes':'\ud83c\udf47',
1638 'green_apple':'\ud83c\udf4f',
1639 'green_book':'\ud83d\udcd7',
1640 'green_heart':'\ud83d\udc9a',
1641 'green_salad':'\ud83e\udd57',
1642 'grey_exclamation':'\u2755',
1643 'grey_question':'\u2754',
1644 'grimacing':'\ud83d\ude2c',
1645 'grin':'\ud83d\ude01',
1646 'grinning':'\ud83d\ude00',
1647 'guardsman':'\ud83d\udc82',
1648 'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
1649 'guitar':'\ud83c\udfb8',
1650 'gun':'\ud83d\udd2b',
1651 'haircut_woman':'\ud83d\udc87',
1652 'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
1653 'hamburger':'\ud83c\udf54',
1654 'hammer':'\ud83d\udd28',
1655 'hammer_and_pick':'\u2692',
1656 'hammer_and_wrench':'\ud83d\udee0',
1657 'hamster':'\ud83d\udc39',
1658 'hand':'\u270b',
1659 'handbag':'\ud83d\udc5c',
1660 'handshake':'\ud83e\udd1d',
1661 'hankey':'\ud83d\udca9',
1662 'hatched_chick':'\ud83d\udc25',
1663 'hatching_chick':'\ud83d\udc23',
1664 'headphones':'\ud83c\udfa7',
1665 'hear_no_evil':'\ud83d\ude49',
1666 'heart':'\u2764\ufe0f',
1667 'heart_decoration':'\ud83d\udc9f',
1668 'heart_eyes':'\ud83d\ude0d',
1669 'heart_eyes_cat':'\ud83d\ude3b',
1670 'heartbeat':'\ud83d\udc93',
1671 'heartpulse':'\ud83d\udc97',
1672 'hearts':'\u2665\ufe0f',
1673 'heavy_check_mark':'\u2714\ufe0f',
1674 'heavy_division_sign':'\u2797',
1675 'heavy_dollar_sign':'\ud83d\udcb2',
1676 'heavy_heart_exclamation':'\u2763\ufe0f',
1677 'heavy_minus_sign':'\u2796',
1678 'heavy_multiplication_x':'\u2716\ufe0f',
1679 'heavy_plus_sign':'\u2795',
1680 'helicopter':'\ud83d\ude81',
1681 'herb':'\ud83c\udf3f',
1682 'hibiscus':'\ud83c\udf3a',
1683 'high_brightness':'\ud83d\udd06',
1684 'high_heel':'\ud83d\udc60',
1685 'hocho':'\ud83d\udd2a',
1686 'hole':'\ud83d\udd73',
1687 'honey_pot':'\ud83c\udf6f',
1688 'horse':'\ud83d\udc34',
1689 'horse_racing':'\ud83c\udfc7',
1690 'hospital':'\ud83c\udfe5',
1691 'hot_pepper':'\ud83c\udf36',
1692 'hotdog':'\ud83c\udf2d',
1693 'hotel':'\ud83c\udfe8',
1694 'hotsprings':'\u2668\ufe0f',
1695 'hourglass':'\u231b\ufe0f',
1696 'hourglass_flowing_sand':'\u23f3',
1697 'house':'\ud83c\udfe0',
1698 'house_with_garden':'\ud83c\udfe1',
1699 'houses':'\ud83c\udfd8',
1700 'hugs':'\ud83e\udd17',
1701 'hushed':'\ud83d\ude2f',
1702 'ice_cream':'\ud83c\udf68',
1703 'ice_hockey':'\ud83c\udfd2',
1704 'ice_skate':'\u26f8',
1705 'icecream':'\ud83c\udf66',
1706 'id':'\ud83c\udd94',
1707 'ideograph_advantage':'\ud83c\ude50',
1708 'imp':'\ud83d\udc7f',
1709 'inbox_tray':'\ud83d\udce5',
1710 'incoming_envelope':'\ud83d\udce8',
1711 'tipping_hand_woman':'\ud83d\udc81',
1712 'information_source':'\u2139\ufe0f',
1713 'innocent':'\ud83d\ude07',
1714 'interrobang':'\u2049\ufe0f',
1715 'iphone':'\ud83d\udcf1',
1716 'izakaya_lantern':'\ud83c\udfee',
1717 'jack_o_lantern':'\ud83c\udf83',
1718 'japan':'\ud83d\uddfe',
1719 'japanese_castle':'\ud83c\udfef',
1720 'japanese_goblin':'\ud83d\udc7a',
1721 'japanese_ogre':'\ud83d\udc79',
1722 'jeans':'\ud83d\udc56',
1723 'joy':'\ud83d\ude02',
1724 'joy_cat':'\ud83d\ude39',
1725 'joystick':'\ud83d\udd79',
1726 'kaaba':'\ud83d\udd4b',
1727 'key':'\ud83d\udd11',
1728 'keyboard':'\u2328\ufe0f',
1729 'keycap_ten':'\ud83d\udd1f',
1730 'kick_scooter':'\ud83d\udef4',
1731 'kimono':'\ud83d\udc58',
1732 'kiss':'\ud83d\udc8b',
1733 'kissing':'\ud83d\ude17',
1734 'kissing_cat':'\ud83d\ude3d',
1735 'kissing_closed_eyes':'\ud83d\ude1a',
1736 'kissing_heart':'\ud83d\ude18',
1737 'kissing_smiling_eyes':'\ud83d\ude19',
1738 'kiwi_fruit':'\ud83e\udd5d',
1739 'koala':'\ud83d\udc28',
1740 'koko':'\ud83c\ude01',
1741 'label':'\ud83c\udff7',
1742 'large_blue_circle':'\ud83d\udd35',
1743 'large_blue_diamond':'\ud83d\udd37',
1744 'large_orange_diamond':'\ud83d\udd36',
1745 'last_quarter_moon':'\ud83c\udf17',
1746 'last_quarter_moon_with_face':'\ud83c\udf1c',
1747 'latin_cross':'\u271d\ufe0f',
1748 'laughing':'\ud83d\ude06',
1749 'leaves':'\ud83c\udf43',
1750 'ledger':'\ud83d\udcd2',
1751 'left_luggage':'\ud83d\udec5',
1752 'left_right_arrow':'\u2194\ufe0f',
1753 'leftwards_arrow_with_hook':'\u21a9\ufe0f',
1754 'lemon':'\ud83c\udf4b',
1755 'leo':'\u264c\ufe0f',
1756 'leopard':'\ud83d\udc06',
1757 'level_slider':'\ud83c\udf9a',
1758 'libra':'\u264e\ufe0f',
1759 'light_rail':'\ud83d\ude88',
1760 'link':'\ud83d\udd17',
1761 'lion':'\ud83e\udd81',
1762 'lips':'\ud83d\udc44',
1763 'lipstick':'\ud83d\udc84',
1764 'lizard':'\ud83e\udd8e',
1765 'lock':'\ud83d\udd12',
1766 'lock_with_ink_pen':'\ud83d\udd0f',
1767 'lollipop':'\ud83c\udf6d',
1768 'loop':'\u27bf',
1769 'loud_sound':'\ud83d\udd0a',
1770 'loudspeaker':'\ud83d\udce2',
1771 'love_hotel':'\ud83c\udfe9',
1772 'love_letter':'\ud83d\udc8c',
1773 'low_brightness':'\ud83d\udd05',
1774 'lying_face':'\ud83e\udd25',
1775 'm':'\u24c2\ufe0f',
1776 'mag':'\ud83d\udd0d',
1777 'mag_right':'\ud83d\udd0e',
1778 'mahjong':'\ud83c\udc04\ufe0f',
1779 'mailbox':'\ud83d\udceb',
1780 'mailbox_closed':'\ud83d\udcea',
1781 'mailbox_with_mail':'\ud83d\udcec',
1782 'mailbox_with_no_mail':'\ud83d\udced',
1783 'man':'\ud83d\udc68',
1784 'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
1785 'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
1786 'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
1787 'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
1788 'man_dancing':'\ud83d\udd7a',
1789 'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
1790 'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
1791 'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
1792 'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
1793 'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
1794 'man_in_tuxedo':'\ud83e\udd35',
1795 'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
1796 'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
1797 'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
1798 'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
1799 'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
1800 'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
1801 'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
1802 'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
1803 'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
1804 'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
1805 'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
1806 'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
1807 'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
1808 'man_with_gua_pi_mao':'\ud83d\udc72',
1809 'man_with_turban':'\ud83d\udc73',
1810 'tangerine':'\ud83c\udf4a',
1811 'mans_shoe':'\ud83d\udc5e',
1812 'mantelpiece_clock':'\ud83d\udd70',
1813 'maple_leaf':'\ud83c\udf41',
1814 'martial_arts_uniform':'\ud83e\udd4b',
1815 'mask':'\ud83d\ude37',
1816 'massage_woman':'\ud83d\udc86',
1817 'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
1818 'meat_on_bone':'\ud83c\udf56',
1819 'medal_military':'\ud83c\udf96',
1820 'medal_sports':'\ud83c\udfc5',
1821 'mega':'\ud83d\udce3',
1822 'melon':'\ud83c\udf48',
1823 'memo':'\ud83d\udcdd',
1824 'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
1825 'menorah':'\ud83d\udd4e',
1826 'mens':'\ud83d\udeb9',
1827 'metal':'\ud83e\udd18',
1828 'metro':'\ud83d\ude87',
1829 'microphone':'\ud83c\udfa4',
1830 'microscope':'\ud83d\udd2c',
1831 'milk_glass':'\ud83e\udd5b',
1832 'milky_way':'\ud83c\udf0c',
1833 'minibus':'\ud83d\ude90',
1834 'minidisc':'\ud83d\udcbd',
1835 'mobile_phone_off':'\ud83d\udcf4',
1836 'money_mouth_face':'\ud83e\udd11',
1837 'money_with_wings':'\ud83d\udcb8',
1838 'moneybag':'\ud83d\udcb0',
1839 'monkey':'\ud83d\udc12',
1840 'monkey_face':'\ud83d\udc35',
1841 'monorail':'\ud83d\ude9d',
1842 'moon':'\ud83c\udf14',
1843 'mortar_board':'\ud83c\udf93',
1844 'mosque':'\ud83d\udd4c',
1845 'motor_boat':'\ud83d\udee5',
1846 'motor_scooter':'\ud83d\udef5',
1847 'motorcycle':'\ud83c\udfcd',
1848 'motorway':'\ud83d\udee3',
1849 'mount_fuji':'\ud83d\uddfb',
1850 'mountain':'\u26f0',
1851 'mountain_biking_man':'\ud83d\udeb5',
1852 'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
1853 'mountain_cableway':'\ud83d\udea0',
1854 'mountain_railway':'\ud83d\ude9e',
1855 'mountain_snow':'\ud83c\udfd4',
1856 'mouse':'\ud83d\udc2d',
1857 'mouse2':'\ud83d\udc01',
1858 'movie_camera':'\ud83c\udfa5',
1859 'moyai':'\ud83d\uddff',
1860 'mrs_claus':'\ud83e\udd36',
1861 'muscle':'\ud83d\udcaa',
1862 'mushroom':'\ud83c\udf44',
1863 'musical_keyboard':'\ud83c\udfb9',
1864 'musical_note':'\ud83c\udfb5',
1865 'musical_score':'\ud83c\udfbc',
1866 'mute':'\ud83d\udd07',
1867 'nail_care':'\ud83d\udc85',
1868 'name_badge':'\ud83d\udcdb',
1869 'national_park':'\ud83c\udfde',
1870 'nauseated_face':'\ud83e\udd22',
1871 'necktie':'\ud83d\udc54',
1872 'negative_squared_cross_mark':'\u274e',
1873 'nerd_face':'\ud83e\udd13',
1874 'neutral_face':'\ud83d\ude10',
1875 'new':'\ud83c\udd95',
1876 'new_moon':'\ud83c\udf11',
1877 'new_moon_with_face':'\ud83c\udf1a',
1878 'newspaper':'\ud83d\udcf0',
1879 'newspaper_roll':'\ud83d\uddde',
1880 'next_track_button':'\u23ed',
1881 'ng':'\ud83c\udd96',
1882 'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
1883 'no_good_woman':'\ud83d\ude45',
1884 'night_with_stars':'\ud83c\udf03',
1885 'no_bell':'\ud83d\udd15',
1886 'no_bicycles':'\ud83d\udeb3',
1887 'no_entry':'\u26d4\ufe0f',
1888 'no_entry_sign':'\ud83d\udeab',
1889 'no_mobile_phones':'\ud83d\udcf5',
1890 'no_mouth':'\ud83d\ude36',
1891 'no_pedestrians':'\ud83d\udeb7',
1892 'no_smoking':'\ud83d\udead',
1893 'non-potable_water':'\ud83d\udeb1',
1894 'nose':'\ud83d\udc43',
1895 'notebook':'\ud83d\udcd3',
1896 'notebook_with_decorative_cover':'\ud83d\udcd4',
1897 'notes':'\ud83c\udfb6',
1898 'nut_and_bolt':'\ud83d\udd29',
1899 'o':'\u2b55\ufe0f',
1900 'o2':'\ud83c\udd7e\ufe0f',
1901 'ocean':'\ud83c\udf0a',
1902 'octopus':'\ud83d\udc19',
1903 'oden':'\ud83c\udf62',
1904 'office':'\ud83c\udfe2',
1905 'oil_drum':'\ud83d\udee2',
1906 'ok':'\ud83c\udd97',
1907 'ok_hand':'\ud83d\udc4c',
1908 'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
1909 'ok_woman':'\ud83d\ude46',
1910 'old_key':'\ud83d\udddd',
1911 'older_man':'\ud83d\udc74',
1912 'older_woman':'\ud83d\udc75',
1913 'om':'\ud83d\udd49',
1914 'on':'\ud83d\udd1b',
1915 'oncoming_automobile':'\ud83d\ude98',
1916 'oncoming_bus':'\ud83d\ude8d',
1917 'oncoming_police_car':'\ud83d\ude94',
1918 'oncoming_taxi':'\ud83d\ude96',
1919 'open_file_folder':'\ud83d\udcc2',
1920 'open_hands':'\ud83d\udc50',
1921 'open_mouth':'\ud83d\ude2e',
1922 'open_umbrella':'\u2602\ufe0f',
1923 'ophiuchus':'\u26ce',
1924 'orange_book':'\ud83d\udcd9',
1925 'orthodox_cross':'\u2626\ufe0f',
1926 'outbox_tray':'\ud83d\udce4',
1927 'owl':'\ud83e\udd89',
1928 'ox':'\ud83d\udc02',
1929 'package':'\ud83d\udce6',
1930 'page_facing_up':'\ud83d\udcc4',
1931 'page_with_curl':'\ud83d\udcc3',
1932 'pager':'\ud83d\udcdf',
1933 'paintbrush':'\ud83d\udd8c',
1934 'palm_tree':'\ud83c\udf34',
1935 'pancakes':'\ud83e\udd5e',
1936 'panda_face':'\ud83d\udc3c',
1937 'paperclip':'\ud83d\udcce',
1938 'paperclips':'\ud83d\udd87',
1939 'parasol_on_ground':'\u26f1',
1940 'parking':'\ud83c\udd7f\ufe0f',
1941 'part_alternation_mark':'\u303d\ufe0f',
1942 'partly_sunny':'\u26c5\ufe0f',
1943 'passenger_ship':'\ud83d\udef3',
1944 'passport_control':'\ud83d\udec2',
1945 'pause_button':'\u23f8',
1946 'peace_symbol':'\u262e\ufe0f',
1947 'peach':'\ud83c\udf51',
1948 'peanuts':'\ud83e\udd5c',
1949 'pear':'\ud83c\udf50',
1950 'pen':'\ud83d\udd8a',
1951 'pencil2':'\u270f\ufe0f',
1952 'penguin':'\ud83d\udc27',
1953 'pensive':'\ud83d\ude14',
1954 'performing_arts':'\ud83c\udfad',
1955 'persevere':'\ud83d\ude23',
1956 'person_fencing':'\ud83e\udd3a',
1957 'pouting_woman':'\ud83d\ude4e',
1958 'phone':'\u260e\ufe0f',
1959 'pick':'\u26cf',
1960 'pig':'\ud83d\udc37',
1961 'pig2':'\ud83d\udc16',
1962 'pig_nose':'\ud83d\udc3d',
1963 'pill':'\ud83d\udc8a',
1964 'pineapple':'\ud83c\udf4d',
1965 'ping_pong':'\ud83c\udfd3',
1966 'pisces':'\u2653\ufe0f',
1967 'pizza':'\ud83c\udf55',
1968 'place_of_worship':'\ud83d\uded0',
1969 'plate_with_cutlery':'\ud83c\udf7d',
1970 'play_or_pause_button':'\u23ef',
1971 'point_down':'\ud83d\udc47',
1972 'point_left':'\ud83d\udc48',
1973 'point_right':'\ud83d\udc49',
1974 'point_up':'\u261d\ufe0f',
1975 'point_up_2':'\ud83d\udc46',
1976 'police_car':'\ud83d\ude93',
1977 'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
1978 'poodle':'\ud83d\udc29',
1979 'popcorn':'\ud83c\udf7f',
1980 'post_office':'\ud83c\udfe3',
1981 'postal_horn':'\ud83d\udcef',
1982 'postbox':'\ud83d\udcee',
1983 'potable_water':'\ud83d\udeb0',
1984 'potato':'\ud83e\udd54',
1985 'pouch':'\ud83d\udc5d',
1986 'poultry_leg':'\ud83c\udf57',
1987 'pound':'\ud83d\udcb7',
1988 'rage':'\ud83d\ude21',
1989 'pouting_cat':'\ud83d\ude3e',
1990 'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
1991 'pray':'\ud83d\ude4f',
1992 'prayer_beads':'\ud83d\udcff',
1993 'pregnant_woman':'\ud83e\udd30',
1994 'previous_track_button':'\u23ee',
1995 'prince':'\ud83e\udd34',
1996 'princess':'\ud83d\udc78',
1997 'printer':'\ud83d\udda8',
1998 'purple_heart':'\ud83d\udc9c',
1999 'purse':'\ud83d\udc5b',
2000 'pushpin':'\ud83d\udccc',
2001 'put_litter_in_its_place':'\ud83d\udeae',
2002 'question':'\u2753',
2003 'rabbit':'\ud83d\udc30',
2004 'rabbit2':'\ud83d\udc07',
2005 'racehorse':'\ud83d\udc0e',
2006 'racing_car':'\ud83c\udfce',
2007 'radio':'\ud83d\udcfb',
2008 'radio_button':'\ud83d\udd18',
2009 'radioactive':'\u2622\ufe0f',
2010 'railway_car':'\ud83d\ude83',
2011 'railway_track':'\ud83d\udee4',
2012 'rainbow':'\ud83c\udf08',
2013 'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
2014 'raised_back_of_hand':'\ud83e\udd1a',
2015 'raised_hand_with_fingers_splayed':'\ud83d\udd90',
2016 'raised_hands':'\ud83d\ude4c',
2017 'raising_hand_woman':'\ud83d\ude4b',
2018 'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
2019 'ram':'\ud83d\udc0f',
2020 'ramen':'\ud83c\udf5c',
2021 'rat':'\ud83d\udc00',
2022 'record_button':'\u23fa',
2023 'recycle':'\u267b\ufe0f',
2024 'red_circle':'\ud83d\udd34',
2025 'registered':'\u00ae\ufe0f',
2026 'relaxed':'\u263a\ufe0f',
2027 'relieved':'\ud83d\ude0c',
2028 'reminder_ribbon':'\ud83c\udf97',
2029 'repeat':'\ud83d\udd01',
2030 'repeat_one':'\ud83d\udd02',
2031 'rescue_worker_helmet':'\u26d1',
2032 'restroom':'\ud83d\udebb',
2033 'revolving_hearts':'\ud83d\udc9e',
2034 'rewind':'\u23ea',
2035 'rhinoceros':'\ud83e\udd8f',
2036 'ribbon':'\ud83c\udf80',
2037 'rice':'\ud83c\udf5a',
2038 'rice_ball':'\ud83c\udf59',
2039 'rice_cracker':'\ud83c\udf58',
2040 'rice_scene':'\ud83c\udf91',
2041 'right_anger_bubble':'\ud83d\uddef',
2042 'ring':'\ud83d\udc8d',
2043 'robot':'\ud83e\udd16',
2044 'rocket':'\ud83d\ude80',
2045 'rofl':'\ud83e\udd23',
2046 'roll_eyes':'\ud83d\ude44',
2047 'roller_coaster':'\ud83c\udfa2',
2048 'rooster':'\ud83d\udc13',
2049 'rose':'\ud83c\udf39',
2050 'rosette':'\ud83c\udff5',
2051 'rotating_light':'\ud83d\udea8',
2052 'round_pushpin':'\ud83d\udccd',
2053 'rowing_man':'\ud83d\udea3',
2054 'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
2055 'rugby_football':'\ud83c\udfc9',
2056 'running_man':'\ud83c\udfc3',
2057 'running_shirt_with_sash':'\ud83c\udfbd',
2058 'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
2059 'sa':'\ud83c\ude02\ufe0f',
2060 'sagittarius':'\u2650\ufe0f',
2061 'sake':'\ud83c\udf76',
2062 'sandal':'\ud83d\udc61',
2063 'santa':'\ud83c\udf85',
2064 'satellite':'\ud83d\udce1',
2065 'saxophone':'\ud83c\udfb7',
2066 'school':'\ud83c\udfeb',
2067 'school_satchel':'\ud83c\udf92',
2068 'scissors':'\u2702\ufe0f',
2069 'scorpion':'\ud83e\udd82',
2070 'scorpius':'\u264f\ufe0f',
2071 'scream':'\ud83d\ude31',
2072 'scream_cat':'\ud83d\ude40',
2073 'scroll':'\ud83d\udcdc',
2074 'seat':'\ud83d\udcba',
2075 'secret':'\u3299\ufe0f',
2076 'see_no_evil':'\ud83d\ude48',
2077 'seedling':'\ud83c\udf31',
2078 'selfie':'\ud83e\udd33',
2079 'shallow_pan_of_food':'\ud83e\udd58',
2080 'shamrock':'\u2618\ufe0f',
2081 'shark':'\ud83e\udd88',
2082 'shaved_ice':'\ud83c\udf67',
2083 'sheep':'\ud83d\udc11',
2084 'shell':'\ud83d\udc1a',
2085 'shield':'\ud83d\udee1',
2086 'shinto_shrine':'\u26e9',
2087 'ship':'\ud83d\udea2',
2088 'shirt':'\ud83d\udc55',
2089 'shopping':'\ud83d\udecd',
2090 'shopping_cart':'\ud83d\uded2',
2091 'shower':'\ud83d\udebf',
2092 'shrimp':'\ud83e\udd90',
2093 'signal_strength':'\ud83d\udcf6',
2094 'six_pointed_star':'\ud83d\udd2f',
2095 'ski':'\ud83c\udfbf',
2096 'skier':'\u26f7',
2097 'skull':'\ud83d\udc80',
2098 'skull_and_crossbones':'\u2620\ufe0f',
2099 'sleeping':'\ud83d\ude34',
2100 'sleeping_bed':'\ud83d\udecc',
2101 'sleepy':'\ud83d\ude2a',
2102 'slightly_frowning_face':'\ud83d\ude41',
2103 'slightly_smiling_face':'\ud83d\ude42',
2104 'slot_machine':'\ud83c\udfb0',
2105 'small_airplane':'\ud83d\udee9',
2106 'small_blue_diamond':'\ud83d\udd39',
2107 'small_orange_diamond':'\ud83d\udd38',
2108 'small_red_triangle':'\ud83d\udd3a',
2109 'small_red_triangle_down':'\ud83d\udd3b',
2110 'smile':'\ud83d\ude04',
2111 'smile_cat':'\ud83d\ude38',
2112 'smiley':'\ud83d\ude03',
2113 'smiley_cat':'\ud83d\ude3a',
2114 'smiling_imp':'\ud83d\ude08',
2115 'smirk':'\ud83d\ude0f',
2116 'smirk_cat':'\ud83d\ude3c',
2117 'smoking':'\ud83d\udeac',
2118 'snail':'\ud83d\udc0c',
2119 'snake':'\ud83d\udc0d',
2120 'sneezing_face':'\ud83e\udd27',
2121 'snowboarder':'\ud83c\udfc2',
2122 'snowflake':'\u2744\ufe0f',
2123 'snowman':'\u26c4\ufe0f',
2124 'snowman_with_snow':'\u2603\ufe0f',
2125 'sob':'\ud83d\ude2d',
2126 'soccer':'\u26bd\ufe0f',
2127 'soon':'\ud83d\udd1c',
2128 'sos':'\ud83c\udd98',
2129 'sound':'\ud83d\udd09',
2130 'space_invader':'\ud83d\udc7e',
2131 'spades':'\u2660\ufe0f',
2132 'spaghetti':'\ud83c\udf5d',
2133 'sparkle':'\u2747\ufe0f',
2134 'sparkler':'\ud83c\udf87',
2135 'sparkles':'\u2728',
2136 'sparkling_heart':'\ud83d\udc96',
2137 'speak_no_evil':'\ud83d\ude4a',
2138 'speaker':'\ud83d\udd08',
2139 'speaking_head':'\ud83d\udde3',
2140 'speech_balloon':'\ud83d\udcac',
2141 'speedboat':'\ud83d\udea4',
2142 'spider':'\ud83d\udd77',
2143 'spider_web':'\ud83d\udd78',
2144 'spiral_calendar':'\ud83d\uddd3',
2145 'spiral_notepad':'\ud83d\uddd2',
2146 'spoon':'\ud83e\udd44',
2147 'squid':'\ud83e\udd91',
2148 'stadium':'\ud83c\udfdf',
2149 'star':'\u2b50\ufe0f',
2150 'star2':'\ud83c\udf1f',
2151 'star_and_crescent':'\u262a\ufe0f',
2152 'star_of_david':'\u2721\ufe0f',
2153 'stars':'\ud83c\udf20',
2154 'station':'\ud83d\ude89',
2155 'statue_of_liberty':'\ud83d\uddfd',
2156 'steam_locomotive':'\ud83d\ude82',
2157 'stew':'\ud83c\udf72',
2158 'stop_button':'\u23f9',
2159 'stop_sign':'\ud83d\uded1',
2160 'stopwatch':'\u23f1',
2161 'straight_ruler':'\ud83d\udccf',
2162 'strawberry':'\ud83c\udf53',
2163 'stuck_out_tongue':'\ud83d\ude1b',
2164 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2165 'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2166 'studio_microphone':'\ud83c\udf99',
2167 'stuffed_flatbread':'\ud83e\udd59',
2168 'sun_behind_large_cloud':'\ud83c\udf25',
2169 'sun_behind_rain_cloud':'\ud83c\udf26',
2170 'sun_behind_small_cloud':'\ud83c\udf24',
2171 'sun_with_face':'\ud83c\udf1e',
2172 'sunflower':'\ud83c\udf3b',
2173 'sunglasses':'\ud83d\ude0e',
2174 'sunny':'\u2600\ufe0f',
2175 'sunrise':'\ud83c\udf05',
2176 'sunrise_over_mountains':'\ud83c\udf04',
2177 'surfing_man':'\ud83c\udfc4',
2178 'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2179 'sushi':'\ud83c\udf63',
2180 'suspension_railway':'\ud83d\ude9f',
2181 'sweat':'\ud83d\ude13',
2182 'sweat_drops':'\ud83d\udca6',
2183 'sweat_smile':'\ud83d\ude05',
2184 'sweet_potato':'\ud83c\udf60',
2185 'swimming_man':'\ud83c\udfca',
2186 'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2187 'symbols':'\ud83d\udd23',
2188 'synagogue':'\ud83d\udd4d',
2189 'syringe':'\ud83d\udc89',
2190 'taco':'\ud83c\udf2e',
2191 'tada':'\ud83c\udf89',
2192 'tanabata_tree':'\ud83c\udf8b',
2193 'taurus':'\u2649\ufe0f',
2194 'taxi':'\ud83d\ude95',
2195 'tea':'\ud83c\udf75',
2196 'telephone_receiver':'\ud83d\udcde',
2197 'telescope':'\ud83d\udd2d',
2198 'tennis':'\ud83c\udfbe',
2199 'tent':'\u26fa\ufe0f',
2200 'thermometer':'\ud83c\udf21',
2201 'thinking':'\ud83e\udd14',
2202 'thought_balloon':'\ud83d\udcad',
2203 'ticket':'\ud83c\udfab',
2204 'tickets':'\ud83c\udf9f',
2205 'tiger':'\ud83d\udc2f',
2206 'tiger2':'\ud83d\udc05',
2207 'timer_clock':'\u23f2',
2208 'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2209 'tired_face':'\ud83d\ude2b',
2210 'tm':'\u2122\ufe0f',
2211 'toilet':'\ud83d\udebd',
2212 'tokyo_tower':'\ud83d\uddfc',
2213 'tomato':'\ud83c\udf45',
2214 'tongue':'\ud83d\udc45',
2215 'top':'\ud83d\udd1d',
2216 'tophat':'\ud83c\udfa9',
2217 'tornado':'\ud83c\udf2a',
2218 'trackball':'\ud83d\uddb2',
2219 'tractor':'\ud83d\ude9c',
2220 'traffic_light':'\ud83d\udea5',
2221 'train':'\ud83d\ude8b',
2222 'train2':'\ud83d\ude86',
2223 'tram':'\ud83d\ude8a',
2224 'triangular_flag_on_post':'\ud83d\udea9',
2225 'triangular_ruler':'\ud83d\udcd0',
2226 'trident':'\ud83d\udd31',
2227 'triumph':'\ud83d\ude24',
2228 'trolleybus':'\ud83d\ude8e',
2229 'trophy':'\ud83c\udfc6',
2230 'tropical_drink':'\ud83c\udf79',
2231 'tropical_fish':'\ud83d\udc20',
2232 'truck':'\ud83d\ude9a',
2233 'trumpet':'\ud83c\udfba',
2234 'tulip':'\ud83c\udf37',
2235 'tumbler_glass':'\ud83e\udd43',
2236 'turkey':'\ud83e\udd83',
2237 'turtle':'\ud83d\udc22',
2238 'tv':'\ud83d\udcfa',
2239 'twisted_rightwards_arrows':'\ud83d\udd00',
2240 'two_hearts':'\ud83d\udc95',
2241 'two_men_holding_hands':'\ud83d\udc6c',
2242 'two_women_holding_hands':'\ud83d\udc6d',
2243 'u5272':'\ud83c\ude39',
2244 'u5408':'\ud83c\ude34',
2245 'u55b6':'\ud83c\ude3a',
2246 'u6307':'\ud83c\ude2f\ufe0f',
2247 'u6708':'\ud83c\ude37\ufe0f',
2248 'u6709':'\ud83c\ude36',
2249 'u6e80':'\ud83c\ude35',
2250 'u7121':'\ud83c\ude1a\ufe0f',
2251 'u7533':'\ud83c\ude38',
2252 'u7981':'\ud83c\ude32',
2253 'u7a7a':'\ud83c\ude33',
2254 'umbrella':'\u2614\ufe0f',
2255 'unamused':'\ud83d\ude12',
2256 'underage':'\ud83d\udd1e',
2257 'unicorn':'\ud83e\udd84',
2258 'unlock':'\ud83d\udd13',
2259 'up':'\ud83c\udd99',
2260 'upside_down_face':'\ud83d\ude43',
2261 'v':'\u270c\ufe0f',
2262 'vertical_traffic_light':'\ud83d\udea6',
2263 'vhs':'\ud83d\udcfc',
2264 'vibration_mode':'\ud83d\udcf3',
2265 'video_camera':'\ud83d\udcf9',
2266 'video_game':'\ud83c\udfae',
2267 'violin':'\ud83c\udfbb',
2268 'virgo':'\u264d\ufe0f',
2269 'volcano':'\ud83c\udf0b',
2270 'volleyball':'\ud83c\udfd0',
2271 'vs':'\ud83c\udd9a',
2272 'vulcan_salute':'\ud83d\udd96',
2273 'walking_man':'\ud83d\udeb6',
2274 'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2275 'waning_crescent_moon':'\ud83c\udf18',
2276 'waning_gibbous_moon':'\ud83c\udf16',
2277 'warning':'\u26a0\ufe0f',
2278 'wastebasket':'\ud83d\uddd1',
2279 'watch':'\u231a\ufe0f',
2280 'water_buffalo':'\ud83d\udc03',
2281 'watermelon':'\ud83c\udf49',
2282 'wave':'\ud83d\udc4b',
2283 'wavy_dash':'\u3030\ufe0f',
2284 'waxing_crescent_moon':'\ud83c\udf12',
2285 'wc':'\ud83d\udebe',
2286 'weary':'\ud83d\ude29',
2287 'wedding':'\ud83d\udc92',
2288 'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2289 'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2290 'whale':'\ud83d\udc33',
2291 'whale2':'\ud83d\udc0b',
2292 'wheel_of_dharma':'\u2638\ufe0f',
2293 'wheelchair':'\u267f\ufe0f',
2294 'white_check_mark':'\u2705',
2295 'white_circle':'\u26aa\ufe0f',
2296 'white_flag':'\ud83c\udff3\ufe0f',
2297 'white_flower':'\ud83d\udcae',
2298 'white_large_square':'\u2b1c\ufe0f',
2299 'white_medium_small_square':'\u25fd\ufe0f',
2300 'white_medium_square':'\u25fb\ufe0f',
2301 'white_small_square':'\u25ab\ufe0f',
2302 'white_square_button':'\ud83d\udd33',
2303 'wilted_flower':'\ud83e\udd40',
2304 'wind_chime':'\ud83c\udf90',
2305 'wind_face':'\ud83c\udf2c',
2306 'wine_glass':'\ud83c\udf77',
2307 'wink':'\ud83d\ude09',
2308 'wolf':'\ud83d\udc3a',
2309 'woman':'\ud83d\udc69',
2310 'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2311 'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2312 'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2313 'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2314 'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2315 'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2316 'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2317 'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2318 'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2319 'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2320 'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2321 'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2322 'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2323 'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2324 'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2325 'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2326 'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2327 'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2328 'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2329 'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2330 'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2331 'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2332 'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2333 'womans_clothes':'\ud83d\udc5a',
2334 'womans_hat':'\ud83d\udc52',
2335 'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2336 'womens':'\ud83d\udeba',
2337 'world_map':'\ud83d\uddfa',
2338 'worried':'\ud83d\ude1f',
2339 'wrench':'\ud83d\udd27',
2340 'writing_hand':'\u270d\ufe0f',
2341 'x':'\u274c',
2342 'yellow_heart':'\ud83d\udc9b',
2343 'yen':'\ud83d\udcb4',
2344 'yin_yang':'\u262f\ufe0f',
2345 'yum':'\ud83d\ude0b',
2346 'zap':'\u26a1\ufe0f',
2347 'zipper_mouth_face':'\ud83e\udd10',
2348 'zzz':'\ud83d\udca4',
2349
2350 /* special emojis :P */
2351 'octocat': '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
2352 '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>'
2353 };
2354
2355 /**
2356 * Created by Estevao on 31-05-2015.
2357 */
2358
2359 /**
2360 * Showdown Converter class
2361 * @class
2362 * @param {object} [converterOptions]
2363 * @returns {Converter}
2364 */
2365 showdown.Converter = function (converterOptions) {
2366 'use strict';
2367
2368 var
2369 /**
2370 * Options used by this converter
2371 * @private
2372 * @type {{}}
2373 */
2374 options = {},
2375
2376 /**
2377 * Language extensions used by this converter
2378 * @private
2379 * @type {Array}
2380 */
2381 langExtensions = [],
2382
2383 /**
2384 * Output modifiers extensions used by this converter
2385 * @private
2386 * @type {Array}
2387 */
2388 outputModifiers = [],
2389
2390 /**
2391 * Event listeners
2392 * @private
2393 * @type {{}}
2394 */
2395 listeners = {},
2396
2397 /**
2398 * The flavor set in this converter
2399 */
2400 setConvFlavor = setFlavor,
2401
2402 /**
2403 * Metadata of the document
2404 * @type {{parsed: {}, raw: string, format: string}}
2405 */
2406 metadata = {
2407 parsed: {},
2408 raw: '',
2409 format: ''
2410 };
2411
2412 _constructor();
2413
2414 /**
2415 * Converter constructor
2416 * @private
2417 */
2418 function _constructor () {
2419 converterOptions = converterOptions || {};
2420
2421 for (var gOpt in globalOptions) {
2422 if (globalOptions.hasOwnProperty(gOpt)) {
2423 options[gOpt] = globalOptions[gOpt];
2424 }
2425 }
2426
2427 // Merge options
2428 if (typeof converterOptions === 'object') {
2429 for (var opt in converterOptions) {
2430 if (converterOptions.hasOwnProperty(opt)) {
2431 options[opt] = converterOptions[opt];
2432 }
2433 }
2434 } else {
2435 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
2436 ' was passed instead.');
2437 }
2438
2439 if (options.extensions) {
2440 showdown.helper.forEach(options.extensions, _parseExtension);
2441 }
2442 }
2443
2444 /**
2445 * Parse extension
2446 * @param {*} ext
2447 * @param {string} [name='']
2448 * @private
2449 */
2450 function _parseExtension (ext, name) {
2451
2452 name = name || null;
2453 // If it's a string, the extension was previously loaded
2454 if (showdown.helper.isString(ext)) {
2455 ext = showdown.helper.stdExtName(ext);
2456 name = ext;
2457
2458 // LEGACY_SUPPORT CODE
2459 if (showdown.extensions[ext]) {
2460 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
2461 'Please inform the developer that the extension should be updated!');
2462 legacyExtensionLoading(showdown.extensions[ext], ext);
2463 return;
2464 // END LEGACY SUPPORT CODE
2465
2466 } else if (!showdown.helper.isUndefined(extensions[ext])) {
2467 ext = extensions[ext];
2468
2469 } else {
2470 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
2471 }
2472 }
2473
2474 if (typeof ext === 'function') {
2475 ext = ext();
2476 }
2477
2478 if (!showdown.helper.isArray(ext)) {
2479 ext = [ext];
2480 }
2481
2482 var validExt = validate(ext, name);
2483 if (!validExt.valid) {
2484 throw Error(validExt.error);
2485 }
2486
2487 for (var i = 0; i < ext.length; ++i) {
2488 switch (ext[i].type) {
2489
2490 case 'lang':
2491 langExtensions.push(ext[i]);
2492 break;
2493
2494 case 'output':
2495 outputModifiers.push(ext[i]);
2496 break;
2497 }
2498 if (ext[i].hasOwnProperty('listeners')) {
2499 for (var ln in ext[i].listeners) {
2500 if (ext[i].listeners.hasOwnProperty(ln)) {
2501 listen(ln, ext[i].listeners[ln]);
2502 }
2503 }
2504 }
2505 }
2506
2507 }
2508
2509 /**
2510 * LEGACY_SUPPORT
2511 * @param {*} ext
2512 * @param {string} name
2513 */
2514 function legacyExtensionLoading (ext, name) {
2515 if (typeof ext === 'function') {
2516 ext = ext(new showdown.Converter());
2517 }
2518 if (!showdown.helper.isArray(ext)) {
2519 ext = [ext];
2520 }
2521 var valid = validate(ext, name);
2522
2523 if (!valid.valid) {
2524 throw Error(valid.error);
2525 }
2526
2527 for (var i = 0; i < ext.length; ++i) {
2528 switch (ext[i].type) {
2529 case 'lang':
2530 langExtensions.push(ext[i]);
2531 break;
2532 case 'output':
2533 outputModifiers.push(ext[i]);
2534 break;
2535 default:// should never reach here
2536 throw Error('Extension loader error: Type unrecognized!!!');
2537 }
2538 }
2539 }
2540
2541 /**
2542 * Listen to an event
2543 * @param {string} name
2544 * @param {function} callback
2545 */
2546 function listen (name, callback) {
2547 if (!showdown.helper.isString(name)) {
2548 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
2549 }
2550
2551 if (typeof callback !== 'function') {
2552 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
2553 }
2554
2555 if (!listeners.hasOwnProperty(name)) {
2556 listeners[name] = [];
2557 }
2558 listeners[name].push(callback);
2559 }
2560
2561 function rTrimInputText (text) {
2562 var rsp = text.match(/^\s*/)[0].length,
2563 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
2564 return text.replace(rgx, '');
2565 }
2566
2567 /**
2568 * Dispatch an event
2569 * @private
2570 * @param {string} evtName Event name
2571 * @param {string} text Text
2572 * @param {{}} options Converter Options
2573 * @param {{}} globals
2574 * @returns {string}
2575 */
2576 this._dispatch = function dispatch (evtName, text, options, globals) {
2577 if (listeners.hasOwnProperty(evtName)) {
2578 for (var ei = 0; ei < listeners[evtName].length; ++ei) {
2579 var nText = listeners[evtName][ei](evtName, text, this, options, globals);
2580 if (nText && typeof nText !== 'undefined') {
2581 text = nText;
2582 }
2583 }
2584 }
2585 return text;
2586 };
2587
2588 /**
2589 * Listen to an event
2590 * @param {string} name
2591 * @param {function} callback
2592 * @returns {showdown.Converter}
2593 */
2594 this.listen = function (name, callback) {
2595 listen(name, callback);
2596 return this;
2597 };
2598
2599 /**
2600 * Converts a markdown string into HTML
2601 * @param {string} text
2602 * @returns {*}
2603 */
2604 this.makeHtml = function (text) {
2605 //check if text is not falsy
2606 if (!text) {
2607 return text;
2608 }
2609
2610 var globals = {
2611 gHtmlBlocks: [],
2612 gHtmlMdBlocks: [],
2613 gHtmlSpans: [],
2614 gUrls: {},
2615 gTitles: {},
2616 gDimensions: {},
2617 gListLevel: 0,
2618 hashLinkCounts: {},
2619 langExtensions: langExtensions,
2620 outputModifiers: outputModifiers,
2621 converter: this,
2622 ghCodeBlocks: [],
2623 metadata: {
2624 parsed: {},
2625 raw: '',
2626 format: ''
2627 }
2628 };
2629
2630 // This lets us use ¨ trema as an escape char to avoid md5 hashes
2631 // The choice of character is arbitrary; anything that isn't
2632 // magic in Markdown will work.
2633 text = text.replace(/¨/g, '¨T');
2634
2635 // Replace $ with ¨D
2636 // RegExp interprets $ as a special character
2637 // when it's in a replacement string
2638 text = text.replace(/\$/g, '¨D');
2639
2640 // Standardize line endings
2641 text = text.replace(/\r\n/g, '\n'); // DOS to Unix
2642 text = text.replace(/\r/g, '\n'); // Mac to Unix
2643
2644 // Stardardize line spaces
2645 text = text.replace(/\u00A0/g, '&nbsp;');
2646
2647 if (options.smartIndentationFix) {
2648 text = rTrimInputText(text);
2649 }
2650
2651 // Make sure text begins and ends with a couple of newlines:
2652 text = '\n\n' + text + '\n\n';
2653
2654 // detab
2655 text = showdown.subParser('detab')(text, options, globals);
2656
2657 /**
2658 * Strip any lines consisting only of spaces and tabs.
2659 * This makes subsequent regexs easier to write, because we can
2660 * match consecutive blank lines with /\n+/ instead of something
2661 * contorted like /[ \t]*\n+/
2662 */
2663 text = text.replace(/^[ \t]+$/mg, '');
2664
2665 //run languageExtensions
2666 showdown.helper.forEach(langExtensions, function (ext) {
2667 text = showdown.subParser('runExtension')(ext, text, options, globals);
2668 });
2669
2670 // run the sub parsers
2671 text = showdown.subParser('metadata')(text, options, globals);
2672 text = showdown.subParser('hashPreCodeTags')(text, options, globals);
2673 text = showdown.subParser('githubCodeBlocks')(text, options, globals);
2674 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
2675 text = showdown.subParser('hashCodeTags')(text, options, globals);
2676 text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
2677 text = showdown.subParser('blockGamut')(text, options, globals);
2678 text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
2679 text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
2680
2681 // attacklab: Restore dollar signs
2682 text = text.replace(/¨D/g, '$$');
2683
2684 // attacklab: Restore tremas
2685 text = text.replace(/¨T/g, '¨');
2686
2687 // render a complete html document instead of a partial if the option is enabled
2688 text = showdown.subParser('completeHTMLDocument')(text, options, globals);
2689
2690 // Run output modifiers
2691 showdown.helper.forEach(outputModifiers, function (ext) {
2692 text = showdown.subParser('runExtension')(ext, text, options, globals);
2693 });
2694
2695 // update metadata
2696 metadata = globals.metadata;
2697 return text;
2698 };
2699
2700 /**
2701 * Converts an HTML string into a markdown string
2702 * @param src
2703 * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
2704 * @returns {string}
2705 */
2706 this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
2707
2708 // replace \r\n with \n
2709 src = src.replace(/\r\n/g, '\n');
2710 src = src.replace(/\r/g, '\n'); // old macs
2711
2712 // due to an edge case, we need to find this: > <
2713 // to prevent removing of non silent white spaces
2714 // ex: <em>this is</em> <strong>sparta</strong>
2715 src = src.replace(/>[ \t]+</, '>¨NBSP;<');
2716
2717 if (!HTMLParser) {
2718 if (window && window.document) {
2719 HTMLParser = window.document;
2720 } else {
2721 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');
2722 }
2723 }
2724
2725 var doc = HTMLParser.createElement('div');
2726 doc.innerHTML = src;
2727
2728 var globals = {
2729 preList: substitutePreCodeTags(doc)
2730 };
2731
2732 // remove all newlines and collapse spaces
2733 clean(doc);
2734
2735 // some stuff, like accidental reference links must now be escaped
2736 // TODO
2737 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
2738
2739 var nodes = doc.childNodes,
2740 mdDoc = '';
2741
2742 for (var i = 0; i < nodes.length; i++) {
2743 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
2744 }
2745
2746 function clean (node) {
2747 for (var n = 0; n < node.childNodes.length; ++n) {
2748 var child = node.childNodes[n];
2749 if (child.nodeType === 3) {
2750 if (!/\S/.test(child.nodeValue)) {
2751 node.removeChild(child);
2752 --n;
2753 } else {
2754 child.nodeValue = child.nodeValue.split('\n').join(' ');
2755 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
2756 }
2757 } else if (child.nodeType === 1) {
2758 clean(child);
2759 }
2760 }
2761 }
2762
2763 // find all pre tags and replace contents with placeholder
2764 // we need this so that we can remove all indentation from html
2765 // to ease up parsing
2766 function substitutePreCodeTags (doc) {
2767
2768 var pres = doc.querySelectorAll('pre'),
2769 presPH = [];
2770
2771 for (var i = 0; i < pres.length; ++i) {
2772
2773 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
2774 var content = pres[i].firstChild.innerHTML.trim(),
2775 language = pres[i].firstChild.getAttribute('data-language') || '';
2776
2777 // if data-language attribute is not defined, then we look for class language-*
2778 if (language === '') {
2779 var classes = pres[i].firstChild.className.split(' ');
2780 for (var c = 0; c < classes.length; ++c) {
2781 var matches = classes[c].match(/^language-(.+)$/);
2782 if (matches !== null) {
2783 language = matches[1];
2784 break;
2785 }
2786 }
2787 }
2788
2789 // unescape html entities in content
2790 content = showdown.helper.unescapeHTMLEntities(content);
2791
2792 presPH.push(content);
2793 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
2794 } else {
2795 presPH.push(pres[i].innerHTML);
2796 pres[i].innerHTML = '';
2797 pres[i].setAttribute('prenum', i.toString());
2798 }
2799 }
2800 return presPH;
2801 }
2802
2803 return mdDoc;
2804 };
2805
2806 /**
2807 * Set an option of this Converter instance
2808 * @param {string} key
2809 * @param {*} value
2810 */
2811 this.setOption = function (key, value) {
2812 options[key] = value;
2813 };
2814
2815 /**
2816 * Get the option of this Converter instance
2817 * @param {string} key
2818 * @returns {*}
2819 */
2820 this.getOption = function (key) {
2821 return options[key];
2822 };
2823
2824 /**
2825 * Get the options of this Converter instance
2826 * @returns {{}}
2827 */
2828 this.getOptions = function () {
2829 return options;
2830 };
2831
2832 /**
2833 * Add extension to THIS converter
2834 * @param {{}} extension
2835 * @param {string} [name=null]
2836 */
2837 this.addExtension = function (extension, name) {
2838 name = name || null;
2839 _parseExtension(extension, name);
2840 };
2841
2842 /**
2843 * Use a global registered extension with THIS converter
2844 * @param {string} extensionName Name of the previously registered extension
2845 */
2846 this.useExtension = function (extensionName) {
2847 _parseExtension(extensionName);
2848 };
2849
2850 /**
2851 * Set the flavor THIS converter should use
2852 * @param {string} name
2853 */
2854 this.setFlavor = function (name) {
2855 if (!flavor.hasOwnProperty(name)) {
2856 throw Error(name + ' flavor was not found');
2857 }
2858 var preset = flavor[name];
2859 setConvFlavor = name;
2860 for (var option in preset) {
2861 if (preset.hasOwnProperty(option)) {
2862 options[option] = preset[option];
2863 }
2864 }
2865 };
2866
2867 /**
2868 * Get the currently set flavor of this converter
2869 * @returns {string}
2870 */
2871 this.getFlavor = function () {
2872 return setConvFlavor;
2873 };
2874
2875 /**
2876 * Remove an extension from THIS converter.
2877 * Note: This is a costly operation. It's better to initialize a new converter
2878 * and specify the extensions you wish to use
2879 * @param {Array} extension
2880 */
2881 this.removeExtension = function (extension) {
2882 if (!showdown.helper.isArray(extension)) {
2883 extension = [extension];
2884 }
2885 for (var a = 0; a < extension.length; ++a) {
2886 var ext = extension[a];
2887 for (var i = 0; i < langExtensions.length; ++i) {
2888 if (langExtensions[i] === ext) {
2889 langExtensions[i].splice(i, 1);
2890 }
2891 }
2892 for (var ii = 0; ii < outputModifiers.length; ++i) {
2893 if (outputModifiers[ii] === ext) {
2894 outputModifiers[ii].splice(i, 1);
2895 }
2896 }
2897 }
2898 };
2899
2900 /**
2901 * Get all extension of THIS converter
2902 * @returns {{language: Array, output: Array}}
2903 */
2904 this.getAllExtensions = function () {
2905 return {
2906 language: langExtensions,
2907 output: outputModifiers
2908 };
2909 };
2910
2911 /**
2912 * Get the metadata of the previously parsed document
2913 * @param raw
2914 * @returns {string|{}}
2915 */
2916 this.getMetadata = function (raw) {
2917 if (raw) {
2918 return metadata.raw;
2919 } else {
2920 return metadata.parsed;
2921 }
2922 };
2923
2924 /**
2925 * Get the metadata format of the previously parsed document
2926 * @returns {string}
2927 */
2928 this.getMetadataFormat = function () {
2929 return metadata.format;
2930 };
2931
2932 /**
2933 * Private: set a single key, value metadata pair
2934 * @param {string} key
2935 * @param {string} value
2936 */
2937 this._setMetadataPair = function (key, value) {
2938 metadata.parsed[key] = value;
2939 };
2940
2941 /**
2942 * Private: set metadata format
2943 * @param {string} format
2944 */
2945 this._setMetadataFormat = function (format) {
2946 metadata.format = format;
2947 };
2948
2949 /**
2950 * Private: set metadata raw text
2951 * @param {string} raw
2952 */
2953 this._setMetadataRaw = function (raw) {
2954 metadata.raw = raw;
2955 };
2956 };
2957
2958 /**
2959 * Turn Markdown link shortcuts into XHTML <a> tags.
2960 */
2961 showdown.subParser('anchors', function (text, options, globals) {
2962 'use strict';
2963
2964 text = globals.converter._dispatch('anchors.before', text, options, globals);
2965
2966 var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
2967 if (showdown.helper.isUndefined(title)) {
2968 title = '';
2969 }
2970 linkId = linkId.toLowerCase();
2971
2972 // Special case for explicit empty url
2973 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
2974 url = '';
2975 } else if (!url) {
2976 if (!linkId) {
2977 // lower-case and turn embedded newlines into spaces
2978 linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
2979 }
2980 url = '#' + linkId;
2981
2982 if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
2983 url = globals.gUrls[linkId];
2984 if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
2985 title = globals.gTitles[linkId];
2986 }
2987 } else {
2988 return wholeMatch;
2989 }
2990 }
2991
2992 //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
2993 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
2994
2995 var result = '<a href="' + url + '"';
2996
2997 if (title !== '' && title !== null) {
2998 title = title.replace(/"/g, '&quot;');
2999 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3000 title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3001 result += ' title="' + title + '"';
3002 }
3003
3004 // optionLinksInNewWindow only applies
3005 // to external links. Hash links (#) open in same page
3006 if (options.openLinksInNewWindow && !/^#/.test(url)) {
3007 // escaped _
3008 result += ' rel="noopener noreferrer" target="¨E95Eblank"';
3009 }
3010
3011 result += '>' + linkText + '</a>';
3012
3013 return result;
3014 };
3015
3016 // First, handle reference-style links: [link text] [id]
3017 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
3018
3019 // Next, inline-style links: [link text](url "optional title")
3020 // cases with crazy urls like ./image/cat1).png
3021 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3022 writeAnchorTag);
3023
3024 // normal cases
3025 text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3026 writeAnchorTag);
3027
3028 // handle reference-style shortcuts: [link text]
3029 // These must come last in case you've also got [link test][1]
3030 // or [link test](/foo)
3031 text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
3032
3033 // Lastly handle GithubMentions if option is enabled
3034 if (options.ghMentions) {
3035 text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
3036 if (escape === '\\') {
3037 return st + mentions;
3038 }
3039
3040 //check if options.ghMentionsLink is a string
3041 if (!showdown.helper.isString(options.ghMentionsLink)) {
3042 throw new Error('ghMentionsLink option must be a string');
3043 }
3044 var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
3045 target = '';
3046 if (options.openLinksInNewWindow) {
3047 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3048 }
3049 return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
3050 });
3051 }
3052
3053 text = globals.converter._dispatch('anchors.after', text, options, globals);
3054 return text;
3055 });
3056
3057 // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
3058
3059 var simpleURLRegex = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
3060 simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
3061 delimUrlRegex = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
3062 simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
3063 delimMailRegex = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
3064
3065 replaceLink = function (options) {
3066 'use strict';
3067 return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
3068 link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3069 var lnkTxt = link,
3070 append = '',
3071 target = '',
3072 lmc = leadingMagicChars || '',
3073 tmc = trailingMagicChars || '';
3074 if (/^www\./i.test(link)) {
3075 link = link.replace(/^www\./i, 'http://www.');
3076 }
3077 if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
3078 append = trailingPunctuation;
3079 }
3080 if (options.openLinksInNewWindow) {
3081 target = ' rel="noopener noreferrer" target="¨E95Eblank"';
3082 }
3083 return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
3084 };
3085 },
3086
3087 replaceMail = function (options, globals) {
3088 'use strict';
3089 return function (wholeMatch, b, mail) {
3090 var href = 'mailto:';
3091 b = b || '';
3092 mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
3093 if (options.encodeEmails) {
3094 href = showdown.helper.encodeEmailAddress(href + mail);
3095 mail = showdown.helper.encodeEmailAddress(mail);
3096 } else {
3097 href = href + mail;
3098 }
3099 return b + '<a href="' + href + '">' + mail + '</a>';
3100 };
3101 };
3102
3103 showdown.subParser('autoLinks', function (text, options, globals) {
3104 'use strict';
3105
3106 text = globals.converter._dispatch('autoLinks.before', text, options, globals);
3107
3108 text = text.replace(delimUrlRegex, replaceLink(options));
3109 text = text.replace(delimMailRegex, replaceMail(options, globals));
3110
3111 text = globals.converter._dispatch('autoLinks.after', text, options, globals);
3112
3113 return text;
3114 });
3115
3116 showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
3117 'use strict';
3118
3119 if (!options.simplifiedAutoLink) {
3120 return text;
3121 }
3122
3123 text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
3124
3125 if (options.excludeTrailingPunctuationFromURLs) {
3126 text = text.replace(simpleURLRegex2, replaceLink(options));
3127 } else {
3128 text = text.replace(simpleURLRegex, replaceLink(options));
3129 }
3130 text = text.replace(simpleMailRegex, replaceMail(options, globals));
3131
3132 text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
3133
3134 return text;
3135 });
3136
3137 /**
3138 * These are all the transformations that form block-level
3139 * tags like paragraphs, headers, and list items.
3140 */
3141 showdown.subParser('blockGamut', function (text, options, globals) {
3142 'use strict';
3143
3144 text = globals.converter._dispatch('blockGamut.before', text, options, globals);
3145
3146 // we parse blockquotes first so that we can have headings and hrs
3147 // inside blockquotes
3148 text = showdown.subParser('blockQuotes')(text, options, globals);
3149 text = showdown.subParser('headers')(text, options, globals);
3150
3151 // Do Horizontal Rules:
3152 text = showdown.subParser('horizontalRule')(text, options, globals);
3153
3154 text = showdown.subParser('lists')(text, options, globals);
3155 text = showdown.subParser('codeBlocks')(text, options, globals);
3156 text = showdown.subParser('tables')(text, options, globals);
3157
3158 // We already ran _HashHTMLBlocks() before, in Markdown(), but that
3159 // was to escape raw HTML in the original Markdown source. This time,
3160 // we're escaping the markup we've just created, so that we don't wrap
3161 // <p> tags around block-level tags.
3162 text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3163 text = showdown.subParser('paragraphs')(text, options, globals);
3164
3165 text = globals.converter._dispatch('blockGamut.after', text, options, globals);
3166
3167 return text;
3168 });
3169
3170 showdown.subParser('blockQuotes', function (text, options, globals) {
3171 'use strict';
3172
3173 text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
3174
3175 // add a couple extra lines after the text and endtext mark
3176 text = text + '\n\n';
3177
3178 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
3179
3180 if (options.splitAdjacentBlockquotes) {
3181 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
3182 }
3183
3184 text = text.replace(rgx, function (bq) {
3185 // attacklab: hack around Konqueror 3.5.4 bug:
3186 // "----------bug".replace(/^-/g,"") == "bug"
3187 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
3188
3189 // attacklab: clean up hack
3190 bq = bq.replace(/¨0/g, '');
3191
3192 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
3193 bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
3194 bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
3195
3196 bq = bq.replace(/(^|\n)/g, '$1 ');
3197 // These leading spaces screw with <pre> content, so we need to fix that:
3198 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
3199 var pre = m1;
3200 // attacklab: hack around Konqueror 3.5.4 bug:
3201 pre = pre.replace(/^ /mg, '¨0');
3202 pre = pre.replace(/¨0/g, '');
3203 return pre;
3204 });
3205
3206 return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
3207 });
3208
3209 text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
3210 return text;
3211 });
3212
3213 /**
3214 * Process Markdown `<pre><code>` blocks.
3215 */
3216 showdown.subParser('codeBlocks', function (text, options, globals) {
3217 'use strict';
3218
3219 text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
3220
3221 // sentinel workarounds for lack of \A and \Z, safari\khtml bug
3222 text += '¨0';
3223
3224 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
3225 text = text.replace(pattern, function (wholeMatch, m1, m2) {
3226 var codeblock = m1,
3227 nextChar = m2,
3228 end = '\n';
3229
3230 codeblock = showdown.subParser('outdent')(codeblock, options, globals);
3231 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3232 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3233 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3234 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
3235
3236 if (options.omitExtraWLInCodeBlocks) {
3237 end = '';
3238 }
3239
3240 codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
3241
3242 return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
3243 });
3244
3245 // strip sentinel
3246 text = text.replace(/¨0/, '');
3247
3248 text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
3249 return text;
3250 });
3251
3252 /**
3253 *
3254 * * Backtick quotes are used for <code></code> spans.
3255 *
3256 * * You can use multiple backticks as the delimiters if you want to
3257 * include literal backticks in the code span. So, this input:
3258 *
3259 * Just type ``foo `bar` baz`` at the prompt.
3260 *
3261 * Will translate to:
3262 *
3263 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
3264 *
3265 * There's no arbitrary limit to the number of backticks you
3266 * can use as delimters. If you need three consecutive backticks
3267 * in your code, use four for delimiters, etc.
3268 *
3269 * * You can use spaces to get literal backticks at the edges:
3270 *
3271 * ... type `` `bar` `` ...
3272 *
3273 * Turns to:
3274 *
3275 * ... type <code>`bar`</code> ...
3276 */
3277 showdown.subParser('codeSpans', function (text, options, globals) {
3278 'use strict';
3279
3280 text = globals.converter._dispatch('codeSpans.before', text, options, globals);
3281
3282 if (typeof text === 'undefined') {
3283 text = '';
3284 }
3285 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
3286 function (wholeMatch, m1, m2, m3) {
3287 var c = m3;
3288 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
3289 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
3290 c = showdown.subParser('encodeCode')(c, options, globals);
3291 c = m1 + '<code>' + c + '</code>';
3292 c = showdown.subParser('hashHTMLSpans')(c, options, globals);
3293 return c;
3294 }
3295 );
3296
3297 text = globals.converter._dispatch('codeSpans.after', text, options, globals);
3298 return text;
3299 });
3300
3301 /**
3302 * Create a full HTML document from the processed markdown
3303 */
3304 showdown.subParser('completeHTMLDocument', function (text, options, globals) {
3305 'use strict';
3306
3307 if (!options.completeHTMLDocument) {
3308 return text;
3309 }
3310
3311 text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
3312
3313 var doctype = 'html',
3314 doctypeParsed = '<!DOCTYPE HTML>\n',
3315 title = '',
3316 charset = '<meta charset="utf-8">\n',
3317 lang = '',
3318 metadata = '';
3319
3320 if (typeof globals.metadata.parsed.doctype !== 'undefined') {
3321 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n';
3322 doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
3323 if (doctype === 'html' || doctype === 'html5') {
3324 charset = '<meta charset="utf-8">';
3325 }
3326 }
3327
3328 for (var meta in globals.metadata.parsed) {
3329 if (globals.metadata.parsed.hasOwnProperty(meta)) {
3330 switch (meta.toLowerCase()) {
3331 case 'doctype':
3332 break;
3333
3334 case 'title':
3335 title = '<title>' + globals.metadata.parsed.title + '</title>\n';
3336 break;
3337
3338 case 'charset':
3339 if (doctype === 'html' || doctype === 'html5') {
3340 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
3341 } else {
3342 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
3343 }
3344 break;
3345
3346 case 'language':
3347 case 'lang':
3348 lang = ' lang="' + globals.metadata.parsed[meta] + '"';
3349 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3350 break;
3351
3352 default:
3353 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3354 }
3355 }
3356 }
3357
3358 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
3359
3360 text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
3361 return text;
3362 });
3363
3364 /**
3365 * Convert all tabs to spaces
3366 */
3367 showdown.subParser('detab', function (text, options, globals) {
3368 'use strict';
3369 text = globals.converter._dispatch('detab.before', text, options, globals);
3370
3371 // expand first n-1 tabs
3372 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
3373
3374 // replace the nth with two sentinels
3375 text = text.replace(/\t/g, '¨A¨B');
3376
3377 // use the sentinel to anchor our regex so it doesn't explode
3378 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
3379 var leadingText = m1,
3380 numSpaces = 4 - leadingText.length % 4; // g_tab_width
3381
3382 // there *must* be a better way to do this:
3383 for (var i = 0; i < numSpaces; i++) {
3384 leadingText += ' ';
3385 }
3386
3387 return leadingText;
3388 });
3389
3390 // clean up sentinels
3391 text = text.replace(/¨A/g, ' '); // g_tab_width
3392 text = text.replace(/¨B/g, '');
3393
3394 text = globals.converter._dispatch('detab.after', text, options, globals);
3395 return text;
3396 });
3397
3398 showdown.subParser('ellipsis', function (text, options, globals) {
3399 'use strict';
3400
3401 text = globals.converter._dispatch('ellipsis.before', text, options, globals);
3402
3403 text = text.replace(/\.\.\./g, '…');
3404
3405 text = globals.converter._dispatch('ellipsis.after', text, options, globals);
3406
3407 return text;
3408 });
3409
3410 /**
3411 * Turn emoji codes into emojis
3412 *
3413 * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
3414 */
3415 showdown.subParser('emoji', function (text, options, globals) {
3416 'use strict';
3417
3418 if (!options.emoji) {
3419 return text;
3420 }
3421
3422 text = globals.converter._dispatch('emoji.before', text, options, globals);
3423
3424 var emojiRgx = /:([\S]+?):/g;
3425
3426 text = text.replace(emojiRgx, function (wm, emojiCode) {
3427 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
3428 return showdown.helper.emojis[emojiCode];
3429 }
3430 return wm;
3431 });
3432
3433 text = globals.converter._dispatch('emoji.after', text, options, globals);
3434
3435 return text;
3436 });
3437
3438 /**
3439 * Smart processing for ampersands and angle brackets that need to be encoded.
3440 */
3441 showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
3442 'use strict';
3443 text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
3444
3445 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
3446 // http://bumppo.net/projects/amputator/
3447 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
3448
3449 // Encode naked <'s
3450 text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3451
3452 // Encode <
3453 text = text.replace(/</g, '&lt;');
3454
3455 // Encode >
3456 text = text.replace(/>/g, '&gt;');
3457
3458 text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
3459 return text;
3460 });
3461
3462 /**
3463 * Returns the string, with after processing the following backslash escape sequences.
3464 *
3465 * attacklab: The polite way to do this is with the new escapeCharacters() function:
3466 *
3467 * text = escapeCharacters(text,"\\",true);
3468 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
3469 *
3470 * ...but we're sidestepping its use of the (slow) RegExp constructor
3471 * as an optimization for Firefox. This function gets called a LOT.
3472 */
3473 showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
3474 'use strict';
3475 text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
3476
3477 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
3478 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
3479
3480 text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
3481 return text;
3482 });
3483
3484 /**
3485 * Encode/escape certain characters inside Markdown code runs.
3486 * The point is that in code, these characters are literals,
3487 * and lose their special Markdown meanings.
3488 */
3489 showdown.subParser('encodeCode', function (text, options, globals) {
3490 'use strict';
3491
3492 text = globals.converter._dispatch('encodeCode.before', text, options, globals);
3493
3494 // Encode all ampersands; HTML entities are not
3495 // entities within a Markdown code span.
3496 text = text
3497 .replace(/&/g, '&amp;')
3498 // Do the angle bracket song and dance:
3499 .replace(/</g, '&lt;')
3500 .replace(/>/g, '&gt;')
3501 // Now, escape characters that are magic in Markdown:
3502 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
3503
3504 text = globals.converter._dispatch('encodeCode.after', text, options, globals);
3505 return text;
3506 });
3507
3508 /**
3509 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
3510 * don't conflict with their use in Markdown for code, italics and strong.
3511 */
3512 showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
3513 'use strict';
3514 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
3515
3516 // Build a regex to find HTML tags.
3517 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
3518 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
3519
3520 text = text.replace(tags, function (wholeMatch) {
3521 return wholeMatch
3522 .replace(/(.)<\/?code>(?=.)/g, '$1`')
3523 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3524 });
3525
3526 text = text.replace(comments, function (wholeMatch) {
3527 return wholeMatch
3528 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3529 });
3530
3531 text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
3532 return text;
3533 });
3534
3535 /**
3536 * Handle github codeblocks prior to running HashHTML so that
3537 * HTML contained within the codeblock gets escaped properly
3538 * Example:
3539 * ```ruby
3540 * def hello_world(x)
3541 * puts "Hello, #{x}"
3542 * end
3543 * ```
3544 */
3545 showdown.subParser('githubCodeBlocks', function (text, options, globals) {
3546 'use strict';
3547
3548 // early exit if option is not enabled
3549 if (!options.ghCodeBlocks) {
3550 return text;
3551 }
3552
3553 text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
3554
3555 text += '¨0';
3556
3557 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
3558 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
3559
3560 // First parse the github code block
3561 codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3562 codeblock = showdown.subParser('detab')(codeblock, options, globals);
3563 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3564 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
3565
3566 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
3567
3568 codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
3569
3570 // Since GHCodeblocks can be false positives, we need to
3571 // store the primitive text and the parsed text in a global var,
3572 // and then return a token
3573 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
3574 });
3575
3576 // attacklab: strip sentinel
3577 text = text.replace(/¨0/, '');
3578
3579 return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
3580 });
3581
3582 showdown.subParser('hashBlock', function (text, options, globals) {
3583 'use strict';
3584 text = globals.converter._dispatch('hashBlock.before', text, options, globals);
3585 text = text.replace(/(^\n+|\n+$)/g, '');
3586 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
3587 text = globals.converter._dispatch('hashBlock.after', text, options, globals);
3588 return text;
3589 });
3590
3591 /**
3592 * Hash and escape <code> elements that should not be parsed as markdown
3593 */
3594 showdown.subParser('hashCodeTags', function (text, options, globals) {
3595 'use strict';
3596 text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
3597
3598 var repFunc = function (wholeMatch, match, left, right) {
3599 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
3600 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
3601 };
3602
3603 // Hash naked <code>
3604 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
3605
3606 text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
3607 return text;
3608 });
3609
3610 showdown.subParser('hashElement', function (text, options, globals) {
3611 'use strict';
3612
3613 return function (wholeMatch, m1) {
3614 var blockText = m1;
3615
3616 // Undo double lines
3617 blockText = blockText.replace(/\n\n/g, '\n');
3618 blockText = blockText.replace(/^\n/, '');
3619
3620 // strip trailing blank lines
3621 blockText = blockText.replace(/\n+$/g, '');
3622
3623 // Replace the element text with a marker ("¨KxK" where x is its key)
3624 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
3625
3626 return blockText;
3627 };
3628 });
3629
3630 showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
3631 'use strict';
3632 text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
3633
3634 var blockTags = [
3635 'pre',
3636 'div',
3637 'h1',
3638 'h2',
3639 'h3',
3640 'h4',
3641 'h5',
3642 'h6',
3643 'blockquote',
3644 'table',
3645 'dl',
3646 'ol',
3647 'ul',
3648 'script',
3649 'noscript',
3650 'form',
3651 'fieldset',
3652 'iframe',
3653 'math',
3654 'style',
3655 'section',
3656 'header',
3657 'footer',
3658 'nav',
3659 'article',
3660 'aside',
3661 'address',
3662 'audio',
3663 'canvas',
3664 'figure',
3665 'hgroup',
3666 'output',
3667 'video',
3668 'p'
3669 ],
3670 repFunc = function (wholeMatch, match, left, right) {
3671 var txt = wholeMatch;
3672 // check if this html element is marked as markdown
3673 // if so, it's contents should be parsed as markdown
3674 if (left.search(/\bmarkdown\b/) !== -1) {
3675 txt = left + globals.converter.makeHtml(match) + right;
3676 }
3677 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
3678 };
3679
3680 if (options.backslashEscapesHTMLTags) {
3681 // encode backslash escaped HTML tags
3682 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
3683 return '&lt;' + inside + '&gt;';
3684 });
3685 }
3686
3687 // hash HTML Blocks
3688 for (var i = 0; i < blockTags.length; ++i) {
3689
3690 var opTagPos,
3691 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
3692 patLeft = '<' + blockTags[i] + '\\b[^>]*>',
3693 patRight = '</' + blockTags[i] + '>';
3694 // 1. Look for the first position of the first opening HTML tag in the text
3695 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
3696
3697 // if the HTML tag is \ escaped, we need to escape it and break
3698
3699
3700 //2. Split the text in that position
3701 var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
3702 //3. Match recursively
3703 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
3704
3705 // prevent an infinite loop
3706 if (newSubText1 === subTexts[1]) {
3707 break;
3708 }
3709 text = subTexts[0].concat(newSubText1);
3710 }
3711 }
3712 // HR SPECIAL CASE
3713 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
3714 showdown.subParser('hashElement')(text, options, globals));
3715
3716 // Special case for standalone HTML comments
3717 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
3718 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
3719 }, '^ {0,3}<!--', '-->', 'gm');
3720
3721 // PHP and ASP-style processor instructions (<?...?> and <%...%>)
3722 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
3723 showdown.subParser('hashElement')(text, options, globals));
3724
3725 text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
3726 return text;
3727 });
3728
3729 /**
3730 * Hash span elements that should not be parsed as markdown
3731 */
3732 showdown.subParser('hashHTMLSpans', function (text, options, globals) {
3733 'use strict';
3734 text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
3735
3736 function hashHTMLSpan (html) {
3737 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
3738 }
3739
3740 // Hash Self Closing tags
3741 text = text.replace(/<[^>]+?\/>/gi, function (wm) {
3742 return hashHTMLSpan(wm);
3743 });
3744
3745 // Hash tags without properties
3746 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
3747 return hashHTMLSpan(wm);
3748 });
3749
3750 // Hash tags with properties
3751 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
3752 return hashHTMLSpan(wm);
3753 });
3754
3755 // Hash self closing tags without />
3756 text = text.replace(/<[^>]+?>/gi, function (wm) {
3757 return hashHTMLSpan(wm);
3758 });
3759
3760 /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
3761
3762 text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
3763 return text;
3764 });
3765
3766 /**
3767 * Unhash HTML spans
3768 */
3769 showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
3770 'use strict';
3771 text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
3772
3773 for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
3774 var repText = globals.gHtmlSpans[i],
3775 // limiter to prevent infinite loop (assume 10 as limit for recurse)
3776 limit = 0;
3777
3778 while (/¨C(\d+)C/.test(repText)) {
3779 var num = RegExp.$1;
3780 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
3781 if (limit === 10) {
3782 console.error('maximum nesting of 10 spans reached!!!');
3783 break;
3784 }
3785 ++limit;
3786 }
3787 text = text.replace('¨C' + i + 'C', repText);
3788 }
3789
3790 text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
3791 return text;
3792 });
3793
3794 /**
3795 * Hash and escape <pre><code> elements that should not be parsed as markdown
3796 */
3797 showdown.subParser('hashPreCodeTags', function (text, options, globals) {
3798 'use strict';
3799 text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
3800
3801 var repFunc = function (wholeMatch, match, left, right) {
3802 // encode html entities
3803 var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
3804 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
3805 };
3806
3807 // Hash <pre><code>
3808 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
3809
3810 text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
3811 return text;
3812 });
3813
3814 showdown.subParser('headers', function (text, options, globals) {
3815 'use strict';
3816
3817 text = globals.converter._dispatch('headers.before', text, options, globals);
3818
3819 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
3820
3821 // Set text-style headers:
3822 // Header 1
3823 // ========
3824 //
3825 // Header 2
3826 // --------
3827 //
3828 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
3829 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
3830
3831 text = text.replace(setextRegexH1, function (wholeMatch, m1) {
3832
3833 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
3834 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
3835 hLevel = headerLevelStart,
3836 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
3837 return showdown.subParser('hashBlock')(hashBlock, options, globals);
3838 });
3839
3840 text = text.replace(setextRegexH2, function (matchFound, m1) {
3841 var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
3842 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
3843 hLevel = headerLevelStart + 1,
3844 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
3845 return showdown.subParser('hashBlock')(hashBlock, options, globals);
3846 });
3847
3848 // atx-style headers:
3849 // # Header 1
3850 // ## Header 2
3851 // ## Header 2 with closing hashes ##
3852 // ...
3853 // ###### Header 6
3854 //
3855 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
3856
3857 text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
3858 var hText = m2;
3859 if (options.customizedHeaderId) {
3860 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
3861 }
3862
3863 var span = showdown.subParser('spanGamut')(hText, options, globals),
3864 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
3865 hLevel = headerLevelStart - 1 + m1.length,
3866 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
3867
3868 return showdown.subParser('hashBlock')(header, options, globals);
3869 });
3870
3871 function headerId (m) {
3872 var title,
3873 prefix;
3874
3875 // It is separate from other options to allow combining prefix and customized
3876 if (options.customizedHeaderId) {
3877 var match = m.match(/\{([^{]+?)}\s*$/);
3878 if (match && match[1]) {
3879 m = match[1];
3880 }
3881 }
3882
3883 title = m;
3884
3885 // Prefix id to prevent causing inadvertent pre-existing style matches.
3886 if (showdown.helper.isString(options.prefixHeaderId)) {
3887 prefix = options.prefixHeaderId;
3888 } else if (options.prefixHeaderId === true) {
3889 prefix = 'section-';
3890 } else {
3891 prefix = '';
3892 }
3893
3894 if (!options.rawPrefixHeaderId) {
3895 title = prefix + title;
3896 }
3897
3898 if (options.ghCompatibleHeaderId) {
3899 title = title
3900 .replace(/ /g, '-')
3901 // replace previously escaped chars (&, ¨ and $)
3902 .replace(/&amp;/g, '')
3903 .replace(/¨T/g, '')
3904 .replace(/¨D/g, '')
3905 // replace rest of the chars (&~$ are repeated as they might have been escaped)
3906 // borrowed from github's redcarpet (some they should produce similar results)
3907 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
3908 .toLowerCase();
3909 } else if (options.rawHeaderId) {
3910 title = title
3911 .replace(/ /g, '-')
3912 // replace previously escaped chars (&, ¨ and $)
3913 .replace(/&amp;/g, '&')
3914 .replace(/¨T/g, '¨')
3915 .replace(/¨D/g, '$')
3916 // replace " and '
3917 .replace(/["']/g, '-')
3918 .toLowerCase();
3919 } else {
3920 title = title
3921 .replace(/[^\w]/g, '')
3922 .toLowerCase();
3923 }
3924
3925 if (options.rawPrefixHeaderId) {
3926 title = prefix + title;
3927 }
3928
3929 if (globals.hashLinkCounts[title]) {
3930 title = title + '-' + (globals.hashLinkCounts[title]++);
3931 } else {
3932 globals.hashLinkCounts[title] = 1;
3933 }
3934 return title;
3935 }
3936
3937 text = globals.converter._dispatch('headers.after', text, options, globals);
3938 return text;
3939 });
3940
3941 /**
3942 * Turn Markdown link shortcuts into XHTML <a> tags.
3943 */
3944 showdown.subParser('horizontalRule', function (text, options, globals) {
3945 'use strict';
3946 text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
3947
3948 var key = showdown.subParser('hashBlock')('<hr />', options, globals);
3949 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
3950 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
3951 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
3952
3953 text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
3954 return text;
3955 });
3956
3957 /**
3958 * Turn Markdown image shortcuts into <img> tags.
3959 */
3960 showdown.subParser('images', function (text, options, globals) {
3961 'use strict';
3962
3963 text = globals.converter._dispatch('images.before', text, options, globals);
3964
3965 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
3966 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
3967 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,
3968 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
3969 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
3970
3971 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
3972 url = url.replace(/\s/g, '');
3973 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
3974 }
3975
3976 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
3977
3978 var gUrls = globals.gUrls,
3979 gTitles = globals.gTitles,
3980 gDims = globals.gDimensions;
3981
3982 linkId = linkId.toLowerCase();
3983
3984 if (!title) {
3985 title = '';
3986 }
3987 // Special case for explicit empty url
3988 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3989 url = '';
3990
3991 } else if (url === '' || url === null) {
3992 if (linkId === '' || linkId === null) {
3993 // lower-case and turn embedded newlines into spaces
3994 linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
3995 }
3996 url = '#' + linkId;
3997
3998 if (!showdown.helper.isUndefined(gUrls[linkId])) {
3999 url = gUrls[linkId];
4000 if (!showdown.helper.isUndefined(gTitles[linkId])) {
4001 title = gTitles[linkId];
4002 }
4003 if (!showdown.helper.isUndefined(gDims[linkId])) {
4004 width = gDims[linkId].width;
4005 height = gDims[linkId].height;
4006 }
4007 } else {
4008 return wholeMatch;
4009 }
4010 }
4011
4012 altText = altText
4013 .replace(/"/g, '&quot;')
4014 //altText = showdown.helper.escapeCharacters(altText, '*_', false);
4015 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4016 //url = showdown.helper.escapeCharacters(url, '*_', false);
4017 url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4018 var result = '<img src="' + url + '" alt="' + altText + '"';
4019
4020 if (title && showdown.helper.isString(title)) {
4021 title = title
4022 .replace(/"/g, '&quot;')
4023 //title = showdown.helper.escapeCharacters(title, '*_', false);
4024 .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4025 result += ' title="' + title + '"';
4026 }
4027
4028 if (width && height) {
4029 width = (width === '*') ? 'auto' : width;
4030 height = (height === '*') ? 'auto' : height;
4031
4032 result += ' width="' + width + '"';
4033 result += ' height="' + height + '"';
4034 }
4035
4036 result += ' />';
4037
4038 return result;
4039 }
4040
4041 // First, handle reference-style labeled images: ![alt text][id]
4042 text = text.replace(referenceRegExp, writeImageTag);
4043
4044 // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
4045
4046 // base64 encoded images
4047 text = text.replace(base64RegExp, writeImageTagBase64);
4048
4049 // cases with crazy urls like ./image/cat1).png
4050 text = text.replace(crazyRegExp, writeImageTag);
4051
4052 // normal cases
4053 text = text.replace(inlineRegExp, writeImageTag);
4054
4055 // handle reference-style shortcuts: ![img text]
4056 text = text.replace(refShortcutRegExp, writeImageTag);
4057
4058 text = globals.converter._dispatch('images.after', text, options, globals);
4059 return text;
4060 });
4061
4062 showdown.subParser('italicsAndBold', function (text, options, globals) {
4063 'use strict';
4064
4065 text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
4066
4067 // it's faster to have 3 separate regexes for each case than have just one
4068 // because of backtracing, in some cases, it could lead to an exponential effect
4069 // called "catastrophic backtrace". Ominous!
4070
4071 function parseInside (txt, left, right) {
4072 /*
4073 if (options.simplifiedAutoLink) {
4074 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4075 }
4076 */
4077 return left + txt + right;
4078 }
4079
4080 // Parse underscores
4081 if (options.literalMidWordUnderscores) {
4082 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4083 return parseInside (txt, '<strong><em>', '</em></strong>');
4084 });
4085 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4086 return parseInside (txt, '<strong>', '</strong>');
4087 });
4088 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
4089 return parseInside (txt, '<em>', '</em>');
4090 });
4091 } else {
4092 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4093 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4094 });
4095 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4096 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4097 });
4098 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
4099 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
4100 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4101 });
4102 }
4103
4104 // Now parse asterisks
4105 if (options.literalMidWordAsterisks) {
4106 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
4107 return parseInside (txt, lead + '<strong><em>', '</em></strong>');
4108 });
4109 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
4110 return parseInside (txt, lead + '<strong>', '</strong>');
4111 });
4112 text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
4113 return parseInside (txt, lead + '<em>', '</em>');
4114 });
4115 } else {
4116 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
4117 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4118 });
4119 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
4120 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4121 });
4122 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
4123 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
4124 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4125 });
4126 }
4127
4128
4129 text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
4130 return text;
4131 });
4132
4133 /**
4134 * Form HTML ordered (numbered) and unordered (bulleted) lists.
4135 */
4136 showdown.subParser('lists', function (text, options, globals) {
4137 'use strict';
4138
4139 /**
4140 * Process the contents of a single ordered or unordered list, splitting it
4141 * into individual list items.
4142 * @param {string} listStr
4143 * @param {boolean} trimTrailing
4144 * @returns {string}
4145 */
4146 function processListItems (listStr, trimTrailing) {
4147 // The $g_list_level global keeps track of when we're inside a list.
4148 // Each time we enter a list, we increment it; when we leave a list,
4149 // we decrement. If it's zero, we're not in a list anymore.
4150 //
4151 // We do this because when we're not inside a list, we want to treat
4152 // something like this:
4153 //
4154 // I recommend upgrading to version
4155 // 8. Oops, now this line is treated
4156 // as a sub-list.
4157 //
4158 // As a single paragraph, despite the fact that the second line starts
4159 // with a digit-period-space sequence.
4160 //
4161 // Whereas when we're inside a list (or sub-list), that line will be
4162 // treated as the start of a sub-list. What a kludge, huh? This is
4163 // an aspect of Markdown's syntax that's hard to parse perfectly
4164 // without resorting to mind-reading. Perhaps the solution is to
4165 // change the syntax rules such that sub-lists must start with a
4166 // starting cardinal number; e.g. "1." or "a.".
4167 globals.gListLevel++;
4168
4169 // trim trailing blank lines:
4170 listStr = listStr.replace(/\n{2,}$/, '\n');
4171
4172 // attacklab: add sentinel to emulate \z
4173 listStr += '¨0';
4174
4175 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
4176 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
4177
4178 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
4179 // which is a syntax breaking change
4180 // activating this option reverts to old behavior
4181 if (options.disableForced4SpacesIndentedSublists) {
4182 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
4183 }
4184
4185 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
4186 checked = (checked && checked.trim() !== '');
4187
4188 var item = showdown.subParser('outdent')(m4, options, globals),
4189 bulletStyle = '';
4190
4191 // Support for github tasklists
4192 if (taskbtn && options.tasklists) {
4193 bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
4194 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
4195 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
4196 if (checked) {
4197 otp += ' checked';
4198 }
4199 otp += '>';
4200 return otp;
4201 });
4202 }
4203
4204 // ISSUE #312
4205 // This input: - - - a
4206 // causes trouble to the parser, since it interprets it as:
4207 // <ul><li><li><li>a</li></li></li></ul>
4208 // instead of:
4209 // <ul><li>- - a</li></ul>
4210 // So, to prevent it, we will put a marker (¨A)in the beginning of the line
4211 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
4212 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
4213 return '¨A' + wm2;
4214 });
4215
4216 // m1 - Leading line or
4217 // Has a double return (multi paragraph) or
4218 // Has sublist
4219 if (m1 || (item.search(/\n{2,}/) > -1)) {
4220 item = showdown.subParser('githubCodeBlocks')(item, options, globals);
4221 item = showdown.subParser('blockGamut')(item, options, globals);
4222 } else {
4223 // Recursion for sub-lists:
4224 item = showdown.subParser('lists')(item, options, globals);
4225 item = item.replace(/\n$/, ''); // chomp(item)
4226 item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
4227
4228 // Colapse double linebreaks
4229 item = item.replace(/\n\n+/g, '\n\n');
4230 if (isParagraphed) {
4231 item = showdown.subParser('paragraphs')(item, options, globals);
4232 } else {
4233 item = showdown.subParser('spanGamut')(item, options, globals);
4234 }
4235 }
4236
4237 // now we need to remove the marker (¨A)
4238 item = item.replace('¨A', '');
4239 // we can finally wrap the line in list item tags
4240 item = '<li' + bulletStyle + '>' + item + '</li>\n';
4241
4242 return item;
4243 });
4244
4245 // attacklab: strip sentinel
4246 listStr = listStr.replace(/¨0/g, '');
4247
4248 globals.gListLevel--;
4249
4250 if (trimTrailing) {
4251 listStr = listStr.replace(/\s+$/, '');
4252 }
4253
4254 return listStr;
4255 }
4256
4257 function styleStartNumber (list, listType) {
4258 // check if ol and starts by a number different than 1
4259 if (listType === 'ol') {
4260 var res = list.match(/^ *(\d+)\./);
4261 if (res && res[1] !== '1') {
4262 return ' start="' + res[1] + '"';
4263 }
4264 }
4265 return '';
4266 }
4267
4268 /**
4269 * Check and parse consecutive lists (better fix for issue #142)
4270 * @param {string} list
4271 * @param {string} listType
4272 * @param {boolean} trimTrailing
4273 * @returns {string}
4274 */
4275 function parseConsecutiveLists (list, listType, trimTrailing) {
4276 // check if we caught 2 or more consecutive lists by mistake
4277 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
4278 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
4279 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
4280 counterRxg = (listType === 'ul') ? olRgx : ulRgx,
4281 result = '';
4282
4283 if (list.search(counterRxg) !== -1) {
4284 (function parseCL (txt) {
4285 var pos = txt.search(counterRxg),
4286 style = styleStartNumber(list, listType);
4287 if (pos !== -1) {
4288 // slice
4289 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
4290
4291 // invert counterType and listType
4292 listType = (listType === 'ul') ? 'ol' : 'ul';
4293 counterRxg = (listType === 'ul') ? olRgx : ulRgx;
4294
4295 //recurse
4296 parseCL(txt.slice(pos));
4297 } else {
4298 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
4299 }
4300 })(list);
4301 } else {
4302 var style = styleStartNumber(list, listType);
4303 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
4304 }
4305
4306 return result;
4307 }
4308
4309 /** Start of list parsing **/
4310 text = globals.converter._dispatch('lists.before', text, options, globals);
4311 // add sentinel to hack around khtml/safari bug:
4312 // http://bugs.webkit.org/show_bug.cgi?id=11231
4313 text += '¨0';
4314
4315 if (globals.gListLevel) {
4316 text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4317 function (wholeMatch, list, m2) {
4318 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4319 return parseConsecutiveLists(list, listType, true);
4320 }
4321 );
4322 } else {
4323 text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4324 function (wholeMatch, m1, list, m3) {
4325 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4326 return parseConsecutiveLists(list, listType, false);
4327 }
4328 );
4329 }
4330
4331 // strip sentinel
4332 text = text.replace(/¨0/, '');
4333 text = globals.converter._dispatch('lists.after', text, options, globals);
4334 return text;
4335 });
4336
4337 /**
4338 * Parse metadata at the top of the document
4339 */
4340 showdown.subParser('metadata', function (text, options, globals) {
4341 'use strict';
4342
4343 if (!options.metadata) {
4344 return text;
4345 }
4346
4347 text = globals.converter._dispatch('metadata.before', text, options, globals);
4348
4349 function parseMetadataContents (content) {
4350 // raw is raw so it's not changed in any way
4351 globals.metadata.raw = content;
4352
4353 // escape chars forbidden in html attributes
4354 // double quotes
4355 content = content
4356 // ampersand first
4357 .replace(/&/g, '&amp;')
4358 // double quotes
4359 .replace(/"/g, '&quot;');
4360
4361 content = content.replace(/\n {4}/g, ' ');
4362 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
4363 globals.metadata.parsed[key] = value;
4364 return '';
4365 });
4366 }
4367
4368 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
4369 parseMetadataContents(content);
4370 return '¨M';
4371 });
4372
4373 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
4374 if (format) {
4375 globals.metadata.format = format;
4376 }
4377 parseMetadataContents(content);
4378 return '¨M';
4379 });
4380
4381 text = text.replace(/¨M/g, '');
4382
4383 text = globals.converter._dispatch('metadata.after', text, options, globals);
4384 return text;
4385 });
4386
4387 /**
4388 * Remove one level of line-leading tabs or spaces
4389 */
4390 showdown.subParser('outdent', function (text, options, globals) {
4391 'use strict';
4392 text = globals.converter._dispatch('outdent.before', text, options, globals);
4393
4394 // attacklab: hack around Konqueror 3.5.4 bug:
4395 // "----------bug".replace(/^-/g,"") == "bug"
4396 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
4397
4398 // attacklab: clean up hack
4399 text = text.replace(/¨0/g, '');
4400
4401 text = globals.converter._dispatch('outdent.after', text, options, globals);
4402 return text;
4403 });
4404
4405 /**
4406 *
4407 */
4408 showdown.subParser('paragraphs', function (text, options, globals) {
4409 'use strict';
4410
4411 text = globals.converter._dispatch('paragraphs.before', text, options, globals);
4412 // Strip leading and trailing lines:
4413 text = text.replace(/^\n+/g, '');
4414 text = text.replace(/\n+$/g, '');
4415
4416 var grafs = text.split(/\n{2,}/g),
4417 grafsOut = [],
4418 end = grafs.length; // Wrap <p> tags
4419
4420 for (var i = 0; i < end; i++) {
4421 var str = grafs[i];
4422 // if this is an HTML marker, copy it
4423 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
4424 grafsOut.push(str);
4425
4426 // test for presence of characters to prevent empty lines being parsed
4427 // as paragraphs (resulting in undesired extra empty paragraphs)
4428 } else if (str.search(/\S/) >= 0) {
4429 str = showdown.subParser('spanGamut')(str, options, globals);
4430 str = str.replace(/^([ \t]*)/g, '<p>');
4431 str += '</p>';
4432 grafsOut.push(str);
4433 }
4434 }
4435
4436 /** Unhashify HTML blocks */
4437 end = grafsOut.length;
4438 for (i = 0; i < end; i++) {
4439 var blockText = '',
4440 grafsOutIt = grafsOut[i],
4441 codeFlag = false;
4442 // if this is a marker for an html block...
4443 // use RegExp.test instead of string.search because of QML bug
4444 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
4445 var delim = RegExp.$1,
4446 num = RegExp.$2;
4447
4448 if (delim === 'K') {
4449 blockText = globals.gHtmlBlocks[num];
4450 } else {
4451 // we need to check if ghBlock is a false positive
4452 if (codeFlag) {
4453 // use encoded version of all text
4454 blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4455 } else {
4456 blockText = globals.ghCodeBlocks[num].codeblock;
4457 }
4458 }
4459 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4460
4461 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4462 // Check if grafsOutIt is a pre->code
4463 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4464 codeFlag = true;
4465 }
4466 }
4467 grafsOut[i] = grafsOutIt;
4468 }
4469 text = grafsOut.join('\n');
4470 // Strip leading and trailing lines:
4471 text = text.replace(/^\n+/g, '');
4472 text = text.replace(/\n+$/g, '');
4473 return globals.converter._dispatch('paragraphs.after', text, options, globals);
4474 });
4475
4476 /**
4477 * Run extension
4478 */
4479 showdown.subParser('runExtension', function (ext, text, options, globals) {
4480 'use strict';
4481
4482 if (ext.filter) {
4483 text = ext.filter(text, globals.converter, options);
4484
4485 } else if (ext.regex) {
4486 // TODO remove this when old extension loading mechanism is deprecated
4487 var re = ext.regex;
4488 if (!(re instanceof RegExp)) {
4489 re = new RegExp(re, 'g');
4490 }
4491 text = text.replace(re, ext.replace);
4492 }
4493
4494 return text;
4495 });
4496
4497 /**
4498 * These are all the transformations that occur *within* block-level
4499 * tags like paragraphs, headers, and list items.
4500 */
4501 showdown.subParser('spanGamut', function (text, options, globals) {
4502 'use strict';
4503
4504 text = globals.converter._dispatch('spanGamut.before', text, options, globals);
4505 text = showdown.subParser('codeSpans')(text, options, globals);
4506 text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4507 text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
4508
4509 // Process anchor and image tags. Images must come first,
4510 // because ![foo][f] looks like an anchor.
4511 text = showdown.subParser('images')(text, options, globals);
4512 text = showdown.subParser('anchors')(text, options, globals);
4513
4514 // Make links out of things like `<http://example.com/>`
4515 // Must come after anchors, because you can use < and >
4516 // delimiters in inline links like [this](<url>).
4517 text = showdown.subParser('autoLinks')(text, options, globals);
4518 text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
4519 text = showdown.subParser('emoji')(text, options, globals);
4520 text = showdown.subParser('underline')(text, options, globals);
4521 text = showdown.subParser('italicsAndBold')(text, options, globals);
4522 text = showdown.subParser('strikethrough')(text, options, globals);
4523 text = showdown.subParser('ellipsis')(text, options, globals);
4524
4525 // we need to hash HTML tags inside spans
4526 text = showdown.subParser('hashHTMLSpans')(text, options, globals);
4527
4528 // now we encode amps and angles
4529 text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
4530
4531 // Do hard breaks
4532 if (options.simpleLineBreaks) {
4533 // GFM style hard breaks
4534 // only add line breaks if the text does not contain a block (special case for lists)
4535 if (!/\n\n¨K/.test(text)) {
4536 text = text.replace(/\n+/g, '<br />\n');
4537 }
4538 } else {
4539 // Vanilla hard breaks
4540 text = text.replace(/ +\n/g, '<br />\n');
4541 }
4542
4543 text = globals.converter._dispatch('spanGamut.after', text, options, globals);
4544 return text;
4545 });
4546
4547 showdown.subParser('strikethrough', function (text, options, globals) {
4548 'use strict';
4549
4550 function parseInside (txt) {
4551 if (options.simplifiedAutoLink) {
4552 txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4553 }
4554 return '<del>' + txt + '</del>';
4555 }
4556
4557 if (options.strikethrough) {
4558 text = globals.converter._dispatch('strikethrough.before', text, options, globals);
4559 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
4560 text = globals.converter._dispatch('strikethrough.after', text, options, globals);
4561 }
4562
4563 return text;
4564 });
4565
4566 /**
4567 * Strips link definitions from text, stores the URLs and titles in
4568 * hash references.
4569 * Link defs are in the form: ^[id]: url "optional title"
4570 */
4571 showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
4572 'use strict';
4573
4574 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,
4575 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;
4576
4577 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
4578 text += '¨0';
4579
4580 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
4581 linkId = linkId.toLowerCase();
4582 if (url.match(/^data:.+?\/.+?;base64,/)) {
4583 // remove newlines
4584 globals.gUrls[linkId] = url.replace(/\s/g, '');
4585 } else {
4586 globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
4587 }
4588
4589 if (blankLines) {
4590 // Oops, found blank lines, so it's not a title.
4591 // Put back the parenthetical statement we stole.
4592 return blankLines + title;
4593
4594 } else {
4595 if (title) {
4596 globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
4597 }
4598 if (options.parseImgDimensions && width && height) {
4599 globals.gDimensions[linkId] = {
4600 width: width,
4601 height: height
4602 };
4603 }
4604 }
4605 // Completely remove the definition from the text
4606 return '';
4607 };
4608
4609 // first we try to find base64 link references
4610 text = text.replace(base64Regex, replaceFunc);
4611
4612 text = text.replace(regex, replaceFunc);
4613
4614 // attacklab: strip sentinel
4615 text = text.replace(/¨0/, '');
4616
4617 return text;
4618 });
4619
4620 showdown.subParser('tables', function (text, options, globals) {
4621 'use strict';
4622
4623 if (!options.tables) {
4624 return text;
4625 }
4626
4627 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
4628 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
4629 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
4630
4631 function parseStyles (sLine) {
4632 if (/^:[ \t]*--*$/.test(sLine)) {
4633 return ' style="text-align:left;"';
4634 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
4635 return ' style="text-align:right;"';
4636 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
4637 return ' style="text-align:center;"';
4638 } else {
4639 return '';
4640 }
4641 }
4642
4643 function parseHeaders (header, style) {
4644 var id = '';
4645 header = header.trim();
4646 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
4647 if (options.tablesHeaderId || options.tableHeaderId) {
4648 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
4649 }
4650 header = showdown.subParser('spanGamut')(header, options, globals);
4651
4652 return '<th' + id + style + '>' + header + '</th>\n';
4653 }
4654
4655 function parseCells (cell, style) {
4656 var subText = showdown.subParser('spanGamut')(cell, options, globals);
4657 return '<td' + style + '>' + subText + '</td>\n';
4658 }
4659
4660 function buildTable (headers, cells) {
4661 var tb = '<table>\n<thead>\n<tr>\n',
4662 tblLgn = headers.length;
4663
4664 for (var i = 0; i < tblLgn; ++i) {
4665 tb += headers[i];
4666 }
4667 tb += '</tr>\n</thead>\n<tbody>\n';
4668
4669 for (i = 0; i < cells.length; ++i) {
4670 tb += '<tr>\n';
4671 for (var ii = 0; ii < tblLgn; ++ii) {
4672 tb += cells[i][ii];
4673 }
4674 tb += '</tr>\n';
4675 }
4676 tb += '</tbody>\n</table>\n';
4677 return tb;
4678 }
4679
4680 function parseTable (rawTable) {
4681 var i, tableLines = rawTable.split('\n');
4682
4683 for (i = 0; i < tableLines.length; ++i) {
4684 // strip wrong first and last column if wrapped tables are used
4685 if (/^ {0,3}\|/.test(tableLines[i])) {
4686 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
4687 }
4688 if (/\|[ \t]*$/.test(tableLines[i])) {
4689 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
4690 }
4691 // parse code spans first, but we only support one line code spans
4692 tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
4693 }
4694
4695 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
4696 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
4697 rawCells = [],
4698 headers = [],
4699 styles = [],
4700 cells = [];
4701
4702 tableLines.shift();
4703 tableLines.shift();
4704
4705 for (i = 0; i < tableLines.length; ++i) {
4706 if (tableLines[i].trim() === '') {
4707 continue;
4708 }
4709 rawCells.push(
4710 tableLines[i]
4711 .split('|')
4712 .map(function (s) {
4713 return s.trim();
4714 })
4715 );
4716 }
4717
4718 if (rawHeaders.length < rawStyles.length) {
4719 return rawTable;
4720 }
4721
4722 for (i = 0; i < rawStyles.length; ++i) {
4723 styles.push(parseStyles(rawStyles[i]));
4724 }
4725
4726 for (i = 0; i < rawHeaders.length; ++i) {
4727 if (showdown.helper.isUndefined(styles[i])) {
4728 styles[i] = '';
4729 }
4730 headers.push(parseHeaders(rawHeaders[i], styles[i]));
4731 }
4732
4733 for (i = 0; i < rawCells.length; ++i) {
4734 var row = [];
4735 for (var ii = 0; ii < headers.length; ++ii) {
4736 if (showdown.helper.isUndefined(rawCells[i][ii])) {
4737
4738 }
4739 row.push(parseCells(rawCells[i][ii], styles[ii]));
4740 }
4741 cells.push(row);
4742 }
4743
4744 return buildTable(headers, cells);
4745 }
4746
4747 text = globals.converter._dispatch('tables.before', text, options, globals);
4748
4749 // find escaped pipe characters
4750 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
4751
4752 // parse multi column tables
4753 text = text.replace(tableRgx, parseTable);
4754
4755 // parse one column tables
4756 text = text.replace(singeColTblRgx, parseTable);
4757
4758 text = globals.converter._dispatch('tables.after', text, options, globals);
4759
4760 return text;
4761 });
4762
4763 showdown.subParser('underline', function (text, options, globals) {
4764 'use strict';
4765
4766 if (!options.underline) {
4767 return text;
4768 }
4769
4770 text = globals.converter._dispatch('underline.before', text, options, globals);
4771
4772 if (options.literalMidWordUnderscores) {
4773 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4774 return '<u>' + txt + '</u>';
4775 });
4776 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4777 return '<u>' + txt + '</u>';
4778 });
4779 } else {
4780 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4781 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4782 });
4783 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4784 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4785 });
4786 }
4787
4788 // escape remaining underscores to prevent them being parsed by italic and bold
4789 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
4790
4791 text = globals.converter._dispatch('underline.after', text, options, globals);
4792
4793 return text;
4794 });
4795
4796 /**
4797 * Swap back in all the special characters we've hidden.
4798 */
4799 showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
4800 'use strict';
4801 text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
4802
4803 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
4804 var charCodeToReplace = parseInt(m1);
4805 return String.fromCharCode(charCodeToReplace);
4806 });
4807
4808 text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
4809 return text;
4810 });
4811
4812 showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
4813 'use strict';
4814
4815 var txt = '';
4816 if (node.hasChildNodes()) {
4817 var children = node.childNodes,
4818 childrenLength = children.length;
4819
4820 for (var i = 0; i < childrenLength; ++i) {
4821 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
4822
4823 if (innerTxt === '') {
4824 continue;
4825 }
4826 txt += innerTxt;
4827 }
4828 }
4829 // cleanup
4830 txt = txt.trim();
4831 txt = '> ' + txt.split('\n').join('\n> ');
4832 return txt;
4833 });
4834
4835 showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
4836 'use strict';
4837
4838 var lang = node.getAttribute('language'),
4839 num = node.getAttribute('precodenum');
4840 return '```' + lang + '\n' + globals.preList[num] + '\n```';
4841 });
4842
4843 showdown.subParser('makeMarkdown.codeSpan', function (node) {
4844 'use strict';
4845
4846 return '`' + node.innerHTML + '`';
4847 });
4848
4849 showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
4850 'use strict';
4851
4852 var txt = '';
4853 if (node.hasChildNodes()) {
4854 txt += '*';
4855 var children = node.childNodes,
4856 childrenLength = children.length;
4857 for (var i = 0; i < childrenLength; ++i) {
4858 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4859 }
4860 txt += '*';
4861 }
4862 return txt;
4863 });
4864
4865 showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
4866 'use strict';
4867
4868 var headerMark = new Array(headerLevel + 1).join('#'),
4869 txt = '';
4870
4871 if (node.hasChildNodes()) {
4872 txt = headerMark + ' ';
4873 var children = node.childNodes,
4874 childrenLength = children.length;
4875
4876 for (var i = 0; i < childrenLength; ++i) {
4877 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4878 }
4879 }
4880 return txt;
4881 });
4882
4883 showdown.subParser('makeMarkdown.hr', function () {
4884 'use strict';
4885
4886 return '---';
4887 });
4888
4889 showdown.subParser('makeMarkdown.image', function (node) {
4890 'use strict';
4891
4892 var txt = '';
4893 if (node.hasAttribute('src')) {
4894 txt += '![' + node.getAttribute('alt') + '](';
4895 txt += '<' + node.getAttribute('src') + '>';
4896 if (node.hasAttribute('width') && node.hasAttribute('height')) {
4897 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
4898 }
4899
4900 if (node.hasAttribute('title')) {
4901 txt += ' "' + node.getAttribute('title') + '"';
4902 }
4903 txt += ')';
4904 }
4905 return txt;
4906 });
4907
4908 showdown.subParser('makeMarkdown.links', function (node, globals) {
4909 'use strict';
4910
4911 var txt = '';
4912 if (node.hasChildNodes() && node.hasAttribute('href')) {
4913 var children = node.childNodes,
4914 childrenLength = children.length;
4915 txt = '[';
4916 for (var i = 0; i < childrenLength; ++i) {
4917 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4918 }
4919 txt += '](';
4920 txt += '<' + node.getAttribute('href') + '>';
4921 if (node.hasAttribute('title')) {
4922 txt += ' "' + node.getAttribute('title') + '"';
4923 }
4924 txt += ')';
4925 }
4926 return txt;
4927 });
4928
4929 showdown.subParser('makeMarkdown.list', function (node, globals, type) {
4930 'use strict';
4931
4932 var txt = '';
4933 if (!node.hasChildNodes()) {
4934 return '';
4935 }
4936 var listItems = node.childNodes,
4937 listItemsLenght = listItems.length,
4938 listNum = node.getAttribute('start') || 1;
4939
4940 for (var i = 0; i < listItemsLenght; ++i) {
4941 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
4942 continue;
4943 }
4944
4945 // define the bullet to use in list
4946 var bullet = '';
4947 if (type === 'ol') {
4948 bullet = listNum.toString() + '. ';
4949 } else {
4950 bullet = '- ';
4951 }
4952
4953 // parse list item
4954 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
4955 ++listNum;
4956 }
4957
4958 // add comment at the end to prevent consecutive lists to be parsed as one
4959 txt += '\n<!-- -->\n';
4960 return txt.trim();
4961 });
4962
4963 showdown.subParser('makeMarkdown.listItem', function (node, globals) {
4964 'use strict';
4965
4966 var listItemTxt = '';
4967
4968 var children = node.childNodes,
4969 childrenLenght = children.length;
4970
4971 for (var i = 0; i < childrenLenght; ++i) {
4972 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4973 }
4974 // if it's only one liner, we need to add a newline at the end
4975 if (!/\n$/.test(listItemTxt)) {
4976 listItemTxt += '\n';
4977 } else {
4978 // it's multiparagraph, so we need to indent
4979 listItemTxt = listItemTxt
4980 .split('\n')
4981 .join('\n ')
4982 .replace(/^ {4}$/gm, '')
4983 .replace(/\n\n+/g, '\n\n');
4984 }
4985
4986 return listItemTxt;
4987 });
4988
4989
4990
4991 showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
4992 'use strict';
4993
4994 spansOnly = spansOnly || false;
4995
4996 var txt = '';
4997
4998 // edge case of text without wrapper paragraph
4999 if (node.nodeType === 3) {
5000 return showdown.subParser('makeMarkdown.txt')(node, globals);
5001 }
5002
5003 // HTML comment
5004 if (node.nodeType === 8) {
5005 return '<!--' + node.data + '-->\n\n';
5006 }
5007
5008 // process only node elements
5009 if (node.nodeType !== 1) {
5010 return '';
5011 }
5012
5013 var tagName = node.tagName.toLowerCase();
5014
5015 switch (tagName) {
5016
5017 //
5018 // BLOCKS
5019 //
5020 case 'h1':
5021 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
5022 break;
5023 case 'h2':
5024 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
5025 break;
5026 case 'h3':
5027 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
5028 break;
5029 case 'h4':
5030 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
5031 break;
5032 case 'h5':
5033 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
5034 break;
5035 case 'h6':
5036 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
5037 break;
5038
5039 case 'p':
5040 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
5041 break;
5042
5043 case 'blockquote':
5044 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
5045 break;
5046
5047 case 'hr':
5048 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
5049 break;
5050
5051 case 'ol':
5052 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
5053 break;
5054
5055 case 'ul':
5056 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
5057 break;
5058
5059 case 'precode':
5060 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
5061 break;
5062
5063 case 'pre':
5064 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
5065 break;
5066
5067 case 'table':
5068 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
5069 break;
5070
5071 //
5072 // SPANS
5073 //
5074 case 'code':
5075 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
5076 break;
5077
5078 case 'em':
5079 case 'i':
5080 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
5081 break;
5082
5083 case 'strong':
5084 case 'b':
5085 txt = showdown.subParser('makeMarkdown.strong')(node, globals);
5086 break;
5087
5088 case 'del':
5089 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
5090 break;
5091
5092 case 'a':
5093 txt = showdown.subParser('makeMarkdown.links')(node, globals);
5094 break;
5095
5096 case 'img':
5097 txt = showdown.subParser('makeMarkdown.image')(node, globals);
5098 break;
5099
5100 default:
5101 txt = node.outerHTML + '\n\n';
5102 }
5103
5104 // common normalization
5105 // TODO eventually
5106
5107 return txt;
5108 });
5109
5110 showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
5111 'use strict';
5112
5113 var txt = '';
5114 if (node.hasChildNodes()) {
5115 var children = node.childNodes,
5116 childrenLength = children.length;
5117 for (var i = 0; i < childrenLength; ++i) {
5118 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5119 }
5120 }
5121
5122 // some text normalization
5123 txt = txt.trim();
5124
5125 return txt;
5126 });
5127
5128 showdown.subParser('makeMarkdown.pre', function (node, globals) {
5129 'use strict';
5130
5131 var num = node.getAttribute('prenum');
5132 return '<pre>' + globals.preList[num] + '</pre>';
5133 });
5134
5135 showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
5136 'use strict';
5137
5138 var txt = '';
5139 if (node.hasChildNodes()) {
5140 txt += '~~';
5141 var children = node.childNodes,
5142 childrenLength = children.length;
5143 for (var i = 0; i < childrenLength; ++i) {
5144 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5145 }
5146 txt += '~~';
5147 }
5148 return txt;
5149 });
5150
5151 showdown.subParser('makeMarkdown.strong', function (node, globals) {
5152 'use strict';
5153
5154 var txt = '';
5155 if (node.hasChildNodes()) {
5156 txt += '**';
5157 var children = node.childNodes,
5158 childrenLength = children.length;
5159 for (var i = 0; i < childrenLength; ++i) {
5160 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5161 }
5162 txt += '**';
5163 }
5164 return txt;
5165 });
5166
5167 showdown.subParser('makeMarkdown.table', function (node, globals) {
5168 'use strict';
5169
5170 var txt = '',
5171 tableArray = [[], []],
5172 headings = node.querySelectorAll('thead>tr>th'),
5173 rows = node.querySelectorAll('tbody>tr'),
5174 i, ii;
5175 for (i = 0; i < headings.length; ++i) {
5176 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
5177 allign = '---';
5178
5179 if (headings[i].hasAttribute('style')) {
5180 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
5181 switch (style) {
5182 case 'text-align:left;':
5183 allign = ':---';
5184 break;
5185 case 'text-align:right;':
5186 allign = '---:';
5187 break;
5188 case 'text-align:center;':
5189 allign = ':---:';
5190 break;
5191 }
5192 }
5193 tableArray[0][i] = headContent.trim();
5194 tableArray[1][i] = allign;
5195 }
5196
5197 for (i = 0; i < rows.length; ++i) {
5198 var r = tableArray.push([]) - 1,
5199 cols = rows[i].getElementsByTagName('td');
5200
5201 for (ii = 0; ii < headings.length; ++ii) {
5202 var cellContent = ' ';
5203 if (typeof cols[ii] !== 'undefined') {
5204 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
5205 }
5206 tableArray[r].push(cellContent);
5207 }
5208 }
5209
5210 var cellSpacesCount = 3;
5211 for (i = 0; i < tableArray.length; ++i) {
5212 for (ii = 0; ii < tableArray[i].length; ++ii) {
5213 var strLen = tableArray[i][ii].length;
5214 if (strLen > cellSpacesCount) {
5215 cellSpacesCount = strLen;
5216 }
5217 }
5218 }
5219
5220 for (i = 0; i < tableArray.length; ++i) {
5221 for (ii = 0; ii < tableArray[i].length; ++ii) {
5222 if (i === 1) {
5223 if (tableArray[i][ii].slice(-1) === ':') {
5224 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
5225 } else {
5226 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
5227 }
5228 } else {
5229 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
5230 }
5231 }
5232 txt += '| ' + tableArray[i].join(' | ') + ' |\n';
5233 }
5234
5235 return txt.trim();
5236 });
5237
5238 showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
5239 'use strict';
5240
5241 var txt = '';
5242 if (!node.hasChildNodes()) {
5243 return '';
5244 }
5245 var children = node.childNodes,
5246 childrenLength = children.length;
5247
5248 for (var i = 0; i < childrenLength; ++i) {
5249 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
5250 }
5251 return txt.trim();
5252 });
5253
5254 showdown.subParser('makeMarkdown.txt', function (node) {
5255 'use strict';
5256
5257 var txt = node.nodeValue;
5258
5259 // multiple spaces are collapsed
5260 txt = txt.replace(/ +/g, ' ');
5261
5262 // replace the custom ¨NBSP; with a space
5263 txt = txt.replace(/¨NBSP;/g, ' ');
5264
5265 // ", <, > and & should replace escaped html entities
5266 txt = showdown.helper.unescapeHTMLEntities(txt);
5267
5268 // escape markdown magic characters
5269 // emphasis, strong and strikethrough - can appear everywhere
5270 // we also escape pipe (|) because of tables
5271 // and escape ` because of code blocks and spans
5272 txt = txt.replace(/([*_~|`])/g, '\\$1');
5273
5274 // escape > because of blockquotes
5275 txt = txt.replace(/^(\s*)>/g, '\\$1>');
5276
5277 // hash character, only troublesome at the beginning of a line because of headers
5278 txt = txt.replace(/^#/gm, '\\#');
5279
5280 // horizontal rules
5281 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
5282
5283 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
5284 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
5285
5286 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
5287 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
5288
5289 // images and links, ] followed by ( is problematic, so we escape it
5290 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
5291
5292 // reference URIs must also be escaped
5293 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
5294
5295 return txt;
5296 });
5297
5298 var root = this;
5299
5300 // AMD Loader
5301 if (true) {
5302 !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {
5303 'use strict';
5304 return showdown;
5305 }).call(exports, __webpack_require__, exports, module),
5306 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5307
5308 // CommonJS/nodeJS Loader
5309 } else {}
5310 }).call(this);
5311
5312
5313
5314
5315 /***/ })
5316
5317 /******/ });
5318 /************************************************************************/
5319 /******/ // The module cache
5320 /******/ var __webpack_module_cache__ = {};
5321 /******/
5322 /******/ // The require function
5323 /******/ function __webpack_require__(moduleId) {
5324 /******/ // Check if module is in cache
5325 /******/ var cachedModule = __webpack_module_cache__[moduleId];
5326 /******/ if (cachedModule !== undefined) {
5327 /******/ return cachedModule.exports;
5328 /******/ }
5329 /******/ // Create a new module (and put it into the cache)
5330 /******/ var module = __webpack_module_cache__[moduleId] = {
5331 /******/ // no module.id needed
5332 /******/ // no module.loaded needed
5333 /******/ exports: {}
5334 /******/ };
5335 /******/
5336 /******/ // Execute the module function
5337 /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
5338 /******/
5339 /******/ // Return the exports of the module
5340 /******/ return module.exports;
5341 /******/ }
5342 /******/
5343 /************************************************************************/
5344 /******/ /* webpack/runtime/compat get default export */
5345 /******/ !function() {
5346 /******/ // getDefaultExport function for compatibility with non-harmony modules
5347 /******/ __webpack_require__.n = function(module) {
5348 /******/ var getter = module && module.__esModule ?
5349 /******/ function() { return module['default']; } :
5350 /******/ function() { return module; };
5351 /******/ __webpack_require__.d(getter, { a: getter });
5352 /******/ return getter;
5353 /******/ };
5354 /******/ }();
5355 /******/
5356 /******/ /* webpack/runtime/define property getters */
5357 /******/ !function() {
5358 /******/ // define getter functions for harmony exports
5359 /******/ __webpack_require__.d = function(exports, definition) {
5360 /******/ for(var key in definition) {
5361 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
5362 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
5363 /******/ }
5364 /******/ }
5365 /******/ };
5366 /******/ }();
5367 /******/
5368 /******/ /* webpack/runtime/hasOwnProperty shorthand */
5369 /******/ !function() {
5370 /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
5371 /******/ }();
5372 /******/
5373 /******/ /* webpack/runtime/make namespace object */
5374 /******/ !function() {
5375 /******/ // define __esModule on exports
5376 /******/ __webpack_require__.r = function(exports) {
5377 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
5378 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5379 /******/ }
5380 /******/ Object.defineProperty(exports, '__esModule', { value: true });
5381 /******/ };
5382 /******/ }();
5383 /******/
5384 /************************************************************************/
5385 var __webpack_exports__ = {};
5386 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
5387 !function() {
5388 "use strict";
5389 // ESM COMPAT FLAG
5390 __webpack_require__.r(__webpack_exports__);
5391
5392 // EXPORTS
5393 __webpack_require__.d(__webpack_exports__, {
5394 "__EXPERIMENTAL_ELEMENTS": function() { return /* reexport */ __EXPERIMENTAL_ELEMENTS; },
5395 "__EXPERIMENTAL_PATHS_WITH_MERGE": function() { return /* reexport */ __EXPERIMENTAL_PATHS_WITH_MERGE; },
5396 "__EXPERIMENTAL_STYLE_PROPERTY": function() { return /* reexport */ __EXPERIMENTAL_STYLE_PROPERTY; },
5397 "__experimentalCloneSanitizedBlock": function() { return /* reexport */ __experimentalCloneSanitizedBlock; },
5398 "__experimentalGetAccessibleBlockLabel": function() { return /* reexport */ getAccessibleBlockLabel; },
5399 "__experimentalGetBlockAttributesNamesByRole": function() { return /* reexport */ __experimentalGetBlockAttributesNamesByRole; },
5400 "__experimentalGetBlockLabel": function() { return /* reexport */ getBlockLabel; },
5401 "__experimentalSanitizeBlockAttributes": function() { return /* reexport */ __experimentalSanitizeBlockAttributes; },
5402 "__unstableGetBlockProps": function() { return /* reexport */ getBlockProps; },
5403 "__unstableGetInnerBlocksProps": function() { return /* reexport */ getInnerBlocksProps; },
5404 "__unstableSerializeAndClean": function() { return /* reexport */ __unstableSerializeAndClean; },
5405 "children": function() { return /* reexport */ children; },
5406 "cloneBlock": function() { return /* reexport */ cloneBlock; },
5407 "createBlock": function() { return /* reexport */ createBlock; },
5408 "createBlocksFromInnerBlocksTemplate": function() { return /* reexport */ createBlocksFromInnerBlocksTemplate; },
5409 "doBlocksMatchTemplate": function() { return /* reexport */ doBlocksMatchTemplate; },
5410 "findTransform": function() { return /* reexport */ findTransform; },
5411 "getBlockAttributes": function() { return /* reexport */ getBlockAttributes; },
5412 "getBlockContent": function() { return /* reexport */ getBlockInnerHTML; },
5413 "getBlockDefaultClassName": function() { return /* reexport */ getBlockDefaultClassName; },
5414 "getBlockFromExample": function() { return /* reexport */ getBlockFromExample; },
5415 "getBlockMenuDefaultClassName": function() { return /* reexport */ getBlockMenuDefaultClassName; },
5416 "getBlockSupport": function() { return /* reexport */ registration_getBlockSupport; },
5417 "getBlockTransforms": function() { return /* reexport */ getBlockTransforms; },
5418 "getBlockType": function() { return /* reexport */ registration_getBlockType; },
5419 "getBlockTypes": function() { return /* reexport */ registration_getBlockTypes; },
5420 "getBlockVariations": function() { return /* reexport */ registration_getBlockVariations; },
5421 "getCategories": function() { return /* reexport */ categories_getCategories; },
5422 "getChildBlockNames": function() { return /* reexport */ registration_getChildBlockNames; },
5423 "getDefaultBlockName": function() { return /* reexport */ registration_getDefaultBlockName; },
5424 "getFreeformContentHandlerName": function() { return /* reexport */ getFreeformContentHandlerName; },
5425 "getGroupingBlockName": function() { return /* reexport */ registration_getGroupingBlockName; },
5426 "getPhrasingContentSchema": function() { return /* reexport */ deprecatedGetPhrasingContentSchema; },
5427 "getPossibleBlockTransformations": function() { return /* reexport */ getPossibleBlockTransformations; },
5428 "getSaveContent": function() { return /* reexport */ getSaveContent; },
5429 "getSaveElement": function() { return /* reexport */ getSaveElement; },
5430 "getUnregisteredTypeHandlerName": function() { return /* reexport */ getUnregisteredTypeHandlerName; },
5431 "hasBlockSupport": function() { return /* reexport */ registration_hasBlockSupport; },
5432 "hasChildBlocks": function() { return /* reexport */ registration_hasChildBlocks; },
5433 "hasChildBlocksWithInserterSupport": function() { return /* reexport */ registration_hasChildBlocksWithInserterSupport; },
5434 "isReusableBlock": function() { return /* reexport */ isReusableBlock; },
5435 "isTemplatePart": function() { return /* reexport */ isTemplatePart; },
5436 "isUnmodifiedDefaultBlock": function() { return /* reexport */ isUnmodifiedDefaultBlock; },
5437 "isValidBlockContent": function() { return /* reexport */ isValidBlockContent; },
5438 "isValidIcon": function() { return /* reexport */ isValidIcon; },
5439 "node": function() { return /* reexport */ node; },
5440 "normalizeIconObject": function() { return /* reexport */ normalizeIconObject; },
5441 "parse": function() { return /* reexport */ parser_parse; },
5442 "parseWithAttributeSchema": function() { return /* reexport */ parseWithAttributeSchema; },
5443 "pasteHandler": function() { return /* reexport */ pasteHandler; },
5444 "rawHandler": function() { return /* reexport */ rawHandler; },
5445 "registerBlockCollection": function() { return /* reexport */ registerBlockCollection; },
5446 "registerBlockStyle": function() { return /* reexport */ registerBlockStyle; },
5447 "registerBlockType": function() { return /* reexport */ registerBlockType; },
5448 "registerBlockVariation": function() { return /* reexport */ registerBlockVariation; },
5449 "serialize": function() { return /* reexport */ serializer_serialize; },
5450 "serializeRawBlock": function() { return /* reexport */ serializeRawBlock; },
5451 "setCategories": function() { return /* reexport */ categories_setCategories; },
5452 "setDefaultBlockName": function() { return /* reexport */ setDefaultBlockName; },
5453 "setFreeformContentHandlerName": function() { return /* reexport */ setFreeformContentHandlerName; },
5454 "setGroupingBlockName": function() { return /* reexport */ setGroupingBlockName; },
5455 "setUnregisteredTypeHandlerName": function() { return /* reexport */ setUnregisteredTypeHandlerName; },
5456 "store": function() { return /* reexport */ store; },
5457 "switchToBlockType": function() { return /* reexport */ switchToBlockType; },
5458 "synchronizeBlocksWithTemplate": function() { return /* reexport */ synchronizeBlocksWithTemplate; },
5459 "unregisterBlockStyle": function() { return /* reexport */ unregisterBlockStyle; },
5460 "unregisterBlockType": function() { return /* reexport */ unregisterBlockType; },
5461 "unregisterBlockVariation": function() { return /* reexport */ unregisterBlockVariation; },
5462 "unstable__bootstrapServerSideBlockDefinitions": function() { return /* reexport */ unstable__bootstrapServerSideBlockDefinitions; },
5463 "updateCategory": function() { return /* reexport */ categories_updateCategory; },
5464 "validateBlock": function() { return /* reexport */ validateBlock; },
5465 "withBlockContentContext": function() { return /* reexport */ withBlockContentContext; }
5466 });
5467
5468 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/selectors.js
5469 var selectors_namespaceObject = {};
5470 __webpack_require__.r(selectors_namespaceObject);
5471 __webpack_require__.d(selectors_namespaceObject, {
5472 "__experimentalGetUnprocessedBlockTypes": function() { return __experimentalGetUnprocessedBlockTypes; },
5473 "getActiveBlockVariation": function() { return getActiveBlockVariation; },
5474 "getBlockStyles": function() { return getBlockStyles; },
5475 "getBlockSupport": function() { return getBlockSupport; },
5476 "getBlockType": function() { return getBlockType; },
5477 "getBlockTypes": function() { return getBlockTypes; },
5478 "getBlockVariations": function() { return getBlockVariations; },
5479 "getCategories": function() { return getCategories; },
5480 "getChildBlockNames": function() { return getChildBlockNames; },
5481 "getCollections": function() { return getCollections; },
5482 "getDefaultBlockName": function() { return getDefaultBlockName; },
5483 "getDefaultBlockVariation": function() { return getDefaultBlockVariation; },
5484 "getFreeformFallbackBlockName": function() { return getFreeformFallbackBlockName; },
5485 "getGroupingBlockName": function() { return getGroupingBlockName; },
5486 "getUnregisteredFallbackBlockName": function() { return getUnregisteredFallbackBlockName; },
5487 "hasBlockSupport": function() { return hasBlockSupport; },
5488 "hasChildBlocks": function() { return hasChildBlocks; },
5489 "hasChildBlocksWithInserterSupport": function() { return hasChildBlocksWithInserterSupport; },
5490 "isMatchingSearchTerm": function() { return isMatchingSearchTerm; }
5491 });
5492
5493 // NAMESPACE OBJECT: ./packages/blocks/build-module/store/actions.js
5494 var actions_namespaceObject = {};
5495 __webpack_require__.r(actions_namespaceObject);
5496 __webpack_require__.d(actions_namespaceObject, {
5497 "__experimentalReapplyBlockTypeFilters": function() { return __experimentalReapplyBlockTypeFilters; },
5498 "__experimentalRegisterBlockType": function() { return __experimentalRegisterBlockType; },
5499 "addBlockCollection": function() { return addBlockCollection; },
5500 "addBlockStyles": function() { return addBlockStyles; },
5501 "addBlockTypes": function() { return addBlockTypes; },
5502 "addBlockVariations": function() { return addBlockVariations; },
5503 "removeBlockCollection": function() { return removeBlockCollection; },
5504 "removeBlockStyles": function() { return removeBlockStyles; },
5505 "removeBlockTypes": function() { return removeBlockTypes; },
5506 "removeBlockVariations": function() { return removeBlockVariations; },
5507 "setCategories": function() { return setCategories; },
5508 "setDefaultBlockName": function() { return actions_setDefaultBlockName; },
5509 "setFreeformFallbackBlockName": function() { return setFreeformFallbackBlockName; },
5510 "setGroupingBlockName": function() { return actions_setGroupingBlockName; },
5511 "setUnregisteredFallbackBlockName": function() { return setUnregisteredFallbackBlockName; },
5512 "updateCategory": function() { return updateCategory; }
5513 });
5514
5515 ;// CONCATENATED MODULE: external ["wp","data"]
5516 var external_wp_data_namespaceObject = window["wp"]["data"];
5517 ;// CONCATENATED MODULE: external "lodash"
5518 var external_lodash_namespaceObject = window["lodash"];
5519 ;// CONCATENATED MODULE: external ["wp","i18n"]
5520 var external_wp_i18n_namespaceObject = window["wp"]["i18n"];
5521 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/reducer.js
5522 /**
5523 * External dependencies
5524 */
5525
5526 /**
5527 * WordPress dependencies
5528 */
5529
5530
5531
5532 /**
5533 * @typedef {Object} WPBlockCategory
5534 *
5535 * @property {string} slug Unique category slug.
5536 * @property {string} title Category label, for display in user interface.
5537 */
5538
5539 /**
5540 * Default set of categories.
5541 *
5542 * @type {WPBlockCategory[]}
5543 */
5544
5545 const DEFAULT_CATEGORIES = [{
5546 slug: 'text',
5547 title: (0,external_wp_i18n_namespaceObject.__)('Text')
5548 }, {
5549 slug: 'media',
5550 title: (0,external_wp_i18n_namespaceObject.__)('Media')
5551 }, {
5552 slug: 'design',
5553 title: (0,external_wp_i18n_namespaceObject.__)('Design')
5554 }, {
5555 slug: 'widgets',
5556 title: (0,external_wp_i18n_namespaceObject.__)('Widgets')
5557 }, {
5558 slug: 'theme',
5559 title: (0,external_wp_i18n_namespaceObject.__)('Theme')
5560 }, {
5561 slug: 'embed',
5562 title: (0,external_wp_i18n_namespaceObject.__)('Embeds')
5563 }, {
5564 slug: 'reusable',
5565 title: (0,external_wp_i18n_namespaceObject.__)('Reusable blocks')
5566 }];
5567 /**
5568 * Reducer managing the unprocessed block types in a form passed when registering the by block.
5569 * It's for internal use only. It allows recomputing the processed block types on-demand after block type filters
5570 * get added or removed.
5571 *
5572 * @param {Object} state Current state.
5573 * @param {Object} action Dispatched action.
5574 *
5575 * @return {Object} Updated state.
5576 */
5577
5578 function unprocessedBlockTypes() {
5579 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5580 let action = arguments.length > 1 ? arguments[1] : undefined;
5581
5582 switch (action.type) {
5583 case 'ADD_UNPROCESSED_BLOCK_TYPE':
5584 return { ...state,
5585 [action.blockType.name]: action.blockType
5586 };
5587
5588 case 'REMOVE_BLOCK_TYPES':
5589 return (0,external_lodash_namespaceObject.omit)(state, action.names);
5590 }
5591
5592 return state;
5593 }
5594 /**
5595 * Reducer managing the processed block types with all filters applied.
5596 * The state is derived from the `unprocessedBlockTypes` reducer.
5597 *
5598 * @param {Object} state Current state.
5599 * @param {Object} action Dispatched action.
5600 *
5601 * @return {Object} Updated state.
5602 */
5603
5604 function blockTypes() {
5605 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5606 let action = arguments.length > 1 ? arguments[1] : undefined;
5607
5608 switch (action.type) {
5609 case 'ADD_BLOCK_TYPES':
5610 return { ...state,
5611 ...(0,external_lodash_namespaceObject.keyBy)(action.blockTypes, 'name')
5612 };
5613
5614 case 'REMOVE_BLOCK_TYPES':
5615 return (0,external_lodash_namespaceObject.omit)(state, action.names);
5616 }
5617
5618 return state;
5619 }
5620 /**
5621 * Reducer managing the block style variations.
5622 *
5623 * @param {Object} state Current state.
5624 * @param {Object} action Dispatched action.
5625 *
5626 * @return {Object} Updated state.
5627 */
5628
5629 function blockStyles() {
5630 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5631 let action = arguments.length > 1 ? arguments[1] : undefined;
5632
5633 switch (action.type) {
5634 case 'ADD_BLOCK_TYPES':
5635 return { ...state,
5636 ...(0,external_lodash_namespaceObject.mapValues)((0,external_lodash_namespaceObject.keyBy)(action.blockTypes, 'name'), blockType => {
5637 return (0,external_lodash_namespaceObject.uniqBy)([...(0,external_lodash_namespaceObject.get)(blockType, ['styles'], []).map(style => ({ ...style,
5638 source: 'block'
5639 })), ...(0,external_lodash_namespaceObject.get)(state, [blockType.name], []).filter(_ref => {
5640 let {
5641 source
5642 } = _ref;
5643 return 'block' !== source;
5644 })], style => style.name);
5645 })
5646 };
5647
5648 case 'ADD_BLOCK_STYLES':
5649 return { ...state,
5650 [action.blockName]: (0,external_lodash_namespaceObject.uniqBy)([...(0,external_lodash_namespaceObject.get)(state, [action.blockName], []), ...action.styles], style => style.name)
5651 };
5652
5653 case 'REMOVE_BLOCK_STYLES':
5654 return { ...state,
5655 [action.blockName]: (0,external_lodash_namespaceObject.filter)((0,external_lodash_namespaceObject.get)(state, [action.blockName], []), style => action.styleNames.indexOf(style.name) === -1)
5656 };
5657 }
5658
5659 return state;
5660 }
5661 /**
5662 * Reducer managing the block variations.
5663 *
5664 * @param {Object} state Current state.
5665 * @param {Object} action Dispatched action.
5666 *
5667 * @return {Object} Updated state.
5668 */
5669
5670 function blockVariations() {
5671 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5672 let action = arguments.length > 1 ? arguments[1] : undefined;
5673
5674 switch (action.type) {
5675 case 'ADD_BLOCK_TYPES':
5676 return { ...state,
5677 ...(0,external_lodash_namespaceObject.mapValues)((0,external_lodash_namespaceObject.keyBy)(action.blockTypes, 'name'), blockType => {
5678 return (0,external_lodash_namespaceObject.uniqBy)([...(0,external_lodash_namespaceObject.get)(blockType, ['variations'], []).map(variation => ({ ...variation,
5679 source: 'block'
5680 })), ...(0,external_lodash_namespaceObject.get)(state, [blockType.name], []).filter(_ref2 => {
5681 let {
5682 source
5683 } = _ref2;
5684 return 'block' !== source;
5685 })], variation => variation.name);
5686 })
5687 };
5688
5689 case 'ADD_BLOCK_VARIATIONS':
5690 return { ...state,
5691 [action.blockName]: (0,external_lodash_namespaceObject.uniqBy)([...(0,external_lodash_namespaceObject.get)(state, [action.blockName], []), ...action.variations], variation => variation.name)
5692 };
5693
5694 case 'REMOVE_BLOCK_VARIATIONS':
5695 return { ...state,
5696 [action.blockName]: (0,external_lodash_namespaceObject.filter)((0,external_lodash_namespaceObject.get)(state, [action.blockName], []), variation => action.variationNames.indexOf(variation.name) === -1)
5697 };
5698 }
5699
5700 return state;
5701 }
5702 /**
5703 * Higher-order Reducer creating a reducer keeping track of given block name.
5704 *
5705 * @param {string} setActionType Action type.
5706 *
5707 * @return {Function} Reducer.
5708 */
5709
5710 function createBlockNameSetterReducer(setActionType) {
5711 return function () {
5712 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
5713 let action = arguments.length > 1 ? arguments[1] : undefined;
5714
5715 switch (action.type) {
5716 case 'REMOVE_BLOCK_TYPES':
5717 if (action.names.indexOf(state) !== -1) {
5718 return null;
5719 }
5720
5721 return state;
5722
5723 case setActionType:
5724 return action.name || null;
5725 }
5726
5727 return state;
5728 };
5729 }
5730 const defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
5731 const freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
5732 const unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
5733 const groupingBlockName = createBlockNameSetterReducer('SET_GROUPING_BLOCK_NAME');
5734 /**
5735 * Reducer managing the categories
5736 *
5737 * @param {WPBlockCategory[]} state Current state.
5738 * @param {Object} action Dispatched action.
5739 *
5740 * @return {WPBlockCategory[]} Updated state.
5741 */
5742
5743 function categories() {
5744 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_CATEGORIES;
5745 let action = arguments.length > 1 ? arguments[1] : undefined;
5746
5747 switch (action.type) {
5748 case 'SET_CATEGORIES':
5749 return action.categories || [];
5750
5751 case 'UPDATE_CATEGORY':
5752 {
5753 if (!action.category || (0,external_lodash_namespaceObject.isEmpty)(action.category)) {
5754 return state;
5755 }
5756
5757 const categoryToChange = (0,external_lodash_namespaceObject.find)(state, ['slug', action.slug]);
5758
5759 if (categoryToChange) {
5760 return (0,external_lodash_namespaceObject.map)(state, category => {
5761 if (category.slug === action.slug) {
5762 return { ...category,
5763 ...action.category
5764 };
5765 }
5766
5767 return category;
5768 });
5769 }
5770 }
5771 }
5772
5773 return state;
5774 }
5775 function collections() {
5776 let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5777 let action = arguments.length > 1 ? arguments[1] : undefined;
5778
5779 switch (action.type) {
5780 case 'ADD_BLOCK_COLLECTION':
5781 return { ...state,
5782 [action.namespace]: {
5783 title: action.title,
5784 icon: action.icon
5785 }
5786 };
5787
5788 case 'REMOVE_BLOCK_COLLECTION':
5789 return (0,external_lodash_namespaceObject.omit)(state, action.namespace);
5790 }
5791
5792 return state;
5793 }
5794 /* harmony default export */ var reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
5795 unprocessedBlockTypes,
5796 blockTypes,
5797 blockStyles,
5798 blockVariations,
5799 defaultBlockName,
5800 freeformFallbackBlockName,
5801 unregisteredFallbackBlockName,
5802 groupingBlockName,
5803 categories,
5804 collections
5805 }));
5806
5807 ;// CONCATENATED MODULE: ./node_modules/rememo/es/rememo.js
5808
5809
5810 /** @typedef {(...args: any[]) => *[]} GetDependants */
5811
5812 /** @typedef {() => void} Clear */
5813
5814 /**
5815 * @typedef {{
5816 * getDependants: GetDependants,
5817 * clear: Clear
5818 * }} EnhancedSelector
5819 */
5820
5821 /**
5822 * Internal cache entry.
5823 *
5824 * @typedef CacheNode
5825 *
5826 * @property {?CacheNode|undefined} [prev] Previous node.
5827 * @property {?CacheNode|undefined} [next] Next node.
5828 * @property {*[]} args Function arguments for cache entry.
5829 * @property {*} val Function result.
5830 */
5831
5832 /**
5833 * @typedef Cache
5834 *
5835 * @property {Clear} clear Function to clear cache.
5836 * @property {boolean} [isUniqueByDependants] Whether dependants are valid in
5837 * considering cache uniqueness. A cache is unique if dependents are all arrays
5838 * or objects.
5839 * @property {CacheNode?} [head] Cache head.
5840 * @property {*[]} [lastDependants] Dependants from previous invocation.
5841 */
5842
5843 /**
5844 * Arbitrary value used as key for referencing cache object in WeakMap tree.
5845 *
5846 * @type {{}}
5847 */
5848 var LEAF_KEY = {};
5849
5850 /**
5851 * Returns the first argument as the sole entry in an array.
5852 *
5853 * @template T
5854 *
5855 * @param {T} value Value to return.
5856 *
5857 * @return {[T]} Value returned as entry in array.
5858 */
5859 function arrayOf(value) {
5860 return [value];
5861 }
5862
5863 /**
5864 * Returns true if the value passed is object-like, or false otherwise. A value
5865 * is object-like if it can support property assignment, e.g. object or array.
5866 *
5867 * @param {*} value Value to test.
5868 *
5869 * @return {boolean} Whether value is object-like.
5870 */
5871 function isObjectLike(value) {
5872 return !!value && 'object' === typeof value;
5873 }
5874
5875 /**
5876 * Creates and returns a new cache object.
5877 *
5878 * @return {Cache} Cache object.
5879 */
5880 function createCache() {
5881 /** @type {Cache} */
5882 var cache = {
5883 clear: function () {
5884 cache.head = null;
5885 },
5886 };
5887
5888 return cache;
5889 }
5890
5891 /**
5892 * Returns true if entries within the two arrays are strictly equal by
5893 * reference from a starting index.
5894 *
5895 * @param {*[]} a First array.
5896 * @param {*[]} b Second array.
5897 * @param {number} fromIndex Index from which to start comparison.
5898 *
5899 * @return {boolean} Whether arrays are shallowly equal.
5900 */
5901 function isShallowEqual(a, b, fromIndex) {
5902 var i;
5903
5904 if (a.length !== b.length) {
5905 return false;
5906 }
5907
5908 for (i = fromIndex; i < a.length; i++) {
5909 if (a[i] !== b[i]) {
5910 return false;
5911 }
5912 }
5913
5914 return true;
5915 }
5916
5917 /**
5918 * Returns a memoized selector function. The getDependants function argument is
5919 * called before the memoized selector and is expected to return an immutable
5920 * reference or array of references on which the selector depends for computing
5921 * its own return value. The memoize cache is preserved only as long as those
5922 * dependant references remain the same. If getDependants returns a different
5923 * reference(s), the cache is cleared and the selector value regenerated.
5924 *
5925 * @template {(...args: *[]) => *} S
5926 *
5927 * @param {S} selector Selector function.
5928 * @param {GetDependants=} getDependants Dependant getter returning an array of
5929 * references used in cache bust consideration.
5930 */
5931 /* harmony default export */ function rememo(selector, getDependants) {
5932 /** @type {WeakMap<*,*>} */
5933 var rootCache;
5934
5935 /** @type {GetDependants} */
5936 var normalizedGetDependants = getDependants ? getDependants : arrayOf;
5937
5938 /**
5939 * Returns the cache for a given dependants array. When possible, a WeakMap
5940 * will be used to create a unique cache for each set of dependants. This
5941 * is feasible due to the nature of WeakMap in allowing garbage collection
5942 * to occur on entries where the key object is no longer referenced. Since
5943 * WeakMap requires the key to be an object, this is only possible when the
5944 * dependant is object-like. The root cache is created as a hierarchy where
5945 * each top-level key is the first entry in a dependants set, the value a
5946 * WeakMap where each key is the next dependant, and so on. This continues
5947 * so long as the dependants are object-like. If no dependants are object-
5948 * like, then the cache is shared across all invocations.
5949 *
5950 * @see isObjectLike
5951 *
5952 * @param {*[]} dependants Selector dependants.
5953 *
5954 * @return {Cache} Cache object.
5955 */
5956 function getCache(dependants) {
5957 var caches = rootCache,
5958 isUniqueByDependants = true,
5959 i,
5960 dependant,
5961 map,
5962 cache;
5963
5964 for (i = 0; i < dependants.length; i++) {
5965 dependant = dependants[i];
5966
5967 // Can only compose WeakMap from object-like key.
5968 if (!isObjectLike(dependant)) {
5969 isUniqueByDependants = false;
5970 break;
5971 }
5972
5973 // Does current segment of cache already have a WeakMap?
5974 if (caches.has(dependant)) {
5975 // Traverse into nested WeakMap.
5976 caches = caches.get(dependant);
5977 } else {
5978 // Create, set, and traverse into a new one.
5979 map = new WeakMap();
5980 caches.set(dependant, map);
5981 caches = map;
5982 }
5983 }
5984
5985 // We use an arbitrary (but consistent) object as key for the last item
5986 // in the WeakMap to serve as our running cache.
5987 if (!caches.has(LEAF_KEY)) {
5988 cache = createCache();
5989 cache.isUniqueByDependants = isUniqueByDependants;
5990 caches.set(LEAF_KEY, cache);
5991 }
5992
5993 return caches.get(LEAF_KEY);
5994 }
5995
5996 /**
5997 * Resets root memoization cache.
5998 */
5999 function clear() {
6000 rootCache = new WeakMap();
6001 }
6002
6003 /* eslint-disable jsdoc/check-param-names */
6004 /**
6005 * The augmented selector call, considering first whether dependants have
6006 * changed before passing it to underlying memoize function.
6007 *
6008 * @param {*} source Source object for derivation.
6009 * @param {...*} extraArgs Additional arguments to pass to selector.
6010 *
6011 * @return {*} Selector result.
6012 */
6013 /* eslint-enable jsdoc/check-param-names */
6014 function callSelector(/* source, ...extraArgs */) {
6015 var len = arguments.length,
6016 cache,
6017 node,
6018 i,
6019 args,
6020 dependants;
6021
6022 // Create copy of arguments (avoid leaking deoptimization).
6023 args = new Array(len);
6024 for (i = 0; i < len; i++) {
6025 args[i] = arguments[i];
6026 }
6027
6028 dependants = normalizedGetDependants.apply(null, args);
6029 cache = getCache(dependants);
6030
6031 // If not guaranteed uniqueness by dependants (primitive type), shallow
6032 // compare against last dependants and, if references have changed,
6033 // destroy cache to recalculate result.
6034 if (!cache.isUniqueByDependants) {
6035 if (
6036 cache.lastDependants &&
6037 !isShallowEqual(dependants, cache.lastDependants, 0)
6038 ) {
6039 cache.clear();
6040 }
6041
6042 cache.lastDependants = dependants;
6043 }
6044
6045 node = cache.head;
6046 while (node) {
6047 // Check whether node arguments match arguments
6048 if (!isShallowEqual(node.args, args, 1)) {
6049 node = node.next;
6050 continue;
6051 }
6052
6053 // At this point we can assume we've found a match
6054
6055 // Surface matched node to head if not already
6056 if (node !== cache.head) {
6057 // Adjust siblings to point to each other.
6058 /** @type {CacheNode} */ (node.prev).next = node.next;
6059 if (node.next) {
6060 node.next.prev = node.prev;
6061 }
6062
6063 node.next = cache.head;
6064 node.prev = null;
6065 /** @type {CacheNode} */ (cache.head).prev = node;
6066 cache.head = node;
6067 }
6068
6069 // Return immediately
6070 return node.val;
6071 }
6072
6073 // No cached value found. Continue to insertion phase:
6074
6075 node = /** @type {CacheNode} */ ({
6076 // Generate the result from original function
6077 val: selector.apply(null, args),
6078 });
6079
6080 // Avoid including the source object in the cache.
6081 args[0] = null;
6082 node.args = args;
6083
6084 // Don't need to check whether node is already head, since it would
6085 // have been returned above already if it was
6086
6087 // Shift existing head down list
6088 if (cache.head) {
6089 cache.head.prev = node;
6090 node.next = cache.head;
6091 }
6092
6093 cache.head = node;
6094
6095 return node.val;
6096 }
6097
6098 callSelector.getDependants = normalizedGetDependants;
6099 callSelector.clear = clear;
6100 clear();
6101
6102 return /** @type {S & EnhancedSelector} */ (callSelector);
6103 }
6104
6105 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/selectors.js
6106 /**
6107 * External dependencies
6108 */
6109
6110
6111 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
6112
6113 /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
6114
6115 /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */
6116
6117 /**
6118 * Given a block name or block type object, returns the corresponding
6119 * normalized block type object.
6120 *
6121 * @param {Object} state Blocks state.
6122 * @param {(string|Object)} nameOrType Block name or type object
6123 *
6124 * @return {Object} Block type object.
6125 */
6126
6127 const getNormalizedBlockType = (state, nameOrType) => 'string' === typeof nameOrType ? getBlockType(state, nameOrType) : nameOrType;
6128 /**
6129 * Returns all the unprocessed block types as passed during the registration.
6130 *
6131 * @param {Object} state Data state.
6132 *
6133 * @return {Array} Unprocessed block types.
6134 */
6135
6136
6137 function __experimentalGetUnprocessedBlockTypes(state) {
6138 return state.unprocessedBlockTypes;
6139 }
6140 /**
6141 * Returns all the available block types.
6142 *
6143 * @param {Object} state Data state.
6144 *
6145 * @return {Array} Block Types.
6146 */
6147
6148 const getBlockTypes = rememo(state => Object.values(state.blockTypes), state => [state.blockTypes]);
6149 /**
6150 * Returns a block type by name.
6151 *
6152 * @param {Object} state Data state.
6153 * @param {string} name Block type name.
6154 *
6155 * @return {Object?} Block Type.
6156 */
6157
6158 function getBlockType(state, name) {
6159 return state.blockTypes[name];
6160 }
6161 /**
6162 * Returns block styles by block name.
6163 *
6164 * @param {Object} state Data state.
6165 * @param {string} name Block type name.
6166 *
6167 * @return {Array?} Block Styles.
6168 */
6169
6170 function getBlockStyles(state, name) {
6171 return state.blockStyles[name];
6172 }
6173 /**
6174 * Returns block variations by block name.
6175 *
6176 * @param {Object} state Data state.
6177 * @param {string} blockName Block type name.
6178 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6179 *
6180 * @return {(WPBlockVariation[]|void)} Block variations.
6181 */
6182
6183 const getBlockVariations = rememo((state, blockName, scope) => {
6184 const variations = state.blockVariations[blockName];
6185
6186 if (!variations || !scope) {
6187 return variations;
6188 }
6189
6190 return variations.filter(variation => {
6191 // For backward compatibility reasons, variation's scope defaults to
6192 // `block` and `inserter` when not set.
6193 return (variation.scope || ['block', 'inserter']).includes(scope);
6194 });
6195 }, (state, blockName) => [state.blockVariations[blockName]]);
6196 /**
6197 * Returns the active block variation for a given block based on its attributes.
6198 * Variations are determined by their `isActive` property.
6199 * Which is either an array of block attribute keys or a function.
6200 *
6201 * In case of an array of block attribute keys, the `attributes` are compared
6202 * to the variation's attributes using strict equality check.
6203 *
6204 * In case of function type, the function should accept a block's attributes
6205 * and the variation's attributes and determines if a variation is active.
6206 * A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
6207 *
6208 * @param {Object} state Data state.
6209 * @param {string} blockName Name of block (example: “core/columns”).
6210 * @param {Object} attributes Block attributes used to determine active variation.
6211 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6212 *
6213 * @return {(WPBlockVariation|undefined)} Active block variation.
6214 */
6215
6216 function getActiveBlockVariation(state, blockName, attributes, scope) {
6217 const variations = getBlockVariations(state, blockName, scope);
6218 const match = variations === null || variations === void 0 ? void 0 : variations.find(variation => {
6219 var _variation$isActive;
6220
6221 if (Array.isArray(variation.isActive)) {
6222 const blockType = getBlockType(state, blockName);
6223 const attributeKeys = Object.keys((blockType === null || blockType === void 0 ? void 0 : blockType.attributes) || {});
6224 const definedAttributes = variation.isActive.filter(attribute => attributeKeys.includes(attribute));
6225
6226 if (definedAttributes.length === 0) {
6227 return false;
6228 }
6229
6230 return definedAttributes.every(attribute => attributes[attribute] === variation.attributes[attribute]);
6231 }
6232
6233 return (_variation$isActive = variation.isActive) === null || _variation$isActive === void 0 ? void 0 : _variation$isActive.call(variation, attributes, variation.attributes);
6234 });
6235 return match;
6236 }
6237 /**
6238 * Returns the default block variation for the given block type.
6239 * When there are multiple variations annotated as the default one,
6240 * the last added item is picked. This simplifies registering overrides.
6241 * When there is no default variation set, it returns the first item.
6242 *
6243 * @param {Object} state Data state.
6244 * @param {string} blockName Block type name.
6245 * @param {WPBlockVariationScope} [scope] Block variation scope name.
6246 *
6247 * @return {?WPBlockVariation} The default block variation.
6248 */
6249
6250 function getDefaultBlockVariation(state, blockName, scope) {
6251 const variations = getBlockVariations(state, blockName, scope);
6252 return (0,external_lodash_namespaceObject.findLast)(variations, 'isDefault') || (0,external_lodash_namespaceObject.first)(variations);
6253 }
6254 /**
6255 * Returns all the available categories.
6256 *
6257 * @param {Object} state Data state.
6258 *
6259 * @return {WPBlockCategory[]} Categories list.
6260 */
6261
6262 function getCategories(state) {
6263 return state.categories;
6264 }
6265 /**
6266 * Returns all the available collections.
6267 *
6268 * @param {Object} state Data state.
6269 *
6270 * @return {Object} Collections list.
6271 */
6272
6273 function getCollections(state) {
6274 return state.collections;
6275 }
6276 /**
6277 * Returns the name of the default block name.
6278 *
6279 * @param {Object} state Data state.
6280 *
6281 * @return {string?} Default block name.
6282 */
6283
6284 function getDefaultBlockName(state) {
6285 return state.defaultBlockName;
6286 }
6287 /**
6288 * Returns the name of the block for handling non-block content.
6289 *
6290 * @param {Object} state Data state.
6291 *
6292 * @return {string?} Name of the block for handling non-block content.
6293 */
6294
6295 function getFreeformFallbackBlockName(state) {
6296 return state.freeformFallbackBlockName;
6297 }
6298 /**
6299 * Returns the name of the block for handling unregistered blocks.
6300 *
6301 * @param {Object} state Data state.
6302 *
6303 * @return {string?} Name of the block for handling unregistered blocks.
6304 */
6305
6306 function getUnregisteredFallbackBlockName(state) {
6307 return state.unregisteredFallbackBlockName;
6308 }
6309 /**
6310 * Returns the name of the block for handling unregistered blocks.
6311 *
6312 * @param {Object} state Data state.
6313 *
6314 * @return {string?} Name of the block for handling unregistered blocks.
6315 */
6316
6317 function getGroupingBlockName(state) {
6318 return state.groupingBlockName;
6319 }
6320 /**
6321 * Returns an array with the child blocks of a given block.
6322 *
6323 * @param {Object} state Data state.
6324 * @param {string} blockName Block type name.
6325 *
6326 * @return {Array} Array of child block names.
6327 */
6328
6329 const getChildBlockNames = rememo((state, blockName) => {
6330 return (0,external_lodash_namespaceObject.map)((0,external_lodash_namespaceObject.filter)(state.blockTypes, blockType => {
6331 return (0,external_lodash_namespaceObject.includes)(blockType.parent, blockName);
6332 }), _ref => {
6333 let {
6334 name
6335 } = _ref;
6336 return name;
6337 });
6338 }, state => [state.blockTypes]);
6339 /**
6340 * Returns the block support value for a feature, if defined.
6341 *
6342 * @param {Object} state Data state.
6343 * @param {(string|Object)} nameOrType Block name or type object
6344 * @param {Array|string} feature Feature to retrieve
6345 * @param {*} defaultSupports Default value to return if not
6346 * explicitly defined
6347 *
6348 * @return {?*} Block support value
6349 */
6350
6351 const getBlockSupport = (state, nameOrType, feature, defaultSupports) => {
6352 const blockType = getNormalizedBlockType(state, nameOrType);
6353
6354 if (!(blockType !== null && blockType !== void 0 && blockType.supports)) {
6355 return defaultSupports;
6356 }
6357
6358 return (0,external_lodash_namespaceObject.get)(blockType.supports, feature, defaultSupports);
6359 };
6360 /**
6361 * Returns true if the block defines support for a feature, or false otherwise.
6362 *
6363 * @param {Object} state Data state.
6364 * @param {(string|Object)} nameOrType Block name or type object.
6365 * @param {string} feature Feature to test.
6366 * @param {boolean} defaultSupports Whether feature is supported by
6367 * default if not explicitly defined.
6368 *
6369 * @return {boolean} Whether block supports feature.
6370 */
6371
6372 function hasBlockSupport(state, nameOrType, feature, defaultSupports) {
6373 return !!getBlockSupport(state, nameOrType, feature, defaultSupports);
6374 }
6375 /**
6376 * Returns true if the block type by the given name or object value matches a
6377 * search term, or false otherwise.
6378 *
6379 * @param {Object} state Blocks state.
6380 * @param {(string|Object)} nameOrType Block name or type object.
6381 * @param {string} searchTerm Search term by which to filter.
6382 *
6383 * @return {Object[]} Whether block type matches search term.
6384 */
6385
6386 function isMatchingSearchTerm(state, nameOrType, searchTerm) {
6387 const blockType = getNormalizedBlockType(state, nameOrType);
6388 const getNormalizedSearchTerm = (0,external_lodash_namespaceObject.flow)([// Disregard diacritics.
6389 // Input: "média"
6390 external_lodash_namespaceObject.deburr, // Lowercase.
6391 // Input: "MEDIA"
6392 term => term.toLowerCase(), // Strip leading and trailing whitespace.
6393 // Input: " media "
6394 term => term.trim()]);
6395 const normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
6396 const isSearchMatch = (0,external_lodash_namespaceObject.flow)([getNormalizedSearchTerm, normalizedCandidate => (0,external_lodash_namespaceObject.includes)(normalizedCandidate, normalizedSearchTerm)]);
6397 return isSearchMatch(blockType.title) || (0,external_lodash_namespaceObject.some)(blockType.keywords, isSearchMatch) || isSearchMatch(blockType.category) || isSearchMatch(blockType.description);
6398 }
6399 /**
6400 * Returns a boolean indicating if a block has child blocks or not.
6401 *
6402 * @param {Object} state Data state.
6403 * @param {string} blockName Block type name.
6404 *
6405 * @return {boolean} True if a block contains child blocks and false otherwise.
6406 */
6407
6408 const hasChildBlocks = (state, blockName) => {
6409 return getChildBlockNames(state, blockName).length > 0;
6410 };
6411 /**
6412 * Returns a boolean indicating if a block has at least one child block with inserter support.
6413 *
6414 * @param {Object} state Data state.
6415 * @param {string} blockName Block type name.
6416 *
6417 * @return {boolean} True if a block contains at least one child blocks with inserter support
6418 * and false otherwise.
6419 */
6420
6421 const hasChildBlocksWithInserterSupport = (state, blockName) => {
6422 return (0,external_lodash_namespaceObject.some)(getChildBlockNames(state, blockName), childBlockName => {
6423 return hasBlockSupport(state, childBlockName, 'inserter', true);
6424 });
6425 };
6426
6427 ;// CONCATENATED MODULE: external ["wp","hooks"]
6428 var external_wp_hooks_namespaceObject = window["wp"]["hooks"];
6429 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/index.mjs
6430 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()})};
6431
6432 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/plugins/names.mjs
6433 /* 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"])}
6434
6435 ;// CONCATENATED MODULE: ./packages/blocks/node_modules/colord/plugins/a11y.mjs
6436 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}}
6437
6438 ;// CONCATENATED MODULE: external ["wp","element"]
6439 var external_wp_element_namespaceObject = window["wp"]["element"];
6440 ;// CONCATENATED MODULE: external ["wp","dom"]
6441 var external_wp_dom_namespaceObject = window["wp"]["dom"];
6442 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/constants.js
6443 const BLOCK_ICON_DEFAULT = 'block-default';
6444 /**
6445 * Array of valid keys in a block type settings deprecation object.
6446 *
6447 * @type {string[]}
6448 */
6449
6450 const DEPRECATED_ENTRY_KEYS = ['attributes', 'supports', 'save', 'migrate', 'isEligible', 'apiVersion'];
6451 const __EXPERIMENTAL_STYLE_PROPERTY = {
6452 // Kept for back-compatibility purposes.
6453 '--wp--style--color--link': {
6454 value: ['color', 'link'],
6455 support: ['color', 'link']
6456 },
6457 background: {
6458 value: ['color', 'gradient'],
6459 support: ['color', 'gradients']
6460 },
6461 backgroundColor: {
6462 value: ['color', 'background'],
6463 support: ['color', 'background'],
6464 requiresOptOut: true,
6465 useEngine: true
6466 },
6467 borderColor: {
6468 value: ['border', 'color'],
6469 support: ['__experimentalBorder', 'color']
6470 },
6471 borderRadius: {
6472 value: ['border', 'radius'],
6473 support: ['__experimentalBorder', 'radius'],
6474 properties: {
6475 borderTopLeftRadius: 'topLeft',
6476 borderTopRightRadius: 'topRight',
6477 borderBottomLeftRadius: 'bottomLeft',
6478 borderBottomRightRadius: 'bottomRight'
6479 }
6480 },
6481 borderStyle: {
6482 value: ['border', 'style'],
6483 support: ['__experimentalBorder', 'style']
6484 },
6485 borderWidth: {
6486 value: ['border', 'width'],
6487 support: ['__experimentalBorder', 'width']
6488 },
6489 borderTopColor: {
6490 value: ['border', 'top', 'color'],
6491 support: ['__experimentalBorder', 'color']
6492 },
6493 borderTopStyle: {
6494 value: ['border', 'top', 'style'],
6495 support: ['__experimentalBorder', 'style']
6496 },
6497 borderTopWidth: {
6498 value: ['border', 'top', 'width'],
6499 support: ['__experimentalBorder', 'width']
6500 },
6501 borderRightColor: {
6502 value: ['border', 'right', 'color'],
6503 support: ['__experimentalBorder', 'color']
6504 },
6505 borderRightStyle: {
6506 value: ['border', 'right', 'style'],
6507 support: ['__experimentalBorder', 'style']
6508 },
6509 borderRightWidth: {
6510 value: ['border', 'right', 'width'],
6511 support: ['__experimentalBorder', 'width']
6512 },
6513 borderBottomColor: {
6514 value: ['border', 'bottom', 'color'],
6515 support: ['__experimentalBorder', 'color']
6516 },
6517 borderBottomStyle: {
6518 value: ['border', 'bottom', 'style'],
6519 support: ['__experimentalBorder', 'style']
6520 },
6521 borderBottomWidth: {
6522 value: ['border', 'bottom', 'width'],
6523 support: ['__experimentalBorder', 'width']
6524 },
6525 borderLeftColor: {
6526 value: ['border', 'left', 'color'],
6527 support: ['__experimentalBorder', 'color']
6528 },
6529 borderLeftStyle: {
6530 value: ['border', 'left', 'style'],
6531 support: ['__experimentalBorder', 'style']
6532 },
6533 borderLeftWidth: {
6534 value: ['border', 'left', 'width'],
6535 support: ['__experimentalBorder', 'width']
6536 },
6537 color: {
6538 value: ['color', 'text'],
6539 support: ['color', 'text'],
6540 requiresOptOut: true,
6541 useEngine: true
6542 },
6543 filter: {
6544 value: ['filter', 'duotone'],
6545 support: ['color', '__experimentalDuotone']
6546 },
6547 linkColor: {
6548 value: ['elements', 'link', 'color', 'text'],
6549 support: ['color', 'link']
6550 },
6551 fontFamily: {
6552 value: ['typography', 'fontFamily'],
6553 support: ['typography', '__experimentalFontFamily']
6554 },
6555 fontSize: {
6556 value: ['typography', 'fontSize'],
6557 support: ['typography', 'fontSize'],
6558 useEngine: true
6559 },
6560 fontStyle: {
6561 value: ['typography', 'fontStyle'],
6562 support: ['typography', '__experimentalFontStyle'],
6563 useEngine: true
6564 },
6565 fontWeight: {
6566 value: ['typography', 'fontWeight'],
6567 support: ['typography', '__experimentalFontWeight'],
6568 useEngine: true
6569 },
6570 lineHeight: {
6571 value: ['typography', 'lineHeight'],
6572 support: ['typography', 'lineHeight'],
6573 useEngine: true
6574 },
6575 margin: {
6576 value: ['spacing', 'margin'],
6577 support: ['spacing', 'margin'],
6578 properties: {
6579 marginTop: 'top',
6580 marginRight: 'right',
6581 marginBottom: 'bottom',
6582 marginLeft: 'left'
6583 },
6584 useEngine: true
6585 },
6586 padding: {
6587 value: ['spacing', 'padding'],
6588 support: ['spacing', 'padding'],
6589 properties: {
6590 paddingTop: 'top',
6591 paddingRight: 'right',
6592 paddingBottom: 'bottom',
6593 paddingLeft: 'left'
6594 },
6595 useEngine: true
6596 },
6597 textDecoration: {
6598 value: ['typography', 'textDecoration'],
6599 support: ['typography', '__experimentalTextDecoration'],
6600 useEngine: true
6601 },
6602 textTransform: {
6603 value: ['typography', 'textTransform'],
6604 support: ['typography', '__experimentalTextTransform'],
6605 useEngine: true
6606 },
6607 letterSpacing: {
6608 value: ['typography', 'letterSpacing'],
6609 support: ['typography', '__experimentalLetterSpacing'],
6610 useEngine: true
6611 },
6612 '--wp--style--block-gap': {
6613 value: ['spacing', 'blockGap'],
6614 support: ['spacing', 'blockGap']
6615 }
6616 };
6617 const __EXPERIMENTAL_ELEMENTS = {
6618 link: 'a',
6619 h1: 'h1',
6620 h2: 'h2',
6621 h3: 'h3',
6622 h4: 'h4',
6623 h5: 'h5',
6624 h6: 'h6',
6625 button: '.wp-element-button, .wp-block-button__link'
6626 };
6627 const __EXPERIMENTAL_PATHS_WITH_MERGE = {
6628 'color.duotone': true,
6629 'color.gradients': true,
6630 'color.palette': true,
6631 'typography.fontFamilies': true,
6632 'typography.fontSizes': true
6633 };
6634
6635 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/registration.js
6636 /* eslint no-console: [ 'error', { allow: [ 'error', 'warn' ] } ] */
6637
6638 /**
6639 * External dependencies
6640 */
6641
6642 /**
6643 * WordPress dependencies
6644 */
6645
6646
6647
6648 /**
6649 * Internal dependencies
6650 */
6651
6652 const i18nBlockSchema = {
6653 title: "block title",
6654 description: "block description",
6655 keywords: ["block keyword"],
6656 styles: [{
6657 label: "block style label"
6658 }],
6659 variations: [{
6660 title: "block variation title",
6661 description: "block variation description",
6662 keywords: ["block variation keyword"]
6663 }]
6664 };
6665
6666
6667 /**
6668 * An icon type definition. One of a Dashicon slug, an element,
6669 * or a component.
6670 *
6671 * @typedef {(string|WPElement|WPComponent)} WPIcon
6672 *
6673 * @see https://developer.wordpress.org/resource/dashicons/
6674 */
6675
6676 /**
6677 * Render behavior of a block type icon; one of a Dashicon slug, an element,
6678 * or a component.
6679 *
6680 * @typedef {WPIcon} WPBlockTypeIconRender
6681 */
6682
6683 /**
6684 * An object describing a normalized block type icon.
6685 *
6686 * @typedef {Object} WPBlockTypeIconDescriptor
6687 *
6688 * @property {WPBlockTypeIconRender} src Render behavior of the icon,
6689 * one of a Dashicon slug, an
6690 * element, or a component.
6691 * @property {string} background Optimal background hex string
6692 * color when displaying icon.
6693 * @property {string} foreground Optimal foreground hex string
6694 * color when displaying icon.
6695 * @property {string} shadowColor Optimal shadow hex string
6696 * color when displaying icon.
6697 */
6698
6699 /**
6700 * Value to use to render the icon for a block type in an editor interface,
6701 * either a Dashicon slug, an element, a component, or an object describing
6702 * the icon.
6703 *
6704 * @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
6705 */
6706
6707 /**
6708 * Named block variation scopes.
6709 *
6710 * @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
6711 */
6712
6713 /**
6714 * An object describing a variation defined for the block type.
6715 *
6716 * @typedef {Object} WPBlockVariation
6717 *
6718 * @property {string} name The unique and machine-readable name.
6719 * @property {string} title A human-readable variation title.
6720 * @property {string} [description] A detailed variation description.
6721 * @property {string} [category] Block type category classification,
6722 * used in search interfaces to arrange
6723 * block types by category.
6724 * @property {WPIcon} [icon] An icon helping to visualize the variation.
6725 * @property {boolean} [isDefault] Indicates whether the current variation is
6726 * the default one. Defaults to `false`.
6727 * @property {Object} [attributes] Values which override block attributes.
6728 * @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
6729 * @property {Object} [example] Example provides structured data for
6730 * the block preview. You can set to
6731 * `undefined` to disable the preview shown
6732 * for the block type.
6733 * @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
6734 * is applicable. When not provided, it
6735 * assumes all available scopes.
6736 * @property {string[]} [keywords] An array of terms (which can be translated)
6737 * that help users discover the variation
6738 * while searching.
6739 * @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
6740 * Function that accepts a block's attributes and the
6741 * variation's attributes and determines if a variation is active.
6742 * This function doesn't try to find a match dynamically based
6743 * on all block's attributes, as in many cases some attributes are irrelevant.
6744 * An example would be for `embed` block where we only care
6745 * about `providerNameSlug` attribute's value.
6746 * We can also use a `string[]` to tell which attributes
6747 * should be compared as a shorthand. Each attributes will
6748 * be matched and the variation will be active if all of them are matching.
6749 */
6750
6751 /**
6752 * Defined behavior of a block type.
6753 *
6754 * @typedef {Object} WPBlockType
6755 *
6756 * @property {string} name Block type's namespaced name.
6757 * @property {string} title Human-readable block type label.
6758 * @property {string} [description] A detailed block type description.
6759 * @property {string} [category] Block type category classification,
6760 * used in search interfaces to arrange
6761 * block types by category.
6762 * @property {WPBlockTypeIcon} [icon] Block type icon.
6763 * @property {string[]} [keywords] Additional keywords to produce block
6764 * type as result in search interfaces.
6765 * @property {Object} [attributes] Block type attributes.
6766 * @property {WPComponent} [save] Optional component describing
6767 * serialized markup structure of a
6768 * block type.
6769 * @property {WPComponent} edit Component rendering an element to
6770 * manipulate the attributes of a block
6771 * in the context of an editor.
6772 * @property {WPBlockVariation[]} [variations] The list of block variations.
6773 * @property {Object} [example] Example provides structured data for
6774 * the block preview. When not defined
6775 * then no preview is shown.
6776 */
6777
6778 const serverSideBlockDefinitions = {};
6779 /**
6780 * Sets the server side block definition of blocks.
6781 *
6782 * @param {Object} definitions Server-side block definitions
6783 */
6784 // eslint-disable-next-line camelcase
6785
6786 function unstable__bootstrapServerSideBlockDefinitions(definitions) {
6787 for (const blockName of Object.keys(definitions)) {
6788 // Don't overwrite if already set. It covers the case when metadata
6789 // was initialized from the server.
6790 if (serverSideBlockDefinitions[blockName]) {
6791 // We still need to polyfill `apiVersion` for WordPress version
6792 // lower than 5.7. If it isn't present in the definition shared
6793 // from the server, we try to fallback to the definition passed.
6794 // @see https://github.com/WordPress/gutenberg/pull/29279
6795 if (serverSideBlockDefinitions[blockName].apiVersion === undefined && definitions[blockName].apiVersion) {
6796 serverSideBlockDefinitions[blockName].apiVersion = definitions[blockName].apiVersion;
6797 } // The `ancestor` prop is not included in the definitions shared
6798 // from the server yet, so it needs to be polyfilled as well.
6799 // @see https://github.com/WordPress/gutenberg/pull/39894
6800
6801
6802 if (serverSideBlockDefinitions[blockName].ancestor === undefined && definitions[blockName].ancestor) {
6803 serverSideBlockDefinitions[blockName].ancestor = definitions[blockName].ancestor;
6804 }
6805
6806 continue;
6807 }
6808
6809 serverSideBlockDefinitions[blockName] = (0,external_lodash_namespaceObject.mapKeys)((0,external_lodash_namespaceObject.pickBy)(definitions[blockName], value => !(0,external_lodash_namespaceObject.isNil)(value)), (value, key) => (0,external_lodash_namespaceObject.camelCase)(key));
6810 }
6811 }
6812 /**
6813 * Gets block settings from metadata loaded from `block.json` file.
6814 *
6815 * @param {Object} metadata Block metadata loaded from `block.json`.
6816 * @param {string} metadata.textdomain Textdomain to use with translations.
6817 *
6818 * @return {Object} Block settings.
6819 */
6820
6821 function getBlockSettingsFromMetadata(_ref) {
6822 let {
6823 textdomain,
6824 ...metadata
6825 } = _ref;
6826 const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'supports', 'styles', 'example', 'variations'];
6827 const settings = (0,external_lodash_namespaceObject.pick)(metadata, allowedFields);
6828
6829 if (textdomain) {
6830 Object.keys(i18nBlockSchema).forEach(key => {
6831 if (!settings[key]) {
6832 return;
6833 }
6834
6835 settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
6836 });
6837 }
6838
6839 return settings;
6840 }
6841 /**
6842 * Registers a new block provided a unique name and an object defining its
6843 * behavior. Once registered, the block is made available as an option to any
6844 * editor interface where blocks are implemented.
6845 *
6846 * @param {string|Object} blockNameOrMetadata Block type name or its metadata.
6847 * @param {Object} settings Block settings.
6848 *
6849 * @return {?WPBlockType} The block, if it has been successfully registered;
6850 * otherwise `undefined`.
6851 */
6852
6853
6854 function registerBlockType(blockNameOrMetadata, settings) {
6855 const name = (0,external_lodash_namespaceObject.isObject)(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
6856
6857 if (typeof name !== 'string') {
6858 console.error('Block names must be strings.');
6859 return;
6860 }
6861
6862 if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
6863 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');
6864 return;
6865 }
6866
6867 if ((0,external_wp_data_namespaceObject.select)(store).getBlockType(name)) {
6868 console.error('Block "' + name + '" is already registered.');
6869 return;
6870 }
6871
6872 if ((0,external_lodash_namespaceObject.isObject)(blockNameOrMetadata)) {
6873 unstable__bootstrapServerSideBlockDefinitions({
6874 [name]: getBlockSettingsFromMetadata(blockNameOrMetadata)
6875 });
6876 }
6877
6878 const blockType = {
6879 name,
6880 icon: BLOCK_ICON_DEFAULT,
6881 keywords: [],
6882 attributes: {},
6883 providesContext: {},
6884 usesContext: [],
6885 supports: {},
6886 styles: [],
6887 variations: [],
6888 save: () => null,
6889 ...(serverSideBlockDefinitions === null || serverSideBlockDefinitions === void 0 ? void 0 : serverSideBlockDefinitions[name]),
6890 ...settings
6891 };
6892
6893 (0,external_wp_data_namespaceObject.dispatch)(store).__experimentalRegisterBlockType(blockType);
6894
6895 return (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
6896 }
6897 /**
6898 * Translates block settings provided with metadata using the i18n schema.
6899 *
6900 * @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
6901 * @param {string|string[]|Object[]} settingValue Value for the block setting.
6902 * @param {string} textdomain Textdomain to use with translations.
6903 *
6904 * @return {string|string[]|Object[]} Translated setting.
6905 */
6906
6907 function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
6908 if ((0,external_lodash_namespaceObject.isString)(i18nSchema) && (0,external_lodash_namespaceObject.isString)(settingValue)) {
6909 // eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
6910 return (0,external_wp_i18n_namespaceObject._x)(settingValue, i18nSchema, textdomain);
6911 }
6912
6913 if ((0,external_lodash_namespaceObject.isArray)(i18nSchema) && !(0,external_lodash_namespaceObject.isEmpty)(i18nSchema) && (0,external_lodash_namespaceObject.isArray)(settingValue)) {
6914 return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
6915 }
6916
6917 if ((0,external_lodash_namespaceObject.isObject)(i18nSchema) && !(0,external_lodash_namespaceObject.isEmpty)(i18nSchema) && (0,external_lodash_namespaceObject.isObject)(settingValue)) {
6918 return Object.keys(settingValue).reduce((accumulator, key) => {
6919 if (!i18nSchema[key]) {
6920 accumulator[key] = settingValue[key];
6921 return accumulator;
6922 }
6923
6924 accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
6925 return accumulator;
6926 }, {});
6927 }
6928
6929 return settingValue;
6930 }
6931 /**
6932 * Registers a new block collection to group blocks in the same namespace in the inserter.
6933 *
6934 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
6935 * @param {Object} settings The block collection settings.
6936 * @param {string} settings.title The title to display in the block inserter.
6937 * @param {Object} [settings.icon] The icon to display in the block inserter.
6938 */
6939
6940
6941 function registerBlockCollection(namespace, _ref2) {
6942 let {
6943 title,
6944 icon
6945 } = _ref2;
6946 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockCollection(namespace, title, icon);
6947 }
6948 /**
6949 * Unregisters a block collection
6950 *
6951 * @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
6952 *
6953 */
6954
6955 function unregisterBlockCollection(namespace) {
6956 dispatch(blocksStore).removeBlockCollection(namespace);
6957 }
6958 /**
6959 * Unregisters a block.
6960 *
6961 * @param {string} name Block name.
6962 *
6963 * @return {?WPBlockType} The previous block value, if it has been successfully
6964 * unregistered; otherwise `undefined`.
6965 */
6966
6967 function unregisterBlockType(name) {
6968 const oldBlock = (0,external_wp_data_namespaceObject.select)(store).getBlockType(name);
6969
6970 if (!oldBlock) {
6971 console.error('Block "' + name + '" is not registered.');
6972 return;
6973 }
6974
6975 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockTypes(name);
6976 return oldBlock;
6977 }
6978 /**
6979 * Assigns name of block for handling non-block content.
6980 *
6981 * @param {string} blockName Block name.
6982 */
6983
6984 function setFreeformContentHandlerName(blockName) {
6985 (0,external_wp_data_namespaceObject.dispatch)(store).setFreeformFallbackBlockName(blockName);
6986 }
6987 /**
6988 * Retrieves name of block handling non-block content, or undefined if no
6989 * handler has been defined.
6990 *
6991 * @return {?string} Block name.
6992 */
6993
6994 function getFreeformContentHandlerName() {
6995 return (0,external_wp_data_namespaceObject.select)(store).getFreeformFallbackBlockName();
6996 }
6997 /**
6998 * Retrieves name of block used for handling grouping interactions.
6999 *
7000 * @return {?string} Block name.
7001 */
7002
7003 function registration_getGroupingBlockName() {
7004 return (0,external_wp_data_namespaceObject.select)(store).getGroupingBlockName();
7005 }
7006 /**
7007 * Assigns name of block handling unregistered block types.
7008 *
7009 * @param {string} blockName Block name.
7010 */
7011
7012 function setUnregisteredTypeHandlerName(blockName) {
7013 (0,external_wp_data_namespaceObject.dispatch)(store).setUnregisteredFallbackBlockName(blockName);
7014 }
7015 /**
7016 * Retrieves name of block handling unregistered block types, or undefined if no
7017 * handler has been defined.
7018 *
7019 * @return {?string} Block name.
7020 */
7021
7022 function getUnregisteredTypeHandlerName() {
7023 return (0,external_wp_data_namespaceObject.select)(store).getUnregisteredFallbackBlockName();
7024 }
7025 /**
7026 * Assigns the default block name.
7027 *
7028 * @param {string} name Block name.
7029 */
7030
7031 function setDefaultBlockName(name) {
7032 (0,external_wp_data_namespaceObject.dispatch)(store).setDefaultBlockName(name);
7033 }
7034 /**
7035 * Assigns name of block for handling block grouping interactions.
7036 *
7037 * @param {string} name Block name.
7038 */
7039
7040 function setGroupingBlockName(name) {
7041 (0,external_wp_data_namespaceObject.dispatch)(store).setGroupingBlockName(name);
7042 }
7043 /**
7044 * Retrieves the default block name.
7045 *
7046 * @return {?string} Block name.
7047 */
7048
7049 function registration_getDefaultBlockName() {
7050 return (0,external_wp_data_namespaceObject.select)(store).getDefaultBlockName();
7051 }
7052 /**
7053 * Returns a registered block type.
7054 *
7055 * @param {string} name Block name.
7056 *
7057 * @return {?Object} Block type.
7058 */
7059
7060 function registration_getBlockType(name) {
7061 var _select;
7062
7063 return (_select = (0,external_wp_data_namespaceObject.select)(store)) === null || _select === void 0 ? void 0 : _select.getBlockType(name);
7064 }
7065 /**
7066 * Returns all registered blocks.
7067 *
7068 * @return {Array} Block settings.
7069 */
7070
7071 function registration_getBlockTypes() {
7072 return (0,external_wp_data_namespaceObject.select)(store).getBlockTypes();
7073 }
7074 /**
7075 * Returns the block support value for a feature, if defined.
7076 *
7077 * @param {(string|Object)} nameOrType Block name or type object
7078 * @param {string} feature Feature to retrieve
7079 * @param {*} defaultSupports Default value to return if not
7080 * explicitly defined
7081 *
7082 * @return {?*} Block support value
7083 */
7084
7085 function registration_getBlockSupport(nameOrType, feature, defaultSupports) {
7086 return (0,external_wp_data_namespaceObject.select)(store).getBlockSupport(nameOrType, feature, defaultSupports);
7087 }
7088 /**
7089 * Returns true if the block defines support for a feature, or false otherwise.
7090 *
7091 * @param {(string|Object)} nameOrType Block name or type object.
7092 * @param {string} feature Feature to test.
7093 * @param {boolean} defaultSupports Whether feature is supported by
7094 * default if not explicitly defined.
7095 *
7096 * @return {boolean} Whether block supports feature.
7097 */
7098
7099 function registration_hasBlockSupport(nameOrType, feature, defaultSupports) {
7100 return (0,external_wp_data_namespaceObject.select)(store).hasBlockSupport(nameOrType, feature, defaultSupports);
7101 }
7102 /**
7103 * Determines whether or not the given block is a reusable block. This is a
7104 * special block type that is used to point to a global block stored via the
7105 * API.
7106 *
7107 * @param {Object} blockOrType Block or Block Type to test.
7108 *
7109 * @return {boolean} Whether the given block is a reusable block.
7110 */
7111
7112 function isReusableBlock(blockOrType) {
7113 return (blockOrType === null || blockOrType === void 0 ? void 0 : blockOrType.name) === 'core/block';
7114 }
7115 /**
7116 * Determines whether or not the given block is a template part. This is a
7117 * special block type that allows composing a page template out of reusable
7118 * design elements.
7119 *
7120 * @param {Object} blockOrType Block or Block Type to test.
7121 *
7122 * @return {boolean} Whether the given block is a template part.
7123 */
7124
7125 function isTemplatePart(blockOrType) {
7126 return blockOrType.name === 'core/template-part';
7127 }
7128 /**
7129 * Returns an array with the child blocks of a given block.
7130 *
7131 * @param {string} blockName Name of block (example: “latest-posts”).
7132 *
7133 * @return {Array} Array of child block names.
7134 */
7135
7136 const registration_getChildBlockNames = blockName => {
7137 return (0,external_wp_data_namespaceObject.select)(store).getChildBlockNames(blockName);
7138 };
7139 /**
7140 * Returns a boolean indicating if a block has child blocks or not.
7141 *
7142 * @param {string} blockName Name of block (example: “latest-posts”).
7143 *
7144 * @return {boolean} True if a block contains child blocks and false otherwise.
7145 */
7146
7147 const registration_hasChildBlocks = blockName => {
7148 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocks(blockName);
7149 };
7150 /**
7151 * Returns a boolean indicating if a block has at least one child block with inserter support.
7152 *
7153 * @param {string} blockName Block type name.
7154 *
7155 * @return {boolean} True if a block contains at least one child blocks with inserter support
7156 * and false otherwise.
7157 */
7158
7159 const registration_hasChildBlocksWithInserterSupport = blockName => {
7160 return (0,external_wp_data_namespaceObject.select)(store).hasChildBlocksWithInserterSupport(blockName);
7161 };
7162 /**
7163 * Registers a new block style variation for the given block.
7164 *
7165 * @param {string} blockName Name of block (example: “core/latest-posts”).
7166 * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
7167 */
7168
7169 const registerBlockStyle = (blockName, styleVariation) => {
7170 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockStyles(blockName, styleVariation);
7171 };
7172 /**
7173 * Unregisters a block style variation for the given block.
7174 *
7175 * @param {string} blockName Name of block (example: “core/latest-posts”).
7176 * @param {string} styleVariationName Name of class applied to the block.
7177 */
7178
7179 const unregisterBlockStyle = (blockName, styleVariationName) => {
7180 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockStyles(blockName, styleVariationName);
7181 };
7182 /**
7183 * Returns an array with the variations of a given block type.
7184 *
7185 * @param {string} blockName Name of block (example: “core/columns”).
7186 * @param {WPBlockVariationScope} [scope] Block variation scope name.
7187 *
7188 * @return {(WPBlockVariation[]|void)} Block variations.
7189 */
7190
7191 const registration_getBlockVariations = (blockName, scope) => {
7192 return (0,external_wp_data_namespaceObject.select)(store).getBlockVariations(blockName, scope);
7193 };
7194 /**
7195 * Registers a new block variation for the given block type.
7196 *
7197 * @param {string} blockName Name of the block (example: “core/columns”).
7198 * @param {WPBlockVariation} variation Object describing a block variation.
7199 */
7200
7201 const registerBlockVariation = (blockName, variation) => {
7202 (0,external_wp_data_namespaceObject.dispatch)(store).addBlockVariations(blockName, variation);
7203 };
7204 /**
7205 * Unregisters a block variation defined for the given block type.
7206 *
7207 * @param {string} blockName Name of the block (example: “core/columns”).
7208 * @param {string} variationName Name of the variation defined for the block.
7209 */
7210
7211 const unregisterBlockVariation = (blockName, variationName) => {
7212 (0,external_wp_data_namespaceObject.dispatch)(store).removeBlockVariations(blockName, variationName);
7213 };
7214
7215 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/rng.js
7216 // Unique ID creation requires a high quality random # generator. In the browser we therefore
7217 // require the crypto API and do not support built-in fallback to lower quality random number
7218 // generators (like Math.random()).
7219 // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
7220 // find the complete implementation of crypto (msCrypto) on IE11.
7221 var getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
7222 var rnds8 = new Uint8Array(16);
7223 function rng() {
7224 if (!getRandomValues) {
7225 throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
7226 }
7227
7228 return getRandomValues(rnds8);
7229 }
7230 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/regex.js
7231 /* harmony default export */ var 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);
7232 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/validate.js
7233
7234
7235 function validate(uuid) {
7236 return typeof uuid === 'string' && regex.test(uuid);
7237 }
7238
7239 /* harmony default export */ var esm_browser_validate = (validate);
7240 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/stringify.js
7241
7242 /**
7243 * Convert array of 16 byte values to UUID string format of the form:
7244 * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
7245 */
7246
7247 var byteToHex = [];
7248
7249 for (var stringify_i = 0; stringify_i < 256; ++stringify_i) {
7250 byteToHex.push((stringify_i + 0x100).toString(16).substr(1));
7251 }
7252
7253 function stringify(arr) {
7254 var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
7255 // Note: Be careful editing this code! It's been tuned for performance
7256 // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
7257 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
7258 // of the following:
7259 // - One or more input array values don't map to a hex octet (leading to
7260 // "undefined" in the uuid)
7261 // - Invalid input values for the RFC `version` or `variant` fields
7262
7263 if (!esm_browser_validate(uuid)) {
7264 throw TypeError('Stringified UUID is invalid');
7265 }
7266
7267 return uuid;
7268 }
7269
7270 /* harmony default export */ var esm_browser_stringify = (stringify);
7271 ;// CONCATENATED MODULE: ./node_modules/uuid/dist/esm-browser/v4.js
7272
7273
7274
7275 function v4(options, buf, offset) {
7276 options = options || {};
7277 var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
7278
7279 rnds[6] = rnds[6] & 0x0f | 0x40;
7280 rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
7281
7282 if (buf) {
7283 offset = offset || 0;
7284
7285 for (var i = 0; i < 16; ++i) {
7286 buf[offset + i] = rnds[i];
7287 }
7288
7289 return buf;
7290 }
7291
7292 return esm_browser_stringify(rnds);
7293 }
7294
7295 /* harmony default export */ var esm_browser_v4 = (v4);
7296 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/factory.js
7297 /**
7298 * External dependencies
7299 */
7300
7301
7302 /**
7303 * WordPress dependencies
7304 */
7305
7306
7307 /**
7308 * Internal dependencies
7309 */
7310
7311
7312
7313 /**
7314 * Returns a block object given its type and attributes.
7315 *
7316 * @param {string} name Block name.
7317 * @param {Object} attributes Block attributes.
7318 * @param {?Array} innerBlocks Nested blocks.
7319 *
7320 * @return {Object} Block object.
7321 */
7322
7323 function createBlock(name) {
7324 let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7325 let innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
7326
7327 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(name, attributes);
7328
7329 const clientId = esm_browser_v4(); // Blocks are stored with a unique ID, the assigned type name, the block
7330 // attributes, and their inner blocks.
7331
7332 return {
7333 clientId,
7334 name,
7335 isValid: true,
7336 attributes: sanitizedAttributes,
7337 innerBlocks
7338 };
7339 }
7340 /**
7341 * Given an array of InnerBlocks templates or Block Objects,
7342 * returns an array of created Blocks from them.
7343 * It handles the case of having InnerBlocks as Blocks by
7344 * converting them to the proper format to continue recursively.
7345 *
7346 * @param {Array} innerBlocksOrTemplate Nested blocks or InnerBlocks templates.
7347 *
7348 * @return {Object[]} Array of Block objects.
7349 */
7350
7351 function createBlocksFromInnerBlocksTemplate() {
7352 let innerBlocksOrTemplate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
7353 return innerBlocksOrTemplate.map(innerBlock => {
7354 const innerBlockTemplate = Array.isArray(innerBlock) ? innerBlock : [innerBlock.name, innerBlock.attributes, innerBlock.innerBlocks];
7355 const [name, attributes, innerBlocks = []] = innerBlockTemplate;
7356 return createBlock(name, attributes, createBlocksFromInnerBlocksTemplate(innerBlocks));
7357 });
7358 }
7359 /**
7360 * Given a block object, returns a copy of the block object while sanitizing its attributes,
7361 * optionally merging new attributes and/or replacing its inner blocks.
7362 *
7363 * @param {Object} block Block instance.
7364 * @param {Object} mergeAttributes Block attributes.
7365 * @param {?Array} newInnerBlocks Nested blocks.
7366 *
7367 * @return {Object} A cloned block.
7368 */
7369
7370 function __experimentalCloneSanitizedBlock(block) {
7371 let mergeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7372 let newInnerBlocks = arguments.length > 2 ? arguments[2] : undefined;
7373 const clientId = esm_browser_v4();
7374
7375 const sanitizedAttributes = __experimentalSanitizeBlockAttributes(block.name, { ...block.attributes,
7376 ...mergeAttributes
7377 });
7378
7379 return { ...block,
7380 clientId,
7381 attributes: sanitizedAttributes,
7382 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => __experimentalCloneSanitizedBlock(innerBlock))
7383 };
7384 }
7385 /**
7386 * Given a block object, returns a copy of the block object,
7387 * optionally merging new attributes and/or replacing its inner blocks.
7388 *
7389 * @param {Object} block Block instance.
7390 * @param {Object} mergeAttributes Block attributes.
7391 * @param {?Array} newInnerBlocks Nested blocks.
7392 *
7393 * @return {Object} A cloned block.
7394 */
7395
7396 function cloneBlock(block) {
7397 let mergeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7398 let newInnerBlocks = arguments.length > 2 ? arguments[2] : undefined;
7399 const clientId = esm_browser_v4();
7400 return { ...block,
7401 clientId,
7402 attributes: { ...block.attributes,
7403 ...mergeAttributes
7404 },
7405 innerBlocks: newInnerBlocks || block.innerBlocks.map(innerBlock => cloneBlock(innerBlock))
7406 };
7407 }
7408 /**
7409 * Returns a boolean indicating whether a transform is possible based on
7410 * various bits of context.
7411 *
7412 * @param {Object} transform The transform object to validate.
7413 * @param {string} direction Is this a 'from' or 'to' transform.
7414 * @param {Array} blocks The blocks to transform from.
7415 *
7416 * @return {boolean} Is the transform possible?
7417 */
7418
7419 const isPossibleTransformForSource = (transform, direction, blocks) => {
7420 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
7421 return false;
7422 } // If multiple blocks are selected, only multi block transforms
7423 // or wildcard transforms are allowed.
7424
7425
7426 const isMultiBlock = blocks.length > 1;
7427 const firstBlockName = (0,external_lodash_namespaceObject.first)(blocks).name;
7428 const isValidForMultiBlocks = isWildcardBlockTransform(transform) || !isMultiBlock || transform.isMultiBlock;
7429
7430 if (!isValidForMultiBlocks) {
7431 return false;
7432 } // Check non-wildcard transforms to ensure that transform is valid
7433 // for a block selection of multiple blocks of different types.
7434
7435
7436 if (!isWildcardBlockTransform(transform) && !(0,external_lodash_namespaceObject.every)(blocks, {
7437 name: firstBlockName
7438 })) {
7439 return false;
7440 } // Only consider 'block' type transforms as valid.
7441
7442
7443 const isBlockType = transform.type === 'block';
7444
7445 if (!isBlockType) {
7446 return false;
7447 } // Check if the transform's block name matches the source block (or is a wildcard)
7448 // only if this is a transform 'from'.
7449
7450
7451 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
7452 const hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1 || isWildcardBlockTransform(transform);
7453
7454 if (!hasMatchingName) {
7455 return false;
7456 } // Don't allow single Grouping blocks to be transformed into
7457 // a Grouping block.
7458
7459
7460 if (!isMultiBlock && isContainerGroupBlock(sourceBlock.name) && isContainerGroupBlock(transform.blockName)) {
7461 return false;
7462 } // If the transform has a `isMatch` function specified, check that it returns true.
7463
7464
7465 if (!maybeCheckTransformIsMatch(transform, blocks)) {
7466 return false;
7467 }
7468
7469 if (transform.usingMobileTransformations && isWildcardBlockTransform(transform) && !isContainerGroupBlock(sourceBlock.name)) {
7470 return false;
7471 }
7472
7473 return true;
7474 };
7475 /**
7476 * Returns block types that the 'blocks' can be transformed into, based on
7477 * 'from' transforms on other blocks.
7478 *
7479 * @param {Array} blocks The blocks to transform from.
7480 *
7481 * @return {Array} Block types that the blocks can be transformed into.
7482 */
7483
7484
7485 const getBlockTypesForPossibleFromTransforms = blocks => {
7486 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
7487 return [];
7488 }
7489
7490 const allBlockTypes = registration_getBlockTypes(); // filter all blocks to find those with a 'from' transform.
7491
7492 const blockTypesWithPossibleFromTransforms = (0,external_lodash_namespaceObject.filter)(allBlockTypes, blockType => {
7493 const fromTransforms = getBlockTransforms('from', blockType.name);
7494 return !!findTransform(fromTransforms, transform => {
7495 return isPossibleTransformForSource(transform, 'from', blocks);
7496 });
7497 });
7498 return blockTypesWithPossibleFromTransforms;
7499 };
7500 /**
7501 * Returns block types that the 'blocks' can be transformed into, based on
7502 * the source block's own 'to' transforms.
7503 *
7504 * @param {Array} blocks The blocks to transform from.
7505 *
7506 * @return {Array} Block types that the source can be transformed into.
7507 */
7508
7509
7510 const getBlockTypesForPossibleToTransforms = blocks => {
7511 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
7512 return [];
7513 }
7514
7515 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
7516 const blockType = registration_getBlockType(sourceBlock.name);
7517 const transformsTo = blockType ? getBlockTransforms('to', blockType.name) : []; // filter all 'to' transforms to find those that are possible.
7518
7519 const possibleTransforms = (0,external_lodash_namespaceObject.filter)(transformsTo, transform => {
7520 return transform && isPossibleTransformForSource(transform, 'to', blocks);
7521 }); // Build a list of block names using the possible 'to' transforms.
7522
7523 const blockNames = (0,external_lodash_namespaceObject.flatMap)(possibleTransforms, transformation => transformation.blocks); // Map block names to block types.
7524
7525 return blockNames.map(name => name === '*' ? name : registration_getBlockType(name));
7526 };
7527 /**
7528 * Determines whether transform is a "block" type
7529 * and if so whether it is a "wildcard" transform
7530 * ie: targets "any" block type
7531 *
7532 * @param {Object} t the Block transform object
7533 *
7534 * @return {boolean} whether transform is a wildcard transform
7535 */
7536
7537
7538 const isWildcardBlockTransform = t => t && t.type === 'block' && Array.isArray(t.blocks) && t.blocks.includes('*');
7539 /**
7540 * Determines whether the given Block is the core Block which
7541 * acts as a container Block for other Blocks as part of the
7542 * Grouping mechanics
7543 *
7544 * @param {string} name the name of the Block to test against
7545 *
7546 * @return {boolean} whether or not the Block is the container Block type
7547 */
7548
7549 const isContainerGroupBlock = name => name === registration_getGroupingBlockName();
7550 /**
7551 * Returns an array of block types that the set of blocks received as argument
7552 * can be transformed into.
7553 *
7554 * @param {Array} blocks Blocks array.
7555 *
7556 * @return {Array} Block types that the blocks argument can be transformed to.
7557 */
7558
7559 function getPossibleBlockTransformations(blocks) {
7560 if ((0,external_lodash_namespaceObject.isEmpty)(blocks)) {
7561 return [];
7562 }
7563
7564 const blockTypesForFromTransforms = getBlockTypesForPossibleFromTransforms(blocks);
7565 const blockTypesForToTransforms = getBlockTypesForPossibleToTransforms(blocks);
7566 return (0,external_lodash_namespaceObject.uniq)([...blockTypesForFromTransforms, ...blockTypesForToTransforms]);
7567 }
7568 /**
7569 * Given an array of transforms, returns the highest-priority transform where
7570 * the predicate function returns a truthy value. A higher-priority transform
7571 * is one with a lower priority value (i.e. first in priority order). Returns
7572 * null if the transforms set is empty or the predicate function returns a
7573 * falsey value for all entries.
7574 *
7575 * @param {Object[]} transforms Transforms to search.
7576 * @param {Function} predicate Function returning true on matching transform.
7577 *
7578 * @return {?Object} Highest-priority transform candidate.
7579 */
7580
7581 function findTransform(transforms, predicate) {
7582 // The hooks library already has built-in mechanisms for managing priority
7583 // queue, so leverage via locally-defined instance.
7584 const hooks = (0,external_wp_hooks_namespaceObject.createHooks)();
7585
7586 for (let i = 0; i < transforms.length; i++) {
7587 const candidate = transforms[i];
7588
7589 if (predicate(candidate)) {
7590 hooks.addFilter('transform', 'transform/' + i.toString(), result => result ? result : candidate, candidate.priority);
7591 }
7592 } // Filter name is arbitrarily chosen but consistent with above aggregation.
7593
7594
7595 return hooks.applyFilters('transform', null);
7596 }
7597 /**
7598 * Returns normal block transforms for a given transform direction, optionally
7599 * for a specific block by name, or an empty array if there are no transforms.
7600 * If no block name is provided, returns transforms for all blocks. A normal
7601 * transform object includes `blockName` as a property.
7602 *
7603 * @param {string} direction Transform direction ("to", "from").
7604 * @param {string|Object} blockTypeOrName Block type or name.
7605 *
7606 * @return {Array} Block transforms for direction.
7607 */
7608
7609 function getBlockTransforms(direction, blockTypeOrName) {
7610 // When retrieving transforms for all block types, recurse into self.
7611 if (blockTypeOrName === undefined) {
7612 return (0,external_lodash_namespaceObject.flatMap)(registration_getBlockTypes(), _ref => {
7613 let {
7614 name
7615 } = _ref;
7616 return getBlockTransforms(direction, name);
7617 });
7618 } // Validate that block type exists and has array of direction.
7619
7620
7621 const blockType = normalizeBlockType(blockTypeOrName);
7622 const {
7623 name: blockName,
7624 transforms
7625 } = blockType || {};
7626
7627 if (!transforms || !Array.isArray(transforms[direction])) {
7628 return [];
7629 }
7630
7631 const usingMobileTransformations = transforms.supportedMobileTransforms && Array.isArray(transforms.supportedMobileTransforms);
7632 const filteredTransforms = usingMobileTransformations ? (0,external_lodash_namespaceObject.filter)(transforms[direction], t => {
7633 if (t.type === 'raw') {
7634 return true;
7635 }
7636
7637 if (!t.blocks || !t.blocks.length) {
7638 return false;
7639 }
7640
7641 if (isWildcardBlockTransform(t)) {
7642 return true;
7643 }
7644
7645 return (0,external_lodash_namespaceObject.every)(t.blocks, transformBlockName => transforms.supportedMobileTransforms.includes(transformBlockName));
7646 }) : transforms[direction]; // Map transforms to normal form.
7647
7648 return filteredTransforms.map(transform => ({ ...transform,
7649 blockName,
7650 usingMobileTransformations
7651 }));
7652 }
7653 /**
7654 * Checks that a given transforms isMatch method passes for given source blocks.
7655 *
7656 * @param {Object} transform A transform object.
7657 * @param {Array} blocks Blocks array.
7658 *
7659 * @return {boolean} True if given blocks are a match for the transform.
7660 */
7661
7662 function maybeCheckTransformIsMatch(transform, blocks) {
7663 if (typeof transform.isMatch !== 'function') {
7664 return true;
7665 }
7666
7667 const sourceBlock = (0,external_lodash_namespaceObject.first)(blocks);
7668 const attributes = transform.isMultiBlock ? blocks.map(block => block.attributes) : sourceBlock.attributes;
7669 const block = transform.isMultiBlock ? blocks : sourceBlock;
7670 return transform.isMatch(attributes, block);
7671 }
7672 /**
7673 * Switch one or more blocks into one or more blocks of the new block type.
7674 *
7675 * @param {Array|Object} blocks Blocks array or block object.
7676 * @param {string} name Block name.
7677 *
7678 * @return {?Array} Array of blocks or null.
7679 */
7680
7681
7682 function switchToBlockType(blocks, name) {
7683 const blocksArray = (0,external_lodash_namespaceObject.castArray)(blocks);
7684 const isMultiBlock = blocksArray.length > 1;
7685 const firstBlock = blocksArray[0];
7686 const sourceName = firstBlock.name; // Find the right transformation by giving priority to the "to"
7687 // transformation.
7688
7689 const transformationsFrom = getBlockTransforms('from', name);
7690 const transformationsTo = getBlockTransforms('to', sourceName);
7691 const transformation = findTransform(transformationsTo, t => t.type === 'block' && (isWildcardBlockTransform(t) || t.blocks.indexOf(name) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)) || findTransform(transformationsFrom, t => t.type === 'block' && (isWildcardBlockTransform(t) || t.blocks.indexOf(sourceName) !== -1) && (!isMultiBlock || t.isMultiBlock) && maybeCheckTransformIsMatch(t, blocksArray)); // Stop if there is no valid transformation.
7692
7693 if (!transformation) {
7694 return null;
7695 }
7696
7697 let transformationResults;
7698
7699 if (transformation.isMultiBlock) {
7700 if ((0,external_lodash_namespaceObject.has)(transformation, '__experimentalConvert')) {
7701 transformationResults = transformation.__experimentalConvert(blocksArray);
7702 } else {
7703 transformationResults = transformation.transform(blocksArray.map(currentBlock => currentBlock.attributes), blocksArray.map(currentBlock => currentBlock.innerBlocks));
7704 }
7705 } else if ((0,external_lodash_namespaceObject.has)(transformation, '__experimentalConvert')) {
7706 transformationResults = transformation.__experimentalConvert(firstBlock);
7707 } else {
7708 transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
7709 } // Ensure that the transformation function returned an object or an array
7710 // of objects.
7711
7712
7713 if (!(0,external_lodash_namespaceObject.isObjectLike)(transformationResults)) {
7714 return null;
7715 } // If the transformation function returned a single object, we want to work
7716 // with an array instead.
7717
7718
7719 transformationResults = (0,external_lodash_namespaceObject.castArray)(transformationResults); // Ensure that every block object returned by the transformation has a
7720 // valid block type.
7721
7722 if (transformationResults.some(result => !registration_getBlockType(result.name))) {
7723 return null;
7724 }
7725
7726 const hasSwitchedBlock = name === '*' || (0,external_lodash_namespaceObject.some)(transformationResults, result => result.name === name); // Ensure that at least one block object returned by the transformation has
7727 // the expected "destination" block type.
7728
7729 if (!hasSwitchedBlock) {
7730 return null;
7731 }
7732
7733 const ret = transformationResults.map((result, index, results) => {
7734 /**
7735 * Filters an individual transform result from block transformation.
7736 * All of the original blocks are passed, since transformations are
7737 * many-to-many, not one-to-one.
7738 *
7739 * @param {Object} transformedBlock The transformed block.
7740 * @param {Object[]} blocks Original blocks transformed.
7741 * @param {Object[]} index Index of the transformed block on the array of results.
7742 * @param {Object[]} results An array all the blocks that resulted from the transformation.
7743 */
7744 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.switchToBlockType.transformedBlock', result, blocks, index, results);
7745 });
7746 return ret;
7747 }
7748 /**
7749 * Create a block object from the example API.
7750 *
7751 * @param {string} name
7752 * @param {Object} example
7753 *
7754 * @return {Object} block.
7755 */
7756
7757 const getBlockFromExample = (name, example) => {
7758 return createBlock(name, example.attributes, (0,external_lodash_namespaceObject.map)(example.innerBlocks, innerBlock => getBlockFromExample(innerBlock.name, innerBlock)));
7759 };
7760
7761 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/utils.js
7762 /**
7763 * External dependencies
7764 */
7765
7766
7767
7768
7769 /**
7770 * WordPress dependencies
7771 */
7772
7773
7774
7775
7776 /**
7777 * Internal dependencies
7778 */
7779
7780
7781
7782
7783 k([names, a11y]);
7784 /**
7785 * Array of icon colors containing a color to be used if the icon color
7786 * was not explicitly set but the icon background color was.
7787 *
7788 * @type {Object}
7789 */
7790
7791 const ICON_COLORS = ['#191e23', '#f8f9f9'];
7792 /**
7793 * Determines whether the block is a default block
7794 * and its attributes are equal to the default attributes
7795 * which means the block is unmodified.
7796 *
7797 * @param {WPBlock} block Block Object
7798 *
7799 * @return {boolean} Whether the block is an unmodified default block
7800 */
7801
7802 function isUnmodifiedDefaultBlock(block) {
7803 const defaultBlockName = registration_getDefaultBlockName();
7804
7805 if (block.name !== defaultBlockName) {
7806 return false;
7807 } // Cache a created default block if no cache exists or the default block
7808 // name changed.
7809
7810
7811 if (!isUnmodifiedDefaultBlock.block || isUnmodifiedDefaultBlock.block.name !== defaultBlockName) {
7812 isUnmodifiedDefaultBlock.block = createBlock(defaultBlockName);
7813 }
7814
7815 const newDefaultBlock = isUnmodifiedDefaultBlock.block;
7816 const blockType = registration_getBlockType(defaultBlockName);
7817 return (0,external_lodash_namespaceObject.every)(blockType === null || blockType === void 0 ? void 0 : blockType.attributes, (value, key) => newDefaultBlock.attributes[key] === block.attributes[key]);
7818 }
7819 /**
7820 * Function that checks if the parameter is a valid icon.
7821 *
7822 * @param {*} icon Parameter to be checked.
7823 *
7824 * @return {boolean} True if the parameter is a valid icon and false otherwise.
7825 */
7826
7827 function isValidIcon(icon) {
7828 return !!icon && ((0,external_lodash_namespaceObject.isString)(icon) || (0,external_wp_element_namespaceObject.isValidElement)(icon) || (0,external_lodash_namespaceObject.isFunction)(icon) || icon instanceof external_wp_element_namespaceObject.Component);
7829 }
7830 /**
7831 * Function that receives an icon as set by the blocks during the registration
7832 * and returns a new icon object that is normalized so we can rely on just on possible icon structure
7833 * in the codebase.
7834 *
7835 * @param {WPBlockTypeIconRender} icon Render behavior of a block type icon;
7836 * one of a Dashicon slug, an element, or a
7837 * component.
7838 *
7839 * @return {WPBlockTypeIconDescriptor} Object describing the icon.
7840 */
7841
7842 function normalizeIconObject(icon) {
7843 icon = icon || BLOCK_ICON_DEFAULT;
7844
7845 if (isValidIcon(icon)) {
7846 return {
7847 src: icon
7848 };
7849 }
7850
7851 if ((0,external_lodash_namespaceObject.has)(icon, ['background'])) {
7852 const colordBgColor = w(icon.background);
7853 return { ...icon,
7854 foreground: icon.foreground ? icon.foreground : (0,external_lodash_namespaceObject.maxBy)(ICON_COLORS, iconColor => colordBgColor.contrast(iconColor)),
7855 shadowColor: colordBgColor.alpha(0.3).toRgbString()
7856 };
7857 }
7858
7859 return icon;
7860 }
7861 /**
7862 * Normalizes block type passed as param. When string is passed then
7863 * it converts it to the matching block type object.
7864 * It passes the original object otherwise.
7865 *
7866 * @param {string|Object} blockTypeOrName Block type or name.
7867 *
7868 * @return {?Object} Block type.
7869 */
7870
7871 function normalizeBlockType(blockTypeOrName) {
7872 if ((0,external_lodash_namespaceObject.isString)(blockTypeOrName)) {
7873 return registration_getBlockType(blockTypeOrName);
7874 }
7875
7876 return blockTypeOrName;
7877 }
7878 /**
7879 * Get the label for the block, usually this is either the block title,
7880 * or the value of the block's `label` function when that's specified.
7881 *
7882 * @param {Object} blockType The block type.
7883 * @param {Object} attributes The values of the block's attributes.
7884 * @param {Object} context The intended use for the label.
7885 *
7886 * @return {string} The block label.
7887 */
7888
7889 function getBlockLabel(blockType, attributes) {
7890 let context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'visual';
7891 const {
7892 __experimentalLabel: getLabel,
7893 title
7894 } = blockType;
7895 const label = getLabel && getLabel(attributes, {
7896 context
7897 });
7898
7899 if (!label) {
7900 return title;
7901 } // Strip any HTML (i.e. RichText formatting) before returning.
7902
7903
7904 return (0,external_wp_dom_namespaceObject.__unstableStripHTML)(label);
7905 }
7906 /**
7907 * Get a label for the block for use by screenreaders, this is more descriptive
7908 * than the visual label and includes the block title and the value of the
7909 * `getLabel` function if it's specified.
7910 *
7911 * @param {Object} blockType The block type.
7912 * @param {Object} attributes The values of the block's attributes.
7913 * @param {?number} position The position of the block in the block list.
7914 * @param {string} [direction='vertical'] The direction of the block layout.
7915 *
7916 * @return {string} The block label.
7917 */
7918
7919 function getAccessibleBlockLabel(blockType, attributes, position) {
7920 let direction = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'vertical';
7921 // `title` is already localized, `label` is a user-supplied value.
7922 const title = blockType === null || blockType === void 0 ? void 0 : blockType.title;
7923 const label = blockType ? getBlockLabel(blockType, attributes, 'accessibility') : '';
7924 const hasPosition = position !== undefined; // getBlockLabel returns the block title as a fallback when there's no label,
7925 // if it did return the title, this function needs to avoid adding the
7926 // title twice within the accessible label. Use this `hasLabel` boolean to
7927 // handle that.
7928
7929 const hasLabel = label && label !== title;
7930
7931 if (hasPosition && direction === 'vertical') {
7932 if (hasLabel) {
7933 return (0,external_wp_i18n_namespaceObject.sprintf)(
7934 /* translators: accessibility text. 1: The block title. 2: The block row number. 3: The block label.. */
7935 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d. %3$s'), title, position, label);
7936 }
7937
7938 return (0,external_wp_i18n_namespaceObject.sprintf)(
7939 /* translators: accessibility text. 1: The block title. 2: The block row number. */
7940 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Row %2$d'), title, position);
7941 } else if (hasPosition && direction === 'horizontal') {
7942 if (hasLabel) {
7943 return (0,external_wp_i18n_namespaceObject.sprintf)(
7944 /* translators: accessibility text. 1: The block title. 2: The block column number. 3: The block label.. */
7945 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d. %3$s'), title, position, label);
7946 }
7947
7948 return (0,external_wp_i18n_namespaceObject.sprintf)(
7949 /* translators: accessibility text. 1: The block title. 2: The block column number. */
7950 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. Column %2$d'), title, position);
7951 }
7952
7953 if (hasLabel) {
7954 return (0,external_wp_i18n_namespaceObject.sprintf)(
7955 /* translators: accessibility text. %1: The block title. %2: The block label. */
7956 (0,external_wp_i18n_namespaceObject.__)('%1$s Block. %2$s'), title, label);
7957 }
7958
7959 return (0,external_wp_i18n_namespaceObject.sprintf)(
7960 /* translators: accessibility text. %s: The block title. */
7961 (0,external_wp_i18n_namespaceObject.__)('%s Block'), title);
7962 }
7963 /**
7964 * Ensure attributes contains only values defined by block type, and merge
7965 * default values for missing attributes.
7966 *
7967 * @param {string} name The block's name.
7968 * @param {Object} attributes The block's attributes.
7969 * @return {Object} The sanitized attributes.
7970 */
7971
7972 function __experimentalSanitizeBlockAttributes(name, attributes) {
7973 // Get the type definition associated with a registered block.
7974 const blockType = registration_getBlockType(name);
7975
7976 if (undefined === blockType) {
7977 throw new Error(`Block type '${name}' is not registered.`);
7978 }
7979
7980 return (0,external_lodash_namespaceObject.reduce)(blockType.attributes, (accumulator, schema, key) => {
7981 const value = attributes[key];
7982
7983 if (undefined !== value) {
7984 accumulator[key] = value;
7985 } else if (schema.hasOwnProperty('default')) {
7986 accumulator[key] = schema.default;
7987 }
7988
7989 if (['node', 'children'].indexOf(schema.source) !== -1) {
7990 // Ensure value passed is always an array, which we're expecting in
7991 // the RichText component to handle the deprecated value.
7992 if (typeof accumulator[key] === 'string') {
7993 accumulator[key] = [accumulator[key]];
7994 } else if (!Array.isArray(accumulator[key])) {
7995 accumulator[key] = [];
7996 }
7997 }
7998
7999 return accumulator;
8000 }, {});
8001 }
8002 /**
8003 * Filter block attributes by `role` and return their names.
8004 *
8005 * @param {string} name Block attribute's name.
8006 * @param {string} role The role of a block attribute.
8007 *
8008 * @return {string[]} The attribute names that have the provided role.
8009 */
8010
8011 function __experimentalGetBlockAttributesNamesByRole(name, role) {
8012 var _getBlockType;
8013
8014 const attributes = (_getBlockType = registration_getBlockType(name)) === null || _getBlockType === void 0 ? void 0 : _getBlockType.attributes;
8015 if (!attributes) return [];
8016 const attributesNames = Object.keys(attributes);
8017 if (!role) return attributesNames;
8018 return attributesNames.filter(attributeName => {
8019 var _attributes$attribute;
8020
8021 return ((_attributes$attribute = attributes[attributeName]) === null || _attributes$attribute === void 0 ? void 0 : _attributes$attribute.__experimentalRole) === role;
8022 });
8023 }
8024
8025 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/actions.js
8026 /**
8027 * External dependencies
8028 */
8029
8030 /**
8031 * WordPress dependencies
8032 */
8033
8034
8035 /**
8036 * Internal dependencies
8037 */
8038
8039
8040
8041 /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
8042
8043 const {
8044 error,
8045 warn
8046 } = window.console;
8047 /**
8048 * Mapping of legacy category slugs to their latest normal values, used to
8049 * accommodate updates of the default set of block categories.
8050 *
8051 * @type {Record<string,string>}
8052 */
8053
8054 const LEGACY_CATEGORY_MAPPING = {
8055 common: 'text',
8056 formatting: 'text',
8057 layout: 'design'
8058 };
8059 /**
8060 * Takes the unprocessed block type data and applies all the existing filters for the registered block type.
8061 * Next, it validates all the settings and performs additional processing to the block type definition.
8062 *
8063 * @param {WPBlockType} blockType Unprocessed block type settings.
8064 * @param {Object} thunkArgs Argument object for the thunk middleware.
8065 * @param {Function} thunkArgs.select Function to select from the store.
8066 *
8067 * @return {?WPBlockType} The block, if it has been successfully registered; otherwise `undefined`.
8068 */
8069
8070 const processBlockType = (blockType, _ref) => {
8071 let {
8072 select
8073 } = _ref;
8074 const {
8075 name
8076 } = blockType;
8077 const settings = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', { ...blockType
8078 }, name, null);
8079
8080 if (settings.deprecated) {
8081 settings.deprecated = settings.deprecated.map(deprecation => (0,external_lodash_namespaceObject.pick)( // Only keep valid deprecation keys.
8082 (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.registerBlockType', // Merge deprecation keys with pre-filter settings
8083 // so that filters that depend on specific keys being
8084 // present don't fail.
8085 { // Omit deprecation keys here so that deprecations
8086 // can opt out of specific keys like "supports".
8087 ...(0,external_lodash_namespaceObject.omit)(blockType, DEPRECATED_ENTRY_KEYS),
8088 ...deprecation
8089 }, name, deprecation), DEPRECATED_ENTRY_KEYS));
8090 }
8091
8092 if (!(0,external_lodash_namespaceObject.isPlainObject)(settings)) {
8093 error('Block settings must be a valid object.');
8094 return;
8095 }
8096
8097 if (!(0,external_lodash_namespaceObject.isFunction)(settings.save)) {
8098 error('The "save" property must be a valid function.');
8099 return;
8100 }
8101
8102 if ('edit' in settings && !(0,external_lodash_namespaceObject.isFunction)(settings.edit)) {
8103 error('The "edit" property must be a valid function.');
8104 return;
8105 } // Canonicalize legacy categories to equivalent fallback.
8106
8107
8108 if (LEGACY_CATEGORY_MAPPING.hasOwnProperty(settings.category)) {
8109 settings.category = LEGACY_CATEGORY_MAPPING[settings.category];
8110 }
8111
8112 if ('category' in settings && !(0,external_lodash_namespaceObject.some)(select.getCategories(), {
8113 slug: settings.category
8114 })) {
8115 warn('The block "' + name + '" is registered with an invalid category "' + settings.category + '".');
8116 delete settings.category;
8117 }
8118
8119 if (!('title' in settings) || settings.title === '') {
8120 error('The block "' + name + '" must have a title.');
8121 return;
8122 }
8123
8124 if (typeof settings.title !== 'string') {
8125 error('Block titles must be strings.');
8126 return;
8127 }
8128
8129 settings.icon = normalizeIconObject(settings.icon);
8130
8131 if (!isValidIcon(settings.icon.src)) {
8132 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');
8133 return;
8134 }
8135
8136 return settings;
8137 };
8138 /**
8139 * Returns an action object used in signalling that block types have been added.
8140 *
8141 * @param {Array|Object} blockTypes Block types received.
8142 *
8143 * @return {Object} Action object.
8144 */
8145
8146
8147 function addBlockTypes(blockTypes) {
8148 return {
8149 type: 'ADD_BLOCK_TYPES',
8150 blockTypes: (0,external_lodash_namespaceObject.castArray)(blockTypes)
8151 };
8152 }
8153 /**
8154 * Signals that the passed block type's settings should be stored in the state.
8155 *
8156 * @param {WPBlockType} blockType Unprocessed block type settings.
8157 */
8158
8159 const __experimentalRegisterBlockType = blockType => _ref2 => {
8160 let {
8161 dispatch,
8162 select
8163 } = _ref2;
8164 dispatch({
8165 type: 'ADD_UNPROCESSED_BLOCK_TYPE',
8166 blockType
8167 });
8168 const processedBlockType = processBlockType(blockType, {
8169 select
8170 });
8171
8172 if (!processedBlockType) {
8173 return;
8174 }
8175
8176 dispatch.addBlockTypes(processedBlockType);
8177 };
8178 /**
8179 * Signals that all block types should be computed again.
8180 * It uses stored unprocessed block types and all the most recent list of registered filters.
8181 *
8182 * It addresses the issue where third party block filters get registered after third party blocks. A sample sequence:
8183 * 1. Filter A.
8184 * 2. Block B.
8185 * 3. Block C.
8186 * 4. Filter D.
8187 * 5. Filter E.
8188 * 6. Block F.
8189 * 7. Filter G.
8190 * In this scenario some filters would not get applied for all blocks because they are registered too late.
8191 */
8192
8193 const __experimentalReapplyBlockTypeFilters = () => _ref3 => {
8194 let {
8195 dispatch,
8196 select
8197 } = _ref3;
8198
8199 const unprocessedBlockTypes = select.__experimentalGetUnprocessedBlockTypes();
8200
8201 const processedBlockTypes = Object.keys(unprocessedBlockTypes).reduce((accumulator, blockName) => {
8202 const result = processBlockType(unprocessedBlockTypes[blockName], {
8203 select
8204 });
8205
8206 if (result) {
8207 accumulator.push(result);
8208 }
8209
8210 return accumulator;
8211 }, []);
8212
8213 if (!processedBlockTypes.length) {
8214 return;
8215 }
8216
8217 dispatch.addBlockTypes(processedBlockTypes);
8218 };
8219 /**
8220 * Returns an action object used to remove a registered block type.
8221 *
8222 * @param {string|Array} names Block name.
8223 *
8224 * @return {Object} Action object.
8225 */
8226
8227 function removeBlockTypes(names) {
8228 return {
8229 type: 'REMOVE_BLOCK_TYPES',
8230 names: (0,external_lodash_namespaceObject.castArray)(names)
8231 };
8232 }
8233 /**
8234 * Returns an action object used in signalling that new block styles have been added.
8235 *
8236 * @param {string} blockName Block name.
8237 * @param {Array|Object} styles Block styles.
8238 *
8239 * @return {Object} Action object.
8240 */
8241
8242 function addBlockStyles(blockName, styles) {
8243 return {
8244 type: 'ADD_BLOCK_STYLES',
8245 styles: (0,external_lodash_namespaceObject.castArray)(styles),
8246 blockName
8247 };
8248 }
8249 /**
8250 * Returns an action object used in signalling that block styles have been removed.
8251 *
8252 * @param {string} blockName Block name.
8253 * @param {Array|string} styleNames Block style names.
8254 *
8255 * @return {Object} Action object.
8256 */
8257
8258 function removeBlockStyles(blockName, styleNames) {
8259 return {
8260 type: 'REMOVE_BLOCK_STYLES',
8261 styleNames: (0,external_lodash_namespaceObject.castArray)(styleNames),
8262 blockName
8263 };
8264 }
8265 /**
8266 * Returns an action object used in signalling that new block variations have been added.
8267 *
8268 * @param {string} blockName Block name.
8269 * @param {WPBlockVariation|WPBlockVariation[]} variations Block variations.
8270 *
8271 * @return {Object} Action object.
8272 */
8273
8274 function addBlockVariations(blockName, variations) {
8275 return {
8276 type: 'ADD_BLOCK_VARIATIONS',
8277 variations: (0,external_lodash_namespaceObject.castArray)(variations),
8278 blockName
8279 };
8280 }
8281 /**
8282 * Returns an action object used in signalling that block variations have been removed.
8283 *
8284 * @param {string} blockName Block name.
8285 * @param {string|string[]} variationNames Block variation names.
8286 *
8287 * @return {Object} Action object.
8288 */
8289
8290 function removeBlockVariations(blockName, variationNames) {
8291 return {
8292 type: 'REMOVE_BLOCK_VARIATIONS',
8293 variationNames: (0,external_lodash_namespaceObject.castArray)(variationNames),
8294 blockName
8295 };
8296 }
8297 /**
8298 * Returns an action object used to set the default block name.
8299 *
8300 * @param {string} name Block name.
8301 *
8302 * @return {Object} Action object.
8303 */
8304
8305 function actions_setDefaultBlockName(name) {
8306 return {
8307 type: 'SET_DEFAULT_BLOCK_NAME',
8308 name
8309 };
8310 }
8311 /**
8312 * Returns an action object used to set the name of the block used as a fallback
8313 * for non-block content.
8314 *
8315 * @param {string} name Block name.
8316 *
8317 * @return {Object} Action object.
8318 */
8319
8320 function setFreeformFallbackBlockName(name) {
8321 return {
8322 type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
8323 name
8324 };
8325 }
8326 /**
8327 * Returns an action object used to set the name of the block used as a fallback
8328 * for unregistered blocks.
8329 *
8330 * @param {string} name Block name.
8331 *
8332 * @return {Object} Action object.
8333 */
8334
8335 function setUnregisteredFallbackBlockName(name) {
8336 return {
8337 type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
8338 name
8339 };
8340 }
8341 /**
8342 * Returns an action object used to set the name of the block used
8343 * when grouping other blocks
8344 * eg: in "Group/Ungroup" interactions
8345 *
8346 * @param {string} name Block name.
8347 *
8348 * @return {Object} Action object.
8349 */
8350
8351 function actions_setGroupingBlockName(name) {
8352 return {
8353 type: 'SET_GROUPING_BLOCK_NAME',
8354 name
8355 };
8356 }
8357 /**
8358 * Returns an action object used to set block categories.
8359 *
8360 * @param {Object[]} categories Block categories.
8361 *
8362 * @return {Object} Action object.
8363 */
8364
8365 function setCategories(categories) {
8366 return {
8367 type: 'SET_CATEGORIES',
8368 categories
8369 };
8370 }
8371 /**
8372 * Returns an action object used to update a category.
8373 *
8374 * @param {string} slug Block category slug.
8375 * @param {Object} category Object containing the category properties that should be updated.
8376 *
8377 * @return {Object} Action object.
8378 */
8379
8380 function updateCategory(slug, category) {
8381 return {
8382 type: 'UPDATE_CATEGORY',
8383 slug,
8384 category
8385 };
8386 }
8387 /**
8388 * Returns an action object used to add block collections
8389 *
8390 * @param {string} namespace The namespace of the blocks to put in the collection
8391 * @param {string} title The title to display in the block inserter
8392 * @param {Object} icon (optional) The icon to display in the block inserter
8393 *
8394 * @return {Object} Action object.
8395 */
8396
8397 function addBlockCollection(namespace, title, icon) {
8398 return {
8399 type: 'ADD_BLOCK_COLLECTION',
8400 namespace,
8401 title,
8402 icon
8403 };
8404 }
8405 /**
8406 * Returns an action object used to remove block collections
8407 *
8408 * @param {string} namespace The namespace of the blocks to put in the collection
8409 *
8410 * @return {Object} Action object.
8411 */
8412
8413 function removeBlockCollection(namespace) {
8414 return {
8415 type: 'REMOVE_BLOCK_COLLECTION',
8416 namespace
8417 };
8418 }
8419
8420 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/constants.js
8421 const STORE_NAME = 'core/blocks';
8422
8423 ;// CONCATENATED MODULE: ./packages/blocks/build-module/store/index.js
8424 /**
8425 * WordPress dependencies
8426 */
8427
8428 /**
8429 * Internal dependencies
8430 */
8431
8432
8433
8434
8435
8436 /**
8437 * Store definition for the blocks namespace.
8438 *
8439 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
8440 *
8441 * @type {Object}
8442 */
8443
8444 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
8445 reducer: reducer,
8446 selectors: selectors_namespaceObject,
8447 actions: actions_namespaceObject
8448 });
8449 (0,external_wp_data_namespaceObject.register)(store);
8450
8451 ;// CONCATENATED MODULE: external ["wp","blockSerializationDefaultParser"]
8452 var external_wp_blockSerializationDefaultParser_namespaceObject = window["wp"]["blockSerializationDefaultParser"];
8453 ;// CONCATENATED MODULE: external ["wp","autop"]
8454 var external_wp_autop_namespaceObject = window["wp"]["autop"];
8455 ;// CONCATENATED MODULE: external ["wp","isShallowEqual"]
8456 var external_wp_isShallowEqual_namespaceObject = window["wp"]["isShallowEqual"];
8457 var external_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_wp_isShallowEqual_namespaceObject);
8458 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/serialize-raw-block.js
8459 /**
8460 * Internal dependencies
8461 */
8462
8463 /**
8464 * @typedef {Object} Options Serialization options.
8465 * @property {boolean} [isCommentDelimited=true] Whether to output HTML comments around blocks.
8466 */
8467
8468 /** @typedef {import("./").WPRawBlock} WPRawBlock */
8469
8470 /**
8471 * Serializes a block node into the native HTML-comment-powered block format.
8472 * CAVEAT: This function is intended for re-serializing blocks as parsed by
8473 * valid parsers and skips any validation steps. This is NOT a generic
8474 * serialization function for in-memory blocks. For most purposes, see the
8475 * following functions available in the `@wordpress/blocks` package:
8476 *
8477 * @see serializeBlock
8478 * @see serialize
8479 *
8480 * For more on the format of block nodes as returned by valid parsers:
8481 *
8482 * @see `@wordpress/block-serialization-default-parser` package
8483 * @see `@wordpress/block-serialization-spec-parser` package
8484 *
8485 * @param {WPRawBlock} rawBlock A block node as returned by a valid parser.
8486 * @param {Options} [options={}] Serialization options.
8487 *
8488 * @return {string} An HTML string representing a block.
8489 */
8490
8491 function serializeRawBlock(rawBlock) {
8492 let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8493 const {
8494 isCommentDelimited = true
8495 } = options;
8496 const {
8497 blockName,
8498 attrs = {},
8499 innerBlocks = [],
8500 innerContent = []
8501 } = rawBlock;
8502 let childIndex = 0;
8503 const content = innerContent.map(item => // `null` denotes a nested block, otherwise we have an HTML fragment.
8504 item !== null ? item : serializeRawBlock(innerBlocks[childIndex++], options)).join('\n').replace(/\n+/g, '\n').trim();
8505 return isCommentDelimited ? getCommentDelimitedContent(blockName, attrs, content) : content;
8506 }
8507
8508 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/serializer.js
8509
8510
8511 /**
8512 * External dependencies
8513 */
8514
8515 /**
8516 * WordPress dependencies
8517 */
8518
8519
8520
8521
8522
8523 /**
8524 * Internal dependencies
8525 */
8526
8527
8528
8529
8530 /** @typedef {import('./parser').WPBlock} WPBlock */
8531
8532 /**
8533 * @typedef {Object} WPBlockSerializationOptions Serialization Options.
8534 *
8535 * @property {boolean} isInnerBlocks Whether we are serializing inner blocks.
8536 */
8537
8538 /**
8539 * Returns the block's default classname from its name.
8540 *
8541 * @param {string} blockName The block name.
8542 *
8543 * @return {string} The block's default class.
8544 */
8545
8546 function getBlockDefaultClassName(blockName) {
8547 // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
8548 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
8549 const className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
8550 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockDefaultClassName', className, blockName);
8551 }
8552 /**
8553 * Returns the block's default menu item classname from its name.
8554 *
8555 * @param {string} blockName The block name.
8556 *
8557 * @return {string} The block's default menu item class.
8558 */
8559
8560 function getBlockMenuDefaultClassName(blockName) {
8561 // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
8562 // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (historically used in 'core-embed/').
8563 const className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
8564 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockMenuDefaultClassName', className, blockName);
8565 }
8566 const blockPropsProvider = {};
8567 const innerBlocksPropsProvider = {};
8568 /**
8569 * Call within a save function to get the props for the block wrapper.
8570 *
8571 * @param {Object} props Optional. Props to pass to the element.
8572 */
8573
8574 function getBlockProps() {
8575 let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8576 const {
8577 blockType,
8578 attributes
8579 } = blockPropsProvider;
8580 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...props
8581 }, blockType, attributes);
8582 }
8583 /**
8584 * Call within a save function to get the props for the inner blocks wrapper.
8585 *
8586 * @param {Object} props Optional. Props to pass to the element.
8587 */
8588
8589 function getInnerBlocksProps() {
8590 let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
8591 const {
8592 innerBlocks
8593 } = innerBlocksPropsProvider; // Value is an array of blocks, so defer to block serializer.
8594
8595 const html = serializer_serialize(innerBlocks, {
8596 isInnerBlocks: true
8597 }); // Use special-cased raw HTML tag to avoid default escaping.
8598
8599 const children = (0,external_wp_element_namespaceObject.createElement)(external_wp_element_namespaceObject.RawHTML, null, html);
8600 return { ...props,
8601 children
8602 };
8603 }
8604 /**
8605 * Given a block type containing a save render implementation and attributes, returns the
8606 * enhanced element to be saved or string when raw HTML expected.
8607 *
8608 * @param {string|Object} blockTypeOrName Block type or name.
8609 * @param {Object} attributes Block attributes.
8610 * @param {?Array} innerBlocks Nested blocks.
8611 *
8612 * @return {Object|string} Save element or raw HTML string.
8613 */
8614
8615 function getSaveElement(blockTypeOrName, attributes) {
8616 let innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
8617 const blockType = normalizeBlockType(blockTypeOrName);
8618 let {
8619 save
8620 } = blockType; // Component classes are unsupported for save since serialization must
8621 // occur synchronously. For improved interoperability with higher-order
8622 // components which often return component class, emulate basic support.
8623
8624 if (save.prototype instanceof external_wp_element_namespaceObject.Component) {
8625 const instance = new save({
8626 attributes
8627 });
8628 save = instance.render.bind(instance);
8629 }
8630
8631 blockPropsProvider.blockType = blockType;
8632 blockPropsProvider.attributes = attributes;
8633 innerBlocksPropsProvider.innerBlocks = innerBlocks;
8634 let element = save({
8635 attributes,
8636 innerBlocks
8637 });
8638
8639 if ((0,external_lodash_namespaceObject.isObject)(element) && (0,external_wp_hooks_namespaceObject.hasFilter)('blocks.getSaveContent.extraProps') && !(blockType.apiVersion > 1)) {
8640 /**
8641 * Filters the props applied to the block save result element.
8642 *
8643 * @param {Object} props Props applied to save element.
8644 * @param {WPBlock} blockType Block type definition.
8645 * @param {Object} attributes Block attributes.
8646 */
8647 const props = (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveContent.extraProps', { ...element.props
8648 }, blockType, attributes);
8649
8650 if (!external_wp_isShallowEqual_default()(props, element.props)) {
8651 element = (0,external_wp_element_namespaceObject.cloneElement)(element, props);
8652 }
8653 }
8654 /**
8655 * Filters the save result of a block during serialization.
8656 *
8657 * @param {WPElement} element Block save result.
8658 * @param {WPBlock} blockType Block type definition.
8659 * @param {Object} attributes Block attributes.
8660 */
8661
8662
8663 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getSaveElement', element, blockType, attributes);
8664 }
8665 /**
8666 * Given a block type containing a save render implementation and attributes, returns the
8667 * static markup to be saved.
8668 *
8669 * @param {string|Object} blockTypeOrName Block type or name.
8670 * @param {Object} attributes Block attributes.
8671 * @param {?Array} innerBlocks Nested blocks.
8672 *
8673 * @return {string} Save content.
8674 */
8675
8676 function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
8677 const blockType = normalizeBlockType(blockTypeOrName);
8678 return (0,external_wp_element_namespaceObject.renderToString)(getSaveElement(blockType, attributes, innerBlocks));
8679 }
8680 /**
8681 * Returns attributes which are to be saved and serialized into the block
8682 * comment delimiter.
8683 *
8684 * When a block exists in memory it contains as its attributes both those
8685 * parsed the block comment delimiter _and_ those which matched from the
8686 * contents of the block.
8687 *
8688 * This function returns only those attributes which are needed to persist and
8689 * which cannot be matched from the block content.
8690 *
8691 * @param {Object<string,*>} blockType Block type.
8692 * @param {Object<string,*>} attributes Attributes from in-memory block data.
8693 *
8694 * @return {Object<string,*>} Subset of attributes for comment serialization.
8695 */
8696
8697 function getCommentAttributes(blockType, attributes) {
8698 return (0,external_lodash_namespaceObject.reduce)(blockType.attributes, (accumulator, attributeSchema, key) => {
8699 const value = attributes[key]; // Ignore undefined values.
8700
8701 if (undefined === value) {
8702 return accumulator;
8703 } // Ignore all attributes but the ones with an "undefined" source
8704 // "undefined" source refers to attributes saved in the block comment.
8705
8706
8707 if (attributeSchema.source !== undefined) {
8708 return accumulator;
8709 } // Ignore default value.
8710
8711
8712 if ('default' in attributeSchema && attributeSchema.default === value) {
8713 return accumulator;
8714 } // Otherwise, include in comment set.
8715
8716
8717 accumulator[key] = value;
8718 return accumulator;
8719 }, {});
8720 }
8721 /**
8722 * Given an attributes object, returns a string in the serialized attributes
8723 * format prepared for post content.
8724 *
8725 * @param {Object} attributes Attributes object.
8726 *
8727 * @return {string} Serialized attributes.
8728 */
8729
8730 function serializeAttributes(attributes) {
8731 return JSON.stringify(attributes) // Don't break HTML comments.
8732 .replace(/--/g, '\\u002d\\u002d') // Don't break non-standard-compliant tools.
8733 .replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026') // Bypass server stripslashes behavior which would unescape stringify's
8734 // escaping of quotation mark.
8735 //
8736 // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
8737 .replace(/\\"/g, '\\u0022');
8738 }
8739 /**
8740 * Given a block object, returns the Block's Inner HTML markup.
8741 *
8742 * @param {Object} block Block instance.
8743 *
8744 * @return {string} HTML.
8745 */
8746
8747 function getBlockInnerHTML(block) {
8748 // If block was parsed as invalid or encounters an error while generating
8749 // save content, use original content instead to avoid content loss. If a
8750 // block contains nested content, exempt it from this condition because we
8751 // otherwise have no access to its original content and content loss would
8752 // still occur.
8753 let saveContent = block.originalContent;
8754
8755 if (block.isValid || block.innerBlocks.length) {
8756 try {
8757 saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
8758 } catch (error) {}
8759 }
8760
8761 return saveContent;
8762 }
8763 /**
8764 * Returns the content of a block, including comment delimiters.
8765 *
8766 * @param {string} rawBlockName Block name.
8767 * @param {Object} attributes Block attributes.
8768 * @param {string} content Block save content.
8769 *
8770 * @return {string} Comment-delimited block content.
8771 */
8772
8773 function getCommentDelimitedContent(rawBlockName, attributes, content) {
8774 const serializedAttributes = !(0,external_lodash_namespaceObject.isEmpty)(attributes) ? serializeAttributes(attributes) + ' ' : ''; // Strip core blocks of their namespace prefix.
8775
8776 const blockName = (0,external_lodash_namespaceObject.startsWith)(rawBlockName, 'core/') ? rawBlockName.slice(5) : rawBlockName; // @todo make the `wp:` prefix potentially configurable.
8777
8778 if (!content) {
8779 return `<!-- wp:${blockName} ${serializedAttributes}/-->`;
8780 }
8781
8782 return `<!-- wp:${blockName} ${serializedAttributes}-->\n` + content + `\n<!-- /wp:${blockName} -->`;
8783 }
8784 /**
8785 * Returns the content of a block, including comment delimiters, determining
8786 * serialized attributes and content form from the current state of the block.
8787 *
8788 * @param {WPBlock} block Block instance.
8789 * @param {WPBlockSerializationOptions} options Serialization options.
8790 *
8791 * @return {string} Serialized block.
8792 */
8793
8794 function serializeBlock(block) {
8795 let {
8796 isInnerBlocks = false
8797 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8798
8799 if (!block.isValid && block.__unstableBlockSource) {
8800 return serializeRawBlock(block.__unstableBlockSource);
8801 }
8802
8803 const blockName = block.name;
8804 const saveContent = getBlockInnerHTML(block);
8805
8806 if (blockName === getUnregisteredTypeHandlerName() || !isInnerBlocks && blockName === getFreeformContentHandlerName()) {
8807 return saveContent;
8808 }
8809
8810 const blockType = registration_getBlockType(blockName);
8811 const saveAttributes = getCommentAttributes(blockType, block.attributes);
8812 return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
8813 }
8814 function __unstableSerializeAndClean(blocks) {
8815 // A single unmodified default block is assumed to
8816 // be equivalent to an empty post.
8817 if (blocks.length === 1 && isUnmodifiedDefaultBlock(blocks[0])) {
8818 blocks = [];
8819 }
8820
8821 let content = serializer_serialize(blocks); // For compatibility, treat a post consisting of a
8822 // single freeform block as legacy content and apply
8823 // pre-block-editor removep'd content formatting.
8824
8825 if (blocks.length === 1 && blocks[0].name === getFreeformContentHandlerName()) {
8826 content = (0,external_wp_autop_namespaceObject.removep)(content);
8827 }
8828
8829 return content;
8830 }
8831 /**
8832 * Takes a block or set of blocks and returns the serialized post content.
8833 *
8834 * @param {Array} blocks Block(s) to serialize.
8835 * @param {WPBlockSerializationOptions} options Serialization options.
8836 *
8837 * @return {string} The post content.
8838 */
8839
8840 function serializer_serialize(blocks, options) {
8841 return (0,external_lodash_namespaceObject.castArray)(blocks).map(block => serializeBlock(block, options)).join('\n\n');
8842 }
8843
8844 ;// CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/index.js
8845 /**
8846 * generated from https://raw.githubusercontent.com/w3c/html/26b5126f96f736f796b9e29718138919dd513744/entities.json
8847 * do not edit
8848 */
8849 var namedCharRefs = {
8850 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"
8851 };
8852
8853 var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/;
8854 var CHARCODE = /^#([0-9]+)$/;
8855 var NAMED = /^([A-Za-z0-9]+)$/;
8856 var EntityParser = /** @class */ (function () {
8857 function EntityParser(named) {
8858 this.named = named;
8859 }
8860 EntityParser.prototype.parse = function (entity) {
8861 if (!entity) {
8862 return;
8863 }
8864 var matches = entity.match(HEXCHARCODE);
8865 if (matches) {
8866 return String.fromCharCode(parseInt(matches[1], 16));
8867 }
8868 matches = entity.match(CHARCODE);
8869 if (matches) {
8870 return String.fromCharCode(parseInt(matches[1], 10));
8871 }
8872 matches = entity.match(NAMED);
8873 if (matches) {
8874 return this.named[matches[1]];
8875 }
8876 };
8877 return EntityParser;
8878 }());
8879
8880 var WSP = /[\t\n\f ]/;
8881 var ALPHA = /[A-Za-z]/;
8882 var CRLF = /\r\n?/g;
8883 function isSpace(char) {
8884 return WSP.test(char);
8885 }
8886 function isAlpha(char) {
8887 return ALPHA.test(char);
8888 }
8889 function preprocessInput(input) {
8890 return input.replace(CRLF, '\n');
8891 }
8892
8893 var EventedTokenizer = /** @class */ (function () {
8894 function EventedTokenizer(delegate, entityParser) {
8895 this.delegate = delegate;
8896 this.entityParser = entityParser;
8897 this.state = "beforeData" /* beforeData */;
8898 this.line = -1;
8899 this.column = -1;
8900 this.input = '';
8901 this.index = -1;
8902 this.tagNameBuffer = '';
8903 this.states = {
8904 beforeData: function () {
8905 var char = this.peek();
8906 if (char === '<') {
8907 this.transitionTo("tagOpen" /* tagOpen */);
8908 this.markTagStart();
8909 this.consume();
8910 }
8911 else {
8912 if (char === '\n') {
8913 var tag = this.tagNameBuffer.toLowerCase();
8914 if (tag === 'pre' || tag === 'textarea') {
8915 this.consume();
8916 }
8917 }
8918 this.transitionTo("data" /* data */);
8919 this.delegate.beginData();
8920 }
8921 },
8922 data: function () {
8923 var char = this.peek();
8924 if (char === '<') {
8925 this.delegate.finishData();
8926 this.transitionTo("tagOpen" /* tagOpen */);
8927 this.markTagStart();
8928 this.consume();
8929 }
8930 else if (char === '&') {
8931 this.consume();
8932 this.delegate.appendToData(this.consumeCharRef() || '&');
8933 }
8934 else {
8935 this.consume();
8936 this.delegate.appendToData(char);
8937 }
8938 },
8939 tagOpen: function () {
8940 var char = this.consume();
8941 if (char === '!') {
8942 this.transitionTo("markupDeclarationOpen" /* markupDeclarationOpen */);
8943 }
8944 else if (char === '/') {
8945 this.transitionTo("endTagOpen" /* endTagOpen */);
8946 }
8947 else if (char === '@' || char === ':' || isAlpha(char)) {
8948 this.transitionTo("tagName" /* tagName */);
8949 this.tagNameBuffer = '';
8950 this.delegate.beginStartTag();
8951 this.appendToTagName(char);
8952 }
8953 },
8954 markupDeclarationOpen: function () {
8955 var char = this.consume();
8956 if (char === '-' && this.input.charAt(this.index) === '-') {
8957 this.consume();
8958 this.transitionTo("commentStart" /* commentStart */);
8959 this.delegate.beginComment();
8960 }
8961 },
8962 commentStart: function () {
8963 var char = this.consume();
8964 if (char === '-') {
8965 this.transitionTo("commentStartDash" /* commentStartDash */);
8966 }
8967 else if (char === '>') {
8968 this.delegate.finishComment();
8969 this.transitionTo("beforeData" /* beforeData */);
8970 }
8971 else {
8972 this.delegate.appendToCommentData(char);
8973 this.transitionTo("comment" /* comment */);
8974 }
8975 },
8976 commentStartDash: function () {
8977 var char = this.consume();
8978 if (char === '-') {
8979 this.transitionTo("commentEnd" /* commentEnd */);
8980 }
8981 else if (char === '>') {
8982 this.delegate.finishComment();
8983 this.transitionTo("beforeData" /* beforeData */);
8984 }
8985 else {
8986 this.delegate.appendToCommentData('-');
8987 this.transitionTo("comment" /* comment */);
8988 }
8989 },
8990 comment: function () {
8991 var char = this.consume();
8992 if (char === '-') {
8993 this.transitionTo("commentEndDash" /* commentEndDash */);
8994 }
8995 else {
8996 this.delegate.appendToCommentData(char);
8997 }
8998 },
8999 commentEndDash: function () {
9000 var char = this.consume();
9001 if (char === '-') {
9002 this.transitionTo("commentEnd" /* commentEnd */);
9003 }
9004 else {
9005 this.delegate.appendToCommentData('-' + char);
9006 this.transitionTo("comment" /* comment */);
9007 }
9008 },
9009 commentEnd: function () {
9010 var char = this.consume();
9011 if (char === '>') {
9012 this.delegate.finishComment();
9013 this.transitionTo("beforeData" /* beforeData */);
9014 }
9015 else {
9016 this.delegate.appendToCommentData('--' + char);
9017 this.transitionTo("comment" /* comment */);
9018 }
9019 },
9020 tagName: function () {
9021 var char = this.consume();
9022 if (isSpace(char)) {
9023 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
9024 }
9025 else if (char === '/') {
9026 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9027 }
9028 else if (char === '>') {
9029 this.delegate.finishTag();
9030 this.transitionTo("beforeData" /* beforeData */);
9031 }
9032 else {
9033 this.appendToTagName(char);
9034 }
9035 },
9036 beforeAttributeName: function () {
9037 var char = this.peek();
9038 if (isSpace(char)) {
9039 this.consume();
9040 return;
9041 }
9042 else if (char === '/') {
9043 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9044 this.consume();
9045 }
9046 else if (char === '>') {
9047 this.consume();
9048 this.delegate.finishTag();
9049 this.transitionTo("beforeData" /* beforeData */);
9050 }
9051 else if (char === '=') {
9052 this.delegate.reportSyntaxError('attribute name cannot start with equals sign');
9053 this.transitionTo("attributeName" /* attributeName */);
9054 this.delegate.beginAttribute();
9055 this.consume();
9056 this.delegate.appendToAttributeName(char);
9057 }
9058 else {
9059 this.transitionTo("attributeName" /* attributeName */);
9060 this.delegate.beginAttribute();
9061 }
9062 },
9063 attributeName: function () {
9064 var char = this.peek();
9065 if (isSpace(char)) {
9066 this.transitionTo("afterAttributeName" /* afterAttributeName */);
9067 this.consume();
9068 }
9069 else if (char === '/') {
9070 this.delegate.beginAttributeValue(false);
9071 this.delegate.finishAttributeValue();
9072 this.consume();
9073 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9074 }
9075 else if (char === '=') {
9076 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
9077 this.consume();
9078 }
9079 else if (char === '>') {
9080 this.delegate.beginAttributeValue(false);
9081 this.delegate.finishAttributeValue();
9082 this.consume();
9083 this.delegate.finishTag();
9084 this.transitionTo("beforeData" /* beforeData */);
9085 }
9086 else if (char === '"' || char === "'" || char === '<') {
9087 this.delegate.reportSyntaxError(char + ' is not a valid character within attribute names');
9088 this.consume();
9089 this.delegate.appendToAttributeName(char);
9090 }
9091 else {
9092 this.consume();
9093 this.delegate.appendToAttributeName(char);
9094 }
9095 },
9096 afterAttributeName: function () {
9097 var char = this.peek();
9098 if (isSpace(char)) {
9099 this.consume();
9100 return;
9101 }
9102 else if (char === '/') {
9103 this.delegate.beginAttributeValue(false);
9104 this.delegate.finishAttributeValue();
9105 this.consume();
9106 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9107 }
9108 else if (char === '=') {
9109 this.consume();
9110 this.transitionTo("beforeAttributeValue" /* beforeAttributeValue */);
9111 }
9112 else if (char === '>') {
9113 this.delegate.beginAttributeValue(false);
9114 this.delegate.finishAttributeValue();
9115 this.consume();
9116 this.delegate.finishTag();
9117 this.transitionTo("beforeData" /* beforeData */);
9118 }
9119 else {
9120 this.delegate.beginAttributeValue(false);
9121 this.delegate.finishAttributeValue();
9122 this.transitionTo("attributeName" /* attributeName */);
9123 this.delegate.beginAttribute();
9124 this.consume();
9125 this.delegate.appendToAttributeName(char);
9126 }
9127 },
9128 beforeAttributeValue: function () {
9129 var char = this.peek();
9130 if (isSpace(char)) {
9131 this.consume();
9132 }
9133 else if (char === '"') {
9134 this.transitionTo("attributeValueDoubleQuoted" /* attributeValueDoubleQuoted */);
9135 this.delegate.beginAttributeValue(true);
9136 this.consume();
9137 }
9138 else if (char === "'") {
9139 this.transitionTo("attributeValueSingleQuoted" /* attributeValueSingleQuoted */);
9140 this.delegate.beginAttributeValue(true);
9141 this.consume();
9142 }
9143 else if (char === '>') {
9144 this.delegate.beginAttributeValue(false);
9145 this.delegate.finishAttributeValue();
9146 this.consume();
9147 this.delegate.finishTag();
9148 this.transitionTo("beforeData" /* beforeData */);
9149 }
9150 else {
9151 this.transitionTo("attributeValueUnquoted" /* attributeValueUnquoted */);
9152 this.delegate.beginAttributeValue(false);
9153 this.consume();
9154 this.delegate.appendToAttributeValue(char);
9155 }
9156 },
9157 attributeValueDoubleQuoted: function () {
9158 var char = this.consume();
9159 if (char === '"') {
9160 this.delegate.finishAttributeValue();
9161 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
9162 }
9163 else if (char === '&') {
9164 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
9165 }
9166 else {
9167 this.delegate.appendToAttributeValue(char);
9168 }
9169 },
9170 attributeValueSingleQuoted: function () {
9171 var char = this.consume();
9172 if (char === "'") {
9173 this.delegate.finishAttributeValue();
9174 this.transitionTo("afterAttributeValueQuoted" /* afterAttributeValueQuoted */);
9175 }
9176 else if (char === '&') {
9177 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
9178 }
9179 else {
9180 this.delegate.appendToAttributeValue(char);
9181 }
9182 },
9183 attributeValueUnquoted: function () {
9184 var char = this.peek();
9185 if (isSpace(char)) {
9186 this.delegate.finishAttributeValue();
9187 this.consume();
9188 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
9189 }
9190 else if (char === '/') {
9191 this.delegate.finishAttributeValue();
9192 this.consume();
9193 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9194 }
9195 else if (char === '&') {
9196 this.consume();
9197 this.delegate.appendToAttributeValue(this.consumeCharRef() || '&');
9198 }
9199 else if (char === '>') {
9200 this.delegate.finishAttributeValue();
9201 this.consume();
9202 this.delegate.finishTag();
9203 this.transitionTo("beforeData" /* beforeData */);
9204 }
9205 else {
9206 this.consume();
9207 this.delegate.appendToAttributeValue(char);
9208 }
9209 },
9210 afterAttributeValueQuoted: function () {
9211 var char = this.peek();
9212 if (isSpace(char)) {
9213 this.consume();
9214 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
9215 }
9216 else if (char === '/') {
9217 this.consume();
9218 this.transitionTo("selfClosingStartTag" /* selfClosingStartTag */);
9219 }
9220 else if (char === '>') {
9221 this.consume();
9222 this.delegate.finishTag();
9223 this.transitionTo("beforeData" /* beforeData */);
9224 }
9225 else {
9226 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
9227 }
9228 },
9229 selfClosingStartTag: function () {
9230 var char = this.peek();
9231 if (char === '>') {
9232 this.consume();
9233 this.delegate.markTagAsSelfClosing();
9234 this.delegate.finishTag();
9235 this.transitionTo("beforeData" /* beforeData */);
9236 }
9237 else {
9238 this.transitionTo("beforeAttributeName" /* beforeAttributeName */);
9239 }
9240 },
9241 endTagOpen: function () {
9242 var char = this.consume();
9243 if (char === '@' || char === ':' || isAlpha(char)) {
9244 this.transitionTo("tagName" /* tagName */);
9245 this.tagNameBuffer = '';
9246 this.delegate.beginEndTag();
9247 this.appendToTagName(char);
9248 }
9249 }
9250 };
9251 this.reset();
9252 }
9253 EventedTokenizer.prototype.reset = function () {
9254 this.transitionTo("beforeData" /* beforeData */);
9255 this.input = '';
9256 this.index = 0;
9257 this.line = 1;
9258 this.column = 0;
9259 this.delegate.reset();
9260 };
9261 EventedTokenizer.prototype.transitionTo = function (state) {
9262 this.state = state;
9263 };
9264 EventedTokenizer.prototype.tokenize = function (input) {
9265 this.reset();
9266 this.tokenizePart(input);
9267 this.tokenizeEOF();
9268 };
9269 EventedTokenizer.prototype.tokenizePart = function (input) {
9270 this.input += preprocessInput(input);
9271 while (this.index < this.input.length) {
9272 var handler = this.states[this.state];
9273 if (handler !== undefined) {
9274 handler.call(this);
9275 }
9276 else {
9277 throw new Error("unhandled state " + this.state);
9278 }
9279 }
9280 };
9281 EventedTokenizer.prototype.tokenizeEOF = function () {
9282 this.flushData();
9283 };
9284 EventedTokenizer.prototype.flushData = function () {
9285 if (this.state === 'data') {
9286 this.delegate.finishData();
9287 this.transitionTo("beforeData" /* beforeData */);
9288 }
9289 };
9290 EventedTokenizer.prototype.peek = function () {
9291 return this.input.charAt(this.index);
9292 };
9293 EventedTokenizer.prototype.consume = function () {
9294 var char = this.peek();
9295 this.index++;
9296 if (char === '\n') {
9297 this.line++;
9298 this.column = 0;
9299 }
9300 else {
9301 this.column++;
9302 }
9303 return char;
9304 };
9305 EventedTokenizer.prototype.consumeCharRef = function () {
9306 var endIndex = this.input.indexOf(';', this.index);
9307 if (endIndex === -1) {
9308 return;
9309 }
9310 var entity = this.input.slice(this.index, endIndex);
9311 var chars = this.entityParser.parse(entity);
9312 if (chars) {
9313 var count = entity.length;
9314 // consume the entity chars
9315 while (count) {
9316 this.consume();
9317 count--;
9318 }
9319 // consume the `;`
9320 this.consume();
9321 return chars;
9322 }
9323 };
9324 EventedTokenizer.prototype.markTagStart = function () {
9325 this.delegate.tagOpen();
9326 };
9327 EventedTokenizer.prototype.appendToTagName = function (char) {
9328 this.tagNameBuffer += char;
9329 this.delegate.appendToTagName(char);
9330 };
9331 return EventedTokenizer;
9332 }());
9333
9334 var Tokenizer = /** @class */ (function () {
9335 function Tokenizer(entityParser, options) {
9336 if (options === void 0) { options = {}; }
9337 this.options = options;
9338 this.token = null;
9339 this.startLine = 1;
9340 this.startColumn = 0;
9341 this.tokens = [];
9342 this.tokenizer = new EventedTokenizer(this, entityParser);
9343 this._currentAttribute = undefined;
9344 }
9345 Tokenizer.prototype.tokenize = function (input) {
9346 this.tokens = [];
9347 this.tokenizer.tokenize(input);
9348 return this.tokens;
9349 };
9350 Tokenizer.prototype.tokenizePart = function (input) {
9351 this.tokens = [];
9352 this.tokenizer.tokenizePart(input);
9353 return this.tokens;
9354 };
9355 Tokenizer.prototype.tokenizeEOF = function () {
9356 this.tokens = [];
9357 this.tokenizer.tokenizeEOF();
9358 return this.tokens[0];
9359 };
9360 Tokenizer.prototype.reset = function () {
9361 this.token = null;
9362 this.startLine = 1;
9363 this.startColumn = 0;
9364 };
9365 Tokenizer.prototype.current = function () {
9366 var token = this.token;
9367 if (token === null) {
9368 throw new Error('token was unexpectedly null');
9369 }
9370 if (arguments.length === 0) {
9371 return token;
9372 }
9373 for (var i = 0; i < arguments.length; i++) {
9374 if (token.type === arguments[i]) {
9375 return token;
9376 }
9377 }
9378 throw new Error("token type was unexpectedly " + token.type);
9379 };
9380 Tokenizer.prototype.push = function (token) {
9381 this.token = token;
9382 this.tokens.push(token);
9383 };
9384 Tokenizer.prototype.currentAttribute = function () {
9385 return this._currentAttribute;
9386 };
9387 Tokenizer.prototype.addLocInfo = function () {
9388 if (this.options.loc) {
9389 this.current().loc = {
9390 start: {
9391 line: this.startLine,
9392 column: this.startColumn
9393 },
9394 end: {
9395 line: this.tokenizer.line,
9396 column: this.tokenizer.column
9397 }
9398 };
9399 }
9400 this.startLine = this.tokenizer.line;
9401 this.startColumn = this.tokenizer.column;
9402 };
9403 // Data
9404 Tokenizer.prototype.beginData = function () {
9405 this.push({
9406 type: "Chars" /* Chars */,
9407 chars: ''
9408 });
9409 };
9410 Tokenizer.prototype.appendToData = function (char) {
9411 this.current("Chars" /* Chars */).chars += char;
9412 };
9413 Tokenizer.prototype.finishData = function () {
9414 this.addLocInfo();
9415 };
9416 // Comment
9417 Tokenizer.prototype.beginComment = function () {
9418 this.push({
9419 type: "Comment" /* Comment */,
9420 chars: ''
9421 });
9422 };
9423 Tokenizer.prototype.appendToCommentData = function (char) {
9424 this.current("Comment" /* Comment */).chars += char;
9425 };
9426 Tokenizer.prototype.finishComment = function () {
9427 this.addLocInfo();
9428 };
9429 // Tags - basic
9430 Tokenizer.prototype.tagOpen = function () { };
9431 Tokenizer.prototype.beginStartTag = function () {
9432 this.push({
9433 type: "StartTag" /* StartTag */,
9434 tagName: '',
9435 attributes: [],
9436 selfClosing: false
9437 });
9438 };
9439 Tokenizer.prototype.beginEndTag = function () {
9440 this.push({
9441 type: "EndTag" /* EndTag */,
9442 tagName: ''
9443 });
9444 };
9445 Tokenizer.prototype.finishTag = function () {
9446 this.addLocInfo();
9447 };
9448 Tokenizer.prototype.markTagAsSelfClosing = function () {
9449 this.current("StartTag" /* StartTag */).selfClosing = true;
9450 };
9451 // Tags - name
9452 Tokenizer.prototype.appendToTagName = function (char) {
9453 this.current("StartTag" /* StartTag */, "EndTag" /* EndTag */).tagName += char;
9454 };
9455 // Tags - attributes
9456 Tokenizer.prototype.beginAttribute = function () {
9457 this._currentAttribute = ['', '', false];
9458 };
9459 Tokenizer.prototype.appendToAttributeName = function (char) {
9460 this.currentAttribute()[0] += char;
9461 };
9462 Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
9463 this.currentAttribute()[2] = isQuoted;
9464 };
9465 Tokenizer.prototype.appendToAttributeValue = function (char) {
9466 this.currentAttribute()[1] += char;
9467 };
9468 Tokenizer.prototype.finishAttributeValue = function () {
9469 this.current("StartTag" /* StartTag */).attributes.push(this._currentAttribute);
9470 };
9471 Tokenizer.prototype.reportSyntaxError = function (message) {
9472 this.current().syntaxError = message;
9473 };
9474 return Tokenizer;
9475 }());
9476
9477 function tokenize(input, options) {
9478 var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);
9479 return tokenizer.tokenize(input);
9480 }
9481
9482
9483
9484 ;// CONCATENATED MODULE: external ["wp","deprecated"]
9485 var external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
9486 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
9487 ;// CONCATENATED MODULE: external ["wp","htmlEntities"]
9488 var external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
9489 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/logger.js
9490 /**
9491 * @typedef LoggerItem
9492 * @property {Function} log Which logger recorded the message
9493 * @property {Array<any>} args White arguments were supplied to the logger
9494 */
9495 function createLogger() {
9496 /**
9497 * Creates a log handler with block validation prefix.
9498 *
9499 * @param {Function} logger Original logger function.
9500 *
9501 * @return {Function} Augmented logger function.
9502 */
9503 function createLogHandler(logger) {
9504 let log = function (message) {
9505 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
9506 args[_key - 1] = arguments[_key];
9507 }
9508
9509 return logger('Block validation: ' + message, ...args);
9510 }; // In test environments, pre-process string substitutions to improve
9511 // readability of error messages. We'd prefer to avoid pulling in this
9512 // dependency in runtime environments, and it can be dropped by a combo
9513 // of Webpack env substitution + UglifyJS dead code elimination.
9514
9515
9516 if (false) {}
9517
9518 return log;
9519 }
9520
9521 return {
9522 // eslint-disable-next-line no-console
9523 error: createLogHandler(console.error),
9524 // eslint-disable-next-line no-console
9525 warning: createLogHandler(console.warn),
9526
9527 getItems() {
9528 return [];
9529 }
9530
9531 };
9532 }
9533 function createQueuedLogger() {
9534 /**
9535 * The list of enqueued log actions to print.
9536 *
9537 * @type {Array<LoggerItem>}
9538 */
9539 const queue = [];
9540 const logger = createLogger();
9541 return {
9542 error() {
9543 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
9544 args[_key2] = arguments[_key2];
9545 }
9546
9547 queue.push({
9548 log: logger.error,
9549 args
9550 });
9551 },
9552
9553 warning() {
9554 for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
9555 args[_key3] = arguments[_key3];
9556 }
9557
9558 queue.push({
9559 log: logger.warning,
9560 args
9561 });
9562 },
9563
9564 getItems() {
9565 return queue;
9566 }
9567
9568 };
9569 }
9570
9571 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/validation/index.js
9572 /**
9573 * External dependencies
9574 */
9575
9576
9577 /**
9578 * WordPress dependencies
9579 */
9580
9581
9582
9583 /**
9584 * Internal dependencies
9585 */
9586
9587
9588
9589
9590
9591 /** @typedef {import('../parser').WPBlock} WPBlock */
9592
9593 /** @typedef {import('../registration').WPBlockType} WPBlockType */
9594
9595 /** @typedef {import('./logger').LoggerItem} LoggerItem */
9596
9597 /**
9598 * Globally matches any consecutive whitespace
9599 *
9600 * @type {RegExp}
9601 */
9602
9603 const REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
9604 /**
9605 * Matches a string containing only whitespace
9606 *
9607 * @type {RegExp}
9608 */
9609
9610 const REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
9611 /**
9612 * Matches a CSS URL type value
9613 *
9614 * @type {RegExp}
9615 */
9616
9617 const REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
9618 /**
9619 * Boolean attributes are attributes whose presence as being assigned is
9620 * meaningful, even if only empty.
9621 *
9622 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
9623 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
9624 *
9625 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
9626 * .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
9627 * .reduce( ( result, tr ) => Object.assign( result, {
9628 * [ tr.firstChild.textContent.trim() ]: true
9629 * } ), {} ) ).sort();
9630 *
9631 * @type {Array}
9632 */
9633
9634 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'];
9635 /**
9636 * Enumerated attributes are attributes which must be of a specific value form.
9637 * Like boolean attributes, these are meaningful if specified, even if not of a
9638 * valid enumerated value.
9639 *
9640 * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
9641 * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
9642 *
9643 * Object.keys( Array.from( document.querySelectorAll( '#attributes-1 > tbody > tr' ) )
9644 * .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
9645 * .reduce( ( result, tr ) => Object.assign( result, {
9646 * [ tr.firstChild.textContent.trim() ]: true
9647 * } ), {} ) ).sort();
9648 *
9649 * @type {Array}
9650 */
9651
9652 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'];
9653 /**
9654 * Meaningful attributes are those who cannot be safely ignored when omitted in
9655 * one HTML markup string and not another.
9656 *
9657 * @type {Array}
9658 */
9659
9660 const MEANINGFUL_ATTRIBUTES = [...BOOLEAN_ATTRIBUTES, ...ENUMERATED_ATTRIBUTES];
9661 /**
9662 * Array of functions which receive a text string on which to apply normalizing
9663 * behavior for consideration in text token equivalence, carefully ordered from
9664 * least-to-most expensive operations.
9665 *
9666 * @type {Array}
9667 */
9668
9669 const TEXT_NORMALIZATIONS = [external_lodash_namespaceObject.identity, getTextWithCollapsedWhitespace];
9670 /**
9671 * Regular expression matching a named character reference. In lieu of bundling
9672 * a full set of references, the pattern covers the minimal necessary to test
9673 * positively against the full set.
9674 *
9675 * "The ampersand must be followed by one of the names given in the named
9676 * character references section, using the same case."
9677 *
9678 * Tested aginst "12.5 Named character references":
9679 *
9680 * ```
9681 * const references = Array.from( document.querySelectorAll(
9682 * '#named-character-references-table tr[id^=entity-] td:first-child'
9683 * ) ).map( ( code ) => code.textContent )
9684 * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
9685 * ```
9686 *
9687 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
9688 * @see https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
9689 *
9690 * @type {RegExp}
9691 */
9692
9693 const REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
9694 /**
9695 * Regular expression matching a decimal character reference.
9696 *
9697 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
9698 * followed by one or more ASCII digits, representing a base-ten integer"
9699 *
9700 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
9701 *
9702 * @type {RegExp}
9703 */
9704
9705 const REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
9706 /**
9707 * Regular expression matching a hexadecimal character reference.
9708 *
9709 * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
9710 * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
9711 * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
9712 * one or more ASCII hex digits, representing a hexadecimal integer"
9713 *
9714 * @see https://html.spec.whatwg.org/multipage/syntax.html#character-references
9715 *
9716 * @type {RegExp}
9717 */
9718
9719 const REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
9720 /**
9721 * Returns true if the given string is a valid character reference segment, or
9722 * false otherwise. The text should be stripped of `&` and `;` demarcations.
9723 *
9724 * @param {string} text Text to test.
9725 *
9726 * @return {boolean} Whether text is valid character reference.
9727 */
9728
9729 function isValidCharacterReference(text) {
9730 return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
9731 }
9732 /**
9733 * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
9734 * implementation of `decodeEntities` from `html-entities`, in order to avoid
9735 * bundling a massive named character reference.
9736 *
9737 * @see https://github.com/tildeio/simple-html-tokenizer/tree/HEAD/src/entity-parser.ts
9738 */
9739
9740 class DecodeEntityParser {
9741 /**
9742 * Returns a substitute string for an entity string sequence between `&`
9743 * and `;`, or undefined if no substitution should occur.
9744 *
9745 * @param {string} entity Entity fragment discovered in HTML.
9746 *
9747 * @return {?string} Entity substitute value.
9748 */
9749 parse(entity) {
9750 if (isValidCharacterReference(entity)) {
9751 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)('&' + entity + ';');
9752 }
9753 }
9754
9755 }
9756 /**
9757 * Given a specified string, returns an array of strings split by consecutive
9758 * whitespace, ignoring leading or trailing whitespace.
9759 *
9760 * @param {string} text Original text.
9761 *
9762 * @return {string[]} Text pieces split on whitespace.
9763 */
9764
9765 function getTextPiecesSplitOnWhitespace(text) {
9766 return text.trim().split(REGEXP_WHITESPACE);
9767 }
9768 /**
9769 * Given a specified string, returns a new trimmed string where all consecutive
9770 * whitespace is collapsed to a single space.
9771 *
9772 * @param {string} text Original text.
9773 *
9774 * @return {string} Trimmed text with consecutive whitespace collapsed.
9775 */
9776
9777 function getTextWithCollapsedWhitespace(text) {
9778 // This is an overly simplified whitespace comparison. The specification is
9779 // more prescriptive of whitespace behavior in inline and block contexts.
9780 //
9781 // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
9782 return getTextPiecesSplitOnWhitespace(text).join(' ');
9783 }
9784 /**
9785 * Returns attribute pairs of the given StartTag token, including only pairs
9786 * where the value is non-empty or the attribute is a boolean attribute, an
9787 * enumerated attribute, or a custom data- attribute.
9788 *
9789 * @see MEANINGFUL_ATTRIBUTES
9790 *
9791 * @param {Object} token StartTag token.
9792 *
9793 * @return {Array[]} Attribute pairs.
9794 */
9795
9796 function getMeaningfulAttributePairs(token) {
9797 return token.attributes.filter(pair => {
9798 const [key, value] = pair;
9799 return value || key.indexOf('data-') === 0 || (0,external_lodash_namespaceObject.includes)(MEANINGFUL_ATTRIBUTES, key);
9800 });
9801 }
9802 /**
9803 * Returns true if two text tokens (with `chars` property) are equivalent, or
9804 * false otherwise.
9805 *
9806 * @param {Object} actual Actual token.
9807 * @param {Object} expected Expected token.
9808 * @param {Object} logger Validation logger object.
9809 *
9810 * @return {boolean} Whether two text tokens are equivalent.
9811 */
9812
9813 function isEquivalentTextTokens(actual, expected) {
9814 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
9815 // This function is intentionally written as syntactically "ugly" as a hot
9816 // path optimization. Text is progressively normalized in order from least-
9817 // to-most operationally expensive, until the earliest point at which text
9818 // can be confidently inferred as being equal.
9819 let actualChars = actual.chars;
9820 let expectedChars = expected.chars;
9821
9822 for (let i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
9823 const normalize = TEXT_NORMALIZATIONS[i];
9824 actualChars = normalize(actualChars);
9825 expectedChars = normalize(expectedChars);
9826
9827 if (actualChars === expectedChars) {
9828 return true;
9829 }
9830 }
9831
9832 logger.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
9833 return false;
9834 }
9835 /**
9836 * Given a CSS length value, returns a normalized CSS length value for strict equality
9837 * comparison.
9838 *
9839 * @param {string} value CSS length value.
9840 *
9841 * @return {string} Normalized CSS length value.
9842 */
9843
9844 function getNormalizedLength(value) {
9845 if (0 === parseFloat(value)) {
9846 return '0';
9847 } // Normalize strings with floats to always include a leading zero.
9848
9849
9850 if (value.indexOf('.') === 0) {
9851 return '0' + value;
9852 }
9853
9854 return value;
9855 }
9856 /**
9857 * Given a style value, returns a normalized style value for strict equality
9858 * comparison.
9859 *
9860 * @param {string} value Style value.
9861 *
9862 * @return {string} Normalized style value.
9863 */
9864
9865 function getNormalizedStyleValue(value) {
9866 const textPieces = getTextPiecesSplitOnWhitespace(value);
9867 const normalizedPieces = textPieces.map(getNormalizedLength);
9868 const result = normalizedPieces.join(' ');
9869 return result // Normalize URL type to omit whitespace or quotes.
9870 .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
9871 }
9872 /**
9873 * Given a style attribute string, returns an object of style properties.
9874 *
9875 * @param {string} text Style attribute.
9876 *
9877 * @return {Object} Style properties.
9878 */
9879
9880 function getStyleProperties(text) {
9881 const pairs = text // Trim ending semicolon (avoid including in split)
9882 .replace(/;?\s*$/, '') // Split on property assignment.
9883 .split(';') // For each property assignment...
9884 .map(style => {
9885 // ...split further into key-value pairs.
9886 const [key, ...valueParts] = style.split(':');
9887 const value = valueParts.join(':');
9888 return [key.trim(), getNormalizedStyleValue(value.trim())];
9889 });
9890 return (0,external_lodash_namespaceObject.fromPairs)(pairs);
9891 }
9892 /**
9893 * Attribute-specific equality handlers
9894 *
9895 * @type {Object}
9896 */
9897
9898 const isEqualAttributesOfName = {
9899 class: (actual, expected) => {
9900 // Class matches if members are the same, even if out of order or
9901 // superfluous whitespace between.
9902 return !(0,external_lodash_namespaceObject.xor)(...[actual, expected].map(getTextPiecesSplitOnWhitespace)).length;
9903 },
9904 style: (actual, expected) => {
9905 return (0,external_lodash_namespaceObject.isEqual)(...[actual, expected].map(getStyleProperties));
9906 },
9907 // For each boolean attribute, mere presence of attribute in both is enough
9908 // to assume equivalence.
9909 ...(0,external_lodash_namespaceObject.fromPairs)(BOOLEAN_ATTRIBUTES.map(attribute => [attribute, external_lodash_namespaceObject.stubTrue]))
9910 };
9911 /**
9912 * Given two sets of attribute tuples, returns true if the attribute sets are
9913 * equivalent.
9914 *
9915 * @param {Array[]} actual Actual attributes tuples.
9916 * @param {Array[]} expected Expected attributes tuples.
9917 * @param {Object} logger Validation logger object.
9918 *
9919 * @return {boolean} Whether attributes are equivalent.
9920 */
9921
9922 function isEqualTagAttributePairs(actual, expected) {
9923 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
9924
9925 // Attributes is tokenized as tuples. Their lengths should match. This also
9926 // avoids us needing to check both attributes sets, since if A has any keys
9927 // which do not exist in B, we know the sets to be different.
9928 if (actual.length !== expected.length) {
9929 logger.warning('Expected attributes %o, instead saw %o.', expected, actual);
9930 return false;
9931 } // Attributes are not guaranteed to occur in the same order. For validating
9932 // actual attributes, first convert the set of expected attribute values to
9933 // an object, for lookup by key.
9934
9935
9936 const expectedAttributes = {};
9937
9938 for (let i = 0; i < expected.length; i++) {
9939 expectedAttributes[expected[i][0].toLowerCase()] = expected[i][1];
9940 }
9941
9942 for (let i = 0; i < actual.length; i++) {
9943 const [name, actualValue] = actual[i];
9944 const nameLower = name.toLowerCase(); // As noted above, if missing member in B, assume different.
9945
9946 if (!expectedAttributes.hasOwnProperty(nameLower)) {
9947 logger.warning('Encountered unexpected attribute `%s`.', name);
9948 return false;
9949 }
9950
9951 const expectedValue = expectedAttributes[nameLower];
9952 const isEqualAttributes = isEqualAttributesOfName[nameLower];
9953
9954 if (isEqualAttributes) {
9955 // Defer custom attribute equality handling.
9956 if (!isEqualAttributes(actualValue, expectedValue)) {
9957 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
9958 return false;
9959 }
9960 } else if (actualValue !== expectedValue) {
9961 // Otherwise strict inequality should bail.
9962 logger.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
9963 return false;
9964 }
9965 }
9966
9967 return true;
9968 }
9969 /**
9970 * Token-type-specific equality handlers
9971 *
9972 * @type {Object}
9973 */
9974
9975 const isEqualTokensOfType = {
9976 StartTag: function (actual, expected) {
9977 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
9978
9979 if (actual.tagName !== expected.tagName && // Optimization: Use short-circuit evaluation to defer case-
9980 // insensitive check on the assumption that the majority case will
9981 // have exactly equal tag names.
9982 actual.tagName.toLowerCase() !== expected.tagName.toLowerCase()) {
9983 logger.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
9984 return false;
9985 }
9986
9987 return isEqualTagAttributePairs(...[actual, expected].map(getMeaningfulAttributePairs), logger);
9988 },
9989 Chars: isEquivalentTextTokens,
9990 Comment: isEquivalentTextTokens
9991 };
9992 /**
9993 * Given an array of tokens, returns the first token which is not purely
9994 * whitespace.
9995 *
9996 * Mutates the tokens array.
9997 *
9998 * @param {Object[]} tokens Set of tokens to search.
9999 *
10000 * @return {Object} Next non-whitespace token.
10001 */
10002
10003 function getNextNonWhitespaceToken(tokens) {
10004 let token;
10005
10006 while (token = tokens.shift()) {
10007 if (token.type !== 'Chars') {
10008 return token;
10009 }
10010
10011 if (!REGEXP_ONLY_WHITESPACE.test(token.chars)) {
10012 return token;
10013 }
10014 }
10015 }
10016 /**
10017 * Tokenize an HTML string, gracefully handling any errors thrown during
10018 * underlying tokenization.
10019 *
10020 * @param {string} html HTML string to tokenize.
10021 * @param {Object} logger Validation logger object.
10022 *
10023 * @return {Object[]|null} Array of valid tokenized HTML elements, or null on error
10024 */
10025
10026 function getHTMLTokens(html) {
10027 let logger = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : createLogger();
10028
10029 try {
10030 return new Tokenizer(new DecodeEntityParser()).tokenize(html);
10031 } catch (e) {
10032 logger.warning('Malformed HTML detected: %s', html);
10033 }
10034
10035 return null;
10036 }
10037 /**
10038 * Returns true if the next HTML token closes the current token.
10039 *
10040 * @param {Object} currentToken Current token to compare with.
10041 * @param {Object|undefined} nextToken Next token to compare against.
10042 *
10043 * @return {boolean} true if `nextToken` closes `currentToken`, false otherwise
10044 */
10045
10046
10047 function isClosedByToken(currentToken, nextToken) {
10048 // Ensure this is a self closed token.
10049 if (!currentToken.selfClosing) {
10050 return false;
10051 } // Check token names and determine if nextToken is the closing tag for currentToken.
10052
10053
10054 if (nextToken && nextToken.tagName === currentToken.tagName && nextToken.type === 'EndTag') {
10055 return true;
10056 }
10057
10058 return false;
10059 }
10060 /**
10061 * Returns true if the given HTML strings are effectively equivalent, or
10062 * false otherwise. Invalid HTML is not considered equivalent, even if the
10063 * strings directly match.
10064 *
10065 * @param {string} actual Actual HTML string.
10066 * @param {string} expected Expected HTML string.
10067 * @param {Object} logger Validation logger object.
10068 *
10069 * @return {boolean} Whether HTML strings are equivalent.
10070 */
10071
10072 function isEquivalentHTML(actual, expected) {
10073 let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : createLogger();
10074
10075 // Short-circuit if markup is identical.
10076 if (actual === expected) {
10077 return true;
10078 } // Tokenize input content and reserialized save content.
10079
10080
10081 const [actualTokens, expectedTokens] = [actual, expected].map(html => getHTMLTokens(html, logger)); // If either is malformed then stop comparing - the strings are not equivalent.
10082
10083 if (!actualTokens || !expectedTokens) {
10084 return false;
10085 }
10086
10087 let actualToken, expectedToken;
10088
10089 while (actualToken = getNextNonWhitespaceToken(actualTokens)) {
10090 expectedToken = getNextNonWhitespaceToken(expectedTokens); // Inequal if exhausted all expected tokens.
10091
10092 if (!expectedToken) {
10093 logger.warning('Expected end of content, instead saw %o.', actualToken);
10094 return false;
10095 } // Inequal if next non-whitespace token of each set are not same type.
10096
10097
10098 if (actualToken.type !== expectedToken.type) {
10099 logger.warning('Expected token of type `%s` (%o), instead saw `%s` (%o).', expectedToken.type, expectedToken, actualToken.type, actualToken);
10100 return false;
10101 } // Defer custom token type equality handling, otherwise continue and
10102 // assume as equal.
10103
10104
10105 const isEqualTokens = isEqualTokensOfType[actualToken.type];
10106
10107 if (isEqualTokens && !isEqualTokens(actualToken, expectedToken, logger)) {
10108 return false;
10109 } // Peek at the next tokens (actual and expected) to see if they close
10110 // a self-closing tag.
10111
10112
10113 if (isClosedByToken(actualToken, expectedTokens[0])) {
10114 // Consume the next expected token that closes the current actual
10115 // self-closing token.
10116 getNextNonWhitespaceToken(expectedTokens);
10117 } else if (isClosedByToken(expectedToken, actualTokens[0])) {
10118 // Consume the next actual token that closes the current expected
10119 // self-closing token.
10120 getNextNonWhitespaceToken(actualTokens);
10121 }
10122 }
10123
10124 if (expectedToken = getNextNonWhitespaceToken(expectedTokens)) {
10125 // If any non-whitespace tokens remain in expected token set, this
10126 // indicates inequality.
10127 logger.warning('Expected %o, instead saw end of content.', expectedToken);
10128 return false;
10129 }
10130
10131 return true;
10132 }
10133 /**
10134 * Returns an object with `isValid` property set to `true` if the parsed block
10135 * is valid given the input content. A block is considered valid if, when serialized
10136 * with assumed attributes, the content matches the original value. If block is
10137 * invalid, this function returns all validations issues as well.
10138 *
10139 * @param {string|Object} blockTypeOrName Block type.
10140 * @param {Object} attributes Parsed block attributes.
10141 * @param {string} originalBlockContent Original block content.
10142 * @param {Object} logger Validation logger object.
10143 *
10144 * @return {Object} Whether block is valid and contains validation messages.
10145 */
10146
10147 /**
10148 * Returns an object with `isValid` property set to `true` if the parsed block
10149 * is valid given the input content. A block is considered valid if, when serialized
10150 * with assumed attributes, the content matches the original value. If block is
10151 * invalid, this function returns all validations issues as well.
10152 *
10153 * @param {WPBlock} block block object.
10154 * @param {WPBlockType|string} [blockTypeOrName = block.name] Block type or name, inferred from block if not given.
10155 *
10156 * @return {[boolean,Array<LoggerItem>]} validation results.
10157 */
10158
10159 function validateBlock(block) {
10160 let blockTypeOrName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : block.name;
10161 const isFallbackBlock = block.name === getFreeformContentHandlerName() || block.name === getUnregisteredTypeHandlerName(); // Shortcut to avoid costly validation.
10162
10163 if (isFallbackBlock) {
10164 return [true, []];
10165 }
10166
10167 const logger = createQueuedLogger();
10168 const blockType = normalizeBlockType(blockTypeOrName);
10169 let generatedBlockContent;
10170
10171 try {
10172 generatedBlockContent = getSaveContent(blockType, block.attributes);
10173 } catch (error) {
10174 logger.error('Block validation failed because an error occurred while generating block content:\n\n%s', error.toString());
10175 return [false, logger.getItems()];
10176 }
10177
10178 const isValid = isEquivalentHTML(block.originalContent, generatedBlockContent, logger);
10179
10180 if (!isValid) {
10181 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);
10182 }
10183
10184 return [isValid, logger.getItems()];
10185 }
10186 /**
10187 * Returns true if the parsed block is valid given the input content. A block
10188 * is considered valid if, when serialized with assumed attributes, the content
10189 * matches the original value.
10190 *
10191 * Logs to console in development environments when invalid.
10192 *
10193 * @deprecated Use validateBlock instead to avoid data loss.
10194 *
10195 * @param {string|Object} blockTypeOrName Block type.
10196 * @param {Object} attributes Parsed block attributes.
10197 * @param {string} originalBlockContent Original block content.
10198 *
10199 * @return {boolean} Whether block is valid.
10200 */
10201
10202 function isValidBlockContent(blockTypeOrName, attributes, originalBlockContent) {
10203 external_wp_deprecated_default()('isValidBlockContent introduces opportunity for data loss', {
10204 since: '12.6',
10205 plugin: 'Gutenberg',
10206 alternative: 'validateBlock'
10207 });
10208 const blockType = normalizeBlockType(blockTypeOrName);
10209 const block = {
10210 name: blockType.name,
10211 attributes,
10212 innerBlocks: [],
10213 originalContent: originalBlockContent
10214 };
10215 const [isValid] = validateBlock(block, blockType);
10216 return isValid;
10217 }
10218
10219 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/convert-legacy-block.js
10220 /**
10221 * Convert legacy blocks to their canonical form. This function is used
10222 * both in the parser level for previous content and to convert such blocks
10223 * used in Custom Post Types templates.
10224 *
10225 * @param {string} name The block's name
10226 * @param {Object} attributes The block's attributes
10227 *
10228 * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found
10229 */
10230 function convertLegacyBlockNameAndAttributes(name, attributes) {
10231 const newAttributes = { ...attributes
10232 }; // Convert 'core/cover-image' block in existing content to 'core/cover'.
10233
10234 if ('core/cover-image' === name) {
10235 name = 'core/cover';
10236 } // Convert 'core/text' blocks in existing content to 'core/paragraph'.
10237
10238
10239 if ('core/text' === name || 'core/cover-text' === name) {
10240 name = 'core/paragraph';
10241 } // Convert derivative blocks such as 'core/social-link-wordpress' to the
10242 // canonical form 'core/social-link'.
10243
10244
10245 if (name && name.indexOf('core/social-link-') === 0) {
10246 // Capture `social-link-wordpress` into `{"service":"wordpress"}`
10247 newAttributes.service = name.substring(17);
10248 name = 'core/social-link';
10249 } // Convert derivative blocks such as 'core-embed/instagram' to the
10250 // canonical form 'core/embed'.
10251
10252
10253 if (name && name.indexOf('core-embed/') === 0) {
10254 // Capture `core-embed/instagram` into `{"providerNameSlug":"instagram"}`
10255 const providerSlug = name.substring(11);
10256 const deprecated = {
10257 speaker: 'speaker-deck',
10258 polldaddy: 'crowdsignal'
10259 };
10260 newAttributes.providerNameSlug = providerSlug in deprecated ? deprecated[providerSlug] : providerSlug; // This is needed as the `responsive` attribute was passed
10261 // in a different way before the refactoring to block variations.
10262
10263 if (!['amazon-kindle', 'wordpress'].includes(providerSlug)) {
10264 newAttributes.responsive = true;
10265 }
10266
10267 name = 'core/embed';
10268 } // Convert 'core/query-loop' blocks in existing content to 'core/post-template'.
10269 // TODO: Remove this check when WordPress 5.9 is released.
10270
10271
10272 if (name === 'core/query-loop') {
10273 name = 'core/post-template';
10274 } // Convert Post Comment blocks in existing content to Comment blocks.
10275 // TODO: Remove these checks when WordPress 6.0 is released.
10276
10277
10278 if (name === 'core/post-comment-author') {
10279 name = 'core/comment-author-name';
10280 }
10281
10282 if (name === 'core/post-comment-content') {
10283 name = 'core/comment-content';
10284 }
10285
10286 if (name === 'core/post-comment-date') {
10287 name = 'core/comment-date';
10288 }
10289
10290 return [name, newAttributes];
10291 }
10292
10293 ;// CONCATENATED MODULE: ./node_modules/hpq/es/get-path.js
10294 /**
10295 * Given object and string of dot-delimited path segments, returns value at
10296 * path or undefined if path cannot be resolved.
10297 *
10298 * @param {Object} object Lookup object
10299 * @param {string} path Path to resolve
10300 * @return {?*} Resolved value
10301 */
10302 function getPath(object, path) {
10303 var segments = path.split('.');
10304 var segment;
10305
10306 while (segment = segments.shift()) {
10307 if (!(segment in object)) {
10308 return;
10309 }
10310
10311 object = object[segment];
10312 }
10313
10314 return object;
10315 }
10316 ;// CONCATENATED MODULE: ./node_modules/hpq/es/index.js
10317 /**
10318 * Internal dependencies
10319 */
10320
10321 /**
10322 * Function returning a DOM document created by `createHTMLDocument`. The same
10323 * document is returned between invocations.
10324 *
10325 * @return {Document} DOM document.
10326 */
10327
10328 var getDocument = function () {
10329 var doc;
10330 return function () {
10331 if (!doc) {
10332 doc = document.implementation.createHTMLDocument('');
10333 }
10334
10335 return doc;
10336 };
10337 }();
10338 /**
10339 * Given a markup string or DOM element, creates an object aligning with the
10340 * shape of the matchers object, or the value returned by the matcher.
10341 *
10342 * @param {(string|Element)} source Source content
10343 * @param {(Object|Function)} matchers Matcher function or object of matchers
10344 * @return {(Object|*)} Matched value(s), shaped by object
10345 */
10346
10347
10348 function parse(source, matchers) {
10349 if (!matchers) {
10350 return;
10351 } // Coerce to element
10352
10353
10354 if ('string' === typeof source) {
10355 var doc = getDocument();
10356 doc.body.innerHTML = source;
10357 source = doc.body;
10358 } // Return singular value
10359
10360
10361 if ('function' === typeof matchers) {
10362 return matchers(source);
10363 } // Bail if we can't handle matchers
10364
10365
10366 if (Object !== matchers.constructor) {
10367 return;
10368 } // Shape result by matcher object
10369
10370
10371 return Object.keys(matchers).reduce(function (memo, key) {
10372 memo[key] = parse(source, matchers[key]);
10373 return memo;
10374 }, {});
10375 }
10376 /**
10377 * Generates a function which matches node of type selector, returning an
10378 * attribute by property if the attribute exists. If no selector is passed,
10379 * returns property of the query element.
10380 *
10381 * @param {?string} selector Optional selector
10382 * @param {string} name Property name
10383 * @return {*} Property value
10384 */
10385
10386 function prop(selector, name) {
10387 if (1 === arguments.length) {
10388 name = selector;
10389 selector = undefined;
10390 }
10391
10392 return function (node) {
10393 var match = node;
10394
10395 if (selector) {
10396 match = node.querySelector(selector);
10397 }
10398
10399 if (match) {
10400 return getPath(match, name);
10401 }
10402 };
10403 }
10404 /**
10405 * Generates a function which matches node of type selector, returning an
10406 * attribute by name if the attribute exists. If no selector is passed,
10407 * returns attribute of the query element.
10408 *
10409 * @param {?string} selector Optional selector
10410 * @param {string} name Attribute name
10411 * @return {?string} Attribute value
10412 */
10413
10414 function attr(selector, name) {
10415 if (1 === arguments.length) {
10416 name = selector;
10417 selector = undefined;
10418 }
10419
10420 return function (node) {
10421 var attributes = prop(selector, 'attributes')(node);
10422
10423 if (attributes && attributes.hasOwnProperty(name)) {
10424 return attributes[name].value;
10425 }
10426 };
10427 }
10428 /**
10429 * Convenience for `prop( selector, 'innerHTML' )`.
10430 *
10431 * @see prop()
10432 *
10433 * @param {?string} selector Optional selector
10434 * @return {string} Inner HTML
10435 */
10436
10437 function html(selector) {
10438 return prop(selector, 'innerHTML');
10439 }
10440 /**
10441 * Convenience for `prop( selector, 'textContent' )`.
10442 *
10443 * @see prop()
10444 *
10445 * @param {?string} selector Optional selector
10446 * @return {string} Text content
10447 */
10448
10449 function es_text(selector) {
10450 return prop(selector, 'textContent');
10451 }
10452 /**
10453 * Creates a new matching context by first finding elements matching selector
10454 * using querySelectorAll before then running another `parse` on `matchers`
10455 * scoped to the matched elements.
10456 *
10457 * @see parse()
10458 *
10459 * @param {string} selector Selector to match
10460 * @param {(Object|Function)} matchers Matcher function or object of matchers
10461 * @return {Array.<*,Object>} Array of matched value(s)
10462 */
10463
10464 function query(selector, matchers) {
10465 return function (node) {
10466 var matches = node.querySelectorAll(selector);
10467 return [].map.call(matches, function (match) {
10468 return parse(match, matchers);
10469 });
10470 };
10471 }
10472 // EXTERNAL MODULE: ./node_modules/memize/index.js
10473 var memize = __webpack_require__(9756);
10474 var memize_default = /*#__PURE__*/__webpack_require__.n(memize);
10475 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/matchers.js
10476 /**
10477 * External dependencies
10478 */
10479
10480 /**
10481 * Internal dependencies
10482 */
10483
10484
10485
10486 function matchers_html(selector, multilineTag) {
10487 return domNode => {
10488 let match = domNode;
10489
10490 if (selector) {
10491 match = domNode.querySelector(selector);
10492 }
10493
10494 if (!match) {
10495 return '';
10496 }
10497
10498 if (multilineTag) {
10499 let value = '';
10500 const length = match.children.length;
10501
10502 for (let index = 0; index < length; index++) {
10503 const child = match.children[index];
10504
10505 if (child.nodeName.toLowerCase() !== multilineTag) {
10506 continue;
10507 }
10508
10509 value += child.outerHTML;
10510 }
10511
10512 return value;
10513 }
10514
10515 return match.innerHTML;
10516 };
10517 }
10518
10519 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/node.js
10520 /**
10521 * Internal dependencies
10522 */
10523
10524 /**
10525 * A representation of a single node within a block's rich text value. If
10526 * representing a text node, the value is simply a string of the node value.
10527 * As representing an element node, it is an object of:
10528 *
10529 * 1. `type` (string): Tag name.
10530 * 2. `props` (object): Attributes and children array of WPBlockNode.
10531 *
10532 * @typedef {string|Object} WPBlockNode
10533 */
10534
10535 /**
10536 * Given a single node and a node type (e.g. `'br'`), returns true if the node
10537 * corresponds to that type, false otherwise.
10538 *
10539 * @param {WPBlockNode} node Block node to test
10540 * @param {string} type Node to type to test against.
10541 *
10542 * @return {boolean} Whether node is of intended type.
10543 */
10544
10545 function isNodeOfType(node, type) {
10546 return node && node.type === type;
10547 }
10548 /**
10549 * Given an object implementing the NamedNodeMap interface, returns a plain
10550 * object equivalent value of name, value key-value pairs.
10551 *
10552 * @see https://dom.spec.whatwg.org/#interface-namednodemap
10553 *
10554 * @param {NamedNodeMap} nodeMap NamedNodeMap to convert to object.
10555 *
10556 * @return {Object} Object equivalent value of NamedNodeMap.
10557 */
10558
10559
10560 function getNamedNodeMapAsObject(nodeMap) {
10561 const result = {};
10562
10563 for (let i = 0; i < nodeMap.length; i++) {
10564 const {
10565 name,
10566 value
10567 } = nodeMap[i];
10568 result[name] = value;
10569 }
10570
10571 return result;
10572 }
10573 /**
10574 * Given a DOM Element or Text node, returns an equivalent block node. Throws
10575 * if passed any node type other than element or text.
10576 *
10577 * @throws {TypeError} If non-element/text node is passed.
10578 *
10579 * @param {Node} domNode DOM node to convert.
10580 *
10581 * @return {WPBlockNode} Block node equivalent to DOM node.
10582 */
10583
10584 function fromDOM(domNode) {
10585 if (domNode.nodeType === domNode.TEXT_NODE) {
10586 return domNode.nodeValue;
10587 }
10588
10589 if (domNode.nodeType !== domNode.ELEMENT_NODE) {
10590 throw new TypeError('A block node can only be created from a node of type text or ' + 'element.');
10591 }
10592
10593 return {
10594 type: domNode.nodeName.toLowerCase(),
10595 props: { ...getNamedNodeMapAsObject(domNode.attributes),
10596 children: children_fromDOM(domNode.childNodes)
10597 }
10598 };
10599 }
10600 /**
10601 * Given a block node, returns its HTML string representation.
10602 *
10603 * @param {WPBlockNode} node Block node to convert to string.
10604 *
10605 * @return {string} String HTML representation of block node.
10606 */
10607
10608 function toHTML(node) {
10609 return children_toHTML([node]);
10610 }
10611 /**
10612 * Given a selector, returns an hpq matcher generating a WPBlockNode value
10613 * matching the selector result.
10614 *
10615 * @param {string} selector DOM selector.
10616 *
10617 * @return {Function} hpq matcher.
10618 */
10619
10620 function node_matcher(selector) {
10621 return domNode => {
10622 let match = domNode;
10623
10624 if (selector) {
10625 match = domNode.querySelector(selector);
10626 }
10627
10628 try {
10629 return fromDOM(match);
10630 } catch (error) {
10631 return null;
10632 }
10633 };
10634 }
10635 /**
10636 * Object of utility functions used in managing block attribute values of
10637 * source `node`.
10638 *
10639 * @see https://github.com/WordPress/gutenberg/pull/10439
10640 *
10641 * @deprecated since 4.0. The `node` source should not be used, and can be
10642 * replaced by the `html` source.
10643 *
10644 * @private
10645 */
10646
10647 /* harmony default export */ var node = ({
10648 isNodeOfType,
10649 fromDOM,
10650 toHTML,
10651 matcher: node_matcher
10652 });
10653
10654 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/children.js
10655 /**
10656 * External dependencies
10657 */
10658
10659 /**
10660 * WordPress dependencies
10661 */
10662
10663
10664 /**
10665 * Internal dependencies
10666 */
10667
10668
10669 /**
10670 * A representation of a block's rich text value.
10671 *
10672 * @typedef {WPBlockNode[]} WPBlockChildren
10673 */
10674
10675 /**
10676 * Given block children, returns a serialize-capable WordPress element.
10677 *
10678 * @param {WPBlockChildren} children Block children object to convert.
10679 *
10680 * @return {WPElement} A serialize-capable element.
10681 */
10682
10683 function getSerializeCapableElement(children) {
10684 // The fact that block children are compatible with the element serializer is
10685 // merely an implementation detail that currently serves to be true, but
10686 // should not be mistaken as being a guarantee on the external API. The
10687 // public API only offers guarantees to work with strings (toHTML) and DOM
10688 // elements (fromDOM), and should provide utilities to manipulate the value
10689 // rather than expect consumers to inspect or construct its shape (concat).
10690 return children;
10691 }
10692 /**
10693 * Given block children, returns an array of block nodes.
10694 *
10695 * @param {WPBlockChildren} children Block children object to convert.
10696 *
10697 * @return {Array<WPBlockNode>} An array of individual block nodes.
10698 */
10699
10700 function getChildrenArray(children) {
10701 // The fact that block children are compatible with the element serializer
10702 // is merely an implementation detail that currently serves to be true, but
10703 // should not be mistaken as being a guarantee on the external API.
10704 return children;
10705 }
10706 /**
10707 * Given two or more block nodes, returns a new block node representing a
10708 * concatenation of its values.
10709 *
10710 * @param {...WPBlockChildren} blockNodes Block nodes to concatenate.
10711 *
10712 * @return {WPBlockChildren} Concatenated block node.
10713 */
10714
10715
10716 function concat() {
10717 const result = [];
10718
10719 for (let i = 0; i < arguments.length; i++) {
10720 const blockNode = (0,external_lodash_namespaceObject.castArray)(i < 0 || arguments.length <= i ? undefined : arguments[i]);
10721
10722 for (let j = 0; j < blockNode.length; j++) {
10723 const child = blockNode[j];
10724 const canConcatToPreviousString = typeof child === 'string' && typeof result[result.length - 1] === 'string';
10725
10726 if (canConcatToPreviousString) {
10727 result[result.length - 1] += child;
10728 } else {
10729 result.push(child);
10730 }
10731 }
10732 }
10733
10734 return result;
10735 }
10736 /**
10737 * Given an iterable set of DOM nodes, returns equivalent block children.
10738 * Ignores any non-element/text nodes included in set.
10739 *
10740 * @param {Iterable.<Node>} domNodes Iterable set of DOM nodes to convert.
10741 *
10742 * @return {WPBlockChildren} Block children equivalent to DOM nodes.
10743 */
10744
10745 function children_fromDOM(domNodes) {
10746 const result = [];
10747
10748 for (let i = 0; i < domNodes.length; i++) {
10749 try {
10750 result.push(fromDOM(domNodes[i]));
10751 } catch (error) {// Simply ignore if DOM node could not be converted.
10752 }
10753 }
10754
10755 return result;
10756 }
10757 /**
10758 * Given a block node, returns its HTML string representation.
10759 *
10760 * @param {WPBlockChildren} children Block node(s) to convert to string.
10761 *
10762 * @return {string} String HTML representation of block node.
10763 */
10764
10765 function children_toHTML(children) {
10766 const element = getSerializeCapableElement(children);
10767 return (0,external_wp_element_namespaceObject.renderToString)(element);
10768 }
10769 /**
10770 * Given a selector, returns an hpq matcher generating a WPBlockChildren value
10771 * matching the selector result.
10772 *
10773 * @param {string} selector DOM selector.
10774 *
10775 * @return {Function} hpq matcher.
10776 */
10777
10778 function children_matcher(selector) {
10779 return domNode => {
10780 let match = domNode;
10781
10782 if (selector) {
10783 match = domNode.querySelector(selector);
10784 }
10785
10786 if (match) {
10787 return children_fromDOM(match.childNodes);
10788 }
10789
10790 return [];
10791 };
10792 }
10793 /**
10794 * Object of utility functions used in managing block attribute values of
10795 * source `children`.
10796 *
10797 * @see https://github.com/WordPress/gutenberg/pull/10439
10798 *
10799 * @deprecated since 4.0. The `children` source should not be used, and can be
10800 * replaced by the `html` source.
10801 *
10802 * @private
10803 */
10804
10805 /* harmony default export */ var children = ({
10806 concat,
10807 getChildrenArray,
10808 fromDOM: children_fromDOM,
10809 toHTML: children_toHTML,
10810 matcher: children_matcher
10811 });
10812
10813 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/get-block-attributes.js
10814 /**
10815 * External dependencies
10816 */
10817
10818
10819
10820 /**
10821 * WordPress dependencies
10822 */
10823
10824
10825 /**
10826 * Internal dependencies
10827 */
10828
10829
10830
10831 /**
10832 * Higher-order hpq matcher which enhances an attribute matcher to return true
10833 * or false depending on whether the original matcher returns undefined. This
10834 * is useful for boolean attributes (e.g. disabled) whose attribute values may
10835 * be technically falsey (empty string), though their mere presence should be
10836 * enough to infer as true.
10837 *
10838 * @param {Function} matcher Original hpq matcher.
10839 *
10840 * @return {Function} Enhanced hpq matcher.
10841 */
10842
10843 const toBooleanAttributeMatcher = matcher => (0,external_lodash_namespaceObject.flow)([matcher, // Expected values from `attr( 'disabled' )`:
10844 //
10845 // <input>
10846 // - Value: `undefined`
10847 // - Transformed: `false`
10848 //
10849 // <input disabled>
10850 // - Value: `''`
10851 // - Transformed: `true`
10852 //
10853 // <input disabled="disabled">
10854 // - Value: `'disabled'`
10855 // - Transformed: `true`
10856 value => value !== undefined]);
10857 /**
10858 * Returns true if value is of the given JSON schema type, or false otherwise.
10859 *
10860 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
10861 *
10862 * @param {*} value Value to test.
10863 * @param {string} type Type to test.
10864 *
10865 * @return {boolean} Whether value is of type.
10866 */
10867
10868 function isOfType(value, type) {
10869 switch (type) {
10870 case 'string':
10871 return typeof value === 'string';
10872
10873 case 'boolean':
10874 return typeof value === 'boolean';
10875
10876 case 'object':
10877 return !!value && value.constructor === Object;
10878
10879 case 'null':
10880 return value === null;
10881
10882 case 'array':
10883 return Array.isArray(value);
10884
10885 case 'integer':
10886 case 'number':
10887 return typeof value === 'number';
10888 }
10889
10890 return true;
10891 }
10892 /**
10893 * Returns true if value is of an array of given JSON schema types, or false
10894 * otherwise.
10895 *
10896 * @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25
10897 *
10898 * @param {*} value Value to test.
10899 * @param {string[]} types Types to test.
10900 *
10901 * @return {boolean} Whether value is of types.
10902 */
10903
10904 function isOfTypes(value, types) {
10905 return types.some(type => isOfType(value, type));
10906 }
10907 /**
10908 * Given an attribute key, an attribute's schema, a block's raw content and the
10909 * commentAttributes returns the attribute value depending on its source
10910 * definition of the given attribute key.
10911 *
10912 * @param {string} attributeKey Attribute key.
10913 * @param {Object} attributeSchema Attribute's schema.
10914 * @param {string|Node} innerHTML Block's raw content.
10915 * @param {Object} commentAttributes Block's comment attributes.
10916 *
10917 * @return {*} Attribute value.
10918 */
10919
10920 function getBlockAttribute(attributeKey, attributeSchema, innerHTML, commentAttributes) {
10921 let value;
10922
10923 switch (attributeSchema.source) {
10924 // An undefined source means that it's an attribute serialized to the
10925 // block's "comment".
10926 case undefined:
10927 value = commentAttributes ? commentAttributes[attributeKey] : undefined;
10928 break;
10929
10930 case 'attribute':
10931 case 'property':
10932 case 'html':
10933 case 'text':
10934 case 'children':
10935 case 'node':
10936 case 'query':
10937 case 'tag':
10938 value = parseWithAttributeSchema(innerHTML, attributeSchema);
10939 break;
10940 }
10941
10942 if (!isValidByType(value, attributeSchema.type) || !isValidByEnum(value, attributeSchema.enum)) {
10943 // Reject the value if it is not valid. Reverting to the undefined
10944 // value ensures the default is respected, if applicable.
10945 value = undefined;
10946 }
10947
10948 if (value === undefined) {
10949 value = attributeSchema.default;
10950 }
10951
10952 return value;
10953 }
10954 /**
10955 * Returns true if value is valid per the given block attribute schema type
10956 * definition, or false otherwise.
10957 *
10958 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1
10959 *
10960 * @param {*} value Value to test.
10961 * @param {?(Array<string>|string)} type Block attribute schema type.
10962 *
10963 * @return {boolean} Whether value is valid.
10964 */
10965
10966 function isValidByType(value, type) {
10967 return type === undefined || isOfTypes(value, (0,external_lodash_namespaceObject.castArray)(type));
10968 }
10969 /**
10970 * Returns true if value is valid per the given block attribute schema enum
10971 * definition, or false otherwise.
10972 *
10973 * @see https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2
10974 *
10975 * @param {*} value Value to test.
10976 * @param {?Array} enumSet Block attribute schema enum.
10977 *
10978 * @return {boolean} Whether value is valid.
10979 */
10980
10981 function isValidByEnum(value, enumSet) {
10982 return !Array.isArray(enumSet) || enumSet.includes(value);
10983 }
10984 /**
10985 * Returns an hpq matcher given a source object.
10986 *
10987 * @param {Object} sourceConfig Attribute Source object.
10988 *
10989 * @return {Function} A hpq Matcher.
10990 */
10991
10992 const matcherFromSource = memize_default()(sourceConfig => {
10993 switch (sourceConfig.source) {
10994 case 'attribute':
10995 let matcher = attr(sourceConfig.selector, sourceConfig.attribute);
10996
10997 if (sourceConfig.type === 'boolean') {
10998 matcher = toBooleanAttributeMatcher(matcher);
10999 }
11000
11001 return matcher;
11002
11003 case 'html':
11004 return matchers_html(sourceConfig.selector, sourceConfig.multiline);
11005
11006 case 'text':
11007 return es_text(sourceConfig.selector);
11008
11009 case 'children':
11010 return children_matcher(sourceConfig.selector);
11011
11012 case 'node':
11013 return node_matcher(sourceConfig.selector);
11014
11015 case 'query':
11016 const subMatchers = (0,external_lodash_namespaceObject.mapValues)(sourceConfig.query, matcherFromSource);
11017 return query(sourceConfig.selector, subMatchers);
11018
11019 case 'tag':
11020 return (0,external_lodash_namespaceObject.flow)([prop(sourceConfig.selector, 'nodeName'), nodeName => nodeName ? nodeName.toLowerCase() : undefined]);
11021
11022 default:
11023 // eslint-disable-next-line no-console
11024 console.error(`Unknown source type "${sourceConfig.source}"`);
11025 }
11026 });
11027 /**
11028 * Parse a HTML string into DOM tree.
11029 *
11030 * @param {string|Node} innerHTML HTML string or already parsed DOM node.
11031 *
11032 * @return {Node} Parsed DOM node.
11033 */
11034
11035 function parseHtml(innerHTML) {
11036 return parse(innerHTML, h => h);
11037 }
11038 /**
11039 * Given a block's raw content and an attribute's schema returns the attribute's
11040 * value depending on its source.
11041 *
11042 * @param {string|Node} innerHTML Block's raw content.
11043 * @param {Object} attributeSchema Attribute's schema.
11044 *
11045 * @return {*} Attribute value.
11046 */
11047
11048
11049 function parseWithAttributeSchema(innerHTML, attributeSchema) {
11050 return matcherFromSource(attributeSchema)(parseHtml(innerHTML));
11051 }
11052 /**
11053 * Returns the block attributes of a registered block node given its type.
11054 *
11055 * @param {string|Object} blockTypeOrName Block type or name.
11056 * @param {string|Node} innerHTML Raw block content.
11057 * @param {?Object} attributes Known block attributes (from delimiters).
11058 *
11059 * @return {Object} All block attributes.
11060 */
11061
11062 function getBlockAttributes(blockTypeOrName, innerHTML) {
11063 let attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
11064 const doc = parseHtml(innerHTML);
11065 const blockType = normalizeBlockType(blockTypeOrName);
11066 const blockAttributes = (0,external_lodash_namespaceObject.mapValues)(blockType.attributes, (schema, key) => getBlockAttribute(key, schema, doc, attributes));
11067 return (0,external_wp_hooks_namespaceObject.applyFilters)('blocks.getBlockAttributes', blockAttributes, blockType, innerHTML, attributes);
11068 }
11069
11070 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/fix-custom-classname.js
11071 /**
11072 * External dependencies
11073 */
11074
11075 /**
11076 * Internal dependencies
11077 */
11078
11079
11080
11081
11082 const CLASS_ATTR_SCHEMA = {
11083 type: 'string',
11084 source: 'attribute',
11085 selector: '[data-custom-class-name] > *',
11086 attribute: 'class'
11087 };
11088 /**
11089 * Given an HTML string, returns an array of class names assigned to the root
11090 * element in the markup.
11091 *
11092 * @param {string} innerHTML Markup string from which to extract classes.
11093 *
11094 * @return {string[]} Array of class names assigned to the root element.
11095 */
11096
11097 function getHTMLRootElementClasses(innerHTML) {
11098 const parsed = parseWithAttributeSchema(`<div data-custom-class-name>${innerHTML}</div>`, CLASS_ATTR_SCHEMA);
11099 return parsed ? parsed.trim().split(/\s+/) : [];
11100 }
11101 /**
11102 * Given a parsed set of block attributes, if the block supports custom class
11103 * names and an unknown class (per the block's serialization behavior) is
11104 * found, the unknown classes are treated as custom classes. This prevents the
11105 * block from being considered as invalid.
11106 *
11107 * @param {Object} blockAttributes Original block attributes.
11108 * @param {Object} blockType Block type settings.
11109 * @param {string} innerHTML Original block markup.
11110 *
11111 * @return {Object} Filtered block attributes.
11112 */
11113
11114 function fixCustomClassname(blockAttributes, blockType, innerHTML) {
11115 if (registration_hasBlockSupport(blockType, 'customClassName', true)) {
11116 // To determine difference, serialize block given the known set of
11117 // attributes, with the exception of `className`. This will determine
11118 // the default set of classes. From there, any difference in innerHTML
11119 // can be considered as custom classes.
11120 const attributesSansClassName = (0,external_lodash_namespaceObject.omit)(blockAttributes, ['className']);
11121 const serialized = getSaveContent(blockType, attributesSansClassName);
11122 const defaultClasses = getHTMLRootElementClasses(serialized);
11123 const actualClasses = getHTMLRootElementClasses(innerHTML);
11124 const customClasses = (0,external_lodash_namespaceObject.difference)(actualClasses, defaultClasses);
11125
11126 if (customClasses.length) {
11127 blockAttributes.className = customClasses.join(' ');
11128 } else if (serialized) {
11129 delete blockAttributes.className;
11130 }
11131 }
11132
11133 return blockAttributes;
11134 }
11135
11136 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-built-in-validation-fixes.js
11137 /**
11138 * Internal dependencies
11139 */
11140
11141 /**
11142 * Attempts to fix block invalidation by applying build-in validation fixes
11143 * like moving all extra classNames to the className attribute.
11144 *
11145 * @param {WPBlock} block block object.
11146 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
11147 * can be inferred from the block name,
11148 * but it's here for performance reasons.
11149 *
11150 * @return {WPBlock} Fixed block object
11151 */
11152
11153 function applyBuiltInValidationFixes(block, blockType) {
11154 const updatedBlockAttributes = fixCustomClassname(block.attributes, blockType, block.originalContent);
11155 return { ...block,
11156 attributes: updatedBlockAttributes
11157 };
11158 }
11159
11160 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/apply-block-deprecated-versions.js
11161 /**
11162 * External dependencies
11163 */
11164
11165 /**
11166 * Internal dependencies
11167 */
11168
11169
11170
11171
11172
11173 /**
11174 * Given a block object, returns a new copy of the block with any applicable
11175 * deprecated migrations applied, or the original block if it was both valid
11176 * and no eligible migrations exist.
11177 *
11178 * @param {import(".").WPBlock} block Parsed and invalid block object.
11179 * @param {import(".").WPRawBlock} rawBlock Raw block object.
11180 * @param {import('../registration').WPBlockType} blockType Block type. This is normalize not necessary and
11181 * can be inferred from the block name,
11182 * but it's here for performance reasons.
11183 *
11184 * @return {import(".").WPBlock} Migrated block object.
11185 */
11186
11187 function applyBlockDeprecatedVersions(block, rawBlock, blockType) {
11188 const parsedAttributes = rawBlock.attrs;
11189 const {
11190 deprecated: deprecatedDefinitions
11191 } = blockType; // Bail early if there are no registered deprecations to be handled.
11192
11193 if (!deprecatedDefinitions || !deprecatedDefinitions.length) {
11194 return block;
11195 } // By design, blocks lack any sort of version tracking. Instead, to process
11196 // outdated content the system operates a queue out of all the defined
11197 // attribute shapes and tries each definition until the input produces a
11198 // valid result. This mechanism seeks to avoid polluting the user-space with
11199 // machine-specific code. An invalid block is thus a block that could not be
11200 // matched successfully with any of the registered deprecation definitions.
11201
11202
11203 for (let i = 0; i < deprecatedDefinitions.length; i++) {
11204 // A block can opt into a migration even if the block is valid by
11205 // defining `isEligible` on its deprecation. If the block is both valid
11206 // and does not opt to migrate, skip.
11207 const {
11208 isEligible = external_lodash_namespaceObject.stubFalse
11209 } = deprecatedDefinitions[i];
11210
11211 if (block.isValid && !isEligible(parsedAttributes, block.innerBlocks)) {
11212 continue;
11213 } // Block type properties which could impact either serialization or
11214 // parsing are not considered in the deprecated block type by default,
11215 // and must be explicitly provided.
11216
11217
11218 const deprecatedBlockType = Object.assign((0,external_lodash_namespaceObject.omit)(blockType, DEPRECATED_ENTRY_KEYS), deprecatedDefinitions[i]);
11219 let migratedBlock = { ...block,
11220 attributes: getBlockAttributes(deprecatedBlockType, block.originalContent, parsedAttributes)
11221 }; // Ignore the deprecation if it produces a block which is not valid.
11222
11223 let [isValid] = validateBlock(migratedBlock, deprecatedBlockType); // If the migrated block is not valid initially, try the built-in fixes.
11224
11225 if (!isValid) {
11226 migratedBlock = applyBuiltInValidationFixes(migratedBlock, deprecatedBlockType);
11227 [isValid] = validateBlock(migratedBlock, deprecatedBlockType);
11228 } // An invalid block does not imply incorrect HTML but the fact block
11229 // source information could be lost on re-serialization.
11230
11231
11232 if (!isValid) {
11233 continue;
11234 }
11235
11236 let migratedInnerBlocks = migratedBlock.innerBlocks;
11237 let migratedAttributes = migratedBlock.attributes; // A block may provide custom behavior to assign new attributes and/or
11238 // inner blocks.
11239
11240 const {
11241 migrate
11242 } = deprecatedBlockType;
11243
11244 if (migrate) {
11245 [migratedAttributes = parsedAttributes, migratedInnerBlocks = block.innerBlocks] = (0,external_lodash_namespaceObject.castArray)(migrate(migratedAttributes, block.innerBlocks));
11246 }
11247
11248 block = { ...block,
11249 attributes: migratedAttributes,
11250 innerBlocks: migratedInnerBlocks,
11251 isValid: true,
11252 validationIssues: []
11253 };
11254 }
11255
11256 return block;
11257 }
11258
11259 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/parser/index.js
11260 /**
11261 * WordPress dependencies
11262 */
11263
11264
11265 /**
11266 * Internal dependencies
11267 */
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278 /**
11279 * The raw structure of a block includes its attributes, inner
11280 * blocks, and inner HTML. It is important to distinguish inner blocks from
11281 * the HTML content of the block as only the latter is relevant for block
11282 * validation and edit operations.
11283 *
11284 * @typedef WPRawBlock
11285 *
11286 * @property {string=} blockName Block name
11287 * @property {Object=} attrs Block raw or comment attributes.
11288 * @property {string} innerHTML HTML content of the block.
11289 * @property {(string|null)[]} innerContent Content without inner blocks.
11290 * @property {WPRawBlock[]} innerBlocks Inner Blocks.
11291 */
11292
11293 /**
11294 * Fully parsed block object.
11295 *
11296 * @typedef WPBlock
11297 *
11298 * @property {string} name Block name
11299 * @property {Object} attributes Block raw or comment attributes.
11300 * @property {WPBlock[]} innerBlocks Inner Blocks.
11301 * @property {string} originalContent Original content of the block before validation fixes.
11302 * @property {boolean} isValid Whether the block is valid.
11303 * @property {Object[]} validationIssues Validation issues.
11304 * @property {WPRawBlock} [__unstableBlockSource] Un-processed original copy of block if created through parser.
11305 */
11306
11307 /**
11308 * @typedef {Object} ParseOptions
11309 * @property {boolean} __unstableSkipMigrationLogs If a block is migrated from a deprecated version, skip logging the migration details.
11310 */
11311
11312 /**
11313 * Convert legacy blocks to their canonical form. This function is used
11314 * both in the parser level for previous content and to convert such blocks
11315 * used in Custom Post Types templates.
11316 *
11317 * @param {WPRawBlock} rawBlock
11318 *
11319 * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found
11320 */
11321
11322 function convertLegacyBlocks(rawBlock) {
11323 const [correctName, correctedAttributes] = convertLegacyBlockNameAndAttributes(rawBlock.blockName, rawBlock.attrs);
11324 return { ...rawBlock,
11325 blockName: correctName,
11326 attrs: correctedAttributes
11327 };
11328 }
11329 /**
11330 * Normalize the raw block by applying the fallback block name if none given,
11331 * sanitize the parsed HTML...
11332 *
11333 * @param {WPRawBlock} rawBlock The raw block object.
11334 *
11335 * @return {WPRawBlock} The normalized block object.
11336 */
11337
11338
11339 function normalizeRawBlock(rawBlock) {
11340 const fallbackBlockName = getFreeformContentHandlerName(); // If the grammar parsing don't produce any block name, use the freeform block.
11341
11342 const rawBlockName = rawBlock.blockName || getFreeformContentHandlerName();
11343 const rawAttributes = rawBlock.attrs || {};
11344 const rawInnerBlocks = rawBlock.innerBlocks || [];
11345 let rawInnerHTML = rawBlock.innerHTML.trim(); // Fallback content may be upgraded from classic content expecting implicit
11346 // automatic paragraphs, so preserve them. Assumes wpautop is idempotent,
11347 // meaning there are no negative consequences to repeated autop calls.
11348
11349 if (rawBlockName === fallbackBlockName) {
11350 rawInnerHTML = (0,external_wp_autop_namespaceObject.autop)(rawInnerHTML).trim();
11351 }
11352
11353 return { ...rawBlock,
11354 blockName: rawBlockName,
11355 attrs: rawAttributes,
11356 innerHTML: rawInnerHTML,
11357 innerBlocks: rawInnerBlocks
11358 };
11359 }
11360 /**
11361 * Uses the "unregistered blockType" to create a block object.
11362 *
11363 * @param {WPRawBlock} rawBlock block.
11364 *
11365 * @return {WPRawBlock} The unregistered block object.
11366 */
11367
11368 function createMissingBlockType(rawBlock) {
11369 const unregisteredFallbackBlock = getUnregisteredTypeHandlerName() || getFreeformContentHandlerName(); // Preserve undelimited content for use by the unregistered type
11370 // handler. A block node's `innerHTML` isn't enough, as that field only
11371 // carries the block's own HTML and not its nested blocks.
11372
11373 const originalUndelimitedContent = serializeRawBlock(rawBlock, {
11374 isCommentDelimited: false
11375 }); // Preserve full block content for use by the unregistered type
11376 // handler, block boundaries included.
11377
11378 const originalContent = serializeRawBlock(rawBlock, {
11379 isCommentDelimited: true
11380 });
11381 return {
11382 blockName: unregisteredFallbackBlock,
11383 attrs: {
11384 originalName: rawBlock.blockName,
11385 originalContent,
11386 originalUndelimitedContent
11387 },
11388 innerHTML: rawBlock.blockName ? originalContent : rawBlock.innerHTML,
11389 innerBlocks: rawBlock.innerBlocks,
11390 innerContent: rawBlock.innerContent
11391 };
11392 }
11393 /**
11394 * Validates a block and wraps with validation meta.
11395 *
11396 * The name here is regrettable but `validateBlock` is already taken.
11397 *
11398 * @param {WPBlock} unvalidatedBlock
11399 * @param {import('../registration').WPBlockType} blockType
11400 * @return {WPBlock} validated block, with auto-fixes if initially invalid
11401 */
11402
11403
11404 function applyBlockValidation(unvalidatedBlock, blockType) {
11405 // Attempt to validate the block.
11406 const [isValid] = validateBlock(unvalidatedBlock, blockType);
11407
11408 if (isValid) {
11409 return { ...unvalidatedBlock,
11410 isValid,
11411 validationIssues: []
11412 };
11413 } // If the block is invalid, attempt some built-in fixes
11414 // like custom classNames handling.
11415
11416
11417 const fixedBlock = applyBuiltInValidationFixes(unvalidatedBlock, blockType); // Attempt to validate the block once again after the built-in fixes.
11418
11419 const [isFixedValid, validationIssues] = validateBlock(unvalidatedBlock, blockType);
11420 return { ...fixedBlock,
11421 isValid: isFixedValid,
11422 validationIssues
11423 };
11424 }
11425 /**
11426 * Given a raw block returned by grammar parsing, returns a fully parsed block.
11427 *
11428 * @param {WPRawBlock} rawBlock The raw block object.
11429 * @param {ParseOptions} options Extra options for handling block parsing.
11430 *
11431 * @return {WPBlock} Fully parsed block.
11432 */
11433
11434
11435 function parseRawBlock(rawBlock, options) {
11436 let normalizedBlock = normalizeRawBlock(rawBlock); // During the lifecycle of the project, we renamed some old blocks
11437 // and transformed others to new blocks. To avoid breaking existing content,
11438 // we added this function to properly parse the old content.
11439
11440 normalizedBlock = convertLegacyBlocks(normalizedBlock); // Try finding the type for known block name.
11441
11442 let blockType = registration_getBlockType(normalizedBlock.blockName); // If not blockType is found for the specified name, fallback to the "unregistedBlockType".
11443
11444 if (!blockType) {
11445 normalizedBlock = createMissingBlockType(normalizedBlock);
11446 blockType = registration_getBlockType(normalizedBlock.blockName);
11447 } // If it's an empty freeform block or there's no blockType (no missing block handler)
11448 // Then, just ignore the block.
11449 // It might be a good idea to throw a warning here.
11450 // TODO: I'm unsure about the unregisteredFallbackBlock check,
11451 // it might ignore some dynamic unregistered third party blocks wrongly.
11452
11453
11454 const isFallbackBlock = normalizedBlock.blockName === getFreeformContentHandlerName() || normalizedBlock.blockName === getUnregisteredTypeHandlerName();
11455
11456 if (!blockType || !normalizedBlock.innerHTML && isFallbackBlock) {
11457 return;
11458 } // Parse inner blocks recursively.
11459
11460
11461 const parsedInnerBlocks = normalizedBlock.innerBlocks.map(innerBlock => parseRawBlock(innerBlock, options)) // See https://github.com/WordPress/gutenberg/pull/17164.
11462 .filter(innerBlock => !!innerBlock); // Get the fully parsed block.
11463
11464 const parsedBlock = createBlock(normalizedBlock.blockName, getBlockAttributes(blockType, normalizedBlock.innerHTML, normalizedBlock.attrs), parsedInnerBlocks);
11465 parsedBlock.originalContent = normalizedBlock.innerHTML;
11466 const validatedBlock = applyBlockValidation(parsedBlock, blockType);
11467 const {
11468 validationIssues
11469 } = validatedBlock; // Run the block deprecation and migrations.
11470 // This is performed on both invalid and valid blocks because
11471 // migration using the `migrate` functions should run even
11472 // if the output is deemed valid.
11473
11474 const updatedBlock = applyBlockDeprecatedVersions(validatedBlock, normalizedBlock, blockType);
11475
11476 if (!updatedBlock.isValid) {
11477 // Preserve the original unprocessed version of the block
11478 // that we received (no fixes, no deprecations) so that
11479 // we can save it as close to exactly the same way as
11480 // we loaded it. This is important to avoid corruption
11481 // and data loss caused by block implementations trying
11482 // to process data that isn't fully recognized.
11483 updatedBlock.__unstableBlockSource = rawBlock;
11484 }
11485
11486 if (!validatedBlock.isValid && updatedBlock.isValid && !(options !== null && options !== void 0 && options.__unstableSkipMigrationLogs)) {
11487 /* eslint-disable no-console */
11488 console.groupCollapsed('Updated Block: %s', blockType.name);
11489 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);
11490 console.groupEnd();
11491 /* eslint-enable no-console */
11492 } else if (!validatedBlock.isValid && !updatedBlock.isValid) {
11493 validationIssues.forEach(_ref => {
11494 let {
11495 log,
11496 args
11497 } = _ref;
11498 return log(...args);
11499 });
11500 }
11501
11502 return updatedBlock;
11503 }
11504 /**
11505 * Utilizes an optimized token-driven parser based on the Gutenberg grammar spec
11506 * defined through a parsing expression grammar to take advantage of the regular
11507 * cadence provided by block delimiters -- composed syntactically through HTML
11508 * comments -- which, given a general HTML document as an input, returns a block
11509 * list array representation.
11510 *
11511 * This is a recursive-descent parser that scans linearly once through the input
11512 * document. Instead of directly recursing it utilizes a trampoline mechanism to
11513 * prevent stack overflow. This initial pass is mainly interested in separating
11514 * and isolating the blocks serialized in the document and manifestly not in the
11515 * content within the blocks.
11516 *
11517 * @see
11518 * https://developer.wordpress.org/block-editor/packages/packages-block-serialization-default-parser/
11519 *
11520 * @param {string} content The post content.
11521 * @param {ParseOptions} options Extra options for handling block parsing.
11522 *
11523 * @return {Array} Block list.
11524 */
11525
11526 function parser_parse(content, options) {
11527 return (0,external_wp_blockSerializationDefaultParser_namespaceObject.parse)(content).reduce((accumulator, rawBlock) => {
11528 const block = parseRawBlock(rawBlock, options);
11529
11530 if (block) {
11531 accumulator.push(block);
11532 }
11533
11534 return accumulator;
11535 }, []);
11536 }
11537
11538 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/get-raw-transforms.js
11539 /**
11540 * External dependencies
11541 */
11542
11543 /**
11544 * Internal dependencies
11545 */
11546
11547
11548 function getRawTransforms() {
11549 return (0,external_lodash_namespaceObject.filter)(getBlockTransforms('from'), {
11550 type: 'raw'
11551 }).map(transform => {
11552 return transform.isMatch ? transform : { ...transform,
11553 isMatch: node => transform.selector && node.matches(transform.selector)
11554 };
11555 });
11556 }
11557
11558 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-to-blocks.js
11559 /**
11560 * Internal dependencies
11561 */
11562
11563
11564
11565 /**
11566 * Converts HTML directly to blocks. Looks for a matching transform for each
11567 * top-level tag. The HTML should be filtered to not have any text between
11568 * top-level tags and formatted in a way that blocks can handle the HTML.
11569 *
11570 * @param {string} html HTML to convert.
11571 *
11572 * @return {Array} An array of blocks.
11573 */
11574
11575 function htmlToBlocks(html) {
11576 const doc = document.implementation.createHTMLDocument('');
11577 doc.body.innerHTML = html;
11578 return Array.from(doc.body.children).flatMap(node => {
11579 const rawTransform = findTransform(getRawTransforms(), _ref => {
11580 let {
11581 isMatch
11582 } = _ref;
11583 return isMatch(node);
11584 });
11585
11586 if (!rawTransform) {
11587 return createBlock( // Should not be hardcoded.
11588 'core/html', getBlockAttributes('core/html', node.outerHTML));
11589 }
11590
11591 const {
11592 transform,
11593 blockName
11594 } = rawTransform;
11595
11596 if (transform) {
11597 return transform(node);
11598 }
11599
11600 return createBlock(blockName, getBlockAttributes(blockName, node.outerHTML));
11601 });
11602 }
11603
11604 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/normalise-blocks.js
11605 /**
11606 * WordPress dependencies
11607 */
11608
11609 function normaliseBlocks(HTML) {
11610 const decuDoc = document.implementation.createHTMLDocument('');
11611 const accuDoc = document.implementation.createHTMLDocument('');
11612 const decu = decuDoc.body;
11613 const accu = accuDoc.body;
11614 decu.innerHTML = HTML;
11615
11616 while (decu.firstChild) {
11617 const node = decu.firstChild; // Text nodes: wrap in a paragraph, or append to previous.
11618
11619 if (node.nodeType === node.TEXT_NODE) {
11620 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
11621 decu.removeChild(node);
11622 } else {
11623 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
11624 accu.appendChild(accuDoc.createElement('P'));
11625 }
11626
11627 accu.lastChild.appendChild(node);
11628 } // Element nodes.
11629
11630 } else if (node.nodeType === node.ELEMENT_NODE) {
11631 // BR nodes: create a new paragraph on double, or append to previous.
11632 if (node.nodeName === 'BR') {
11633 if (node.nextSibling && node.nextSibling.nodeName === 'BR') {
11634 accu.appendChild(accuDoc.createElement('P'));
11635 decu.removeChild(node.nextSibling);
11636 } // Don't append to an empty paragraph.
11637
11638
11639 if (accu.lastChild && accu.lastChild.nodeName === 'P' && accu.lastChild.hasChildNodes()) {
11640 accu.lastChild.appendChild(node);
11641 } else {
11642 decu.removeChild(node);
11643 }
11644 } else if (node.nodeName === 'P') {
11645 // Only append non-empty paragraph nodes.
11646 if ((0,external_wp_dom_namespaceObject.isEmpty)(node)) {
11647 decu.removeChild(node);
11648 } else {
11649 accu.appendChild(node);
11650 }
11651 } else if ((0,external_wp_dom_namespaceObject.isPhrasingContent)(node)) {
11652 if (!accu.lastChild || accu.lastChild.nodeName !== 'P') {
11653 accu.appendChild(accuDoc.createElement('P'));
11654 }
11655
11656 accu.lastChild.appendChild(node);
11657 } else {
11658 accu.appendChild(node);
11659 }
11660 } else {
11661 decu.removeChild(node);
11662 }
11663 }
11664
11665 return accu.innerHTML;
11666 }
11667
11668 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/special-comment-converter.js
11669 /**
11670 * WordPress dependencies
11671 */
11672
11673 /**
11674 * Looks for `<!--nextpage-->` and `<!--more-->` comments, as well as the
11675 * `<!--more Some text-->` variant and its `<!--noteaser-->` companion,
11676 * and replaces them with a custom element representing a future block.
11677 *
11678 * The custom element is a way to bypass the rest of the `raw-handling`
11679 * transforms, which would eliminate other kinds of node with which to carry
11680 * `<!--more-->`'s data: nodes with `data` attributes, empty paragraphs, etc.
11681 *
11682 * The custom element is then expected to be recognized by any registered
11683 * block's `raw` transform.
11684 *
11685 * @param {Node} node The node to be processed.
11686 * @param {Document} doc The document of the node.
11687 * @return {void}
11688 */
11689
11690 function specialCommentConverter(node, doc) {
11691 if (node.nodeType !== node.COMMENT_NODE) {
11692 return;
11693 }
11694
11695 if (node.nodeValue === 'nextpage') {
11696 (0,external_wp_dom_namespaceObject.replace)(node, createNextpage(doc));
11697 return;
11698 }
11699
11700 if (node.nodeValue.indexOf('more') === 0) {
11701 // Grab any custom text in the comment.
11702 const customText = node.nodeValue.slice(4).trim();
11703 /*
11704 * When a `<!--more-->` comment is found, we need to look for any
11705 * `<!--noteaser-->` sibling, but it may not be a direct sibling
11706 * (whitespace typically lies in between)
11707 */
11708
11709 let sibling = node;
11710 let noTeaser = false;
11711
11712 while (sibling = sibling.nextSibling) {
11713 if (sibling.nodeType === sibling.COMMENT_NODE && sibling.nodeValue === 'noteaser') {
11714 noTeaser = true;
11715 (0,external_wp_dom_namespaceObject.remove)(sibling);
11716 break;
11717 }
11718 }
11719
11720 (0,external_wp_dom_namespaceObject.replace)(node, createMore(customText, noTeaser, doc));
11721 }
11722 }
11723
11724 function createMore(customText, noTeaser, doc) {
11725 const node = doc.createElement('wp-block');
11726 node.dataset.block = 'core/more';
11727
11728 if (customText) {
11729 node.dataset.customText = customText;
11730 }
11731
11732 if (noTeaser) {
11733 // "Boolean" data attribute.
11734 node.dataset.noTeaser = '';
11735 }
11736
11737 return node;
11738 }
11739
11740 function createNextpage(doc) {
11741 const node = doc.createElement('wp-block');
11742 node.dataset.block = 'core/nextpage';
11743 return node;
11744 }
11745
11746 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/list-reducer.js
11747 /**
11748 * WordPress dependencies
11749 */
11750
11751
11752 function isList(node) {
11753 return node.nodeName === 'OL' || node.nodeName === 'UL';
11754 }
11755
11756 function shallowTextContent(element) {
11757 return Array.from(element.childNodes).map(_ref => {
11758 let {
11759 nodeValue = ''
11760 } = _ref;
11761 return nodeValue;
11762 }).join('');
11763 }
11764
11765 function listReducer(node) {
11766 if (!isList(node)) {
11767 return;
11768 }
11769
11770 const list = node;
11771 const prevElement = node.previousElementSibling; // Merge with previous list if:
11772 // * There is a previous list of the same type.
11773 // * There is only one list item.
11774
11775 if (prevElement && prevElement.nodeName === node.nodeName && list.children.length === 1) {
11776 // Move all child nodes, including any text nodes, if any.
11777 while (list.firstChild) {
11778 prevElement.appendChild(list.firstChild);
11779 }
11780
11781 list.parentNode.removeChild(list);
11782 }
11783
11784 const parentElement = node.parentNode; // Nested list with empty parent item.
11785
11786 if (parentElement && parentElement.nodeName === 'LI' && parentElement.children.length === 1 && !/\S/.test(shallowTextContent(parentElement))) {
11787 const parentListItem = parentElement;
11788 const prevListItem = parentListItem.previousElementSibling;
11789 const parentList = parentListItem.parentNode;
11790
11791 if (prevListItem) {
11792 prevListItem.appendChild(list);
11793 parentList.removeChild(parentListItem);
11794 } else {
11795 parentList.parentNode.insertBefore(list, parentList);
11796 parentList.parentNode.removeChild(parentList);
11797 }
11798 } // Invalid: OL/UL > OL/UL.
11799
11800
11801 if (parentElement && isList(parentElement)) {
11802 const prevListItem = node.previousElementSibling;
11803
11804 if (prevListItem) {
11805 prevListItem.appendChild(node);
11806 } else {
11807 (0,external_wp_dom_namespaceObject.unwrap)(node);
11808 }
11809 }
11810 }
11811
11812 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/blockquote-normaliser.js
11813 /**
11814 * Internal dependencies
11815 */
11816
11817 function blockquoteNormaliser(node) {
11818 if (node.nodeName !== 'BLOCKQUOTE') {
11819 return;
11820 }
11821
11822 node.innerHTML = normaliseBlocks(node.innerHTML);
11823 }
11824
11825 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/figure-content-reducer.js
11826 /**
11827 * External dependencies
11828 */
11829
11830 /**
11831 * WordPress dependencies
11832 */
11833
11834
11835 /**
11836 * Whether or not the given node is figure content.
11837 *
11838 * @param {Node} node The node to check.
11839 * @param {Object} schema The schema to use.
11840 *
11841 * @return {boolean} True if figure content, false if not.
11842 */
11843
11844 function isFigureContent(node, schema) {
11845 const tag = node.nodeName.toLowerCase(); // We are looking for tags that can be a child of the figure tag, excluding
11846 // `figcaption` and any phrasing content.
11847
11848 if (tag === 'figcaption' || (0,external_wp_dom_namespaceObject.isTextContent)(node)) {
11849 return false;
11850 }
11851
11852 return (0,external_lodash_namespaceObject.has)(schema, ['figure', 'children', tag]);
11853 }
11854 /**
11855 * Whether or not the given node can have an anchor.
11856 *
11857 * @param {Node} node The node to check.
11858 * @param {Object} schema The schema to use.
11859 *
11860 * @return {boolean} True if it can, false if not.
11861 */
11862
11863
11864 function canHaveAnchor(node, schema) {
11865 const tag = node.nodeName.toLowerCase();
11866 return (0,external_lodash_namespaceObject.has)(schema, ['figure', 'children', 'a', 'children', tag]);
11867 }
11868 /**
11869 * Wraps the given element in a figure element.
11870 *
11871 * @param {Element} element The element to wrap.
11872 * @param {Element} beforeElement The element before which to place the figure.
11873 */
11874
11875
11876 function wrapFigureContent(element) {
11877 let beforeElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element;
11878 const figure = element.ownerDocument.createElement('figure');
11879 beforeElement.parentNode.insertBefore(figure, beforeElement);
11880 figure.appendChild(element);
11881 }
11882 /**
11883 * This filter takes figure content out of paragraphs, wraps it in a figure
11884 * element, and moves any anchors with it if needed.
11885 *
11886 * @param {Node} node The node to filter.
11887 * @param {Document} doc The document of the node.
11888 * @param {Object} schema The schema to use.
11889 *
11890 * @return {void}
11891 */
11892
11893
11894 function figureContentReducer(node, doc, schema) {
11895 if (!isFigureContent(node, schema)) {
11896 return;
11897 }
11898
11899 let nodeToInsert = node;
11900 const parentNode = node.parentNode; // If the figure content can have an anchor and its parent is an anchor with
11901 // only the figure content, take the anchor out instead of just the content.
11902
11903 if (canHaveAnchor(node, schema) && parentNode.nodeName === 'A' && parentNode.childNodes.length === 1) {
11904 nodeToInsert = node.parentNode;
11905 }
11906
11907 const wrapper = nodeToInsert.closest('p,div'); // If wrapped in a paragraph or div, only extract if it's aligned or if
11908 // there is no text content.
11909 // Otherwise, if directly at the root, wrap in a figure element.
11910
11911 if (wrapper) {
11912 // In jsdom-jscore, 'node.classList' can be undefined.
11913 // In this case, default to extract as it offers a better UI experience on mobile.
11914 if (!node.classList) {
11915 wrapFigureContent(nodeToInsert, wrapper);
11916 } else if (node.classList.contains('alignright') || node.classList.contains('alignleft') || node.classList.contains('aligncenter') || !wrapper.textContent.trim()) {
11917 wrapFigureContent(nodeToInsert, wrapper);
11918 }
11919 } else if (nodeToInsert.parentNode.nodeName === 'BODY') {
11920 wrapFigureContent(nodeToInsert);
11921 }
11922 }
11923
11924 ;// CONCATENATED MODULE: external ["wp","shortcode"]
11925 var external_wp_shortcode_namespaceObject = window["wp"]["shortcode"];
11926 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/shortcode-converter.js
11927 /**
11928 * External dependencies
11929 */
11930
11931 /**
11932 * WordPress dependencies
11933 */
11934
11935
11936 /**
11937 * Internal dependencies
11938 */
11939
11940
11941
11942
11943
11944
11945 function segmentHTMLToShortcodeBlock(HTML) {
11946 let lastIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
11947 let excludedBlockNames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
11948 // Get all matches.
11949 const transformsFrom = getBlockTransforms('from');
11950 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)));
11951
11952 if (!transformation) {
11953 return [HTML];
11954 }
11955
11956 const transformTags = (0,external_lodash_namespaceObject.castArray)(transformation.tag);
11957 const transformTag = (0,external_lodash_namespaceObject.find)(transformTags, tag => (0,external_wp_shortcode_namespaceObject.regexp)(tag).test(HTML));
11958 let match;
11959 const previousIndex = lastIndex;
11960
11961 if (match = (0,external_wp_shortcode_namespaceObject.next)(transformTag, HTML, lastIndex)) {
11962 lastIndex = match.index + match.content.length;
11963 const beforeHTML = HTML.substr(0, match.index);
11964 const afterHTML = HTML.substr(lastIndex); // If the shortcode content does not contain HTML and the shortcode is
11965 // not on a new line (or in paragraph from Markdown converter),
11966 // consider the shortcode as inline text, and thus skip conversion for
11967 // this segment.
11968
11969 if (!(0,external_lodash_namespaceObject.includes)(match.shortcode.content || '', '<') && !(/(\n|<p>)\s*$/.test(beforeHTML) && /^\s*(\n|<\/p>)/.test(afterHTML))) {
11970 return segmentHTMLToShortcodeBlock(HTML, lastIndex);
11971 } // If a transformation's `isMatch` predicate fails for the inbound
11972 // shortcode, try again by excluding the current block type.
11973 //
11974 // This is the only call to `segmentHTMLToShortcodeBlock` that should
11975 // ever carry over `excludedBlockNames`. Other calls in the module
11976 // should skip that argument as a way to reset the exclusion state, so
11977 // that one `isMatch` fail in an HTML fragment doesn't prevent any
11978 // valid matches in subsequent fragments.
11979
11980
11981 if (transformation.isMatch && !transformation.isMatch(match.shortcode.attrs)) {
11982 return segmentHTMLToShortcodeBlock(HTML, previousIndex, [...excludedBlockNames, transformation.blockName]);
11983 }
11984
11985 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
11986 // but shouldn't be too relied upon.
11987 //
11988 // See: https://github.com/WordPress/gutenberg/pull/3610#discussion_r152546926
11989 schema => schema.shortcode(match.shortcode.attrs, match));
11990 const transformationBlockType = { ...registration_getBlockType(transformation.blockName),
11991 attributes: transformation.attributes
11992 };
11993 let block = createBlock(transformation.blockName, getBlockAttributes(transformationBlockType, match.shortcode.content, attributes));
11994 block.originalContent = match.shortcode.content; // Applying the built-in fixes can enhance the attributes with missing content like "className".
11995
11996 block = applyBuiltInValidationFixes(block, transformationBlockType);
11997 return [...segmentHTMLToShortcodeBlock(beforeHTML), block, ...segmentHTMLToShortcodeBlock(afterHTML)];
11998 }
11999
12000 return [HTML];
12001 }
12002
12003 /* harmony default export */ var shortcode_converter = (segmentHTMLToShortcodeBlock);
12004
12005 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/utils.js
12006 /**
12007 * External dependencies
12008 */
12009
12010 /**
12011 * WordPress dependencies
12012 */
12013
12014
12015 /**
12016 * Internal dependencies
12017 */
12018
12019
12020
12021 function getBlockContentSchemaFromTransforms(transforms, context) {
12022 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
12023 const schemaArgs = {
12024 phrasingContentSchema,
12025 isPaste: context === 'paste'
12026 };
12027 const schemas = transforms.map(_ref => {
12028 let {
12029 isMatch,
12030 blockName,
12031 schema
12032 } = _ref;
12033 const hasAnchorSupport = registration_hasBlockSupport(blockName, 'anchor');
12034 schema = (0,external_lodash_namespaceObject.isFunction)(schema) ? schema(schemaArgs) : schema; // If the block does not has anchor support and the transform does not
12035 // provides an isMatch we can return the schema right away.
12036
12037 if (!hasAnchorSupport && !isMatch) {
12038 return schema;
12039 }
12040
12041 return (0,external_lodash_namespaceObject.mapValues)(schema, value => {
12042 let attributes = value.attributes || []; // If the block supports the "anchor" functionality, it needs to keep its ID attribute.
12043
12044 if (hasAnchorSupport) {
12045 attributes = [...attributes, 'id'];
12046 }
12047
12048 return { ...value,
12049 attributes,
12050 isMatch: isMatch ? isMatch : undefined
12051 };
12052 });
12053 });
12054 return (0,external_lodash_namespaceObject.mergeWith)({}, ...schemas, (objValue, srcValue, key) => {
12055 switch (key) {
12056 case 'children':
12057 {
12058 if (objValue === '*' || srcValue === '*') {
12059 return '*';
12060 }
12061
12062 return { ...objValue,
12063 ...srcValue
12064 };
12065 }
12066
12067 case 'attributes':
12068 case 'require':
12069 {
12070 return [...(objValue || []), ...(srcValue || [])];
12071 }
12072
12073 case 'isMatch':
12074 {
12075 // If one of the values being merge is undefined (matches everything),
12076 // the result of the merge will be undefined.
12077 if (!objValue || !srcValue) {
12078 return undefined;
12079 } // When merging two isMatch functions, the result is a new function
12080 // that returns if one of the source functions returns true.
12081
12082
12083 return function () {
12084 return objValue(...arguments) || srcValue(...arguments);
12085 };
12086 }
12087 }
12088 });
12089 }
12090 /**
12091 * Gets the block content schema, which is extracted and merged from all
12092 * registered blocks with raw transfroms.
12093 *
12094 * @param {string} context Set to "paste" when in paste context, where the
12095 * schema is more strict.
12096 *
12097 * @return {Object} A complete block content schema.
12098 */
12099
12100 function getBlockContentSchema(context) {
12101 return getBlockContentSchemaFromTransforms(getRawTransforms(), context);
12102 }
12103 /**
12104 * Checks whether HTML can be considered plain text. That is, it does not contain
12105 * any elements that are not line breaks.
12106 *
12107 * @param {string} HTML The HTML to check.
12108 *
12109 * @return {boolean} Whether the HTML can be considered plain text.
12110 */
12111
12112 function isPlain(HTML) {
12113 return !/<(?!br[ />])/i.test(HTML);
12114 }
12115 /**
12116 * Given node filters, deeply filters and mutates a NodeList.
12117 *
12118 * @param {NodeList} nodeList The nodeList to filter.
12119 * @param {Array} filters An array of functions that can mutate with the provided node.
12120 * @param {Document} doc The document of the nodeList.
12121 * @param {Object} schema The schema to use.
12122 */
12123
12124 function deepFilterNodeList(nodeList, filters, doc, schema) {
12125 Array.from(nodeList).forEach(node => {
12126 deepFilterNodeList(node.childNodes, filters, doc, schema);
12127 filters.forEach(item => {
12128 // Make sure the node is still attached to the document.
12129 if (!doc.contains(node)) {
12130 return;
12131 }
12132
12133 item(node, doc, schema);
12134 });
12135 });
12136 }
12137 /**
12138 * Given node filters, deeply filters HTML tags.
12139 * Filters from the deepest nodes to the top.
12140 *
12141 * @param {string} HTML The HTML to filter.
12142 * @param {Array} filters An array of functions that can mutate with the provided node.
12143 * @param {Object} schema The schema to use.
12144 *
12145 * @return {string} The filtered HTML.
12146 */
12147
12148 function deepFilterHTML(HTML) {
12149 let filters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
12150 let schema = arguments.length > 2 ? arguments[2] : undefined;
12151 const doc = document.implementation.createHTMLDocument('');
12152 doc.body.innerHTML = HTML;
12153 deepFilterNodeList(doc.body.childNodes, filters, doc, schema);
12154 return doc.body.innerHTML;
12155 }
12156 /**
12157 * Gets a sibling within text-level context.
12158 *
12159 * @param {Element} node The subject node.
12160 * @param {string} which "next" or "previous".
12161 */
12162
12163 function getSibling(node, which) {
12164 const sibling = node[`${which}Sibling`];
12165
12166 if (sibling && (0,external_wp_dom_namespaceObject.isPhrasingContent)(sibling)) {
12167 return sibling;
12168 }
12169
12170 const {
12171 parentNode
12172 } = node;
12173
12174 if (!parentNode || !(0,external_wp_dom_namespaceObject.isPhrasingContent)(parentNode)) {
12175 return;
12176 }
12177
12178 return getSibling(parentNode, which);
12179 }
12180
12181 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/index.js
12182 /**
12183 * External dependencies
12184 */
12185
12186 /**
12187 * WordPress dependencies
12188 */
12189
12190
12191
12192 /**
12193 * Internal dependencies
12194 */
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206 function deprecatedGetPhrasingContentSchema(context) {
12207 external_wp_deprecated_default()('wp.blocks.getPhrasingContentSchema', {
12208 since: '5.6',
12209 alternative: 'wp.dom.getPhrasingContentSchema'
12210 });
12211 return (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)(context);
12212 }
12213 /**
12214 * Converts an HTML string to known blocks.
12215 *
12216 * @param {Object} $1
12217 * @param {string} $1.HTML The HTML to convert.
12218 *
12219 * @return {Array} A list of blocks.
12220 */
12221
12222 function rawHandler(_ref) {
12223 let {
12224 HTML = ''
12225 } = _ref;
12226
12227 // If we detect block delimiters, parse entirely as blocks.
12228 if (HTML.indexOf('<!-- wp:') !== -1) {
12229 return parser_parse(HTML);
12230 } // An array of HTML strings and block objects. The blocks replace matched
12231 // shortcodes.
12232
12233
12234 const pieces = shortcode_converter(HTML);
12235 const blockContentSchema = getBlockContentSchema();
12236 return (0,external_lodash_namespaceObject.compact)((0,external_lodash_namespaceObject.flatMap)(pieces, piece => {
12237 // Already a block from shortcode.
12238 if (typeof piece !== 'string') {
12239 return piece;
12240 } // These filters are essential for some blocks to be able to transform
12241 // from raw HTML. These filters move around some content or add
12242 // additional tags, they do not remove any content.
12243
12244
12245 const filters = [// Needed to adjust invalid lists.
12246 listReducer, // Needed to create more and nextpage blocks.
12247 specialCommentConverter, // Needed to create media blocks.
12248 figureContentReducer, // Needed to create the quote block, which cannot handle text
12249 // without wrapper paragraphs.
12250 blockquoteNormaliser];
12251 piece = deepFilterHTML(piece, filters, blockContentSchema);
12252 piece = normaliseBlocks(piece);
12253 return htmlToBlocks(piece);
12254 }));
12255 }
12256
12257 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/comment-remover.js
12258 /**
12259 * WordPress dependencies
12260 */
12261
12262 /**
12263 * Looks for comments, and removes them.
12264 *
12265 * @param {Node} node The node to be processed.
12266 * @return {void}
12267 */
12268
12269 function commentRemover(node) {
12270 if (node.nodeType === node.COMMENT_NODE) {
12271 (0,external_wp_dom_namespaceObject.remove)(node);
12272 }
12273 }
12274
12275 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/is-inline-content.js
12276 /**
12277 * External dependencies
12278 */
12279
12280 /**
12281 * WordPress dependencies
12282 */
12283
12284
12285 /**
12286 * Checks if the given node should be considered inline content, optionally
12287 * depending on a context tag.
12288 *
12289 * @param {Node} node Node name.
12290 * @param {string} contextTag Tag name.
12291 *
12292 * @return {boolean} True if the node is inline content, false if nohe.
12293 */
12294
12295 function isInline(node, contextTag) {
12296 if ((0,external_wp_dom_namespaceObject.isTextContent)(node)) {
12297 return true;
12298 }
12299
12300 if (!contextTag) {
12301 return false;
12302 }
12303
12304 const tag = node.nodeName.toLowerCase();
12305 const inlineAllowedTagGroups = [['ul', 'li', 'ol'], ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']];
12306 return inlineAllowedTagGroups.some(tagGroup => (0,external_lodash_namespaceObject.difference)([tag, contextTag], tagGroup).length === 0);
12307 }
12308
12309 function deepCheck(nodes, contextTag) {
12310 return nodes.every(node => isInline(node, contextTag) && deepCheck(Array.from(node.children), contextTag));
12311 }
12312
12313 function isDoubleBR(node) {
12314 return node.nodeName === 'BR' && node.previousSibling && node.previousSibling.nodeName === 'BR';
12315 }
12316
12317 function isInlineContent(HTML, contextTag) {
12318 const doc = document.implementation.createHTMLDocument('');
12319 doc.body.innerHTML = HTML;
12320 const nodes = Array.from(doc.body.children);
12321 return !nodes.some(isDoubleBR) && deepCheck(nodes, contextTag);
12322 }
12323
12324 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/phrasing-content-reducer.js
12325 /**
12326 * External dependencies
12327 */
12328
12329 /**
12330 * WordPress dependencies
12331 */
12332
12333
12334 function phrasingContentReducer(node, doc) {
12335 // In jsdom-jscore, 'node.style' can be null.
12336 // TODO: Explore fixing this by patching jsdom-jscore.
12337 if (node.nodeName === 'SPAN' && node.style) {
12338 const {
12339 fontWeight,
12340 fontStyle,
12341 textDecorationLine,
12342 textDecoration,
12343 verticalAlign
12344 } = node.style;
12345
12346 if (fontWeight === 'bold' || fontWeight === '700') {
12347 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('strong'), node);
12348 }
12349
12350 if (fontStyle === 'italic') {
12351 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('em'), node);
12352 } // Some DOM implementations (Safari, JSDom) don't support
12353 // style.textDecorationLine, so we check style.textDecoration as a
12354 // fallback.
12355
12356
12357 if (textDecorationLine === 'line-through' || (0,external_lodash_namespaceObject.includes)(textDecoration, 'line-through')) {
12358 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('s'), node);
12359 }
12360
12361 if (verticalAlign === 'super') {
12362 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sup'), node);
12363 } else if (verticalAlign === 'sub') {
12364 (0,external_wp_dom_namespaceObject.wrap)(doc.createElement('sub'), node);
12365 }
12366 } else if (node.nodeName === 'B') {
12367 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'strong');
12368 } else if (node.nodeName === 'I') {
12369 node = (0,external_wp_dom_namespaceObject.replaceTag)(node, 'em');
12370 } else if (node.nodeName === 'A') {
12371 // In jsdom-jscore, 'node.target' can be null.
12372 // TODO: Explore fixing this by patching jsdom-jscore.
12373 if (node.target && node.target.toLowerCase() === '_blank') {
12374 node.rel = 'noreferrer noopener';
12375 } else {
12376 node.removeAttribute('target');
12377 node.removeAttribute('rel');
12378 } // Saves anchor elements name attribute as id
12379
12380
12381 if (node.name && !node.id) {
12382 node.id = node.name;
12383 } // Keeps id only if there is an internal link pointing to it
12384
12385
12386 if (node.id && !node.ownerDocument.querySelector(`[href="#${node.id}"]`)) {
12387 node.removeAttribute('id');
12388 }
12389 }
12390 }
12391
12392 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/head-remover.js
12393 function headRemover(node) {
12394 if (node.nodeName !== 'SCRIPT' && node.nodeName !== 'NOSCRIPT' && node.nodeName !== 'TEMPLATE' && node.nodeName !== 'STYLE') {
12395 return;
12396 }
12397
12398 node.parentNode.removeChild(node);
12399 }
12400
12401 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/ms-list-converter.js
12402 /**
12403 * Browser dependencies
12404 */
12405 const {
12406 parseInt: ms_list_converter_parseInt
12407 } = window;
12408
12409 function ms_list_converter_isList(node) {
12410 return node.nodeName === 'OL' || node.nodeName === 'UL';
12411 }
12412
12413 function msListConverter(node, doc) {
12414 if (node.nodeName !== 'P') {
12415 return;
12416 }
12417
12418 const style = node.getAttribute('style');
12419
12420 if (!style) {
12421 return;
12422 } // Quick check.
12423
12424
12425 if (style.indexOf('mso-list') === -1) {
12426 return;
12427 }
12428
12429 const matches = /mso-list\s*:[^;]+level([0-9]+)/i.exec(style);
12430
12431 if (!matches) {
12432 return;
12433 }
12434
12435 let level = ms_list_converter_parseInt(matches[1], 10) - 1 || 0;
12436 const prevNode = node.previousElementSibling; // Add new list if no previous.
12437
12438 if (!prevNode || !ms_list_converter_isList(prevNode)) {
12439 // See https://html.spec.whatwg.org/multipage/grouping-content.html#attr-ol-type.
12440 const type = node.textContent.trim().slice(0, 1);
12441 const isNumeric = /[1iIaA]/.test(type);
12442 const newListNode = doc.createElement(isNumeric ? 'ol' : 'ul');
12443
12444 if (isNumeric) {
12445 newListNode.setAttribute('type', type);
12446 }
12447
12448 node.parentNode.insertBefore(newListNode, node);
12449 }
12450
12451 const listNode = node.previousElementSibling;
12452 const listType = listNode.nodeName;
12453 const listItem = doc.createElement('li');
12454 let receivingNode = listNode; // Remove the first span with list info.
12455
12456 node.removeChild(node.firstChild); // Add content.
12457
12458 while (node.firstChild) {
12459 listItem.appendChild(node.firstChild);
12460 } // Change pointer depending on indentation level.
12461
12462
12463 while (level--) {
12464 receivingNode = receivingNode.lastChild || receivingNode; // If it's a list, move pointer to the last item.
12465
12466 if (ms_list_converter_isList(receivingNode)) {
12467 receivingNode = receivingNode.lastChild || receivingNode;
12468 }
12469 } // Make sure we append to a list.
12470
12471
12472 if (!ms_list_converter_isList(receivingNode)) {
12473 receivingNode = receivingNode.appendChild(doc.createElement(listType));
12474 } // Append the list item to the list.
12475
12476
12477 receivingNode.appendChild(listItem); // Remove the wrapper paragraph.
12478
12479 node.parentNode.removeChild(node);
12480 }
12481
12482 ;// CONCATENATED MODULE: external ["wp","blob"]
12483 var external_wp_blob_namespaceObject = window["wp"]["blob"];
12484 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/image-corrector.js
12485 /**
12486 * WordPress dependencies
12487 */
12488
12489 /**
12490 * Browser dependencies
12491 */
12492
12493 const {
12494 atob,
12495 File
12496 } = window;
12497 function imageCorrector(node) {
12498 if (node.nodeName !== 'IMG') {
12499 return;
12500 }
12501
12502 if (node.src.indexOf('file:') === 0) {
12503 node.src = '';
12504 } // This piece cannot be tested outside a browser env.
12505
12506
12507 if (node.src.indexOf('data:') === 0) {
12508 const [properties, data] = node.src.split(',');
12509 const [type] = properties.slice(5).split(';');
12510
12511 if (!data || !type) {
12512 node.src = '';
12513 return;
12514 }
12515
12516 let decoded; // Can throw DOMException!
12517
12518 try {
12519 decoded = atob(data);
12520 } catch (e) {
12521 node.src = '';
12522 return;
12523 }
12524
12525 const uint8Array = new Uint8Array(decoded.length);
12526
12527 for (let i = 0; i < uint8Array.length; i++) {
12528 uint8Array[i] = decoded.charCodeAt(i);
12529 }
12530
12531 const name = type.replace('/', '.');
12532 const file = new File([uint8Array], name, {
12533 type
12534 });
12535 node.src = (0,external_wp_blob_namespaceObject.createBlobURL)(file);
12536 } // Remove trackers and hardly visible images.
12537
12538
12539 if (node.height === 1 || node.width === 1) {
12540 node.parentNode.removeChild(node);
12541 }
12542 }
12543
12544 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/div-normaliser.js
12545 /**
12546 * Internal dependencies
12547 */
12548
12549 function divNormaliser(node) {
12550 if (node.nodeName !== 'DIV') {
12551 return;
12552 }
12553
12554 node.innerHTML = normaliseBlocks(node.innerHTML);
12555 }
12556
12557 // EXTERNAL MODULE: ./node_modules/showdown/dist/showdown.js
12558 var showdown = __webpack_require__(7308);
12559 var showdown_default = /*#__PURE__*/__webpack_require__.n(showdown);
12560 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/markdown-converter.js
12561 /**
12562 * External dependencies
12563 */
12564 // Reuse the same showdown converter.
12565
12566 const converter = new (showdown_default()).Converter({
12567 noHeaderId: true,
12568 tables: true,
12569 literalMidWordUnderscores: true,
12570 omitExtraWLInCodeBlocks: true,
12571 simpleLineBreaks: true,
12572 strikethrough: true
12573 });
12574 /**
12575 * Corrects the Slack Markdown variant of the code block.
12576 * If uncorrected, it will be converted to inline code.
12577 *
12578 * @see https://get.slack.help/hc/en-us/articles/202288908-how-can-i-add-formatting-to-my-messages-#code-blocks
12579 *
12580 * @param {string} text The potential Markdown text to correct.
12581 *
12582 * @return {string} The corrected Markdown.
12583 */
12584
12585 function slackMarkdownVariantCorrector(text) {
12586 return text.replace(/((?:^|\n)```)([^\n`]+)(```(?:$|\n))/, (match, p1, p2, p3) => `${p1}\n${p2}\n${p3}`);
12587 }
12588 /**
12589 * Converts a piece of text into HTML based on any Markdown present.
12590 * Also decodes any encoded HTML.
12591 *
12592 * @param {string} text The plain text to convert.
12593 *
12594 * @return {string} HTML.
12595 */
12596
12597
12598 function markdownConverter(text) {
12599 return converter.makeHtml(slackMarkdownVariantCorrector(text));
12600 }
12601
12602 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/iframe-remover.js
12603 /**
12604 * Removes iframes.
12605 *
12606 * @param {Node} node The node to check.
12607 *
12608 * @return {void}
12609 */
12610 function iframeRemover(node) {
12611 if (node.nodeName === 'IFRAME') {
12612 const text = node.ownerDocument.createTextNode(node.src);
12613 node.parentNode.replaceChild(text, node);
12614 }
12615 }
12616
12617 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/google-docs-uid-remover.js
12618 /**
12619 * WordPress dependencies
12620 */
12621
12622 function googleDocsUIdRemover(node) {
12623 if (!node.id || node.id.indexOf('docs-internal-guid-') !== 0) {
12624 return;
12625 }
12626
12627 (0,external_wp_dom_namespaceObject.unwrap)(node);
12628 }
12629
12630 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/html-formatting-remover.js
12631 /**
12632 * Internal dependencies
12633 */
12634
12635
12636 function isFormattingSpace(character) {
12637 return character === ' ' || character === '\r' || character === '\n' || character === '\t';
12638 }
12639 /**
12640 * Removes spacing that formats HTML.
12641 *
12642 * @see https://www.w3.org/TR/css-text-3/#white-space-processing
12643 *
12644 * @param {Node} node The node to be processed.
12645 * @return {void}
12646 */
12647
12648
12649 function htmlFormattingRemover(node) {
12650 if (node.nodeType !== node.TEXT_NODE) {
12651 return;
12652 } // Ignore pre content. Note that this does not use Element#closest due to
12653 // a combination of (a) node may not be Element and (b) node.parentElement
12654 // does not have full support in all browsers (Internet Exporer).
12655 //
12656 // See: https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement#Browser_compatibility
12657
12658 /** @type {Node?} */
12659
12660
12661 let parent = node;
12662
12663 while (parent = parent.parentNode) {
12664 if (parent.nodeType === parent.ELEMENT_NODE && parent.nodeName === 'PRE') {
12665 return;
12666 }
12667 } // First, replace any sequence of HTML formatting space with a single space.
12668
12669
12670 let newData = node.data.replace(/[ \r\n\t]+/g, ' '); // Remove the leading space if the text element is at the start of a block,
12671 // is preceded by a line break element, or has a space in the previous
12672 // node.
12673
12674 if (newData[0] === ' ') {
12675 const previousSibling = getSibling(node, 'previous');
12676
12677 if (!previousSibling || previousSibling.nodeName === 'BR' || previousSibling.textContent.slice(-1) === ' ') {
12678 newData = newData.slice(1);
12679 }
12680 } // Remove the trailing space if the text element is at the end of a block,
12681 // is succeded by a line break element, or has a space in the next text
12682 // node.
12683
12684
12685 if (newData[newData.length - 1] === ' ') {
12686 const nextSibling = getSibling(node, 'next');
12687
12688 if (!nextSibling || nextSibling.nodeName === 'BR' || nextSibling.nodeType === nextSibling.TEXT_NODE && isFormattingSpace(nextSibling.textContent[0])) {
12689 newData = newData.slice(0, -1);
12690 }
12691 } // If there's no data left, remove the node, so `previousSibling` stays
12692 // accurate. Otherwise, update the node data.
12693
12694
12695 if (!newData) {
12696 node.parentNode.removeChild(node);
12697 } else {
12698 node.data = newData;
12699 }
12700 }
12701
12702 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/br-remover.js
12703 /**
12704 * Internal dependencies
12705 */
12706
12707 /**
12708 * Removes trailing br elements from text-level content.
12709 *
12710 * @param {Element} node Node to check.
12711 */
12712
12713 function brRemover(node) {
12714 if (node.nodeName !== 'BR') {
12715 return;
12716 }
12717
12718 if (getSibling(node, 'next')) {
12719 return;
12720 }
12721
12722 node.parentNode.removeChild(node);
12723 }
12724
12725 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/empty-paragraph-remover.js
12726 /**
12727 * Removes empty paragraph elements.
12728 *
12729 * @param {Element} node Node to check.
12730 */
12731 function emptyParagraphRemover(node) {
12732 if (node.nodeName !== 'P') {
12733 return;
12734 }
12735
12736 if (node.hasChildNodes()) {
12737 return;
12738 }
12739
12740 node.parentNode.removeChild(node);
12741 }
12742
12743 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/raw-handling/paste-handler.js
12744 /**
12745 * External dependencies
12746 */
12747
12748 /**
12749 * WordPress dependencies
12750 */
12751
12752
12753 /**
12754 * Internal dependencies
12755 */
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781 /**
12782 * Browser dependencies
12783 */
12784
12785 const {
12786 console: paste_handler_console
12787 } = window;
12788 /**
12789 * Filters HTML to only contain phrasing content.
12790 *
12791 * @param {string} HTML The HTML to filter.
12792 * @param {boolean} preserveWhiteSpace Whether or not to preserve consequent white space.
12793 *
12794 * @return {string} HTML only containing phrasing content.
12795 */
12796
12797 function filterInlineHTML(HTML, preserveWhiteSpace) {
12798 HTML = deepFilterHTML(HTML, [googleDocsUIdRemover, phrasingContentReducer, commentRemover]);
12799 HTML = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(HTML, (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste'), {
12800 inline: true
12801 });
12802
12803 if (!preserveWhiteSpace) {
12804 HTML = deepFilterHTML(HTML, [htmlFormattingRemover, brRemover]);
12805 } // Allows us to ask for this information when we get a report.
12806
12807
12808 paste_handler_console.log('Processed inline HTML:\n\n', HTML);
12809 return HTML;
12810 }
12811 /**
12812 * Converts an HTML string to known blocks. Strips everything else.
12813 *
12814 * @param {Object} options
12815 * @param {string} [options.HTML] The HTML to convert.
12816 * @param {string} [options.plainText] Plain text version.
12817 * @param {string} [options.mode] Handle content as blocks or inline content.
12818 * * 'AUTO': Decide based on the content passed.
12819 * * 'INLINE': Always handle as inline content, and return string.
12820 * * 'BLOCKS': Always handle as blocks, and return array of blocks.
12821 * @param {Array} [options.tagName] The tag into which content will be inserted.
12822 * @param {boolean} [options.preserveWhiteSpace] Whether or not to preserve consequent white space.
12823 *
12824 * @return {Array|string} A list of blocks or a string, depending on `handlerMode`.
12825 */
12826
12827
12828 function pasteHandler(_ref) {
12829 let {
12830 HTML = '',
12831 plainText = '',
12832 mode = 'AUTO',
12833 tagName,
12834 preserveWhiteSpace
12835 } = _ref;
12836 // First of all, strip any meta tags.
12837 HTML = HTML.replace(/<meta[^>]+>/g, ''); // Strip Windows markers.
12838
12839 HTML = HTML.replace(/^\s*<html[^>]*>\s*<body[^>]*>(?:\s*<!--\s*StartFragment\s*-->)?/i, '');
12840 HTML = HTML.replace(/(?:<!--\s*EndFragment\s*-->\s*)?<\/body>\s*<\/html>\s*$/i, ''); // If we detect block delimiters in HTML, parse entirely as blocks.
12841
12842 if (mode !== 'INLINE') {
12843 // Check plain text if there is no HTML.
12844 const content = HTML ? HTML : plainText;
12845
12846 if (content.indexOf('<!-- wp:') !== -1) {
12847 return parser_parse(content);
12848 }
12849 } // Normalize unicode to use composed characters.
12850 // This is unsupported in IE 11 but it's a nice-to-have feature, not mandatory.
12851 // Not normalizing the content will only affect older browsers and won't
12852 // entirely break the app.
12853 // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
12854 // See: https://core.trac.wordpress.org/ticket/30130
12855 // See: https://github.com/WordPress/gutenberg/pull/6983#pullrequestreview-125151075
12856
12857
12858 if (String.prototype.normalize) {
12859 HTML = HTML.normalize();
12860 } // Parse Markdown (and encoded HTML) if:
12861 // * There is a plain text version.
12862 // * There is no HTML version, or it has no formatting.
12863
12864
12865 if (plainText && (!HTML || isPlain(HTML))) {
12866 HTML = plainText; // The markdown converter (Showdown) trims whitespace.
12867
12868 if (!/^\s+$/.test(plainText)) {
12869 HTML = markdownConverter(HTML);
12870 } // Switch to inline mode if:
12871 // * The current mode is AUTO.
12872 // * The original plain text had no line breaks.
12873 // * The original plain text was not an HTML paragraph.
12874 // * The converted text is just a paragraph.
12875
12876
12877 if (mode === 'AUTO' && plainText.indexOf('\n') === -1 && plainText.indexOf('<p>') !== 0 && HTML.indexOf('<p>') === 0) {
12878 mode = 'INLINE';
12879 }
12880 }
12881
12882 if (mode === 'INLINE') {
12883 return filterInlineHTML(HTML, preserveWhiteSpace);
12884 } // An array of HTML strings and block objects. The blocks replace matched
12885 // shortcodes.
12886
12887
12888 const pieces = shortcode_converter(HTML); // The call to shortcodeConverter will always return more than one element
12889 // if shortcodes are matched. The reason is when shortcodes are matched
12890 // empty HTML strings are included.
12891
12892 const hasShortcodes = pieces.length > 1;
12893
12894 if (mode === 'AUTO' && !hasShortcodes && isInlineContent(HTML, tagName)) {
12895 return filterInlineHTML(HTML, preserveWhiteSpace);
12896 }
12897
12898 const phrasingContentSchema = (0,external_wp_dom_namespaceObject.getPhrasingContentSchema)('paste');
12899 const blockContentSchema = getBlockContentSchema('paste');
12900 const blocks = (0,external_lodash_namespaceObject.compact)((0,external_lodash_namespaceObject.flatMap)(pieces, piece => {
12901 // Already a block from shortcode.
12902 if (typeof piece !== 'string') {
12903 return piece;
12904 }
12905
12906 const filters = [googleDocsUIdRemover, msListConverter, headRemover, listReducer, imageCorrector, phrasingContentReducer, specialCommentConverter, commentRemover, iframeRemover, figureContentReducer, blockquoteNormaliser, divNormaliser];
12907 const schema = { ...blockContentSchema,
12908 // Keep top-level phrasing content, normalised by `normaliseBlocks`.
12909 ...phrasingContentSchema
12910 };
12911 piece = deepFilterHTML(piece, filters, blockContentSchema);
12912 piece = (0,external_wp_dom_namespaceObject.removeInvalidHTML)(piece, schema);
12913 piece = normaliseBlocks(piece);
12914 piece = deepFilterHTML(piece, [htmlFormattingRemover, brRemover, emptyParagraphRemover], blockContentSchema); // Allows us to ask for this information when we get a report.
12915
12916 paste_handler_console.log('Processed HTML piece:\n\n', piece);
12917 return htmlToBlocks(piece);
12918 })); // If we're allowed to return inline content, and there is only one
12919 // inlineable block, and the original plain text content does not have any
12920 // line breaks, then treat it as inline paste.
12921
12922 if (mode === 'AUTO' && blocks.length === 1 && registration_hasBlockSupport(blocks[0].name, '__unstablePasteTextInline', false)) {
12923 // Don't catch line breaks at the start or end.
12924 const trimmedPlainText = plainText.replace(/^[\n]+|[\n]+$/g, '');
12925
12926 if (trimmedPlainText !== '' && trimmedPlainText.indexOf('\n') === -1) {
12927 return (0,external_wp_dom_namespaceObject.removeInvalidHTML)(getBlockInnerHTML(blocks[0]), phrasingContentSchema);
12928 }
12929 }
12930
12931 return blocks;
12932 }
12933
12934 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/categories.js
12935 /**
12936 * WordPress dependencies
12937 */
12938
12939 /**
12940 * Internal dependencies
12941 */
12942
12943
12944 /** @typedef {import('../store/reducer').WPBlockCategory} WPBlockCategory */
12945
12946 /**
12947 * Returns all the block categories.
12948 *
12949 * @return {WPBlockCategory[]} Block categories.
12950 */
12951
12952 function categories_getCategories() {
12953 return (0,external_wp_data_namespaceObject.select)(store).getCategories();
12954 }
12955 /**
12956 * Sets the block categories.
12957 *
12958 * @param {WPBlockCategory[]} categories Block categories.
12959 */
12960
12961 function categories_setCategories(categories) {
12962 (0,external_wp_data_namespaceObject.dispatch)(store).setCategories(categories);
12963 }
12964 /**
12965 * Updates a category.
12966 *
12967 * @param {string} slug Block category slug.
12968 * @param {WPBlockCategory} category Object containing the category properties
12969 * that should be updated.
12970 */
12971
12972 function categories_updateCategory(slug, category) {
12973 (0,external_wp_data_namespaceObject.dispatch)(store).updateCategory(slug, category);
12974 }
12975
12976 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/templates.js
12977 /**
12978 * External dependencies
12979 */
12980
12981 /**
12982 * WordPress dependencies
12983 */
12984
12985
12986 /**
12987 * Internal dependencies
12988 */
12989
12990
12991
12992
12993 /**
12994 * Checks whether a list of blocks matches a template by comparing the block names.
12995 *
12996 * @param {Array} blocks Block list.
12997 * @param {Array} template Block template.
12998 *
12999 * @return {boolean} Whether the list of blocks matches a templates.
13000 */
13001
13002 function doBlocksMatchTemplate() {
13003 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
13004 let template = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
13005 return blocks.length === template.length && (0,external_lodash_namespaceObject.every)(template, (_ref, index) => {
13006 let [name,, innerBlocksTemplate] = _ref;
13007 const block = blocks[index];
13008 return name === block.name && doBlocksMatchTemplate(block.innerBlocks, innerBlocksTemplate);
13009 });
13010 }
13011 /**
13012 * Synchronize a block list with a block template.
13013 *
13014 * Synchronizing a block list with a block template means that we loop over the blocks
13015 * keep the block as is if it matches the block at the same position in the template
13016 * (If it has the same name) and if doesn't match, we create a new block based on the template.
13017 * Extra blocks not present in the template are removed.
13018 *
13019 * @param {Array} blocks Block list.
13020 * @param {Array} template Block template.
13021 *
13022 * @return {Array} Updated Block list.
13023 */
13024
13025 function synchronizeBlocksWithTemplate() {
13026 let blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
13027 let template = arguments.length > 1 ? arguments[1] : undefined;
13028
13029 // If no template is provided, return blocks unmodified.
13030 if (!template) {
13031 return blocks;
13032 }
13033
13034 return (0,external_lodash_namespaceObject.map)(template, (_ref2, index) => {
13035 let [name, attributes, innerBlocksTemplate] = _ref2;
13036 const block = blocks[index];
13037
13038 if (block && block.name === name) {
13039 const innerBlocks = synchronizeBlocksWithTemplate(block.innerBlocks, innerBlocksTemplate);
13040 return { ...block,
13041 innerBlocks
13042 };
13043 } // To support old templates that were using the "children" format
13044 // for the attributes using "html" strings now, we normalize the template attributes
13045 // before creating the blocks.
13046
13047
13048 const blockType = registration_getBlockType(name);
13049
13050 const isHTMLAttribute = attributeDefinition => (0,external_lodash_namespaceObject.get)(attributeDefinition, ['source']) === 'html';
13051
13052 const isQueryAttribute = attributeDefinition => (0,external_lodash_namespaceObject.get)(attributeDefinition, ['source']) === 'query';
13053
13054 const normalizeAttributes = (schema, values) => {
13055 return (0,external_lodash_namespaceObject.mapValues)(values, (value, key) => {
13056 return normalizeAttribute(schema[key], value);
13057 });
13058 };
13059
13060 const normalizeAttribute = (definition, value) => {
13061 if (isHTMLAttribute(definition) && (0,external_lodash_namespaceObject.isArray)(value)) {
13062 // Introduce a deprecated call at this point
13063 // When we're confident that "children" format should be removed from the templates.
13064 return (0,external_wp_element_namespaceObject.renderToString)(value);
13065 }
13066
13067 if (isQueryAttribute(definition) && value) {
13068 return value.map(subValues => {
13069 return normalizeAttributes(definition.query, subValues);
13070 });
13071 }
13072
13073 return value;
13074 };
13075
13076 const normalizedAttributes = normalizeAttributes((0,external_lodash_namespaceObject.get)(blockType, ['attributes'], {}), attributes);
13077 let [blockName, blockAttributes] = convertLegacyBlockNameAndAttributes(name, normalizedAttributes); // If a Block is undefined at this point, use the core/missing block as
13078 // a placeholder for a better user experience.
13079
13080 if (undefined === registration_getBlockType(blockName)) {
13081 blockAttributes = {
13082 originalName: name,
13083 originalContent: '',
13084 originalUndelimitedContent: ''
13085 };
13086 blockName = 'core/missing';
13087 }
13088
13089 return createBlock(blockName, blockAttributes, synchronizeBlocksWithTemplate([], innerBlocksTemplate));
13090 });
13091 }
13092
13093 ;// CONCATENATED MODULE: ./packages/blocks/build-module/api/index.js
13094 // The blocktype is the most important concept within the block API. It defines
13095 // all aspects of the block configuration and its interfaces, including `edit`
13096 // and `save`. The transforms specification allows converting one blocktype to
13097 // another through formulas defined by either the source or the destination.
13098 // Switching a blocktype is to be considered a one-way operation implying a
13099 // transformation in the opposite way has to be handled explicitly.
13100 // The block tree is composed of a collection of block nodes. Blocks contained
13101 // within other blocks are called inner blocks. An important design
13102 // consideration is that inner blocks are -- conceptually -- not part of the
13103 // territory established by the parent block that contains them.
13104 //
13105 // This has multiple practical implications: when parsing, we can safely dispose
13106 // of any block boundary found within a block from the innerHTML property when
13107 // transfering to state. Not doing so would have a compounding effect on memory
13108 // and uncertainty over the source of truth. This can be illustrated in how,
13109 // given a tree of `n` nested blocks, the entry node would have to contain the
13110 // actual content of each block while each subsequent block node in the state
13111 // tree would replicate the entire chain `n-1`, meaning the extreme end node
13112 // would have been replicated `n` times as the tree is traversed and would
13113 // generate uncertainty as to which one is to hold the current value of the
13114 // block. For composition, it also means inner blocks can effectively be child
13115 // components whose mechanisms can be shielded from the `edit` implementation
13116 // and just passed along.
13117
13118
13119
13120 // While block transformations account for a specific surface of the API, there
13121 // are also raw transformations which handle arbitrary sources not made out of
13122 // blocks but producing block basaed on various heursitics. This includes
13123 // pasting rich text or HTML data.
13124
13125 // The process of serialization aims to deflate the internal memory of the block
13126 // editor and its state representation back into an HTML valid string. This
13127 // process restores the document integrity and inserts invisible delimiters
13128 // around each block with HTML comment boundaries which can contain any extra
13129 // attributes needed to operate with the block later on.
13130
13131 // Validation is the process of comparing a block source with its output before
13132 // there is any user input or interaction with a block. When this operation
13133 // fails -- for whatever reason -- the block is to be considered invalid. As
13134 // part of validating a block the system will attempt to run the source against
13135 // any provided deprecation definitions.
13136 //
13137 // Worth emphasizing that validation is not a case of whether the markup is
13138 // merely HTML spec-compliant but about how the editor knows to create such
13139 // markup and that its inability to create an identical result can be a strong
13140 // indicator of potential data loss (the invalidation is then a protective
13141 // measure).
13142 //
13143 // The invalidation process can also be deconstructed in phases: 1) validate the
13144 // block exists; 2) validate the source matches the output; 3) validate the
13145 // source matches deprecated outputs; 4) work through the significance of
13146 // differences. These are stacked in a way that favors performance and optimizes
13147 // for the majority of cases. That is to say, the evaluation logic can become
13148 // more sophisticated the further down it goes in the process as the cost is
13149 // accounted for. The first logic checks have to be extremely efficient since
13150 // they will be run for all valid and invalid blocks alike. However, once a
13151 // block is detected as invalid -- failing the three first steps -- it is
13152 // adequate to spend more time determining validity before throwing a conflict.
13153
13154
13155 // Blocks are inherently indifferent about where the data they operate with ends
13156 // up being saved. For example, all blocks can have a static and dynamic aspect
13157 // to them depending on the needs. The static nature of a block is the `save()`
13158 // definition that is meant to be serialized into HTML and which can be left
13159 // void. Any block can also register a `render_callback` on the server, which
13160 // makes its output dynamic either in part or in its totality.
13161 //
13162 // Child blocks are defined as a relationship that builds on top of the inner
13163 // blocks mechanism. A child block is a block node of a particular type that can
13164 // only exist within the inner block boundaries of a specific parent type. This
13165 // allows block authors to compose specific blocks that are not meant to be used
13166 // outside of a specified parent block context. Thus, child blocks extend the
13167 // concept of inner blocks to support a more direct relationship between sets of
13168 // blocks. The addition of parent–child would be a subset of the inner block
13169 // functionality under the premise that certain blocks only make sense as
13170 // children of another block.
13171
13172
13173 // Templates are, in a general sense, a basic collection of block nodes with any
13174 // given set of predefined attributes that are supplied as the initial state of
13175 // an inner blocks group. These nodes can, in turn, contain any number of nested
13176 // blocks within their definition. Templates allow both to specify a default
13177 // state for an editor session or a default set of blocks for any inner block
13178 // implementation within a specific block.
13179
13180
13181
13182
13183
13184
13185 ;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/extends.js
13186 function _extends() {
13187 _extends = Object.assign || function (target) {
13188 for (var i = 1; i < arguments.length; i++) {
13189 var source = arguments[i];
13190
13191 for (var key in source) {
13192 if (Object.prototype.hasOwnProperty.call(source, key)) {
13193 target[key] = source[key];
13194 }
13195 }
13196 }
13197
13198 return target;
13199 };
13200
13201 return _extends.apply(this, arguments);
13202 }
13203 ;// CONCATENATED MODULE: external ["wp","compose"]
13204 var external_wp_compose_namespaceObject = window["wp"]["compose"];
13205 ;// CONCATENATED MODULE: ./packages/blocks/build-module/block-content-provider/index.js
13206
13207
13208
13209 /**
13210 * WordPress dependencies
13211 */
13212
13213
13214 /**
13215 * Internal dependencies
13216 */
13217
13218
13219 const {
13220 Consumer,
13221 Provider
13222 } = (0,external_wp_element_namespaceObject.createContext)(() => {});
13223 /**
13224 * An internal block component used in block content serialization to inject
13225 * nested block content within the `save` implementation of the ancestor
13226 * component in which it is nested. The component provides a pre-bound
13227 * `BlockContent` component via context, which is used by the developer-facing
13228 * `InnerBlocks.Content` component to render block content.
13229 *
13230 * @example
13231 *
13232 * ```jsx
13233 * <BlockContentProvider innerBlocks={ innerBlocks }>
13234 * { blockSaveElement }
13235 * </BlockContentProvider>
13236 * ```
13237 *
13238 * @param {Object} props Component props.
13239 * @param {WPElement} props.children Block save result.
13240 * @param {Array} props.innerBlocks Block(s) to serialize.
13241 *
13242 * @return {WPComponent} Element with BlockContent injected via context.
13243 */
13244
13245 const BlockContentProvider = _ref => {
13246 let {
13247 children,
13248 innerBlocks
13249 } = _ref;
13250
13251 const BlockContent = () => {
13252 // Value is an array of blocks, so defer to block serializer.
13253 const html = serialize(innerBlocks, {
13254 isInnerBlocks: true
13255 }); // Use special-cased raw HTML tag to avoid default escaping
13256
13257 return createElement(RawHTML, null, html);
13258 };
13259
13260 return createElement(Provider, {
13261 value: BlockContent
13262 }, children);
13263 };
13264 /**
13265 * A Higher Order Component used to inject BlockContent using context to the
13266 * wrapped component.
13267 *
13268 * @return {WPComponent} Enhanced component with injected BlockContent as prop.
13269 */
13270
13271
13272 const withBlockContentContext = (0,external_wp_compose_namespaceObject.createHigherOrderComponent)(OriginalComponent => {
13273 return props => (0,external_wp_element_namespaceObject.createElement)(Consumer, null, context => (0,external_wp_element_namespaceObject.createElement)(OriginalComponent, _extends({}, props, {
13274 BlockContent: context
13275 })));
13276 }, 'withBlockContentContext');
13277 /* harmony default export */ var block_content_provider = ((/* unused pure expression or super */ null && (BlockContentProvider)));
13278
13279 ;// CONCATENATED MODULE: ./packages/blocks/build-module/index.js
13280 // A "block" is the abstract term used to describe units of markup that,
13281 // when composed together, form the content or layout of a page.
13282 // The API for blocks is exposed via `wp.blocks`.
13283 //
13284 // Supported blocks are registered by calling `registerBlockType`. Once registered,
13285 // the block is made available as an option to the editor interface.
13286 //
13287 // Blocks are inferred from the HTML source of a post through a parsing mechanism
13288 // and then stored as objects in state, from which it is then rendered for editing.
13289
13290
13291
13292
13293 }();
13294 (window.wp = window.wp || {}).blocks = __webpack_exports__;
13295 /******/ })()
13296 ;