[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/js/dist/ -> blocks.js (source)

   1  this["wp"] = this["wp"] || {}; this["wp"]["blocks"] =
   2  /******/ (function(modules) { // webpackBootstrap
   3  /******/     // The module cache
   4  /******/     var installedModules = {};
   5  /******/
   6  /******/     // The require function
   7  /******/ 	function __webpack_require__(moduleId) {
   8  /******/
   9  /******/         // Check if module is in cache
  10  /******/         if(installedModules[moduleId]) {
  11  /******/             return installedModules[moduleId].exports;
  12  /******/         }
  13  /******/         // Create a new module (and put it into the cache)
  14  /******/         var module = installedModules[moduleId] = {
  15  /******/             i: moduleId,
  16  /******/             l: false,
  17  /******/             exports: {}
  18  /******/         };
  19  /******/
  20  /******/         // Execute the module function
  21  /******/         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  22  /******/
  23  /******/         // Flag the module as loaded
  24  /******/         module.l = true;
  25  /******/
  26  /******/         // Return the exports of the module
  27  /******/         return module.exports;
  28  /******/     }
  29  /******/
  30  /******/
  31  /******/     // expose the modules object (__webpack_modules__)
  32  /******/     __webpack_require__.m = modules;
  33  /******/
  34  /******/     // expose the module cache
  35  /******/     __webpack_require__.c = installedModules;
  36  /******/
  37  /******/     // define getter function for harmony exports
  38  /******/     __webpack_require__.d = function(exports, name, getter) {
  39  /******/         if(!__webpack_require__.o(exports, name)) {
  40  /******/             Object.defineProperty(exports, name, { enumerable: true, get: getter });
  41  /******/         }
  42  /******/     };
  43  /******/
  44  /******/     // define __esModule on exports
  45  /******/     __webpack_require__.r = function(exports) {
  46  /******/         if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  47  /******/             Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  48  /******/         }
  49  /******/         Object.defineProperty(exports, '__esModule', { value: true });
  50  /******/     };
  51  /******/
  52  /******/     // create a fake namespace object
  53  /******/     // mode & 1: value is a module id, require it
  54  /******/     // mode & 2: merge all properties of value into the ns
  55  /******/     // mode & 4: return value when already ns object
  56  /******/     // mode & 8|1: behave like require
  57  /******/     __webpack_require__.t = function(value, mode) {
  58  /******/         if(mode & 1) value = __webpack_require__(value);
  59  /******/         if(mode & 8) return value;
  60  /******/         if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  61  /******/         var ns = Object.create(null);
  62  /******/         __webpack_require__.r(ns);
  63  /******/         Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  64  /******/         if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  65  /******/         return ns;
  66  /******/     };
  67  /******/
  68  /******/     // getDefaultExport function for compatibility with non-harmony modules
  69  /******/     __webpack_require__.n = function(module) {
  70  /******/         var getter = module && module.__esModule ?
  71  /******/ 			function getDefault() { return module['default']; } :
  72  /******/ 			function getModuleExports() { return module; };
  73  /******/         __webpack_require__.d(getter, 'a', getter);
  74  /******/         return getter;
  75  /******/     };
  76  /******/
  77  /******/     // Object.prototype.hasOwnProperty.call
  78  /******/     __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  79  /******/
  80  /******/     // __webpack_public_path__
  81  /******/     __webpack_require__.p = "";
  82  /******/
  83  /******/
  84  /******/     // Load entry module and return exports
  85  /******/     return __webpack_require__(__webpack_require__.s = 348);
  86  /******/ })
  87  /************************************************************************/
  88  /******/ ({
  89  
  90  /***/ 0:
  91  /***/ (function(module, exports) {
  92  
  93  (function() { module.exports = this["wp"]["element"]; }());
  94  
  95  /***/ }),
  96  
  97  /***/ 1:
  98  /***/ (function(module, exports) {
  99  
 100  (function() { module.exports = this["wp"]["i18n"]; }());
 101  
 102  /***/ }),
 103  
 104  /***/ 10:
 105  /***/ (function(module, __webpack_exports__, __webpack_require__) {
 106  
 107  "use strict";
 108  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _classCallCheck; });
 109  function _classCallCheck(instance, Constructor) {
 110    if (!(instance instanceof Constructor)) {
 111      throw new TypeError("Cannot call a class as a function");
 112    }
 113  }
 114  
 115  /***/ }),
 116  
 117  /***/ 136:
 118  /***/ (function(module, exports) {
 119  
 120  (function() { module.exports = this["wp"]["shortcode"]; }());
 121  
 122  /***/ }),
 123  
 124  /***/ 15:
 125  /***/ (function(module, __webpack_exports__, __webpack_require__) {
 126  
 127  "use strict";
 128  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _defineProperty; });
 129  function _defineProperty(obj, key, value) {
 130    if (key in obj) {
 131      Object.defineProperty(obj, key, {
 132        value: value,
 133        enumerable: true,
 134        configurable: true,
 135        writable: true
 136      });
 137    } else {
 138      obj[key] = value;
 139    }
 140  
 141    return obj;
 142  }
 143  
 144  /***/ }),
 145  
 146  /***/ 17:
 147  /***/ (function(module, __webpack_exports__, __webpack_require__) {
 148  
 149  "use strict";
 150  
 151  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js
 152  function _arrayWithoutHoles(arr) {
 153    if (Array.isArray(arr)) {
 154      for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
 155        arr2[i] = arr[i];
 156      }
 157  
 158      return arr2;
 159    }
 160  }
 161  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/iterableToArray.js
 162  var iterableToArray = __webpack_require__(34);
 163  
 164  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js
 165  function _nonIterableSpread() {
 166    throw new TypeError("Invalid attempt to spread non-iterable instance");
 167  }
 168  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js
 169  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _toConsumableArray; });
 170  
 171  
 172  
 173  function _toConsumableArray(arr) {
 174    return _arrayWithoutHoles(arr) || Object(iterableToArray["a" /* default */])(arr) || _nonIterableSpread();
 175  }
 176  
 177  /***/ }),
 178  
 179  /***/ 19:
 180  /***/ (function(module, __webpack_exports__, __webpack_require__) {
 181  
 182  "use strict";
 183  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _extends; });
 184  function _extends() {
 185    _extends = Object.assign || function (target) {
 186      for (var i = 1; i < arguments.length; i++) {
 187        var source = arguments[i];
 188  
 189        for (var key in source) {
 190          if (Object.prototype.hasOwnProperty.call(source, key)) {
 191            target[key] = source[key];
 192          }
 193        }
 194      }
 195  
 196      return target;
 197    };
 198  
 199    return _extends.apply(this, arguments);
 200  }
 201  
 202  /***/ }),
 203  
 204  /***/ 199:
 205  /***/ (function(module, exports) {
 206  
 207  (function() { module.exports = this["wp"]["blockSerializationDefaultParser"]; }());
 208  
 209  /***/ }),
 210  
 211  /***/ 2:
 212  /***/ (function(module, exports) {
 213  
 214  (function() { module.exports = this["lodash"]; }());
 215  
 216  /***/ }),
 217  
 218  /***/ 200:
 219  /***/ (function(module, exports, __webpack_require__) {
 220  
 221  var __WEBPACK_AMD_DEFINE_RESULT__;;/*! showdown v 1.9.0 - 10-11-2018 */
 222  (function(){
 223  /**
 224   * Created by Tivie on 13-07-2015.
 225   */
 226  
 227  function getDefaultOpts (simple) {
 228    'use strict';
 229  
 230    var defaultOptions = {
 231      omitExtraWLInCodeBlocks: {
 232        defaultValue: false,
 233        describe: 'Omit the default extra whiteline added to code blocks',
 234        type: 'boolean'
 235      },
 236      noHeaderId: {
 237        defaultValue: false,
 238        describe: 'Turn on/off generated header id',
 239        type: 'boolean'
 240      },
 241      prefixHeaderId: {
 242        defaultValue: false,
 243        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',
 244        type: 'string'
 245      },
 246      rawPrefixHeaderId: {
 247        defaultValue: false,
 248        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)',
 249        type: 'boolean'
 250      },
 251      ghCompatibleHeaderId: {
 252        defaultValue: false,
 253        describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
 254        type: 'boolean'
 255      },
 256      rawHeaderId: {
 257        defaultValue: false,
 258        describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
 259        type: 'boolean'
 260      },
 261      headerLevelStart: {
 262        defaultValue: false,
 263        describe: 'The header blocks level start',
 264        type: 'integer'
 265      },
 266      parseImgDimensions: {
 267        defaultValue: false,
 268        describe: 'Turn on/off image dimension parsing',
 269        type: 'boolean'
 270      },
 271      simplifiedAutoLink: {
 272        defaultValue: false,
 273        describe: 'Turn on/off GFM autolink style',
 274        type: 'boolean'
 275      },
 276      excludeTrailingPunctuationFromURLs: {
 277        defaultValue: false,
 278        describe: 'Excludes trailing punctuation from links generated with autoLinking',
 279        type: 'boolean'
 280      },
 281      literalMidWordUnderscores: {
 282        defaultValue: false,
 283        describe: 'Parse midword underscores as literal underscores',
 284        type: 'boolean'
 285      },
 286      literalMidWordAsterisks: {
 287        defaultValue: false,
 288        describe: 'Parse midword asterisks as literal asterisks',
 289        type: 'boolean'
 290      },
 291      strikethrough: {
 292        defaultValue: false,
 293        describe: 'Turn on/off strikethrough support',
 294        type: 'boolean'
 295      },
 296      tables: {
 297        defaultValue: false,
 298        describe: 'Turn on/off tables support',
 299        type: 'boolean'
 300      },
 301      tablesHeaderId: {
 302        defaultValue: false,
 303        describe: 'Add an id to table headers',
 304        type: 'boolean'
 305      },
 306      ghCodeBlocks: {
 307        defaultValue: true,
 308        describe: 'Turn on/off GFM fenced code blocks support',
 309        type: 'boolean'
 310      },
 311      tasklists: {
 312        defaultValue: false,
 313        describe: 'Turn on/off GFM tasklist support',
 314        type: 'boolean'
 315      },
 316      smoothLivePreview: {
 317        defaultValue: false,
 318        describe: 'Prevents weird effects in live previews due to incomplete input',
 319        type: 'boolean'
 320      },
 321      smartIndentationFix: {
 322        defaultValue: false,
 323        description: 'Tries to smartly fix indentation in es6 strings',
 324        type: 'boolean'
 325      },
 326      disableForced4SpacesIndentedSublists: {
 327        defaultValue: false,
 328        description: 'Disables the requirement of indenting nested sublists by 4 spaces',
 329        type: 'boolean'
 330      },
 331      simpleLineBreaks: {
 332        defaultValue: false,
 333        description: 'Parses simple line breaks as <br> (GFM Style)',
 334        type: 'boolean'
 335      },
 336      requireSpaceBeforeHeadingText: {
 337        defaultValue: false,
 338        description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
 339        type: 'boolean'
 340      },
 341      ghMentions: {
 342        defaultValue: false,
 343        description: 'Enables github @mentions',
 344        type: 'boolean'
 345      },
 346      ghMentionsLink: {
 347        defaultValue: 'https://github.com/{u}',
 348        description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
 349        type: 'string'
 350      },
 351      encodeEmails: {
 352        defaultValue: true,
 353        description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
 354        type: 'boolean'
 355      },
 356      openLinksInNewWindow: {
 357        defaultValue: false,
 358        description: 'Open all links in new windows',
 359        type: 'boolean'
 360      },
 361      backslashEscapesHTMLTags: {
 362        defaultValue: false,
 363        description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
 364        type: 'boolean'
 365      },
 366      emoji: {
 367        defaultValue: false,
 368        description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
 369        type: 'boolean'
 370      },
 371      underline: {
 372        defaultValue: false,
 373        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>`',
 374        type: 'boolean'
 375      },
 376      completeHTMLDocument: {
 377        defaultValue: false,
 378        description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
 379        type: 'boolean'
 380      },
 381      metadata: {
 382        defaultValue: false,
 383        description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
 384        type: 'boolean'
 385      },
 386      splitAdjacentBlockquotes: {
 387        defaultValue: false,
 388        description: 'Split adjacent blockquote blocks',
 389        type: 'boolean'
 390      }
 391    };
 392    if (simple === false) {
 393      return JSON.parse(JSON.stringify(defaultOptions));
 394    }
 395    var ret = {};
 396    for (var opt in defaultOptions) {
 397      if (defaultOptions.hasOwnProperty(opt)) {
 398        ret[opt] = defaultOptions[opt].defaultValue;
 399      }
 400    }
 401    return ret;
 402  }
 403  
 404  function allOptionsOn () {
 405    'use strict';
 406    var options = getDefaultOpts(true),
 407        ret = {};
 408    for (var opt in options) {
 409      if (options.hasOwnProperty(opt)) {
 410        ret[opt] = true;
 411      }
 412    }
 413    return ret;
 414  }
 415  
 416  /**
 417   * Created by Tivie on 06-01-2015.
 418   */
 419  
 420  // Private properties
 421  var showdown = {},
 422      parsers = {},
 423      extensions = {},
 424      globalOptions = getDefaultOpts(true),
 425      setFlavor = 'vanilla',
 426      flavor = {
 427        github: {
 428          omitExtraWLInCodeBlocks:              true,
 429          simplifiedAutoLink:                   true,
 430          excludeTrailingPunctuationFromURLs:   true,
 431          literalMidWordUnderscores:            true,
 432          strikethrough:                        true,
 433          tables:                               true,
 434          tablesHeaderId:                       true,
 435          ghCodeBlocks:                         true,
 436          tasklists:                            true,
 437          disableForced4SpacesIndentedSublists: true,
 438          simpleLineBreaks:                     true,
 439          requireSpaceBeforeHeadingText:        true,
 440          ghCompatibleHeaderId:                 true,
 441          ghMentions:                           true,
 442          backslashEscapesHTMLTags:             true,
 443          emoji:                                true,
 444          splitAdjacentBlockquotes:             true
 445        },
 446        original: {
 447          noHeaderId:                           true,
 448          ghCodeBlocks:                         false
 449        },
 450        ghost: {
 451          omitExtraWLInCodeBlocks:              true,
 452          parseImgDimensions:                   true,
 453          simplifiedAutoLink:                   true,
 454          excludeTrailingPunctuationFromURLs:   true,
 455          literalMidWordUnderscores:            true,
 456          strikethrough:                        true,
 457          tables:                               true,
 458          tablesHeaderId:                       true,
 459          ghCodeBlocks:                         true,
 460          tasklists:                            true,
 461          smoothLivePreview:                    true,
 462          simpleLineBreaks:                     true,
 463          requireSpaceBeforeHeadingText:        true,
 464          ghMentions:                           false,
 465          encodeEmails:                         true
 466        },
 467        vanilla: getDefaultOpts(true),
 468        allOn: allOptionsOn()
 469      };
 470  
 471  /**
 472   * helper namespace
 473   * @type {{}}
 474   */
 475  showdown.helper = {};
 476  
 477  /**
 478   * TODO LEGACY SUPPORT CODE
 479   * @type {{}}
 480   */
 481  showdown.extensions = {};
 482  
 483  /**
 484   * Set a global option
 485   * @static
 486   * @param {string} key
 487   * @param {*} value
 488   * @returns {showdown}
 489   */
 490  showdown.setOption = function (key, value) {
 491    'use strict';
 492    globalOptions[key] = value;
 493    return this;
 494  };
 495  
 496  /**
 497   * Get a global option
 498   * @static
 499   * @param {string} key
 500   * @returns {*}
 501   */
 502  showdown.getOption = function (key) {
 503    'use strict';
 504    return globalOptions[key];
 505  };
 506  
 507  /**
 508   * Get the global options
 509   * @static
 510   * @returns {{}}
 511   */
 512  showdown.getOptions = function () {
 513    'use strict';
 514    return globalOptions;
 515  };
 516  
 517  /**
 518   * Reset global options to the default values
 519   * @static
 520   */
 521  showdown.resetOptions = function () {
 522    'use strict';
 523    globalOptions = getDefaultOpts(true);
 524  };
 525  
 526  /**
 527   * Set the flavor showdown should use as default
 528   * @param {string} name
 529   */
 530  showdown.setFlavor = function (name) {
 531    'use strict';
 532    if (!flavor.hasOwnProperty(name)) {
 533      throw Error(name + ' flavor was not found');
 534    }
 535    showdown.resetOptions();
 536    var preset = flavor[name];
 537    setFlavor = name;
 538    for (var option in preset) {
 539      if (preset.hasOwnProperty(option)) {
 540        globalOptions[option] = preset[option];
 541      }
 542    }
 543  };
 544  
 545  /**
 546   * Get the currently set flavor
 547   * @returns {string}
 548   */
 549  showdown.getFlavor = function () {
 550    'use strict';
 551    return setFlavor;
 552  };
 553  
 554  /**
 555   * Get the options of a specified flavor. Returns undefined if the flavor was not found
 556   * @param {string} name Name of the flavor
 557   * @returns {{}|undefined}
 558   */
 559  showdown.getFlavorOptions = function (name) {
 560    'use strict';
 561    if (flavor.hasOwnProperty(name)) {
 562      return flavor[name];
 563    }
 564  };
 565  
 566  /**
 567   * Get the default options
 568   * @static
 569   * @param {boolean} [simple=true]
 570   * @returns {{}}
 571   */
 572  showdown.getDefaultOptions = function (simple) {
 573    'use strict';
 574    return getDefaultOpts(simple);
 575  };
 576  
 577  /**
 578   * Get or set a subParser
 579   *
 580   * subParser(name)       - Get a registered subParser
 581   * subParser(name, func) - Register a subParser
 582   * @static
 583   * @param {string} name
 584   * @param {function} [func]
 585   * @returns {*}
 586   */
 587  showdown.subParser = function (name, func) {
 588    'use strict';
 589    if (showdown.helper.isString(name)) {
 590      if (typeof func !== 'undefined') {
 591        parsers[name] = func;
 592      } else {
 593        if (parsers.hasOwnProperty(name)) {
 594          return parsers[name];
 595        } else {
 596          throw Error('SubParser named ' + name + ' not registered!');
 597        }
 598      }
 599    }
 600  };
 601  
 602  /**
 603   * Gets or registers an extension
 604   * @static
 605   * @param {string} name
 606   * @param {object|function=} ext
 607   * @returns {*}
 608   */
 609  showdown.extension = function (name, ext) {
 610    'use strict';
 611  
 612    if (!showdown.helper.isString(name)) {
 613      throw Error('Extension \'name\' must be a string');
 614    }
 615  
 616    name = showdown.helper.stdExtName(name);
 617  
 618    // Getter
 619    if (showdown.helper.isUndefined(ext)) {
 620      if (!extensions.hasOwnProperty(name)) {
 621        throw Error('Extension named ' + name + ' is not registered!');
 622      }
 623      return extensions[name];
 624  
 625      // Setter
 626    } else {
 627      // Expand extension if it's wrapped in a function
 628      if (typeof ext === 'function') {
 629        ext = ext();
 630      }
 631  
 632      // Ensure extension is an array
 633      if (!showdown.helper.isArray(ext)) {
 634        ext = [ext];
 635      }
 636  
 637      var validExtension = validate(ext, name);
 638  
 639      if (validExtension.valid) {
 640        extensions[name] = ext;
 641      } else {
 642        throw Error(validExtension.error);
 643      }
 644    }
 645  };
 646  
 647  /**
 648   * Gets all extensions registered
 649   * @returns {{}}
 650   */
 651  showdown.getAllExtensions = function () {
 652    'use strict';
 653    return extensions;
 654  };
 655  
 656  /**
 657   * Remove an extension
 658   * @param {string} name
 659   */
 660  showdown.removeExtension = function (name) {
 661    'use strict';
 662    delete extensions[name];
 663  };
 664  
 665  /**
 666   * Removes all extensions
 667   */
 668  showdown.resetExtensions = function () {
 669    'use strict';
 670    extensions = {};
 671  };
 672  
 673  /**
 674   * Validate extension
 675   * @param {array} extension
 676   * @param {string} name
 677   * @returns {{valid: boolean, error: string}}
 678   */
 679  function validate (extension, name) {
 680    'use strict';
 681  
 682    var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
 683        ret = {
 684          valid: true,
 685          error: ''
 686        };
 687  
 688    if (!showdown.helper.isArray(extension)) {
 689      extension = [extension];
 690    }
 691  
 692    for (var i = 0; i < extension.length; ++i) {
 693      var baseMsg = errMsg + ' sub-extension ' + i + ': ',
 694          ext = extension[i];
 695      if (typeof ext !== 'object') {
 696        ret.valid = false;
 697        ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
 698        return ret;
 699      }
 700  
 701      if (!showdown.helper.isString(ext.type)) {
 702        ret.valid = false;
 703        ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
 704        return ret;
 705      }
 706  
 707      var type = ext.type = ext.type.toLowerCase();
 708  
 709      // normalize extension type
 710      if (type === 'language') {
 711        type = ext.type = 'lang';
 712      }
 713  
 714      if (type === 'html') {
 715        type = ext.type = 'output';
 716      }
 717  
 718      if (type !== 'lang' && type !== 'output' && type !== 'listener') {
 719        ret.valid = false;
 720        ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
 721        return ret;
 722      }
 723  
 724      if (type === 'listener') {
 725        if (showdown.helper.isUndefined(ext.listeners)) {
 726          ret.valid = false;
 727          ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
 728          return ret;
 729        }
 730      } else {
 731        if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
 732          ret.valid = false;
 733          ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
 734          return ret;
 735        }
 736      }
 737  
 738      if (ext.listeners) {
 739        if (typeof ext.listeners !== 'object') {
 740          ret.valid = false;
 741          ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
 742          return ret;
 743        }
 744        for (var ln in ext.listeners) {
 745          if (ext.listeners.hasOwnProperty(ln)) {
 746            if (typeof ext.listeners[ln] !== 'function') {
 747              ret.valid = false;
 748              ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
 749                ' must be a function but ' + typeof ext.listeners[ln] + ' given';
 750              return ret;
 751            }
 752          }
 753        }
 754      }
 755  
 756      if (ext.filter) {
 757        if (typeof ext.filter !== 'function') {
 758          ret.valid = false;
 759          ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
 760          return ret;
 761        }
 762      } else if (ext.regex) {
 763        if (showdown.helper.isString(ext.regex)) {
 764          ext.regex = new RegExp(ext.regex, 'g');
 765        }
 766        if (!(ext.regex instanceof RegExp)) {
 767          ret.valid = false;
 768          ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
 769          return ret;
 770        }
 771        if (showdown.helper.isUndefined(ext.replace)) {
 772          ret.valid = false;
 773          ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
 774          return ret;
 775        }
 776      }
 777    }
 778    return ret;
 779  }
 780  
 781  /**
 782   * Validate extension
 783   * @param {object} ext
 784   * @returns {boolean}
 785   */
 786  showdown.validateExtension = function (ext) {
 787    'use strict';
 788  
 789    var validateExtension = validate(ext, null);
 790    if (!validateExtension.valid) {
 791      console.warn(validateExtension.error);
 792      return false;
 793    }
 794    return true;
 795  };
 796  
 797  /**
 798   * showdownjs helper functions
 799   */
 800  
 801  if (!showdown.hasOwnProperty('helper')) {
 802    showdown.helper = {};
 803  }
 804  
 805  /**
 806   * Check if var is string
 807   * @static
 808   * @param {string} a
 809   * @returns {boolean}
 810   */
 811  showdown.helper.isString = function (a) {
 812    'use strict';
 813    return (typeof a === 'string' || a instanceof String);
 814  };
 815  
 816  /**
 817   * Check if var is a function
 818   * @static
 819   * @param {*} a
 820   * @returns {boolean}
 821   */
 822  showdown.helper.isFunction = function (a) {
 823    'use strict';
 824    var getType = {};
 825    return a && getType.toString.call(a) === '[object Function]';
 826  };
 827  
 828  /**
 829   * isArray helper function
 830   * @static
 831   * @param {*} a
 832   * @returns {boolean}
 833   */
 834  showdown.helper.isArray = function (a) {
 835    'use strict';
 836    return Array.isArray(a);
 837  };
 838  
 839  /**
 840   * Check if value is undefined
 841   * @static
 842   * @param {*} value The value to check.
 843   * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
 844   */
 845  showdown.helper.isUndefined = function (value) {
 846    'use strict';
 847    return typeof value === 'undefined';
 848  };
 849  
 850  /**
 851   * ForEach helper function
 852   * Iterates over Arrays and Objects (own properties only)
 853   * @static
 854   * @param {*} obj
 855   * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
 856   */
 857  showdown.helper.forEach = function (obj, callback) {
 858    'use strict';
 859    // check if obj is defined
 860    if (showdown.helper.isUndefined(obj)) {
 861      throw new Error('obj param is required');
 862    }
 863  
 864    if (showdown.helper.isUndefined(callback)) {
 865      throw new Error('callback param is required');
 866    }
 867  
 868    if (!showdown.helper.isFunction(callback)) {
 869      throw new Error('callback param must be a function/closure');
 870    }
 871  
 872    if (typeof obj.forEach === 'function') {
 873      obj.forEach(callback);
 874    } else if (showdown.helper.isArray(obj)) {
 875      for (var i = 0; i < obj.length; i++) {
 876        callback(obj[i], i, obj);
 877      }
 878    } else if (typeof (obj) === 'object') {
 879      for (var prop in obj) {
 880        if (obj.hasOwnProperty(prop)) {
 881          callback(obj[prop], prop, obj);
 882        }
 883      }
 884    } else {
 885      throw new Error('obj does not seem to be an array or an iterable object');
 886    }
 887  };
 888  
 889  /**
 890   * Standardidize extension name
 891   * @static
 892   * @param {string} s extension name
 893   * @returns {string}
 894   */
 895  showdown.helper.stdExtName = function (s) {
 896    'use strict';
 897    return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
 898  };
 899  
 900  function escapeCharactersCallback (wholeMatch, m1) {
 901    'use strict';
 902    var charCodeToEscape = m1.charCodeAt(0);
 903    return '¨E' + charCodeToEscape + 'E';
 904  }
 905  
 906  /**
 907   * Callback used to escape characters when passing through String.replace
 908   * @static
 909   * @param {string} wholeMatch
 910   * @param {string} m1
 911   * @returns {string}
 912   */
 913  showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
 914  
 915  /**
 916   * Escape characters in a string
 917   * @static
 918   * @param {string} text
 919   * @param {string} charsToEscape
 920   * @param {boolean} afterBackslash
 921   * @returns {XML|string|void|*}
 922   */
 923  showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
 924    'use strict';
 925    // First we have to escape the escape characters so that
 926    // we can build a character class out of them
 927    var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
 928  
 929    if (afterBackslash) {
 930      regexString = '\\\\' + regexString;
 931    }
 932  
 933    var regex = new RegExp(regexString, 'g');
 934    text = text.replace(regex, escapeCharactersCallback);
 935  
 936    return text;
 937  };
 938  
 939  /**
 940   * Unescape HTML entities
 941   * @param txt
 942   * @returns {string}
 943   */
 944  showdown.helper.unescapeHTMLEntities = function (txt) {
 945    'use strict';
 946  
 947    return txt
 948      .replace(/&quot;/g, '"')
 949      .replace(/&lt;/g, '<')
 950      .replace(/&gt;/g, '>')
 951      .replace(/&amp;/g, '&');
 952  };
 953  
 954  var rgxFindMatchPos = function (str, left, right, flags) {
 955    'use strict';
 956    var f = flags || '',
 957        g = f.indexOf('g') > -1,
 958        x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
 959        l = new RegExp(left, f.replace(/g/g, '')),
 960        pos = [],
 961        t, s, m, start, end;
 962  
 963    do {
 964      t = 0;
 965      while ((m = x.exec(str))) {
 966        if (l.test(m[0])) {
 967          if (!(t++)) {
 968            s = x.lastIndex;
 969            start = s - m[0].length;
 970          }
 971        } else if (t) {
 972          if (!--t) {
 973            end = m.index + m[0].length;
 974            var obj = {
 975              left: {start: start, end: s},
 976              match: {start: s, end: m.index},
 977              right: {start: m.index, end: end},
 978              wholeMatch: {start: start, end: end}
 979            };
 980            pos.push(obj);
 981            if (!g) {
 982              return pos;
 983            }
 984          }
 985        }
 986      }
 987    } while (t && (x.lastIndex = s));
 988  
 989    return pos;
 990  };
 991  
 992  /**
 993   * matchRecursiveRegExp
 994   *
 995   * (c) 2007 Steven Levithan <stevenlevithan.com>
 996   * MIT License
 997   *
 998   * Accepts a string to search, a left and right format delimiter
 999   * as regex patterns, and optional regex flags. Returns an array
1000   * of matches, allowing nested instances of left/right delimiters.
1001   * Use the "g" flag to return all matches, otherwise only the
1002   * first is returned. Be careful to ensure that the left and
1003   * right format delimiters produce mutually exclusive matches.
1004   * Backreferences are not supported within the right delimiter
1005   * due to how it is internally combined with the left delimiter.
1006   * When matching strings whose format delimiters are unbalanced
1007   * to the left or right, the output is intentionally as a
1008   * conventional regex library with recursion support would
1009   * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
1010   * "<" and ">" as the delimiters (both strings contain a single,
1011   * balanced instance of "<x>").
1012   *
1013   * examples:
1014   * matchRecursiveRegExp("test", "\\(", "\\)")
1015   * returns: []
1016   * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
1017   * returns: ["t<<e>><s>", ""]
1018   * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
1019   * returns: ["test"]
1020   */
1021  showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
1022    'use strict';
1023  
1024    var matchPos = rgxFindMatchPos (str, left, right, flags),
1025        results = [];
1026  
1027    for (var i = 0; i < matchPos.length; ++i) {
1028      results.push([
1029        str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1030        str.slice(matchPos[i].match.start, matchPos[i].match.end),
1031        str.slice(matchPos[i].left.start, matchPos[i].left.end),
1032        str.slice(matchPos[i].right.start, matchPos[i].right.end)
1033      ]);
1034    }
1035    return results;
1036  };
1037  
1038  /**
1039   *
1040   * @param {string} str
1041   * @param {string|function} replacement
1042   * @param {string} left
1043   * @param {string} right
1044   * @param {string} flags
1045   * @returns {string}
1046   */
1047  showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
1048    'use strict';
1049  
1050    if (!showdown.helper.isFunction(replacement)) {
1051      var repStr = replacement;
1052      replacement = function () {
1053        return repStr;
1054      };
1055    }
1056  
1057    var matchPos = rgxFindMatchPos(str, left, right, flags),
1058        finalStr = str,
1059        lng = matchPos.length;
1060  
1061    if (lng > 0) {
1062      var bits = [];
1063      if (matchPos[0].wholeMatch.start !== 0) {
1064        bits.push(str.slice(0, matchPos[0].wholeMatch.start));
1065      }
1066      for (var i = 0; i < lng; ++i) {
1067        bits.push(
1068          replacement(
1069            str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
1070            str.slice(matchPos[i].match.start, matchPos[i].match.end),
1071            str.slice(matchPos[i].left.start, matchPos[i].left.end),
1072            str.slice(matchPos[i].right.start, matchPos[i].right.end)
1073          )
1074        );
1075        if (i < lng - 1) {
1076          bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
1077        }
1078      }
1079      if (matchPos[lng - 1].wholeMatch.end < str.length) {
1080        bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
1081      }
1082      finalStr = bits.join('');
1083    }
1084    return finalStr;
1085  };
1086  
1087  /**
1088   * Returns the index within the passed String object of the first occurrence of the specified regex,
1089   * starting the search at fromIndex. Returns -1 if the value is not found.
1090   *
1091   * @param {string} str string to search
1092   * @param {RegExp} regex Regular expression to search
1093   * @param {int} [fromIndex = 0] Index to start the search
1094   * @returns {Number}
1095   * @throws InvalidArgumentError
1096   */
1097  showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
1098    'use strict';
1099    if (!showdown.helper.isString(str)) {
1100      throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1101    }
1102    if (regex instanceof RegExp === false) {
1103      throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
1104    }
1105    var indexOf = str.substring(fromIndex || 0).search(regex);
1106    return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
1107  };
1108  
1109  /**
1110   * Splits the passed string object at the defined index, and returns an array composed of the two substrings
1111   * @param {string} str string to split
1112   * @param {int} index index to split string at
1113   * @returns {[string,string]}
1114   * @throws InvalidArgumentError
1115   */
1116  showdown.helper.splitAtIndex = function (str, index) {
1117    'use strict';
1118    if (!showdown.helper.isString(str)) {
1119      throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
1120    }
1121    return [str.substring(0, index), str.substring(index)];
1122  };
1123  
1124  /**
1125   * Obfuscate an e-mail address through the use of Character Entities,
1126   * transforming ASCII characters into their equivalent decimal or hex entities.
1127   *
1128   * Since it has a random component, subsequent calls to this function produce different results
1129   *
1130   * @param {string} mail
1131   * @returns {string}
1132   */
1133  showdown.helper.encodeEmailAddress = function (mail) {
1134    'use strict';
1135    var encode = [
1136      function (ch) {
1137        return '&#' + ch.charCodeAt(0) + ';';
1138      },
1139      function (ch) {
1140        return '&#x' + ch.charCodeAt(0).toString(16) + ';';
1141      },
1142      function (ch) {
1143        return ch;
1144      }
1145    ];
1146  
1147    mail = mail.replace(/./g, function (ch) {
1148      if (ch === '@') {
1149        // this *must* be encoded. I insist.
1150        ch = encode[Math.floor(Math.random() * 2)](ch);
1151      } else {
1152        var r = Math.random();
1153        // roughly 10% raw, 45% hex, 45% dec
1154        ch = (
1155          r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1156        );
1157      }
1158      return ch;
1159    });
1160  
1161    return mail;
1162  };
1163  
1164  /**
1165   *
1166   * @param str
1167   * @param targetLength
1168   * @param padString
1169   * @returns {string}
1170   */
1171  showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
1172    'use strict';
1173    /*jshint bitwise: false*/
1174    // eslint-disable-next-line space-infix-ops
1175    targetLength = targetLength>>0; //floor if number or convert non-number to 0;
1176    /*jshint bitwise: true*/
1177    padString = String(padString || ' ');
1178    if (str.length > targetLength) {
1179      return String(str);
1180    } else {
1181      targetLength = targetLength - str.length;
1182      if (targetLength > padString.length) {
1183        padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
1184      }
1185      return String(str) + padString.slice(0,targetLength);
1186    }
1187  };
1188  
1189  /**
1190   * POLYFILLS
1191   */
1192  // use this instead of builtin is undefined for IE8 compatibility
1193  if (typeof(console) === 'undefined') {
1194    console = {
1195      warn: function (msg) {
1196        'use strict';
1197        alert(msg);
1198      },
1199      log: function (msg) {
1200        'use strict';
1201        alert(msg);
1202      },
1203      error: function (msg) {
1204        'use strict';
1205        throw msg;
1206      }
1207    };
1208  }
1209  
1210  /**
1211   * Common regexes.
1212   * We declare some common regexes to improve performance
1213   */
1214  showdown.helper.regexes = {
1215    asteriskDashAndColon: /([*_:~])/g
1216  };
1217  
1218  /**
1219   * EMOJIS LIST
1220   */
1221  showdown.helper.emojis = {
1222    '+1':'\ud83d\udc4d',
1223    '-1':'\ud83d\udc4e',
1224    '100':'\ud83d\udcaf',
1225    '1234':'\ud83d\udd22',
1226    '1st_place_medal':'\ud83e\udd47',
1227    '2nd_place_medal':'\ud83e\udd48',
1228    '3rd_place_medal':'\ud83e\udd49',
1229    '8ball':'\ud83c\udfb1',
1230    'a':'\ud83c\udd70\ufe0f',
1231    'ab':'\ud83c\udd8e',
1232    'abc':'\ud83d\udd24',
1233    'abcd':'\ud83d\udd21',
1234    'accept':'\ud83c\ude51',
1235    'aerial_tramway':'\ud83d\udea1',
1236    'airplane':'\u2708\ufe0f',
1237    'alarm_clock':'\u23f0',
1238    'alembic':'\u2697\ufe0f',
1239    'alien':'\ud83d\udc7d',
1240    'ambulance':'\ud83d\ude91',
1241    'amphora':'\ud83c\udffa',
1242    'anchor':'\u2693\ufe0f',
1243    'angel':'\ud83d\udc7c',
1244    'anger':'\ud83d\udca2',
1245    'angry':'\ud83d\ude20',
1246    'anguished':'\ud83d\ude27',
1247    'ant':'\ud83d\udc1c',
1248    'apple':'\ud83c\udf4e',
1249    'aquarius':'\u2652\ufe0f',
1250    'aries':'\u2648\ufe0f',
1251    'arrow_backward':'\u25c0\ufe0f',
1252    'arrow_double_down':'\u23ec',
1253    'arrow_double_up':'\u23eb',
1254    'arrow_down':'\u2b07\ufe0f',
1255    'arrow_down_small':'\ud83d\udd3d',
1256    'arrow_forward':'\u25b6\ufe0f',
1257    'arrow_heading_down':'\u2935\ufe0f',
1258    'arrow_heading_up':'\u2934\ufe0f',
1259    'arrow_left':'\u2b05\ufe0f',
1260    'arrow_lower_left':'\u2199\ufe0f',
1261    'arrow_lower_right':'\u2198\ufe0f',
1262    'arrow_right':'\u27a1\ufe0f',
1263    'arrow_right_hook':'\u21aa\ufe0f',
1264    'arrow_up':'\u2b06\ufe0f',
1265    'arrow_up_down':'\u2195\ufe0f',
1266    'arrow_up_small':'\ud83d\udd3c',
1267    'arrow_upper_left':'\u2196\ufe0f',
1268    'arrow_upper_right':'\u2197\ufe0f',
1269    'arrows_clockwise':'\ud83d\udd03',
1270    'arrows_counterclockwise':'\ud83d\udd04',
1271    'art':'\ud83c\udfa8',
1272    'articulated_lorry':'\ud83d\ude9b',
1273    'artificial_satellite':'\ud83d\udef0',
1274    'astonished':'\ud83d\ude32',
1275    'athletic_shoe':'\ud83d\udc5f',
1276    'atm':'\ud83c\udfe7',
1277    'atom_symbol':'\u269b\ufe0f',
1278    'avocado':'\ud83e\udd51',
1279    'b':'\ud83c\udd71\ufe0f',
1280    'baby':'\ud83d\udc76',
1281    'baby_bottle':'\ud83c\udf7c',
1282    'baby_chick':'\ud83d\udc24',
1283    'baby_symbol':'\ud83d\udebc',
1284    'back':'\ud83d\udd19',
1285    'bacon':'\ud83e\udd53',
1286    'badminton':'\ud83c\udff8',
1287    'baggage_claim':'\ud83d\udec4',
1288    'baguette_bread':'\ud83e\udd56',
1289    'balance_scale':'\u2696\ufe0f',
1290    'balloon':'\ud83c\udf88',
1291    'ballot_box':'\ud83d\uddf3',
1292    'ballot_box_with_check':'\u2611\ufe0f',
1293    'bamboo':'\ud83c\udf8d',
1294    'banana':'\ud83c\udf4c',
1295    'bangbang':'\u203c\ufe0f',
1296    'bank':'\ud83c\udfe6',
1297    'bar_chart':'\ud83d\udcca',
1298    'barber':'\ud83d\udc88',
1299    'baseball':'\u26be\ufe0f',
1300    'basketball':'\ud83c\udfc0',
1301    'basketball_man':'\u26f9\ufe0f',
1302    'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1303    'bat':'\ud83e\udd87',
1304    'bath':'\ud83d\udec0',
1305    'bathtub':'\ud83d\udec1',
1306    'battery':'\ud83d\udd0b',
1307    'beach_umbrella':'\ud83c\udfd6',
1308    'bear':'\ud83d\udc3b',
1309    'bed':'\ud83d\udecf',
1310    'bee':'\ud83d\udc1d',
1311    'beer':'\ud83c\udf7a',
1312    'beers':'\ud83c\udf7b',
1313    'beetle':'\ud83d\udc1e',
1314    'beginner':'\ud83d\udd30',
1315    'bell':'\ud83d\udd14',
1316    'bellhop_bell':'\ud83d\udece',
1317    'bento':'\ud83c\udf71',
1318    'biking_man':'\ud83d\udeb4',
1319    'bike':'\ud83d\udeb2',
1320    'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1321    'bikini':'\ud83d\udc59',
1322    'biohazard':'\u2623\ufe0f',
1323    'bird':'\ud83d\udc26',
1324    'birthday':'\ud83c\udf82',
1325    'black_circle':'\u26ab\ufe0f',
1326    'black_flag':'\ud83c\udff4',
1327    'black_heart':'\ud83d\udda4',
1328    'black_joker':'\ud83c\udccf',
1329    'black_large_square':'\u2b1b\ufe0f',
1330    'black_medium_small_square':'\u25fe\ufe0f',
1331    'black_medium_square':'\u25fc\ufe0f',
1332    'black_nib':'\u2712\ufe0f',
1333    'black_small_square':'\u25aa\ufe0f',
1334    'black_square_button':'\ud83d\udd32',
1335    'blonde_man':'\ud83d\udc71',
1336    'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1337    'blossom':'\ud83c\udf3c',
1338    'blowfish':'\ud83d\udc21',
1339    'blue_book':'\ud83d\udcd8',
1340    'blue_car':'\ud83d\ude99',
1341    'blue_heart':'\ud83d\udc99',
1342    'blush':'\ud83d\ude0a',
1343    'boar':'\ud83d\udc17',
1344    'boat':'\u26f5\ufe0f',
1345    'bomb':'\ud83d\udca3',
1346    'book':'\ud83d\udcd6',
1347    'bookmark':'\ud83d\udd16',
1348    'bookmark_tabs':'\ud83d\udcd1',
1349    'books':'\ud83d\udcda',
1350    'boom':'\ud83d\udca5',
1351    'boot':'\ud83d\udc62',
1352    'bouquet':'\ud83d\udc90',
1353    'bowing_man':'\ud83d\ude47',
1354    'bow_and_arrow':'\ud83c\udff9',
1355    'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1356    'bowling':'\ud83c\udfb3',
1357    'boxing_glove':'\ud83e\udd4a',
1358    'boy':'\ud83d\udc66',
1359    'bread':'\ud83c\udf5e',
1360    'bride_with_veil':'\ud83d\udc70',
1361    'bridge_at_night':'\ud83c\udf09',
1362    'briefcase':'\ud83d\udcbc',
1363    'broken_heart':'\ud83d\udc94',
1364    'bug':'\ud83d\udc1b',
1365    'building_construction':'\ud83c\udfd7',
1366    'bulb':'\ud83d\udca1',
1367    'bullettrain_front':'\ud83d\ude85',
1368    'bullettrain_side':'\ud83d\ude84',
1369    'burrito':'\ud83c\udf2f',
1370    'bus':'\ud83d\ude8c',
1371    'business_suit_levitating':'\ud83d\udd74',
1372    'busstop':'\ud83d\ude8f',
1373    'bust_in_silhouette':'\ud83d\udc64',
1374    'busts_in_silhouette':'\ud83d\udc65',
1375    'butterfly':'\ud83e\udd8b',
1376    'cactus':'\ud83c\udf35',
1377    'cake':'\ud83c\udf70',
1378    'calendar':'\ud83d\udcc6',
1379    'call_me_hand':'\ud83e\udd19',
1380    'calling':'\ud83d\udcf2',
1381    'camel':'\ud83d\udc2b',
1382    'camera':'\ud83d\udcf7',
1383    'camera_flash':'\ud83d\udcf8',
1384    'camping':'\ud83c\udfd5',
1385    'cancer':'\u264b\ufe0f',
1386    'candle':'\ud83d\udd6f',
1387    'candy':'\ud83c\udf6c',
1388    'canoe':'\ud83d\udef6',
1389    'capital_abcd':'\ud83d\udd20',
1390    'capricorn':'\u2651\ufe0f',
1391    'car':'\ud83d\ude97',
1392    'card_file_box':'\ud83d\uddc3',
1393    'card_index':'\ud83d\udcc7',
1394    'card_index_dividers':'\ud83d\uddc2',
1395    'carousel_horse':'\ud83c\udfa0',
1396    'carrot':'\ud83e\udd55',
1397    'cat':'\ud83d\udc31',
1398    'cat2':'\ud83d\udc08',
1399    'cd':'\ud83d\udcbf',
1400    'chains':'\u26d3',
1401    'champagne':'\ud83c\udf7e',
1402    'chart':'\ud83d\udcb9',
1403    'chart_with_downwards_trend':'\ud83d\udcc9',
1404    'chart_with_upwards_trend':'\ud83d\udcc8',
1405    'checkered_flag':'\ud83c\udfc1',
1406    'cheese':'\ud83e\uddc0',
1407    'cherries':'\ud83c\udf52',
1408    'cherry_blossom':'\ud83c\udf38',
1409    'chestnut':'\ud83c\udf30',
1410    'chicken':'\ud83d\udc14',
1411    'children_crossing':'\ud83d\udeb8',
1412    'chipmunk':'\ud83d\udc3f',
1413    'chocolate_bar':'\ud83c\udf6b',
1414    'christmas_tree':'\ud83c\udf84',
1415    'church':'\u26ea\ufe0f',
1416    'cinema':'\ud83c\udfa6',
1417    'circus_tent':'\ud83c\udfaa',
1418    'city_sunrise':'\ud83c\udf07',
1419    'city_sunset':'\ud83c\udf06',
1420    'cityscape':'\ud83c\udfd9',
1421    'cl':'\ud83c\udd91',
1422    'clamp':'\ud83d\udddc',
1423    'clap':'\ud83d\udc4f',
1424    'clapper':'\ud83c\udfac',
1425    'classical_building':'\ud83c\udfdb',
1426    'clinking_glasses':'\ud83e\udd42',
1427    'clipboard':'\ud83d\udccb',
1428    'clock1':'\ud83d\udd50',
1429    'clock10':'\ud83d\udd59',
1430    'clock1030':'\ud83d\udd65',
1431    'clock11':'\ud83d\udd5a',
1432    'clock1130':'\ud83d\udd66',
1433    'clock12':'\ud83d\udd5b',
1434    'clock1230':'\ud83d\udd67',
1435    'clock130':'\ud83d\udd5c',
1436    'clock2':'\ud83d\udd51',
1437    'clock230':'\ud83d\udd5d',
1438    'clock3':'\ud83d\udd52',
1439    'clock330':'\ud83d\udd5e',
1440    'clock4':'\ud83d\udd53',
1441    'clock430':'\ud83d\udd5f',
1442    'clock5':'\ud83d\udd54',
1443    'clock530':'\ud83d\udd60',
1444    'clock6':'\ud83d\udd55',
1445    'clock630':'\ud83d\udd61',
1446    'clock7':'\ud83d\udd56',
1447    'clock730':'\ud83d\udd62',
1448    'clock8':'\ud83d\udd57',
1449    'clock830':'\ud83d\udd63',
1450    'clock9':'\ud83d\udd58',
1451    'clock930':'\ud83d\udd64',
1452    'closed_book':'\ud83d\udcd5',
1453    'closed_lock_with_key':'\ud83d\udd10',
1454    'closed_umbrella':'\ud83c\udf02',
1455    'cloud':'\u2601\ufe0f',
1456    'cloud_with_lightning':'\ud83c\udf29',
1457    'cloud_with_lightning_and_rain':'\u26c8',
1458    'cloud_with_rain':'\ud83c\udf27',
1459    'cloud_with_snow':'\ud83c\udf28',
1460    'clown_face':'\ud83e\udd21',
1461    'clubs':'\u2663\ufe0f',
1462    'cocktail':'\ud83c\udf78',
1463    'coffee':'\u2615\ufe0f',
1464    'coffin':'\u26b0\ufe0f',
1465    'cold_sweat':'\ud83d\ude30',
1466    'comet':'\u2604\ufe0f',
1467    'computer':'\ud83d\udcbb',
1468    'computer_mouse':'\ud83d\uddb1',
1469    'confetti_ball':'\ud83c\udf8a',
1470    'confounded':'\ud83d\ude16',
1471    'confused':'\ud83d\ude15',
1472    'congratulations':'\u3297\ufe0f',
1473    'construction':'\ud83d\udea7',
1474    'construction_worker_man':'\ud83d\udc77',
1475    'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1476    'control_knobs':'\ud83c\udf9b',
1477    'convenience_store':'\ud83c\udfea',
1478    'cookie':'\ud83c\udf6a',
1479    'cool':'\ud83c\udd92',
1480    'policeman':'\ud83d\udc6e',
1481    'copyright':'\u00a9\ufe0f',
1482    'corn':'\ud83c\udf3d',
1483    'couch_and_lamp':'\ud83d\udecb',
1484    'couple':'\ud83d\udc6b',
1485    'couple_with_heart_woman_man':'\ud83d\udc91',
1486    'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1487    'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1488    'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1489    'couplekiss_man_woman':'\ud83d\udc8f',
1490    'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1491    'cow':'\ud83d\udc2e',
1492    'cow2':'\ud83d\udc04',
1493    'cowboy_hat_face':'\ud83e\udd20',
1494    'crab':'\ud83e\udd80',
1495    'crayon':'\ud83d\udd8d',
1496    'credit_card':'\ud83d\udcb3',
1497    'crescent_moon':'\ud83c\udf19',
1498    'cricket':'\ud83c\udfcf',
1499    'crocodile':'\ud83d\udc0a',
1500    'croissant':'\ud83e\udd50',
1501    'crossed_fingers':'\ud83e\udd1e',
1502    'crossed_flags':'\ud83c\udf8c',
1503    'crossed_swords':'\u2694\ufe0f',
1504    'crown':'\ud83d\udc51',
1505    'cry':'\ud83d\ude22',
1506    'crying_cat_face':'\ud83d\ude3f',
1507    'crystal_ball':'\ud83d\udd2e',
1508    'cucumber':'\ud83e\udd52',
1509    'cupid':'\ud83d\udc98',
1510    'curly_loop':'\u27b0',
1511    'currency_exchange':'\ud83d\udcb1',
1512    'curry':'\ud83c\udf5b',
1513    'custard':'\ud83c\udf6e',
1514    'customs':'\ud83d\udec3',
1515    'cyclone':'\ud83c\udf00',
1516    'dagger':'\ud83d\udde1',
1517    'dancer':'\ud83d\udc83',
1518    'dancing_women':'\ud83d\udc6f',
1519    'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1520    'dango':'\ud83c\udf61',
1521    'dark_sunglasses':'\ud83d\udd76',
1522    'dart':'\ud83c\udfaf',
1523    'dash':'\ud83d\udca8',
1524    'date':'\ud83d\udcc5',
1525    'deciduous_tree':'\ud83c\udf33',
1526    'deer':'\ud83e\udd8c',
1527    'department_store':'\ud83c\udfec',
1528    'derelict_house':'\ud83c\udfda',
1529    'desert':'\ud83c\udfdc',
1530    'desert_island':'\ud83c\udfdd',
1531    'desktop_computer':'\ud83d\udda5',
1532    'male_detective':'\ud83d\udd75\ufe0f',
1533    'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1534    'diamonds':'\u2666\ufe0f',
1535    'disappointed':'\ud83d\ude1e',
1536    'disappointed_relieved':'\ud83d\ude25',
1537    'dizzy':'\ud83d\udcab',
1538    'dizzy_face':'\ud83d\ude35',
1539    'do_not_litter':'\ud83d\udeaf',
1540    'dog':'\ud83d\udc36',
1541    'dog2':'\ud83d\udc15',
1542    'dollar':'\ud83d\udcb5',
1543    'dolls':'\ud83c\udf8e',
1544    'dolphin':'\ud83d\udc2c',
1545    'door':'\ud83d\udeaa',
1546    'doughnut':'\ud83c\udf69',
1547    'dove':'\ud83d\udd4a',
1548    'dragon':'\ud83d\udc09',
1549    'dragon_face':'\ud83d\udc32',
1550    'dress':'\ud83d\udc57',
1551    'dromedary_camel':'\ud83d\udc2a',
1552    'drooling_face':'\ud83e\udd24',
1553    'droplet':'\ud83d\udca7',
1554    'drum':'\ud83e\udd41',
1555    'duck':'\ud83e\udd86',
1556    'dvd':'\ud83d\udcc0',
1557    'e-mail':'\ud83d\udce7',
1558    'eagle':'\ud83e\udd85',
1559    'ear':'\ud83d\udc42',
1560    'ear_of_rice':'\ud83c\udf3e',
1561    'earth_africa':'\ud83c\udf0d',
1562    'earth_americas':'\ud83c\udf0e',
1563    'earth_asia':'\ud83c\udf0f',
1564    'egg':'\ud83e\udd5a',
1565    'eggplant':'\ud83c\udf46',
1566    'eight_pointed_black_star':'\u2734\ufe0f',
1567    'eight_spoked_asterisk':'\u2733\ufe0f',
1568    'electric_plug':'\ud83d\udd0c',
1569    'elephant':'\ud83d\udc18',
1570    'email':'\u2709\ufe0f',
1571    'end':'\ud83d\udd1a',
1572    'envelope_with_arrow':'\ud83d\udce9',
1573    'euro':'\ud83d\udcb6',
1574    'european_castle':'\ud83c\udff0',
1575    'european_post_office':'\ud83c\udfe4',
1576    'evergreen_tree':'\ud83c\udf32',
1577    'exclamation':'\u2757\ufe0f',
1578    'expressionless':'\ud83d\ude11',
1579    'eye':'\ud83d\udc41',
1580    'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
1581    'eyeglasses':'\ud83d\udc53',
1582    'eyes':'\ud83d\udc40',
1583    'face_with_head_bandage':'\ud83e\udd15',
1584    'face_with_thermometer':'\ud83e\udd12',
1585    'fist_oncoming':'\ud83d\udc4a',
1586    'factory':'\ud83c\udfed',
1587    'fallen_leaf':'\ud83c\udf42',
1588    'family_man_woman_boy':'\ud83d\udc6a',
1589    'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
1590    'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1591    'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1592    'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1593    'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1594    'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1595    'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1596    'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1597    'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1598    'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1599    'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1600    'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1601    'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1602    'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1603    'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1604    'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1605    'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1606    'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1607    'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1608    'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1609    'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1610    'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1611    'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1612    'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1613    'fast_forward':'\u23e9',
1614    'fax':'\ud83d\udce0',
1615    'fearful':'\ud83d\ude28',
1616    'feet':'\ud83d\udc3e',
1617    'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
1618    'ferris_wheel':'\ud83c\udfa1',
1619    'ferry':'\u26f4',
1620    'field_hockey':'\ud83c\udfd1',
1621    'file_cabinet':'\ud83d\uddc4',
1622    'file_folder':'\ud83d\udcc1',
1623    'film_projector':'\ud83d\udcfd',
1624    'film_strip':'\ud83c\udf9e',
1625    'fire':'\ud83d\udd25',
1626    'fire_engine':'\ud83d\ude92',
1627    'fireworks':'\ud83c\udf86',
1628    'first_quarter_moon':'\ud83c\udf13',
1629    'first_quarter_moon_with_face':'\ud83c\udf1b',
1630    'fish':'\ud83d\udc1f',
1631    'fish_cake':'\ud83c\udf65',
1632    'fishing_pole_and_fish':'\ud83c\udfa3',
1633    'fist_raised':'\u270a',
1634    'fist_left':'\ud83e\udd1b',
1635    'fist_right':'\ud83e\udd1c',
1636    'flags':'\ud83c\udf8f',
1637    'flashlight':'\ud83d\udd26',
1638    'fleur_de_lis':'\u269c\ufe0f',
1639    'flight_arrival':'\ud83d\udeec',
1640    'flight_departure':'\ud83d\udeeb',
1641    'floppy_disk':'\ud83d\udcbe',
1642    'flower_playing_cards':'\ud83c\udfb4',
1643    'flushed':'\ud83d\ude33',
1644    'fog':'\ud83c\udf2b',
1645    'foggy':'\ud83c\udf01',
1646    'football':'\ud83c\udfc8',
1647    'footprints':'\ud83d\udc63',
1648    'fork_and_knife':'\ud83c\udf74',
1649    'fountain':'\u26f2\ufe0f',
1650    'fountain_pen':'\ud83d\udd8b',
1651    'four_leaf_clover':'\ud83c\udf40',
1652    'fox_face':'\ud83e\udd8a',
1653    'framed_picture':'\ud83d\uddbc',
1654    'free':'\ud83c\udd93',
1655    'fried_egg':'\ud83c\udf73',
1656    'fried_shrimp':'\ud83c\udf64',
1657    'fries':'\ud83c\udf5f',
1658    'frog':'\ud83d\udc38',
1659    'frowning':'\ud83d\ude26',
1660    'frowning_face':'\u2639\ufe0f',
1661    'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
1662    'frowning_woman':'\ud83d\ude4d',
1663    'middle_finger':'\ud83d\udd95',
1664    'fuelpump':'\u26fd\ufe0f',
1665    'full_moon':'\ud83c\udf15',
1666    'full_moon_with_face':'\ud83c\udf1d',
1667    'funeral_urn':'\u26b1\ufe0f',
1668    'game_die':'\ud83c\udfb2',
1669    'gear':'\u2699\ufe0f',
1670    'gem':'\ud83d\udc8e',
1671    'gemini':'\u264a\ufe0f',
1672    'ghost':'\ud83d\udc7b',
1673    'gift':'\ud83c\udf81',
1674    'gift_heart':'\ud83d\udc9d',
1675    'girl':'\ud83d\udc67',
1676    'globe_with_meridians':'\ud83c\udf10',
1677    'goal_net':'\ud83e\udd45',
1678    'goat':'\ud83d\udc10',
1679    'golf':'\u26f3\ufe0f',
1680    'golfing_man':'\ud83c\udfcc\ufe0f',
1681    'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
1682    'gorilla':'\ud83e\udd8d',
1683    'grapes':'\ud83c\udf47',
1684    'green_apple':'\ud83c\udf4f',
1685    'green_book':'\ud83d\udcd7',
1686    'green_heart':'\ud83d\udc9a',
1687    'green_salad':'\ud83e\udd57',
1688    'grey_exclamation':'\u2755',
1689    'grey_question':'\u2754',
1690    'grimacing':'\ud83d\ude2c',
1691    'grin':'\ud83d\ude01',
1692    'grinning':'\ud83d\ude00',
1693    'guardsman':'\ud83d\udc82',
1694    'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
1695    'guitar':'\ud83c\udfb8',
1696    'gun':'\ud83d\udd2b',
1697    'haircut_woman':'\ud83d\udc87',
1698    'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
1699    'hamburger':'\ud83c\udf54',
1700    'hammer':'\ud83d\udd28',
1701    'hammer_and_pick':'\u2692',
1702    'hammer_and_wrench':'\ud83d\udee0',
1703    'hamster':'\ud83d\udc39',
1704    'hand':'\u270b',
1705    'handbag':'\ud83d\udc5c',
1706    'handshake':'\ud83e\udd1d',
1707    'hankey':'\ud83d\udca9',
1708    'hatched_chick':'\ud83d\udc25',
1709    'hatching_chick':'\ud83d\udc23',
1710    'headphones':'\ud83c\udfa7',
1711    'hear_no_evil':'\ud83d\ude49',
1712    'heart':'\u2764\ufe0f',
1713    'heart_decoration':'\ud83d\udc9f',
1714    'heart_eyes':'\ud83d\ude0d',
1715    'heart_eyes_cat':'\ud83d\ude3b',
1716    'heartbeat':'\ud83d\udc93',
1717    'heartpulse':'\ud83d\udc97',
1718    'hearts':'\u2665\ufe0f',
1719    'heavy_check_mark':'\u2714\ufe0f',
1720    'heavy_division_sign':'\u2797',
1721    'heavy_dollar_sign':'\ud83d\udcb2',
1722    'heavy_heart_exclamation':'\u2763\ufe0f',
1723    'heavy_minus_sign':'\u2796',
1724    'heavy_multiplication_x':'\u2716\ufe0f',
1725    'heavy_plus_sign':'\u2795',
1726    'helicopter':'\ud83d\ude81',
1727    'herb':'\ud83c\udf3f',
1728    'hibiscus':'\ud83c\udf3a',
1729    'high_brightness':'\ud83d\udd06',
1730    'high_heel':'\ud83d\udc60',
1731    'hocho':'\ud83d\udd2a',
1732    'hole':'\ud83d\udd73',
1733    'honey_pot':'\ud83c\udf6f',
1734    'horse':'\ud83d\udc34',
1735    'horse_racing':'\ud83c\udfc7',
1736    'hospital':'\ud83c\udfe5',
1737    'hot_pepper':'\ud83c\udf36',
1738    'hotdog':'\ud83c\udf2d',
1739    'hotel':'\ud83c\udfe8',
1740    'hotsprings':'\u2668\ufe0f',
1741    'hourglass':'\u231b\ufe0f',
1742    'hourglass_flowing_sand':'\u23f3',
1743    'house':'\ud83c\udfe0',
1744    'house_with_garden':'\ud83c\udfe1',
1745    'houses':'\ud83c\udfd8',
1746    'hugs':'\ud83e\udd17',
1747    'hushed':'\ud83d\ude2f',
1748    'ice_cream':'\ud83c\udf68',
1749    'ice_hockey':'\ud83c\udfd2',
1750    'ice_skate':'\u26f8',
1751    'icecream':'\ud83c\udf66',
1752    'id':'\ud83c\udd94',
1753    'ideograph_advantage':'\ud83c\ude50',
1754    'imp':'\ud83d\udc7f',
1755    'inbox_tray':'\ud83d\udce5',
1756    'incoming_envelope':'\ud83d\udce8',
1757    'tipping_hand_woman':'\ud83d\udc81',
1758    'information_source':'\u2139\ufe0f',
1759    'innocent':'\ud83d\ude07',
1760    'interrobang':'\u2049\ufe0f',
1761    'iphone':'\ud83d\udcf1',
1762    'izakaya_lantern':'\ud83c\udfee',
1763    'jack_o_lantern':'\ud83c\udf83',
1764    'japan':'\ud83d\uddfe',
1765    'japanese_castle':'\ud83c\udfef',
1766    'japanese_goblin':'\ud83d\udc7a',
1767    'japanese_ogre':'\ud83d\udc79',
1768    'jeans':'\ud83d\udc56',
1769    'joy':'\ud83d\ude02',
1770    'joy_cat':'\ud83d\ude39',
1771    'joystick':'\ud83d\udd79',
1772    'kaaba':'\ud83d\udd4b',
1773    'key':'\ud83d\udd11',
1774    'keyboard':'\u2328\ufe0f',
1775    'keycap_ten':'\ud83d\udd1f',
1776    'kick_scooter':'\ud83d\udef4',
1777    'kimono':'\ud83d\udc58',
1778    'kiss':'\ud83d\udc8b',
1779    'kissing':'\ud83d\ude17',
1780    'kissing_cat':'\ud83d\ude3d',
1781    'kissing_closed_eyes':'\ud83d\ude1a',
1782    'kissing_heart':'\ud83d\ude18',
1783    'kissing_smiling_eyes':'\ud83d\ude19',
1784    'kiwi_fruit':'\ud83e\udd5d',
1785    'koala':'\ud83d\udc28',
1786    'koko':'\ud83c\ude01',
1787    'label':'\ud83c\udff7',
1788    'large_blue_circle':'\ud83d\udd35',
1789    'large_blue_diamond':'\ud83d\udd37',
1790    'large_orange_diamond':'\ud83d\udd36',
1791    'last_quarter_moon':'\ud83c\udf17',
1792    'last_quarter_moon_with_face':'\ud83c\udf1c',
1793    'latin_cross':'\u271d\ufe0f',
1794    'laughing':'\ud83d\ude06',
1795    'leaves':'\ud83c\udf43',
1796    'ledger':'\ud83d\udcd2',
1797    'left_luggage':'\ud83d\udec5',
1798    'left_right_arrow':'\u2194\ufe0f',
1799    'leftwards_arrow_with_hook':'\u21a9\ufe0f',
1800    'lemon':'\ud83c\udf4b',
1801    'leo':'\u264c\ufe0f',
1802    'leopard':'\ud83d\udc06',
1803    'level_slider':'\ud83c\udf9a',
1804    'libra':'\u264e\ufe0f',
1805    'light_rail':'\ud83d\ude88',
1806    'link':'\ud83d\udd17',
1807    'lion':'\ud83e\udd81',
1808    'lips':'\ud83d\udc44',
1809    'lipstick':'\ud83d\udc84',
1810    'lizard':'\ud83e\udd8e',
1811    'lock':'\ud83d\udd12',
1812    'lock_with_ink_pen':'\ud83d\udd0f',
1813    'lollipop':'\ud83c\udf6d',
1814    'loop':'\u27bf',
1815    'loud_sound':'\ud83d\udd0a',
1816    'loudspeaker':'\ud83d\udce2',
1817    'love_hotel':'\ud83c\udfe9',
1818    'love_letter':'\ud83d\udc8c',
1819    'low_brightness':'\ud83d\udd05',
1820    'lying_face':'\ud83e\udd25',
1821    'm':'\u24c2\ufe0f',
1822    'mag':'\ud83d\udd0d',
1823    'mag_right':'\ud83d\udd0e',
1824    'mahjong':'\ud83c\udc04\ufe0f',
1825    'mailbox':'\ud83d\udceb',
1826    'mailbox_closed':'\ud83d\udcea',
1827    'mailbox_with_mail':'\ud83d\udcec',
1828    'mailbox_with_no_mail':'\ud83d\udced',
1829    'man':'\ud83d\udc68',
1830    'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
1831    'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
1832    'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
1833    'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
1834    'man_dancing':'\ud83d\udd7a',
1835    'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
1836    'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
1837    'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
1838    'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
1839    'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
1840    'man_in_tuxedo':'\ud83e\udd35',
1841    'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
1842    'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
1843    'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
1844    'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
1845    'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
1846    'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
1847    'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
1848    'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
1849    'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
1850    'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
1851    'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
1852    'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
1853    'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
1854    'man_with_gua_pi_mao':'\ud83d\udc72',
1855    'man_with_turban':'\ud83d\udc73',
1856    'tangerine':'\ud83c\udf4a',
1857    'mans_shoe':'\ud83d\udc5e',
1858    'mantelpiece_clock':'\ud83d\udd70',
1859    'maple_leaf':'\ud83c\udf41',
1860    'martial_arts_uniform':'\ud83e\udd4b',
1861    'mask':'\ud83d\ude37',
1862    'massage_woman':'\ud83d\udc86',
1863    'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
1864    'meat_on_bone':'\ud83c\udf56',
1865    'medal_military':'\ud83c\udf96',
1866    'medal_sports':'\ud83c\udfc5',
1867    'mega':'\ud83d\udce3',
1868    'melon':'\ud83c\udf48',
1869    'memo':'\ud83d\udcdd',
1870    'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
1871    'menorah':'\ud83d\udd4e',
1872    'mens':'\ud83d\udeb9',
1873    'metal':'\ud83e\udd18',
1874    'metro':'\ud83d\ude87',
1875    'microphone':'\ud83c\udfa4',
1876    'microscope':'\ud83d\udd2c',
1877    'milk_glass':'\ud83e\udd5b',
1878    'milky_way':'\ud83c\udf0c',
1879    'minibus':'\ud83d\ude90',
1880    'minidisc':'\ud83d\udcbd',
1881    'mobile_phone_off':'\ud83d\udcf4',
1882    'money_mouth_face':'\ud83e\udd11',
1883    'money_with_wings':'\ud83d\udcb8',
1884    'moneybag':'\ud83d\udcb0',
1885    'monkey':'\ud83d\udc12',
1886    'monkey_face':'\ud83d\udc35',
1887    'monorail':'\ud83d\ude9d',
1888    'moon':'\ud83c\udf14',
1889    'mortar_board':'\ud83c\udf93',
1890    'mosque':'\ud83d\udd4c',
1891    'motor_boat':'\ud83d\udee5',
1892    'motor_scooter':'\ud83d\udef5',
1893    'motorcycle':'\ud83c\udfcd',
1894    'motorway':'\ud83d\udee3',
1895    'mount_fuji':'\ud83d\uddfb',
1896    'mountain':'\u26f0',
1897    'mountain_biking_man':'\ud83d\udeb5',
1898    'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
1899    'mountain_cableway':'\ud83d\udea0',
1900    'mountain_railway':'\ud83d\ude9e',
1901    'mountain_snow':'\ud83c\udfd4',
1902    'mouse':'\ud83d\udc2d',
1903    'mouse2':'\ud83d\udc01',
1904    'movie_camera':'\ud83c\udfa5',
1905    'moyai':'\ud83d\uddff',
1906    'mrs_claus':'\ud83e\udd36',
1907    'muscle':'\ud83d\udcaa',
1908    'mushroom':'\ud83c\udf44',
1909    'musical_keyboard':'\ud83c\udfb9',
1910    'musical_note':'\ud83c\udfb5',
1911    'musical_score':'\ud83c\udfbc',
1912    'mute':'\ud83d\udd07',
1913    'nail_care':'\ud83d\udc85',
1914    'name_badge':'\ud83d\udcdb',
1915    'national_park':'\ud83c\udfde',
1916    'nauseated_face':'\ud83e\udd22',
1917    'necktie':'\ud83d\udc54',
1918    'negative_squared_cross_mark':'\u274e',
1919    'nerd_face':'\ud83e\udd13',
1920    'neutral_face':'\ud83d\ude10',
1921    'new':'\ud83c\udd95',
1922    'new_moon':'\ud83c\udf11',
1923    'new_moon_with_face':'\ud83c\udf1a',
1924    'newspaper':'\ud83d\udcf0',
1925    'newspaper_roll':'\ud83d\uddde',
1926    'next_track_button':'\u23ed',
1927    'ng':'\ud83c\udd96',
1928    'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
1929    'no_good_woman':'\ud83d\ude45',
1930    'night_with_stars':'\ud83c\udf03',
1931    'no_bell':'\ud83d\udd15',
1932    'no_bicycles':'\ud83d\udeb3',
1933    'no_entry':'\u26d4\ufe0f',
1934    'no_entry_sign':'\ud83d\udeab',
1935    'no_mobile_phones':'\ud83d\udcf5',
1936    'no_mouth':'\ud83d\ude36',
1937    'no_pedestrians':'\ud83d\udeb7',
1938    'no_smoking':'\ud83d\udead',
1939    'non-potable_water':'\ud83d\udeb1',
1940    'nose':'\ud83d\udc43',
1941    'notebook':'\ud83d\udcd3',
1942    'notebook_with_decorative_cover':'\ud83d\udcd4',
1943    'notes':'\ud83c\udfb6',
1944    'nut_and_bolt':'\ud83d\udd29',
1945    'o':'\u2b55\ufe0f',
1946    'o2':'\ud83c\udd7e\ufe0f',
1947    'ocean':'\ud83c\udf0a',
1948    'octopus':'\ud83d\udc19',
1949    'oden':'\ud83c\udf62',
1950    'office':'\ud83c\udfe2',
1951    'oil_drum':'\ud83d\udee2',
1952    'ok':'\ud83c\udd97',
1953    'ok_hand':'\ud83d\udc4c',
1954    'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
1955    'ok_woman':'\ud83d\ude46',
1956    'old_key':'\ud83d\udddd',
1957    'older_man':'\ud83d\udc74',
1958    'older_woman':'\ud83d\udc75',
1959    'om':'\ud83d\udd49',
1960    'on':'\ud83d\udd1b',
1961    'oncoming_automobile':'\ud83d\ude98',
1962    'oncoming_bus':'\ud83d\ude8d',
1963    'oncoming_police_car':'\ud83d\ude94',
1964    'oncoming_taxi':'\ud83d\ude96',
1965    'open_file_folder':'\ud83d\udcc2',
1966    'open_hands':'\ud83d\udc50',
1967    'open_mouth':'\ud83d\ude2e',
1968    'open_umbrella':'\u2602\ufe0f',
1969    'ophiuchus':'\u26ce',
1970    'orange_book':'\ud83d\udcd9',
1971    'orthodox_cross':'\u2626\ufe0f',
1972    'outbox_tray':'\ud83d\udce4',
1973    'owl':'\ud83e\udd89',
1974    'ox':'\ud83d\udc02',
1975    'package':'\ud83d\udce6',
1976    'page_facing_up':'\ud83d\udcc4',
1977    'page_with_curl':'\ud83d\udcc3',
1978    'pager':'\ud83d\udcdf',
1979    'paintbrush':'\ud83d\udd8c',
1980    'palm_tree':'\ud83c\udf34',
1981    'pancakes':'\ud83e\udd5e',
1982    'panda_face':'\ud83d\udc3c',
1983    'paperclip':'\ud83d\udcce',
1984    'paperclips':'\ud83d\udd87',
1985    'parasol_on_ground':'\u26f1',
1986    'parking':'\ud83c\udd7f\ufe0f',
1987    'part_alternation_mark':'\u303d\ufe0f',
1988    'partly_sunny':'\u26c5\ufe0f',
1989    'passenger_ship':'\ud83d\udef3',
1990    'passport_control':'\ud83d\udec2',
1991    'pause_button':'\u23f8',
1992    'peace_symbol':'\u262e\ufe0f',
1993    'peach':'\ud83c\udf51',
1994    'peanuts':'\ud83e\udd5c',
1995    'pear':'\ud83c\udf50',
1996    'pen':'\ud83d\udd8a',
1997    'pencil2':'\u270f\ufe0f',
1998    'penguin':'\ud83d\udc27',
1999    'pensive':'\ud83d\ude14',
2000    'performing_arts':'\ud83c\udfad',
2001    'persevere':'\ud83d\ude23',
2002    'person_fencing':'\ud83e\udd3a',
2003    'pouting_woman':'\ud83d\ude4e',
2004    'phone':'\u260e\ufe0f',
2005    'pick':'\u26cf',
2006    'pig':'\ud83d\udc37',
2007    'pig2':'\ud83d\udc16',
2008    'pig_nose':'\ud83d\udc3d',
2009    'pill':'\ud83d\udc8a',
2010    'pineapple':'\ud83c\udf4d',
2011    'ping_pong':'\ud83c\udfd3',
2012    'pisces':'\u2653\ufe0f',
2013    'pizza':'\ud83c\udf55',
2014    'place_of_worship':'\ud83d\uded0',
2015    'plate_with_cutlery':'\ud83c\udf7d',
2016    'play_or_pause_button':'\u23ef',
2017    'point_down':'\ud83d\udc47',
2018    'point_left':'\ud83d\udc48',
2019    'point_right':'\ud83d\udc49',
2020    'point_up':'\u261d\ufe0f',
2021    'point_up_2':'\ud83d\udc46',
2022    'police_car':'\ud83d\ude93',
2023    'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
2024    'poodle':'\ud83d\udc29',
2025    'popcorn':'\ud83c\udf7f',
2026    'post_office':'\ud83c\udfe3',
2027    'postal_horn':'\ud83d\udcef',
2028    'postbox':'\ud83d\udcee',
2029    'potable_water':'\ud83d\udeb0',
2030    'potato':'\ud83e\udd54',
2031    'pouch':'\ud83d\udc5d',
2032    'poultry_leg':'\ud83c\udf57',
2033    'pound':'\ud83d\udcb7',
2034    'rage':'\ud83d\ude21',
2035    'pouting_cat':'\ud83d\ude3e',
2036    'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
2037    'pray':'\ud83d\ude4f',
2038    'prayer_beads':'\ud83d\udcff',
2039    'pregnant_woman':'\ud83e\udd30',
2040    'previous_track_button':'\u23ee',
2041    'prince':'\ud83e\udd34',
2042    'princess':'\ud83d\udc78',
2043    'printer':'\ud83d\udda8',
2044    'purple_heart':'\ud83d\udc9c',
2045    'purse':'\ud83d\udc5b',
2046    'pushpin':'\ud83d\udccc',
2047    'put_litter_in_its_place':'\ud83d\udeae',
2048    'question':'\u2753',
2049    'rabbit':'\ud83d\udc30',
2050    'rabbit2':'\ud83d\udc07',
2051    'racehorse':'\ud83d\udc0e',
2052    'racing_car':'\ud83c\udfce',
2053    'radio':'\ud83d\udcfb',
2054    'radio_button':'\ud83d\udd18',
2055    'radioactive':'\u2622\ufe0f',
2056    'railway_car':'\ud83d\ude83',
2057    'railway_track':'\ud83d\udee4',
2058    'rainbow':'\ud83c\udf08',
2059    'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
2060    'raised_back_of_hand':'\ud83e\udd1a',
2061    'raised_hand_with_fingers_splayed':'\ud83d\udd90',
2062    'raised_hands':'\ud83d\ude4c',
2063    'raising_hand_woman':'\ud83d\ude4b',
2064    'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
2065    'ram':'\ud83d\udc0f',
2066    'ramen':'\ud83c\udf5c',
2067    'rat':'\ud83d\udc00',
2068    'record_button':'\u23fa',
2069    'recycle':'\u267b\ufe0f',
2070    'red_circle':'\ud83d\udd34',
2071    'registered':'\u00ae\ufe0f',
2072    'relaxed':'\u263a\ufe0f',
2073    'relieved':'\ud83d\ude0c',
2074    'reminder_ribbon':'\ud83c\udf97',
2075    'repeat':'\ud83d\udd01',
2076    'repeat_one':'\ud83d\udd02',
2077    'rescue_worker_helmet':'\u26d1',
2078    'restroom':'\ud83d\udebb',
2079    'revolving_hearts':'\ud83d\udc9e',
2080    'rewind':'\u23ea',
2081    'rhinoceros':'\ud83e\udd8f',
2082    'ribbon':'\ud83c\udf80',
2083    'rice':'\ud83c\udf5a',
2084    'rice_ball':'\ud83c\udf59',
2085    'rice_cracker':'\ud83c\udf58',
2086    'rice_scene':'\ud83c\udf91',
2087    'right_anger_bubble':'\ud83d\uddef',
2088    'ring':'\ud83d\udc8d',
2089    'robot':'\ud83e\udd16',
2090    'rocket':'\ud83d\ude80',
2091    'rofl':'\ud83e\udd23',
2092    'roll_eyes':'\ud83d\ude44',
2093    'roller_coaster':'\ud83c\udfa2',
2094    'rooster':'\ud83d\udc13',
2095    'rose':'\ud83c\udf39',
2096    'rosette':'\ud83c\udff5',
2097    'rotating_light':'\ud83d\udea8',
2098    'round_pushpin':'\ud83d\udccd',
2099    'rowing_man':'\ud83d\udea3',
2100    'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
2101    'rugby_football':'\ud83c\udfc9',
2102    'running_man':'\ud83c\udfc3',
2103    'running_shirt_with_sash':'\ud83c\udfbd',
2104    'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
2105    'sa':'\ud83c\ude02\ufe0f',
2106    'sagittarius':'\u2650\ufe0f',
2107    'sake':'\ud83c\udf76',
2108    'sandal':'\ud83d\udc61',
2109    'santa':'\ud83c\udf85',
2110    'satellite':'\ud83d\udce1',
2111    'saxophone':'\ud83c\udfb7',
2112    'school':'\ud83c\udfeb',
2113    'school_satchel':'\ud83c\udf92',
2114    'scissors':'\u2702\ufe0f',
2115    'scorpion':'\ud83e\udd82',
2116    'scorpius':'\u264f\ufe0f',
2117    'scream':'\ud83d\ude31',
2118    'scream_cat':'\ud83d\ude40',
2119    'scroll':'\ud83d\udcdc',
2120    'seat':'\ud83d\udcba',
2121    'secret':'\u3299\ufe0f',
2122    'see_no_evil':'\ud83d\ude48',
2123    'seedling':'\ud83c\udf31',
2124    'selfie':'\ud83e\udd33',
2125    'shallow_pan_of_food':'\ud83e\udd58',
2126    'shamrock':'\u2618\ufe0f',
2127    'shark':'\ud83e\udd88',
2128    'shaved_ice':'\ud83c\udf67',
2129    'sheep':'\ud83d\udc11',
2130    'shell':'\ud83d\udc1a',
2131    'shield':'\ud83d\udee1',
2132    'shinto_shrine':'\u26e9',
2133    'ship':'\ud83d\udea2',
2134    'shirt':'\ud83d\udc55',
2135    'shopping':'\ud83d\udecd',
2136    'shopping_cart':'\ud83d\uded2',
2137    'shower':'\ud83d\udebf',
2138    'shrimp':'\ud83e\udd90',
2139    'signal_strength':'\ud83d\udcf6',
2140    'six_pointed_star':'\ud83d\udd2f',
2141    'ski':'\ud83c\udfbf',
2142    'skier':'\u26f7',
2143    'skull':'\ud83d\udc80',
2144    'skull_and_crossbones':'\u2620\ufe0f',
2145    'sleeping':'\ud83d\ude34',
2146    'sleeping_bed':'\ud83d\udecc',
2147    'sleepy':'\ud83d\ude2a',
2148    'slightly_frowning_face':'\ud83d\ude41',
2149    'slightly_smiling_face':'\ud83d\ude42',
2150    'slot_machine':'\ud83c\udfb0',
2151    'small_airplane':'\ud83d\udee9',
2152    'small_blue_diamond':'\ud83d\udd39',
2153    'small_orange_diamond':'\ud83d\udd38',
2154    'small_red_triangle':'\ud83d\udd3a',
2155    'small_red_triangle_down':'\ud83d\udd3b',
2156    'smile':'\ud83d\ude04',
2157    'smile_cat':'\ud83d\ude38',
2158    'smiley':'\ud83d\ude03',
2159    'smiley_cat':'\ud83d\ude3a',
2160    'smiling_imp':'\ud83d\ude08',
2161    'smirk':'\ud83d\ude0f',
2162    'smirk_cat':'\ud83d\ude3c',
2163    'smoking':'\ud83d\udeac',
2164    'snail':'\ud83d\udc0c',
2165    'snake':'\ud83d\udc0d',
2166    'sneezing_face':'\ud83e\udd27',
2167    'snowboarder':'\ud83c\udfc2',
2168    'snowflake':'\u2744\ufe0f',
2169    'snowman':'\u26c4\ufe0f',
2170    'snowman_with_snow':'\u2603\ufe0f',
2171    'sob':'\ud83d\ude2d',
2172    'soccer':'\u26bd\ufe0f',
2173    'soon':'\ud83d\udd1c',
2174    'sos':'\ud83c\udd98',
2175    'sound':'\ud83d\udd09',
2176    'space_invader':'\ud83d\udc7e',
2177    'spades':'\u2660\ufe0f',
2178    'spaghetti':'\ud83c\udf5d',
2179    'sparkle':'\u2747\ufe0f',
2180    'sparkler':'\ud83c\udf87',
2181    'sparkles':'\u2728',
2182    'sparkling_heart':'\ud83d\udc96',
2183    'speak_no_evil':'\ud83d\ude4a',
2184    'speaker':'\ud83d\udd08',
2185    'speaking_head':'\ud83d\udde3',
2186    'speech_balloon':'\ud83d\udcac',
2187    'speedboat':'\ud83d\udea4',
2188    'spider':'\ud83d\udd77',
2189    'spider_web':'\ud83d\udd78',
2190    'spiral_calendar':'\ud83d\uddd3',
2191    'spiral_notepad':'\ud83d\uddd2',
2192    'spoon':'\ud83e\udd44',
2193    'squid':'\ud83e\udd91',
2194    'stadium':'\ud83c\udfdf',
2195    'star':'\u2b50\ufe0f',
2196    'star2':'\ud83c\udf1f',
2197    'star_and_crescent':'\u262a\ufe0f',
2198    'star_of_david':'\u2721\ufe0f',
2199    'stars':'\ud83c\udf20',
2200    'station':'\ud83d\ude89',
2201    'statue_of_liberty':'\ud83d\uddfd',
2202    'steam_locomotive':'\ud83d\ude82',
2203    'stew':'\ud83c\udf72',
2204    'stop_button':'\u23f9',
2205    'stop_sign':'\ud83d\uded1',
2206    'stopwatch':'\u23f1',
2207    'straight_ruler':'\ud83d\udccf',
2208    'strawberry':'\ud83c\udf53',
2209    'stuck_out_tongue':'\ud83d\ude1b',
2210    'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2211    'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2212    'studio_microphone':'\ud83c\udf99',
2213    'stuffed_flatbread':'\ud83e\udd59',
2214    'sun_behind_large_cloud':'\ud83c\udf25',
2215    'sun_behind_rain_cloud':'\ud83c\udf26',
2216    'sun_behind_small_cloud':'\ud83c\udf24',
2217    'sun_with_face':'\ud83c\udf1e',
2218    'sunflower':'\ud83c\udf3b',
2219    'sunglasses':'\ud83d\ude0e',
2220    'sunny':'\u2600\ufe0f',
2221    'sunrise':'\ud83c\udf05',
2222    'sunrise_over_mountains':'\ud83c\udf04',
2223    'surfing_man':'\ud83c\udfc4',
2224    'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2225    'sushi':'\ud83c\udf63',
2226    'suspension_railway':'\ud83d\ude9f',
2227    'sweat':'\ud83d\ude13',
2228    'sweat_drops':'\ud83d\udca6',
2229    'sweat_smile':'\ud83d\ude05',
2230    'sweet_potato':'\ud83c\udf60',
2231    'swimming_man':'\ud83c\udfca',
2232    'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2233    'symbols':'\ud83d\udd23',
2234    'synagogue':'\ud83d\udd4d',
2235    'syringe':'\ud83d\udc89',
2236    'taco':'\ud83c\udf2e',
2237    'tada':'\ud83c\udf89',
2238    'tanabata_tree':'\ud83c\udf8b',
2239    'taurus':'\u2649\ufe0f',
2240    'taxi':'\ud83d\ude95',
2241    'tea':'\ud83c\udf75',
2242    'telephone_receiver':'\ud83d\udcde',
2243    'telescope':'\ud83d\udd2d',
2244    'tennis':'\ud83c\udfbe',
2245    'tent':'\u26fa\ufe0f',
2246    'thermometer':'\ud83c\udf21',
2247    'thinking':'\ud83e\udd14',
2248    'thought_balloon':'\ud83d\udcad',
2249    'ticket':'\ud83c\udfab',
2250    'tickets':'\ud83c\udf9f',
2251    'tiger':'\ud83d\udc2f',
2252    'tiger2':'\ud83d\udc05',
2253    'timer_clock':'\u23f2',
2254    'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2255    'tired_face':'\ud83d\ude2b',
2256    'tm':'\u2122\ufe0f',
2257    'toilet':'\ud83d\udebd',
2258    'tokyo_tower':'\ud83d\uddfc',
2259    'tomato':'\ud83c\udf45',
2260    'tongue':'\ud83d\udc45',
2261    'top':'\ud83d\udd1d',
2262    'tophat':'\ud83c\udfa9',
2263    'tornado':'\ud83c\udf2a',
2264    'trackball':'\ud83d\uddb2',
2265    'tractor':'\ud83d\ude9c',
2266    'traffic_light':'\ud83d\udea5',
2267    'train':'\ud83d\ude8b',
2268    'train2':'\ud83d\ude86',
2269    'tram':'\ud83d\ude8a',
2270    'triangular_flag_on_post':'\ud83d\udea9',
2271    'triangular_ruler':'\ud83d\udcd0',
2272    'trident':'\ud83d\udd31',
2273    'triumph':'\ud83d\ude24',
2274    'trolleybus':'\ud83d\ude8e',
2275    'trophy':'\ud83c\udfc6',
2276    'tropical_drink':'\ud83c\udf79',
2277    'tropical_fish':'\ud83d\udc20',
2278    'truck':'\ud83d\ude9a',
2279    'trumpet':'\ud83c\udfba',
2280    'tulip':'\ud83c\udf37',
2281    'tumbler_glass':'\ud83e\udd43',
2282    'turkey':'\ud83e\udd83',
2283    'turtle':'\ud83d\udc22',
2284    'tv':'\ud83d\udcfa',
2285    'twisted_rightwards_arrows':'\ud83d\udd00',
2286    'two_hearts':'\ud83d\udc95',
2287    'two_men_holding_hands':'\ud83d\udc6c',
2288    'two_women_holding_hands':'\ud83d\udc6d',
2289    'u5272':'\ud83c\ude39',
2290    'u5408':'\ud83c\ude34',
2291    'u55b6':'\ud83c\ude3a',
2292    'u6307':'\ud83c\ude2f\ufe0f',
2293    'u6708':'\ud83c\ude37\ufe0f',
2294    'u6709':'\ud83c\ude36',
2295    'u6e80':'\ud83c\ude35',
2296    'u7121':'\ud83c\ude1a\ufe0f',
2297    'u7533':'\ud83c\ude38',
2298    'u7981':'\ud83c\ude32',
2299    'u7a7a':'\ud83c\ude33',
2300    'umbrella':'\u2614\ufe0f',
2301    'unamused':'\ud83d\ude12',
2302    'underage':'\ud83d\udd1e',
2303    'unicorn':'\ud83e\udd84',
2304    'unlock':'\ud83d\udd13',
2305    'up':'\ud83c\udd99',
2306    'upside_down_face':'\ud83d\ude43',
2307    'v':'\u270c\ufe0f',
2308    'vertical_traffic_light':'\ud83d\udea6',
2309    'vhs':'\ud83d\udcfc',
2310    'vibration_mode':'\ud83d\udcf3',
2311    'video_camera':'\ud83d\udcf9',
2312    'video_game':'\ud83c\udfae',
2313    'violin':'\ud83c\udfbb',
2314    'virgo':'\u264d\ufe0f',
2315    'volcano':'\ud83c\udf0b',
2316    'volleyball':'\ud83c\udfd0',
2317    'vs':'\ud83c\udd9a',
2318    'vulcan_salute':'\ud83d\udd96',
2319    'walking_man':'\ud83d\udeb6',
2320    'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2321    'waning_crescent_moon':'\ud83c\udf18',
2322    'waning_gibbous_moon':'\ud83c\udf16',
2323    'warning':'\u26a0\ufe0f',
2324    'wastebasket':'\ud83d\uddd1',
2325    'watch':'\u231a\ufe0f',
2326    'water_buffalo':'\ud83d\udc03',
2327    'watermelon':'\ud83c\udf49',
2328    'wave':'\ud83d\udc4b',
2329    'wavy_dash':'\u3030\ufe0f',
2330    'waxing_crescent_moon':'\ud83c\udf12',
2331    'wc':'\ud83d\udebe',
2332    'weary':'\ud83d\ude29',
2333    'wedding':'\ud83d\udc92',
2334    'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2335    'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2336    'whale':'\ud83d\udc33',
2337    'whale2':'\ud83d\udc0b',
2338    'wheel_of_dharma':'\u2638\ufe0f',
2339    'wheelchair':'\u267f\ufe0f',
2340    'white_check_mark':'\u2705',
2341    'white_circle':'\u26aa\ufe0f',
2342    'white_flag':'\ud83c\udff3\ufe0f',
2343    'white_flower':'\ud83d\udcae',
2344    'white_large_square':'\u2b1c\ufe0f',
2345    'white_medium_small_square':'\u25fd\ufe0f',
2346    'white_medium_square':'\u25fb\ufe0f',
2347    'white_small_square':'\u25ab\ufe0f',
2348    'white_square_button':'\ud83d\udd33',
2349    'wilted_flower':'\ud83e\udd40',
2350    'wind_chime':'\ud83c\udf90',
2351    'wind_face':'\ud83c\udf2c',
2352    'wine_glass':'\ud83c\udf77',
2353    'wink':'\ud83d\ude09',
2354    'wolf':'\ud83d\udc3a',
2355    'woman':'\ud83d\udc69',
2356    'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2357    'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2358    'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2359    'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2360    'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2361    'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2362    'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2363    'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2364    'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2365    'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2366    'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2367    'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2368    'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2369    'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2370    'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2371    'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2372    'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2373    'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2374    'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2375    'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2376    'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2377    'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2378    'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2379    'womans_clothes':'\ud83d\udc5a',
2380    'womans_hat':'\ud83d\udc52',
2381    'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2382    'womens':'\ud83d\udeba',
2383    'world_map':'\ud83d\uddfa',
2384    'worried':'\ud83d\ude1f',
2385    'wrench':'\ud83d\udd27',
2386    'writing_hand':'\u270d\ufe0f',
2387    'x':'\u274c',
2388    'yellow_heart':'\ud83d\udc9b',
2389    'yen':'\ud83d\udcb4',
2390    'yin_yang':'\u262f\ufe0f',
2391    'yum':'\ud83d\ude0b',
2392    'zap':'\u26a1\ufe0f',
2393    'zipper_mouth_face':'\ud83e\udd10',
2394    'zzz':'\ud83d\udca4',
2395  
2396    /* special emojis :P */
2397    'octocat':  '<img alt=":octocat:" height="20" width="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',
2398    '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>'
2399  };
2400  
2401  /**
2402   * Created by Estevao on 31-05-2015.
2403   */
2404  
2405  /**
2406   * Showdown Converter class
2407   * @class
2408   * @param {object} [converterOptions]
2409   * @returns {Converter}
2410   */
2411  showdown.Converter = function (converterOptions) {
2412    'use strict';
2413  
2414    var
2415        /**
2416         * Options used by this converter
2417         * @private
2418         * @type {{}}
2419         */
2420        options = {},
2421  
2422        /**
2423         * Language extensions used by this converter
2424         * @private
2425         * @type {Array}
2426         */
2427        langExtensions = [],
2428  
2429        /**
2430         * Output modifiers extensions used by this converter
2431         * @private
2432         * @type {Array}
2433         */
2434        outputModifiers = [],
2435  
2436        /**
2437         * Event listeners
2438         * @private
2439         * @type {{}}
2440         */
2441        listeners = {},
2442  
2443        /**
2444         * The flavor set in this converter
2445         */
2446        setConvFlavor = setFlavor,
2447  
2448      /**
2449       * Metadata of the document
2450       * @type {{parsed: {}, raw: string, format: string}}
2451       */
2452        metadata = {
2453          parsed: {},
2454          raw: '',
2455          format: ''
2456        };
2457  
2458    _constructor();
2459  
2460    /**
2461     * Converter constructor
2462     * @private
2463     */
2464    function _constructor () {
2465      converterOptions = converterOptions || {};
2466  
2467      for (var gOpt in globalOptions) {
2468        if (globalOptions.hasOwnProperty(gOpt)) {
2469          options[gOpt] = globalOptions[gOpt];
2470        }
2471      }
2472  
2473      // Merge options
2474      if (typeof converterOptions === 'object') {
2475        for (var opt in converterOptions) {
2476          if (converterOptions.hasOwnProperty(opt)) {
2477            options[opt] = converterOptions[opt];
2478          }
2479        }
2480      } else {
2481        throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
2482        ' was passed instead.');
2483      }
2484  
2485      if (options.extensions) {
2486        showdown.helper.forEach(options.extensions, _parseExtension);
2487      }
2488    }
2489  
2490    /**
2491     * Parse extension
2492     * @param {*} ext
2493     * @param {string} [name='']
2494     * @private
2495     */
2496    function _parseExtension (ext, name) {
2497  
2498      name = name || null;
2499      // If it's a string, the extension was previously loaded
2500      if (showdown.helper.isString(ext)) {
2501        ext = showdown.helper.stdExtName(ext);
2502        name = ext;
2503  
2504        // LEGACY_SUPPORT CODE
2505        if (showdown.extensions[ext]) {
2506          console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
2507            'Please inform the developer that the extension should be updated!');
2508          legacyExtensionLoading(showdown.extensions[ext], ext);
2509          return;
2510        // END LEGACY SUPPORT CODE
2511  
2512        } else if (!showdown.helper.isUndefined(extensions[ext])) {
2513          ext = extensions[ext];
2514  
2515        } else {
2516          throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
2517        }
2518      }
2519  
2520      if (typeof ext === 'function') {
2521        ext = ext();
2522      }
2523  
2524      if (!showdown.helper.isArray(ext)) {
2525        ext = [ext];
2526      }
2527  
2528      var validExt = validate(ext, name);
2529      if (!validExt.valid) {
2530        throw Error(validExt.error);
2531      }
2532  
2533      for (var i = 0; i < ext.length; ++i) {
2534        switch (ext[i].type) {
2535  
2536          case 'lang':
2537            langExtensions.push(ext[i]);
2538            break;
2539  
2540          case 'output':
2541            outputModifiers.push(ext[i]);
2542            break;
2543        }
2544        if (ext[i].hasOwnProperty('listeners')) {
2545          for (var ln in ext[i].listeners) {
2546            if (ext[i].listeners.hasOwnProperty(ln)) {
2547              listen(ln, ext[i].listeners[ln]);
2548            }
2549          }
2550        }
2551      }
2552  
2553    }
2554  
2555    /**
2556     * LEGACY_SUPPORT
2557     * @param {*} ext
2558     * @param {string} name
2559     */
2560    function legacyExtensionLoading (ext, name) {
2561      if (typeof ext === 'function') {
2562        ext = ext(new showdown.Converter());
2563      }
2564      if (!showdown.helper.isArray(ext)) {
2565        ext = [ext];
2566      }
2567      var valid = validate(ext, name);
2568  
2569      if (!valid.valid) {
2570        throw Error(valid.error);
2571      }
2572  
2573      for (var i = 0; i < ext.length; ++i) {
2574        switch (ext[i].type) {
2575          case 'lang':
2576            langExtensions.push(ext[i]);
2577            break;
2578          case 'output':
2579            outputModifiers.push(ext[i]);
2580            break;
2581          default:// should never reach here
2582            throw Error('Extension loader error: Type unrecognized!!!');
2583        }
2584      }
2585    }
2586  
2587    /**
2588     * Listen to an event
2589     * @param {string} name
2590     * @param {function} callback
2591     */
2592    function listen (name, callback) {
2593      if (!showdown.helper.isString(name)) {
2594        throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
2595      }
2596  
2597      if (typeof callback !== 'function') {
2598        throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
2599      }
2600  
2601      if (!listeners.hasOwnProperty(name)) {
2602        listeners[name] = [];
2603      }
2604      listeners[name].push(callback);
2605    }
2606  
2607    function rTrimInputText (text) {
2608      var rsp = text.match(/^\s*/)[0].length,
2609          rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
2610      return text.replace(rgx, '');
2611    }
2612  
2613    /**
2614     * Dispatch an event
2615     * @private
2616     * @param {string} evtName Event name
2617     * @param {string} text Text
2618     * @param {{}} options Converter Options
2619     * @param {{}} globals
2620     * @returns {string}
2621     */
2622    this._dispatch = function dispatch (evtName, text, options, globals) {
2623      if (listeners.hasOwnProperty(evtName)) {
2624        for (var ei = 0; ei < listeners[evtName].length; ++ei) {
2625          var nText = listeners[evtName][ei](evtName, text, this, options, globals);
2626          if (nText && typeof nText !== 'undefined') {
2627            text = nText;
2628          }
2629        }
2630      }
2631      return text;
2632    };
2633  
2634    /**
2635     * Listen to an event
2636     * @param {string} name
2637     * @param {function} callback
2638     * @returns {showdown.Converter}
2639     */
2640    this.listen = function (name, callback) {
2641      listen(name, callback);
2642      return this;
2643    };
2644  
2645    /**
2646     * Converts a markdown string into HTML
2647     * @param {string} text
2648     * @returns {*}
2649     */
2650    this.makeHtml = function (text) {
2651      //check if text is not falsy
2652      if (!text) {
2653        return text;
2654      }
2655  
2656      var globals = {
2657        gHtmlBlocks:     [],
2658        gHtmlMdBlocks:   [],
2659        gHtmlSpans:      [],
2660        gUrls:           {},
2661        gTitles:         {},
2662        gDimensions:     {},
2663        gListLevel:      0,
2664        hashLinkCounts:  {},
2665        langExtensions:  langExtensions,
2666        outputModifiers: outputModifiers,
2667        converter:       this,
2668        ghCodeBlocks:    [],
2669        metadata: {
2670          parsed: {},
2671          raw: '',
2672          format: ''
2673        }
2674      };
2675  
2676      // This lets us use ¨ trema as an escape char to avoid md5 hashes
2677      // The choice of character is arbitrary; anything that isn't
2678      // magic in Markdown will work.
2679      text = text.replace(/¨/g, '¨T');
2680  
2681      // Replace $ with ¨D
2682      // RegExp interprets $ as a special character
2683      // when it's in a replacement string
2684      text = text.replace(/\$/g, '¨D');
2685  
2686      // Standardize line endings
2687      text = text.replace(/\r\n/g, '\n'); // DOS to Unix
2688      text = text.replace(/\r/g, '\n'); // Mac to Unix
2689  
2690      // Stardardize line spaces
2691      text = text.replace(/\u00A0/g, '&nbsp;');
2692  
2693      if (options.smartIndentationFix) {
2694        text = rTrimInputText(text);
2695      }
2696  
2697      // Make sure text begins and ends with a couple of newlines:
2698      text = '\n\n' + text + '\n\n';
2699  
2700      // detab
2701      text = showdown.subParser('detab')(text, options, globals);
2702  
2703      /**
2704       * Strip any lines consisting only of spaces and tabs.
2705       * This makes subsequent regexs easier to write, because we can
2706       * match consecutive blank lines with /\n+/ instead of something
2707       * contorted like /[ \t]*\n+/
2708       */
2709      text = text.replace(/^[ \t]+$/mg, '');
2710  
2711      //run languageExtensions
2712      showdown.helper.forEach(langExtensions, function (ext) {
2713        text = showdown.subParser('runExtension')(ext, text, options, globals);
2714      });
2715  
2716      // run the sub parsers
2717      text = showdown.subParser('metadata')(text, options, globals);
2718      text = showdown.subParser('hashPreCodeTags')(text, options, globals);
2719      text = showdown.subParser('githubCodeBlocks')(text, options, globals);
2720      text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
2721      text = showdown.subParser('hashCodeTags')(text, options, globals);
2722      text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
2723      text = showdown.subParser('blockGamut')(text, options, globals);
2724      text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
2725      text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
2726  
2727      // attacklab: Restore dollar signs
2728      text = text.replace(/¨D/g, '$$');
2729  
2730      // attacklab: Restore tremas
2731      text = text.replace(/¨T/g, '¨');
2732  
2733      // render a complete html document instead of a partial if the option is enabled
2734      text = showdown.subParser('completeHTMLDocument')(text, options, globals);
2735  
2736      // Run output modifiers
2737      showdown.helper.forEach(outputModifiers, function (ext) {
2738        text = showdown.subParser('runExtension')(ext, text, options, globals);
2739      });
2740  
2741      // update metadata
2742      metadata = globals.metadata;
2743      return text;
2744    };
2745  
2746    /**
2747     * Converts an HTML string into a markdown string
2748     * @param src
2749     * @param [HTMLParser] A WHATWG DOM and HTML parser, such as JSDOM. If none is supplied, window.document will be used.
2750     * @returns {string}
2751     */
2752    this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
2753  
2754      // replace \r\n with \n
2755      src = src.replace(/\r\n/g, '\n');
2756      src = src.replace(/\r/g, '\n'); // old macs
2757  
2758      // due to an edge case, we need to find this: > <
2759      // to prevent removing of non silent white spaces
2760      // ex: <em>this is</em> <strong>sparta</strong>
2761      src = src.replace(/>[ \t]+</, '>¨NBSP;<');
2762  
2763      if (!HTMLParser) {
2764        if (window && window.document) {
2765          HTMLParser = window.document;
2766        } else {
2767          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');
2768        }
2769      }
2770  
2771      var doc = HTMLParser.createElement('div');
2772      doc.innerHTML = src;
2773  
2774      var globals = {
2775        preList: substitutePreCodeTags(doc)
2776      };
2777  
2778      // remove all newlines and collapse spaces
2779      clean(doc);
2780  
2781      // some stuff, like accidental reference links must now be escaped
2782      // TODO
2783      // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
2784  
2785      var nodes = doc.childNodes,
2786          mdDoc = '';
2787  
2788      for (var i = 0; i < nodes.length; i++) {
2789        mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
2790      }
2791  
2792      function clean (node) {
2793        for (var n = 0; n < node.childNodes.length; ++n) {
2794          var child = node.childNodes[n];
2795          if (child.nodeType === 3) {
2796            if (!/\S/.test(child.nodeValue)) {
2797              node.removeChild(child);
2798              --n;
2799            } else {
2800              child.nodeValue = child.nodeValue.split('\n').join(' ');
2801              child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
2802            }
2803          } else if (child.nodeType === 1) {
2804            clean(child);
2805          }
2806        }
2807      }
2808  
2809      // find all pre tags and replace contents with placeholder
2810      // we need this so that we can remove all indentation from html
2811      // to ease up parsing
2812      function substitutePreCodeTags (doc) {
2813  
2814        var pres = doc.querySelectorAll('pre'),
2815            presPH = [];
2816  
2817        for (var i = 0; i < pres.length; ++i) {
2818  
2819          if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
2820            var content = pres[i].firstChild.innerHTML.trim(),
2821                language = pres[i].firstChild.getAttribute('data-language') || '';
2822  
2823            // if data-language attribute is not defined, then we look for class language-*
2824            if (language === '') {
2825              var classes = pres[i].firstChild.className.split(' ');
2826              for (var c = 0; c < classes.length; ++c) {
2827                var matches = classes[c].match(/^language-(.+)$/);
2828                if (matches !== null) {
2829                  language = matches[1];
2830                  break;
2831                }
2832              }
2833            }
2834  
2835            // unescape html entities in content
2836            content = showdown.helper.unescapeHTMLEntities(content);
2837  
2838            presPH.push(content);
2839            pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
2840          } else {
2841            presPH.push(pres[i].innerHTML);
2842            pres[i].innerHTML = '';
2843            pres[i].setAttribute('prenum', i.toString());
2844          }
2845        }
2846        return presPH;
2847      }
2848  
2849      return mdDoc;
2850    };
2851  
2852    /**
2853     * Set an option of this Converter instance
2854     * @param {string} key
2855     * @param {*} value
2856     */
2857    this.setOption = function (key, value) {
2858      options[key] = value;
2859    };
2860  
2861    /**
2862     * Get the option of this Converter instance
2863     * @param {string} key
2864     * @returns {*}
2865     */
2866    this.getOption = function (key) {
2867      return options[key];
2868    };
2869  
2870    /**
2871     * Get the options of this Converter instance
2872     * @returns {{}}
2873     */
2874    this.getOptions = function () {
2875      return options;
2876    };
2877  
2878    /**
2879     * Add extension to THIS converter
2880     * @param {{}} extension
2881     * @param {string} [name=null]
2882     */
2883    this.addExtension = function (extension, name) {
2884      name = name || null;
2885      _parseExtension(extension, name);
2886    };
2887  
2888    /**
2889     * Use a global registered extension with THIS converter
2890     * @param {string} extensionName Name of the previously registered extension
2891     */
2892    this.useExtension = function (extensionName) {
2893      _parseExtension(extensionName);
2894    };
2895  
2896    /**
2897     * Set the flavor THIS converter should use
2898     * @param {string} name
2899     */
2900    this.setFlavor = function (name) {
2901      if (!flavor.hasOwnProperty(name)) {
2902        throw Error(name + ' flavor was not found');
2903      }
2904      var preset = flavor[name];
2905      setConvFlavor = name;
2906      for (var option in preset) {
2907        if (preset.hasOwnProperty(option)) {
2908          options[option] = preset[option];
2909        }
2910      }
2911    };
2912  
2913    /**
2914     * Get the currently set flavor of this converter
2915     * @returns {string}
2916     */
2917    this.getFlavor = function () {
2918      return setConvFlavor;
2919    };
2920  
2921    /**
2922     * Remove an extension from THIS converter.
2923     * Note: This is a costly operation. It's better to initialize a new converter
2924     * and specify the extensions you wish to use
2925     * @param {Array} extension
2926     */
2927    this.removeExtension = function (extension) {
2928      if (!showdown.helper.isArray(extension)) {
2929        extension = [extension];
2930      }
2931      for (var a = 0; a < extension.length; ++a) {
2932        var ext = extension[a];
2933        for (var i = 0; i < langExtensions.length; ++i) {
2934          if (langExtensions[i] === ext) {
2935            langExtensions[i].splice(i, 1);
2936          }
2937        }
2938        for (var ii = 0; ii < outputModifiers.length; ++i) {
2939          if (outputModifiers[ii] === ext) {
2940            outputModifiers[ii].splice(i, 1);
2941          }
2942        }
2943      }
2944    };
2945  
2946    /**
2947     * Get all extension of THIS converter
2948     * @returns {{language: Array, output: Array}}
2949     */
2950    this.getAllExtensions = function () {
2951      return {
2952        language: langExtensions,
2953        output: outputModifiers
2954      };
2955    };
2956  
2957    /**
2958     * Get the metadata of the previously parsed document
2959     * @param raw
2960     * @returns {string|{}}
2961     */
2962    this.getMetadata = function (raw) {
2963      if (raw) {
2964        return metadata.raw;
2965      } else {
2966        return metadata.parsed;
2967      }
2968    };
2969  
2970    /**
2971     * Get the metadata format of the previously parsed document
2972     * @returns {string}
2973     */
2974    this.getMetadataFormat = function () {
2975      return metadata.format;
2976    };
2977  
2978    /**
2979     * Private: set a single key, value metadata pair
2980     * @param {string} key
2981     * @param {string} value
2982     */
2983    this._setMetadataPair = function (key, value) {
2984      metadata.parsed[key] = value;
2985    };
2986  
2987    /**
2988     * Private: set metadata format
2989     * @param {string} format
2990     */
2991    this._setMetadataFormat = function (format) {
2992      metadata.format = format;
2993    };
2994  
2995    /**
2996     * Private: set metadata raw text
2997     * @param {string} raw
2998     */
2999    this._setMetadataRaw = function (raw) {
3000      metadata.raw = raw;
3001    };
3002  };
3003  
3004  /**
3005   * Turn Markdown link shortcuts into XHTML <a> tags.
3006   */
3007  showdown.subParser('anchors', function (text, options, globals) {
3008    'use strict';
3009  
3010    text = globals.converter._dispatch('anchors.before', text, options, globals);
3011  
3012    var writeAnchorTag = function (wholeMatch, linkText, linkId, url, m5, m6, title) {
3013      if (showdown.helper.isUndefined(title)) {
3014        title = '';
3015      }
3016      linkId = linkId.toLowerCase();
3017  
3018      // Special case for explicit empty url
3019      if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3020        url = '';
3021      } else if (!url) {
3022        if (!linkId) {
3023          // lower-case and turn embedded newlines into spaces
3024          linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
3025        }
3026        url = '#' + linkId;
3027  
3028        if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
3029          url = globals.gUrls[linkId];
3030          if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
3031            title = globals.gTitles[linkId];
3032          }
3033        } else {
3034          return wholeMatch;
3035        }
3036      }
3037  
3038      //url = showdown.helper.escapeCharacters(url, '*_', false); // replaced line to improve performance
3039      url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3040  
3041      var result = '<a href="' + url + '"';
3042  
3043      if (title !== '' && title !== null) {
3044        title = title.replace(/"/g, '&quot;');
3045        //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3046        title = title.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3047        result += ' title="' + title + '"';
3048      }
3049  
3050      // optionLinksInNewWindow only applies
3051      // to external links. Hash links (#) open in same page
3052      if (options.openLinksInNewWindow && !/^#/.test(url)) {
3053        // escaped _
3054        result += ' target="¨E95Eblank"';
3055      }
3056  
3057      result += '>' + linkText + '</a>';
3058  
3059      return result;
3060    };
3061  
3062    // First, handle reference-style links: [link text] [id]
3063    text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g, writeAnchorTag);
3064  
3065    // Next, inline-style links: [link text](url "optional title")
3066    // cases with crazy urls like ./image/cat1).png
3067    text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3068      writeAnchorTag);
3069  
3070    // normal cases
3071    text = text.replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,
3072                        writeAnchorTag);
3073  
3074    // handle reference-style shortcuts: [link text]
3075    // These must come last in case you've also got [link test][1]
3076    // or [link test](/foo)
3077    text = text.replace(/\[([^\[\]]+)]()()()()()/g, writeAnchorTag);
3078  
3079    // Lastly handle GithubMentions if option is enabled
3080    if (options.ghMentions) {
3081      text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
3082        if (escape === '\\') {
3083          return st + mentions;
3084        }
3085  
3086        //check if options.ghMentionsLink is a string
3087        if (!showdown.helper.isString(options.ghMentionsLink)) {
3088          throw new Error('ghMentionsLink option must be a string');
3089        }
3090        var lnk = options.ghMentionsLink.replace(/\{u}/g, username),
3091            target = '';
3092        if (options.openLinksInNewWindow) {
3093          target = ' target="¨E95Eblank"';
3094        }
3095        return st + '<a href="' + lnk + '"' + target + '>' + mentions + '</a>';
3096      });
3097    }
3098  
3099    text = globals.converter._dispatch('anchors.after', text, options, globals);
3100    return text;
3101  });
3102  
3103  // url allowed chars [a-z\d_.~:/?#[]@!$&'()*+,;=-]
3104  
3105  var simpleURLRegex  = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,
3106      simpleURLRegex2 = /([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,
3107      delimUrlRegex   = /()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,
3108      simpleMailRegex = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi,
3109      delimMailRegex  = /<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
3110  
3111      replaceLink = function (options) {
3112        'use strict';
3113        return function (wm, leadingMagicChars, link, m2, m3, trailingPunctuation, trailingMagicChars) {
3114          link = link.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
3115          var lnkTxt = link,
3116              append = '',
3117              target = '',
3118              lmc    = leadingMagicChars || '',
3119              tmc    = trailingMagicChars || '';
3120          if (/^www\./i.test(link)) {
3121            link = link.replace(/^www\./i, 'http://www.');
3122          }
3123          if (options.excludeTrailingPunctuationFromURLs && trailingPunctuation) {
3124            append = trailingPunctuation;
3125          }
3126          if (options.openLinksInNewWindow) {
3127            target = ' target="¨E95Eblank"';
3128          }
3129          return lmc + '<a href="' + link + '"' + target + '>' + lnkTxt + '</a>' + append + tmc;
3130        };
3131      },
3132  
3133      replaceMail = function (options, globals) {
3134        'use strict';
3135        return function (wholeMatch, b, mail) {
3136          var href = 'mailto:';
3137          b = b || '';
3138          mail = showdown.subParser('unescapeSpecialChars')(mail, options, globals);
3139          if (options.encodeEmails) {
3140            href = showdown.helper.encodeEmailAddress(href + mail);
3141            mail = showdown.helper.encodeEmailAddress(mail);
3142          } else {
3143            href = href + mail;
3144          }
3145          return b + '<a href="' + href + '">' + mail + '</a>';
3146        };
3147      };
3148  
3149  showdown.subParser('autoLinks', function (text, options, globals) {
3150    'use strict';
3151  
3152    text = globals.converter._dispatch('autoLinks.before', text, options, globals);
3153  
3154    text = text.replace(delimUrlRegex, replaceLink(options));
3155    text = text.replace(delimMailRegex, replaceMail(options, globals));
3156  
3157    text = globals.converter._dispatch('autoLinks.after', text, options, globals);
3158  
3159    return text;
3160  });
3161  
3162  showdown.subParser('simplifiedAutoLinks', function (text, options, globals) {
3163    'use strict';
3164  
3165    if (!options.simplifiedAutoLink) {
3166      return text;
3167    }
3168  
3169    text = globals.converter._dispatch('simplifiedAutoLinks.before', text, options, globals);
3170  
3171    if (options.excludeTrailingPunctuationFromURLs) {
3172      text = text.replace(simpleURLRegex2, replaceLink(options));
3173    } else {
3174      text = text.replace(simpleURLRegex, replaceLink(options));
3175    }
3176    text = text.replace(simpleMailRegex, replaceMail(options, globals));
3177  
3178    text = globals.converter._dispatch('simplifiedAutoLinks.after', text, options, globals);
3179  
3180    return text;
3181  });
3182  
3183  /**
3184   * These are all the transformations that form block-level
3185   * tags like paragraphs, headers, and list items.
3186   */
3187  showdown.subParser('blockGamut', function (text, options, globals) {
3188    'use strict';
3189  
3190    text = globals.converter._dispatch('blockGamut.before', text, options, globals);
3191  
3192    // we parse blockquotes first so that we can have headings and hrs
3193    // inside blockquotes
3194    text = showdown.subParser('blockQuotes')(text, options, globals);
3195    text = showdown.subParser('headers')(text, options, globals);
3196  
3197    // Do Horizontal Rules:
3198    text = showdown.subParser('horizontalRule')(text, options, globals);
3199  
3200    text = showdown.subParser('lists')(text, options, globals);
3201    text = showdown.subParser('codeBlocks')(text, options, globals);
3202    text = showdown.subParser('tables')(text, options, globals);
3203  
3204    // We already ran _HashHTMLBlocks() before, in Markdown(), but that
3205    // was to escape raw HTML in the original Markdown source. This time,
3206    // we're escaping the markup we've just created, so that we don't wrap
3207    // <p> tags around block-level tags.
3208    text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
3209    text = showdown.subParser('paragraphs')(text, options, globals);
3210  
3211    text = globals.converter._dispatch('blockGamut.after', text, options, globals);
3212  
3213    return text;
3214  });
3215  
3216  showdown.subParser('blockQuotes', function (text, options, globals) {
3217    'use strict';
3218  
3219    text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
3220  
3221    // add a couple extra lines after the text and endtext mark
3222    text = text + '\n\n';
3223  
3224    var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
3225  
3226    if (options.splitAdjacentBlockquotes) {
3227      rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
3228    }
3229  
3230    text = text.replace(rgx, function (bq) {
3231      // attacklab: hack around Konqueror 3.5.4 bug:
3232      // "----------bug".replace(/^-/g,"") == "bug"
3233      bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
3234  
3235      // attacklab: clean up hack
3236      bq = bq.replace(/¨0/g, '');
3237  
3238      bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
3239      bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
3240      bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
3241  
3242      bq = bq.replace(/(^|\n)/g, '$1  ');
3243      // These leading spaces screw with <pre> content, so we need to fix that:
3244      bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
3245        var pre = m1;
3246        // attacklab: hack around Konqueror 3.5.4 bug:
3247        pre = pre.replace(/^  /mg, '¨0');
3248        pre = pre.replace(/¨0/g, '');
3249        return pre;
3250      });
3251  
3252      return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
3253    });
3254  
3255    text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
3256    return text;
3257  });
3258  
3259  /**
3260   * Process Markdown `<pre><code>` blocks.
3261   */
3262  showdown.subParser('codeBlocks', function (text, options, globals) {
3263    'use strict';
3264  
3265    text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
3266  
3267    // sentinel workarounds for lack of \A and \Z, safari\khtml bug
3268    text += '¨0';
3269  
3270    var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
3271    text = text.replace(pattern, function (wholeMatch, m1, m2) {
3272      var codeblock = m1,
3273          nextChar = m2,
3274          end = '\n';
3275  
3276      codeblock = showdown.subParser('outdent')(codeblock, options, globals);
3277      codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3278      codeblock = showdown.subParser('detab')(codeblock, options, globals);
3279      codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3280      codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
3281  
3282      if (options.omitExtraWLInCodeBlocks) {
3283        end = '';
3284      }
3285  
3286      codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
3287  
3288      return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
3289    });
3290  
3291    // strip sentinel
3292    text = text.replace(/¨0/, '');
3293  
3294    text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
3295    return text;
3296  });
3297  
3298  /**
3299   *
3300   *   *  Backtick quotes are used for <code></code> spans.
3301   *
3302   *   *  You can use multiple backticks as the delimiters if you want to
3303   *     include literal backticks in the code span. So, this input:
3304   *
3305   *         Just type ``foo `bar` baz`` at the prompt.
3306   *
3307   *       Will translate to:
3308   *
3309   *         <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
3310   *
3311   *    There's no arbitrary limit to the number of backticks you
3312   *    can use as delimters. If you need three consecutive backticks
3313   *    in your code, use four for delimiters, etc.
3314   *
3315   *  *  You can use spaces to get literal backticks at the edges:
3316   *
3317   *         ... type `` `bar` `` ...
3318   *
3319   *       Turns to:
3320   *
3321   *         ... type <code>`bar`</code> ...
3322   */
3323  showdown.subParser('codeSpans', function (text, options, globals) {
3324    'use strict';
3325  
3326    text = globals.converter._dispatch('codeSpans.before', text, options, globals);
3327  
3328    if (typeof(text) === 'undefined') {
3329      text = '';
3330    }
3331    text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
3332      function (wholeMatch, m1, m2, m3) {
3333        var c = m3;
3334        c = c.replace(/^([ \t]*)/g, '');    // leading whitespace
3335        c = c.replace(/[ \t]*$/g, '');    // trailing whitespace
3336        c = showdown.subParser('encodeCode')(c, options, globals);
3337        c = m1 + '<code>' + c + '</code>';
3338        c = showdown.subParser('hashHTMLSpans')(c, options, globals);
3339        return c;
3340      }
3341    );
3342  
3343    text = globals.converter._dispatch('codeSpans.after', text, options, globals);
3344    return text;
3345  });
3346  
3347  /**
3348   * Create a full HTML document from the processed markdown
3349   */
3350  showdown.subParser('completeHTMLDocument', function (text, options, globals) {
3351    'use strict';
3352  
3353    if (!options.completeHTMLDocument) {
3354      return text;
3355    }
3356  
3357    text = globals.converter._dispatch('completeHTMLDocument.before', text, options, globals);
3358  
3359    var doctype = 'html',
3360        doctypeParsed = '<!DOCTYPE HTML>\n',
3361        title = '',
3362        charset = '<meta charset="utf-8">\n',
3363        lang = '',
3364        metadata = '';
3365  
3366    if (typeof globals.metadata.parsed.doctype !== 'undefined') {
3367      doctypeParsed = '<!DOCTYPE ' +  globals.metadata.parsed.doctype + '>\n';
3368      doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
3369      if (doctype === 'html' || doctype === 'html5') {
3370        charset = '<meta charset="utf-8">';
3371      }
3372    }
3373  
3374    for (var meta in globals.metadata.parsed) {
3375      if (globals.metadata.parsed.hasOwnProperty(meta)) {
3376        switch (meta.toLowerCase()) {
3377          case 'doctype':
3378            break;
3379  
3380          case 'title':
3381            title = '<title>' +  globals.metadata.parsed.title + '</title>\n';
3382            break;
3383  
3384          case 'charset':
3385            if (doctype === 'html' || doctype === 'html5') {
3386              charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
3387            } else {
3388              charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
3389            }
3390            break;
3391  
3392          case 'language':
3393          case 'lang':
3394            lang = ' lang="' + globals.metadata.parsed[meta] + '"';
3395            metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3396            break;
3397  
3398          default:
3399            metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
3400        }
3401      }
3402    }
3403  
3404    text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
3405  
3406    text = globals.converter._dispatch('completeHTMLDocument.after', text, options, globals);
3407    return text;
3408  });
3409  
3410  /**
3411   * Convert all tabs to spaces
3412   */
3413  showdown.subParser('detab', function (text, options, globals) {
3414    'use strict';
3415    text = globals.converter._dispatch('detab.before', text, options, globals);
3416  
3417    // expand first n-1 tabs
3418    text = text.replace(/\t(?=\t)/g, '    '); // g_tab_width
3419  
3420    // replace the nth with two sentinels
3421    text = text.replace(/\t/g, '¨A¨B');
3422  
3423    // use the sentinel to anchor our regex so it doesn't explode
3424    text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
3425      var leadingText = m1,
3426          numSpaces = 4 - leadingText.length % 4;  // g_tab_width
3427  
3428      // there *must* be a better way to do this:
3429      for (var i = 0; i < numSpaces; i++) {
3430        leadingText += ' ';
3431      }
3432  
3433      return leadingText;
3434    });
3435  
3436    // clean up sentinels
3437    text = text.replace(/¨A/g, '    ');  // g_tab_width
3438    text = text.replace(/¨B/g, '');
3439  
3440    text = globals.converter._dispatch('detab.after', text, options, globals);
3441    return text;
3442  });
3443  
3444  showdown.subParser('ellipsis', function (text, options, globals) {
3445    'use strict';
3446  
3447    text = globals.converter._dispatch('ellipsis.before', text, options, globals);
3448  
3449    text = text.replace(/\.\.\./g, '…');
3450  
3451    text = globals.converter._dispatch('ellipsis.after', text, options, globals);
3452  
3453    return text;
3454  });
3455  
3456  /**
3457   * Turn emoji codes into emojis
3458   *
3459   * List of supported emojis: https://github.com/showdownjs/showdown/wiki/Emojis
3460   */
3461  showdown.subParser('emoji', function (text, options, globals) {
3462    'use strict';
3463  
3464    if (!options.emoji) {
3465      return text;
3466    }
3467  
3468    text = globals.converter._dispatch('emoji.before', text, options, globals);
3469  
3470    var emojiRgx = /:([\S]+?):/g;
3471  
3472    text = text.replace(emojiRgx, function (wm, emojiCode) {
3473      if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
3474        return showdown.helper.emojis[emojiCode];
3475      }
3476      return wm;
3477    });
3478  
3479    text = globals.converter._dispatch('emoji.after', text, options, globals);
3480  
3481    return text;
3482  });
3483  
3484  /**
3485   * Smart processing for ampersands and angle brackets that need to be encoded.
3486   */
3487  showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
3488    'use strict';
3489    text = globals.converter._dispatch('encodeAmpsAndAngles.before', text, options, globals);
3490  
3491    // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
3492    // http://bumppo.net/projects/amputator/
3493    text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
3494  
3495    // Encode naked <'s
3496    text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
3497  
3498    // Encode <
3499    text = text.replace(/</g, '&lt;');
3500  
3501    // Encode >
3502    text = text.replace(/>/g, '&gt;');
3503  
3504    text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
3505    return text;
3506  });
3507  
3508  /**
3509   * Returns the string, with after processing the following backslash escape sequences.
3510   *
3511   * attacklab: The polite way to do this is with the new escapeCharacters() function:
3512   *
3513   *    text = escapeCharacters(text,"\\",true);
3514   *    text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
3515   *
3516   * ...but we're sidestepping its use of the (slow) RegExp constructor
3517   * as an optimization for Firefox.  This function gets called a LOT.
3518   */
3519  showdown.subParser('encodeBackslashEscapes', function (text, options, globals) {
3520    'use strict';
3521    text = globals.converter._dispatch('encodeBackslashEscapes.before', text, options, globals);
3522  
3523    text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
3524    text = text.replace(/\\([`*_{}\[\]()>#+.!~=|-])/g, showdown.helper.escapeCharactersCallback);
3525  
3526    text = globals.converter._dispatch('encodeBackslashEscapes.after', text, options, globals);
3527    return text;
3528  });
3529  
3530  /**
3531   * Encode/escape certain characters inside Markdown code runs.
3532   * The point is that in code, these characters are literals,
3533   * and lose their special Markdown meanings.
3534   */
3535  showdown.subParser('encodeCode', function (text, options, globals) {
3536    'use strict';
3537  
3538    text = globals.converter._dispatch('encodeCode.before', text, options, globals);
3539  
3540    // Encode all ampersands; HTML entities are not
3541    // entities within a Markdown code span.
3542    text = text
3543      .replace(/&/g, '&amp;')
3544    // Do the angle bracket song and dance:
3545      .replace(/</g, '&lt;')
3546      .replace(/>/g, '&gt;')
3547    // Now, escape characters that are magic in Markdown:
3548      .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
3549  
3550    text = globals.converter._dispatch('encodeCode.after', text, options, globals);
3551    return text;
3552  });
3553  
3554  /**
3555   * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
3556   * don't conflict with their use in Markdown for code, italics and strong.
3557   */
3558  showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
3559    'use strict';
3560    text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.before', text, options, globals);
3561  
3562    // Build a regex to find HTML tags.
3563    var tags     = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
3564        comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
3565  
3566    text = text.replace(tags, function (wholeMatch) {
3567      return wholeMatch
3568        .replace(/(.)<\/?code>(?=.)/g, '$1`')
3569        .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3570    });
3571  
3572    text = text.replace(comments, function (wholeMatch) {
3573      return wholeMatch
3574        .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
3575    });
3576  
3577    text = globals.converter._dispatch('escapeSpecialCharsWithinTagAttributes.after', text, options, globals);
3578    return text;
3579  });
3580  
3581  /**
3582   * Handle github codeblocks prior to running HashHTML so that
3583   * HTML contained within the codeblock gets escaped properly
3584   * Example:
3585   * ```ruby
3586   *     def hello_world(x)
3587   *       puts "Hello, #{x}"
3588   *     end
3589   * ```
3590   */
3591  showdown.subParser('githubCodeBlocks', function (text, options, globals) {
3592    'use strict';
3593  
3594    // early exit if option is not enabled
3595    if (!options.ghCodeBlocks) {
3596      return text;
3597    }
3598  
3599    text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
3600  
3601    text += '¨0';
3602  
3603    text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
3604      var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
3605  
3606      // First parse the github code block
3607      codeblock = showdown.subParser('encodeCode')(codeblock, options, globals);
3608      codeblock = showdown.subParser('detab')(codeblock, options, globals);
3609      codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
3610      codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
3611  
3612      codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
3613  
3614      codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
3615  
3616      // Since GHCodeblocks can be false positives, we need to
3617      // store the primitive text and the parsed text in a global var,
3618      // and then return a token
3619      return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
3620    });
3621  
3622    // attacklab: strip sentinel
3623    text = text.replace(/¨0/, '');
3624  
3625    return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
3626  });
3627  
3628  showdown.subParser('hashBlock', function (text, options, globals) {
3629    'use strict';
3630    text = globals.converter._dispatch('hashBlock.before', text, options, globals);
3631    text = text.replace(/(^\n+|\n+$)/g, '');
3632    text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
3633    text = globals.converter._dispatch('hashBlock.after', text, options, globals);
3634    return text;
3635  });
3636  
3637  /**
3638   * Hash and escape <code> elements that should not be parsed as markdown
3639   */
3640  showdown.subParser('hashCodeTags', function (text, options, globals) {
3641    'use strict';
3642    text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
3643  
3644    var repFunc = function (wholeMatch, match, left, right) {
3645      var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
3646      return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
3647    };
3648  
3649    // Hash naked <code>
3650    text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
3651  
3652    text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
3653    return text;
3654  });
3655  
3656  showdown.subParser('hashElement', function (text, options, globals) {
3657    'use strict';
3658  
3659    return function (wholeMatch, m1) {
3660      var blockText = m1;
3661  
3662      // Undo double lines
3663      blockText = blockText.replace(/\n\n/g, '\n');
3664      blockText = blockText.replace(/^\n/, '');
3665  
3666      // strip trailing blank lines
3667      blockText = blockText.replace(/\n+$/g, '');
3668  
3669      // Replace the element text with a marker ("¨KxK" where x is its key)
3670      blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
3671  
3672      return blockText;
3673    };
3674  });
3675  
3676  showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
3677    'use strict';
3678    text = globals.converter._dispatch('hashHTMLBlocks.before', text, options, globals);
3679  
3680    var blockTags = [
3681          'pre',
3682          'div',
3683          'h1',
3684          'h2',
3685          'h3',
3686          'h4',
3687          'h5',
3688          'h6',
3689          'blockquote',
3690          'table',
3691          'dl',
3692          'ol',
3693          'ul',
3694          'script',
3695          'noscript',
3696          'form',
3697          'fieldset',
3698          'iframe',
3699          'math',
3700          'style',
3701          'section',
3702          'header',
3703          'footer',
3704          'nav',
3705          'article',
3706          'aside',
3707          'address',
3708          'audio',
3709          'canvas',
3710          'figure',
3711          'hgroup',
3712          'output',
3713          'video',
3714          'p'
3715        ],
3716        repFunc = function (wholeMatch, match, left, right) {
3717          var txt = wholeMatch;
3718          // check if this html element is marked as markdown
3719          // if so, it's contents should be parsed as markdown
3720          if (left.search(/\bmarkdown\b/) !== -1) {
3721            txt = left + globals.converter.makeHtml(match) + right;
3722          }
3723          return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
3724        };
3725  
3726    if (options.backslashEscapesHTMLTags) {
3727      // encode backslash escaped HTML tags
3728      text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
3729        return '&lt;' + inside + '&gt;';
3730      });
3731    }
3732  
3733    // hash HTML Blocks
3734    for (var i = 0; i < blockTags.length; ++i) {
3735  
3736      var opTagPos,
3737          rgx1     = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
3738          patLeft  = '<' + blockTags[i] + '\\b[^>]*>',
3739          patRight = '</' + blockTags[i] + '>';
3740      // 1. Look for the first position of the first opening HTML tag in the text
3741      while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
3742  
3743        // if the HTML tag is \ escaped, we need to escape it and break
3744  
3745  
3746        //2. Split the text in that position
3747        var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
3748        //3. Match recursively
3749            newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
3750  
3751        // prevent an infinite loop
3752        if (newSubText1 === subTexts[1]) {
3753          break;
3754        }
3755        text = subTexts[0].concat(newSubText1);
3756      }
3757    }
3758    // HR SPECIAL CASE
3759    text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
3760      showdown.subParser('hashElement')(text, options, globals));
3761  
3762    // Special case for standalone HTML comments
3763    text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
3764      return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
3765    }, '^ {0,3}<!--', '-->', 'gm');
3766  
3767    // PHP and ASP-style processor instructions (<?...?> and <%...%>)
3768    text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
3769      showdown.subParser('hashElement')(text, options, globals));
3770  
3771    text = globals.converter._dispatch('hashHTMLBlocks.after', text, options, globals);
3772    return text;
3773  });
3774  
3775  /**
3776   * Hash span elements that should not be parsed as markdown
3777   */
3778  showdown.subParser('hashHTMLSpans', function (text, options, globals) {
3779    'use strict';
3780    text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);
3781  
3782    function hashHTMLSpan (html) {
3783      return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
3784    }
3785  
3786    // Hash Self Closing tags
3787    text = text.replace(/<[^>]+?\/>/gi, function (wm) {
3788      return hashHTMLSpan(wm);
3789    });
3790  
3791    // Hash tags without properties
3792    text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
3793      return hashHTMLSpan(wm);
3794    });
3795  
3796    // Hash tags with properties
3797    text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
3798      return hashHTMLSpan(wm);
3799    });
3800  
3801    // Hash self closing tags without />
3802    text = text.replace(/<[^>]+?>/gi, function (wm) {
3803      return hashHTMLSpan(wm);
3804    });
3805  
3806    /*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/
3807  
3808    text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
3809    return text;
3810  });
3811  
3812  /**
3813   * Unhash HTML spans
3814   */
3815  showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
3816    'use strict';
3817    text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
3818  
3819    for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
3820      var repText = globals.gHtmlSpans[i],
3821          // limiter to prevent infinite loop (assume 10 as limit for recurse)
3822          limit = 0;
3823  
3824      while (/¨C(\d+)C/.test(repText)) {
3825        var num = RegExp.$1;
3826        repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
3827        if (limit === 10) {
3828          console.error('maximum nesting of 10 spans reached!!!');
3829          break;
3830        }
3831        ++limit;
3832      }
3833      text = text.replace('¨C' + i + 'C', repText);
3834    }
3835  
3836    text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
3837    return text;
3838  });
3839  
3840  /**
3841   * Hash and escape <pre><code> elements that should not be parsed as markdown
3842   */
3843  showdown.subParser('hashPreCodeTags', function (text, options, globals) {
3844    'use strict';
3845    text = globals.converter._dispatch('hashPreCodeTags.before', text, options, globals);
3846  
3847    var repFunc = function (wholeMatch, match, left, right) {
3848      // encode html entities
3849      var codeblock = left + showdown.subParser('encodeCode')(match, options, globals) + right;
3850      return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
3851    };
3852  
3853    // Hash <pre><code>
3854    text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
3855  
3856    text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
3857    return text;
3858  });
3859  
3860  showdown.subParser('headers', function (text, options, globals) {
3861    'use strict';
3862  
3863    text = globals.converter._dispatch('headers.before', text, options, globals);
3864  
3865    var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
3866  
3867    // Set text-style headers:
3868    //    Header 1
3869    //    ========
3870    //
3871    //    Header 2
3872    //    --------
3873    //
3874        setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
3875        setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
3876  
3877    text = text.replace(setextRegexH1, function (wholeMatch, m1) {
3878  
3879      var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
3880          hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
3881          hLevel = headerLevelStart,
3882          hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
3883      return showdown.subParser('hashBlock')(hashBlock, options, globals);
3884    });
3885  
3886    text = text.replace(setextRegexH2, function (matchFound, m1) {
3887      var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
3888          hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
3889          hLevel = headerLevelStart + 1,
3890          hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
3891      return showdown.subParser('hashBlock')(hashBlock, options, globals);
3892    });
3893  
3894    // atx-style headers:
3895    //  # Header 1
3896    //  ## Header 2
3897    //  ## Header 2 with closing hashes ##
3898    //  ...
3899    //  ###### Header 6
3900    //
3901    var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
3902  
3903    text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
3904      var hText = m2;
3905      if (options.customizedHeaderId) {
3906        hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
3907      }
3908  
3909      var span = showdown.subParser('spanGamut')(hText, options, globals),
3910          hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
3911          hLevel = headerLevelStart - 1 + m1.length,
3912          header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
3913  
3914      return showdown.subParser('hashBlock')(header, options, globals);
3915    });
3916  
3917    function headerId (m) {
3918      var title,
3919          prefix;
3920  
3921      // It is separate from other options to allow combining prefix and customized
3922      if (options.customizedHeaderId) {
3923        var match = m.match(/\{([^{]+?)}\s*$/);
3924        if (match && match[1]) {
3925          m = match[1];
3926        }
3927      }
3928  
3929      title = m;
3930  
3931      // Prefix id to prevent causing inadvertent pre-existing style matches.
3932      if (showdown.helper.isString(options.prefixHeaderId)) {
3933        prefix = options.prefixHeaderId;
3934      } else if (options.prefixHeaderId === true) {
3935        prefix = 'section-';
3936      } else {
3937        prefix = '';
3938      }
3939  
3940      if (!options.rawPrefixHeaderId) {
3941        title = prefix + title;
3942      }
3943  
3944      if (options.ghCompatibleHeaderId) {
3945        title = title
3946          .replace(/ /g, '-')
3947          // replace previously escaped chars (&, ¨ and $)
3948          .replace(/&amp;/g, '')
3949          .replace(/¨T/g, '')
3950          .replace(/¨D/g, '')
3951          // replace rest of the chars (&~$ are repeated as they might have been escaped)
3952          // borrowed from github's redcarpet (some they should produce similar results)
3953          .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
3954          .toLowerCase();
3955      } else if (options.rawHeaderId) {
3956        title = title
3957          .replace(/ /g, '-')
3958          // replace previously escaped chars (&, ¨ and $)
3959          .replace(/&amp;/g, '&')
3960          .replace(/¨T/g, '¨')
3961          .replace(/¨D/g, '$')
3962          // replace " and '
3963          .replace(/["']/g, '-')
3964          .toLowerCase();
3965      } else {
3966        title = title
3967          .replace(/[^\w]/g, '')
3968          .toLowerCase();
3969      }
3970  
3971      if (options.rawPrefixHeaderId) {
3972        title = prefix + title;
3973      }
3974  
3975      if (globals.hashLinkCounts[title]) {
3976        title = title + '-' + (globals.hashLinkCounts[title]++);
3977      } else {
3978        globals.hashLinkCounts[title] = 1;
3979      }
3980      return title;
3981    }
3982  
3983    text = globals.converter._dispatch('headers.after', text, options, globals);
3984    return text;
3985  });
3986  
3987  /**
3988   * Turn Markdown link shortcuts into XHTML <a> tags.
3989   */
3990  showdown.subParser('horizontalRule', function (text, options, globals) {
3991    'use strict';
3992    text = globals.converter._dispatch('horizontalRule.before', text, options, globals);
3993  
3994    var key = showdown.subParser('hashBlock')('<hr />', options, globals);
3995    text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
3996    text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
3997    text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
3998  
3999    text = globals.converter._dispatch('horizontalRule.after', text, options, globals);
4000    return text;
4001  });
4002  
4003  /**
4004   * Turn Markdown image shortcuts into <img> tags.
4005   */
4006  showdown.subParser('images', function (text, options, globals) {
4007    'use strict';
4008  
4009    text = globals.converter._dispatch('images.before', text, options, globals);
4010  
4011    var inlineRegExp      = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
4012        crazyRegExp       = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
4013        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,
4014        referenceRegExp   = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
4015        refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
4016  
4017    function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
4018      url = url.replace(/\s/g, '');
4019      return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
4020    }
4021  
4022    function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
4023  
4024      var gUrls   = globals.gUrls,
4025          gTitles = globals.gTitles,
4026          gDims   = globals.gDimensions;
4027  
4028      linkId = linkId.toLowerCase();
4029  
4030      if (!title) {
4031        title = '';
4032      }
4033      // Special case for explicit empty url
4034      if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
4035        url = '';
4036  
4037      } else if (url === '' || url === null) {
4038        if (linkId === '' || linkId === null) {
4039          // lower-case and turn embedded newlines into spaces
4040          linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
4041        }
4042        url = '#' + linkId;
4043  
4044        if (!showdown.helper.isUndefined(gUrls[linkId])) {
4045          url = gUrls[linkId];
4046          if (!showdown.helper.isUndefined(gTitles[linkId])) {
4047            title = gTitles[linkId];
4048          }
4049          if (!showdown.helper.isUndefined(gDims[linkId])) {
4050            width = gDims[linkId].width;
4051            height = gDims[linkId].height;
4052          }
4053        } else {
4054          return wholeMatch;
4055        }
4056      }
4057  
4058      altText = altText
4059        .replace(/"/g, '&quot;')
4060      //altText = showdown.helper.escapeCharacters(altText, '*_', false);
4061        .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4062      //url = showdown.helper.escapeCharacters(url, '*_', false);
4063      url = url.replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4064      var result = '<img src="' + url + '" alt="' + altText + '"';
4065  
4066      if (title && showdown.helper.isString(title)) {
4067        title = title
4068          .replace(/"/g, '&quot;')
4069        //title = showdown.helper.escapeCharacters(title, '*_', false);
4070          .replace(showdown.helper.regexes.asteriskDashAndColon, showdown.helper.escapeCharactersCallback);
4071        result += ' title="' + title + '"';
4072      }
4073  
4074      if (width && height) {
4075        width  = (width === '*') ? 'auto' : width;
4076        height = (height === '*') ? 'auto' : height;
4077  
4078        result += ' width="' + width + '"';
4079        result += ' height="' + height + '"';
4080      }
4081  
4082      result += ' />';
4083  
4084      return result;
4085    }
4086  
4087    // First, handle reference-style labeled images: ![alt text][id]
4088    text = text.replace(referenceRegExp, writeImageTag);
4089  
4090    // Next, handle inline images:  ![alt text](url =<width>x<height> "optional title")
4091  
4092    // base64 encoded images
4093    text = text.replace(base64RegExp, writeImageTagBase64);
4094  
4095    // cases with crazy urls like ./image/cat1).png
4096    text = text.replace(crazyRegExp, writeImageTag);
4097  
4098    // normal cases
4099    text = text.replace(inlineRegExp, writeImageTag);
4100  
4101    // handle reference-style shortcuts: ![img text]
4102    text = text.replace(refShortcutRegExp, writeImageTag);
4103  
4104    text = globals.converter._dispatch('images.after', text, options, globals);
4105    return text;
4106  });
4107  
4108  showdown.subParser('italicsAndBold', function (text, options, globals) {
4109    'use strict';
4110  
4111    text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
4112  
4113    // it's faster to have 3 separate regexes for each case than have just one
4114    // because of backtracing, in some cases, it could lead to an exponential effect
4115    // called "catastrophic backtrace". Ominous!
4116  
4117    function parseInside (txt, left, right) {
4118      /*
4119      if (options.simplifiedAutoLink) {
4120        txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4121      }
4122      */
4123      return left + txt + right;
4124    }
4125  
4126    // Parse underscores
4127    if (options.literalMidWordUnderscores) {
4128      text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4129        return parseInside (txt, '<strong><em>', '</em></strong>');
4130      });
4131      text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4132        return parseInside (txt, '<strong>', '</strong>');
4133      });
4134      text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
4135        return parseInside (txt, '<em>', '</em>');
4136      });
4137    } else {
4138      text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4139        return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4140      });
4141      text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4142        return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4143      });
4144      text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
4145        // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
4146        return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4147      });
4148    }
4149  
4150    // Now parse asterisks
4151    if (options.literalMidWordAsterisks) {
4152      text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
4153        return parseInside (txt, lead + '<strong><em>', '</em></strong>');
4154      });
4155      text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
4156        return parseInside (txt, lead + '<strong>', '</strong>');
4157      });
4158      text = text.replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g, function (wm, lead, txt) {
4159        return parseInside (txt, lead + '<em>', '</em>');
4160      });
4161    } else {
4162      text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
4163        return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
4164      });
4165      text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
4166        return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
4167      });
4168      text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
4169        // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
4170        return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
4171      });
4172    }
4173  
4174  
4175    text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
4176    return text;
4177  });
4178  
4179  /**
4180   * Form HTML ordered (numbered) and unordered (bulleted) lists.
4181   */
4182  showdown.subParser('lists', function (text, options, globals) {
4183    'use strict';
4184  
4185    /**
4186     * Process the contents of a single ordered or unordered list, splitting it
4187     * into individual list items.
4188     * @param {string} listStr
4189     * @param {boolean} trimTrailing
4190     * @returns {string}
4191     */
4192    function processListItems (listStr, trimTrailing) {
4193      // The $g_list_level global keeps track of when we're inside a list.
4194      // Each time we enter a list, we increment it; when we leave a list,
4195      // we decrement. If it's zero, we're not in a list anymore.
4196      //
4197      // We do this because when we're not inside a list, we want to treat
4198      // something like this:
4199      //
4200      //    I recommend upgrading to version
4201      //    8. Oops, now this line is treated
4202      //    as a sub-list.
4203      //
4204      // As a single paragraph, despite the fact that the second line starts
4205      // with a digit-period-space sequence.
4206      //
4207      // Whereas when we're inside a list (or sub-list), that line will be
4208      // treated as the start of a sub-list. What a kludge, huh? This is
4209      // an aspect of Markdown's syntax that's hard to parse perfectly
4210      // without resorting to mind-reading. Perhaps the solution is to
4211      // change the syntax rules such that sub-lists must start with a
4212      // starting cardinal number; e.g. "1." or "a.".
4213      globals.gListLevel++;
4214  
4215      // trim trailing blank lines:
4216      listStr = listStr.replace(/\n{2,}$/, '\n');
4217  
4218      // attacklab: add sentinel to emulate \z
4219      listStr += '¨0';
4220  
4221      var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
4222          isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
4223  
4224      // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
4225      // which is a syntax breaking change
4226      // activating this option reverts to old behavior
4227      if (options.disableForced4SpacesIndentedSublists) {
4228        rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
4229      }
4230  
4231      listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
4232        checked = (checked && checked.trim() !== '');
4233  
4234        var item = showdown.subParser('outdent')(m4, options, globals),
4235            bulletStyle = '';
4236  
4237        // Support for github tasklists
4238        if (taskbtn && options.tasklists) {
4239          bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
4240          item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
4241            var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
4242            if (checked) {
4243              otp += ' checked';
4244            }
4245            otp += '>';
4246            return otp;
4247          });
4248        }
4249  
4250        // ISSUE #312
4251        // This input: - - - a
4252        // causes trouble to the parser, since it interprets it as:
4253        // <ul><li><li><li>a</li></li></li></ul>
4254        // instead of:
4255        // <ul><li>- - a</li></ul>
4256        // So, to prevent it, we will put a marker (¨A)in the beginning of the line
4257        // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
4258        item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
4259          return '¨A' + wm2;
4260        });
4261  
4262        // m1 - Leading line or
4263        // Has a double return (multi paragraph) or
4264        // Has sublist
4265        if (m1 || (item.search(/\n{2,}/) > -1)) {
4266          item = showdown.subParser('githubCodeBlocks')(item, options, globals);
4267          item = showdown.subParser('blockGamut')(item, options, globals);
4268        } else {
4269          // Recursion for sub-lists:
4270          item = showdown.subParser('lists')(item, options, globals);
4271          item = item.replace(/\n$/, ''); // chomp(item)
4272          item = showdown.subParser('hashHTMLBlocks')(item, options, globals);
4273  
4274          // Colapse double linebreaks
4275          item = item.replace(/\n\n+/g, '\n\n');
4276          if (isParagraphed) {
4277            item = showdown.subParser('paragraphs')(item, options, globals);
4278          } else {
4279            item = showdown.subParser('spanGamut')(item, options, globals);
4280          }
4281        }
4282  
4283        // now we need to remove the marker (¨A)
4284        item = item.replace('¨A', '');
4285        // we can finally wrap the line in list item tags
4286        item =  '<li' + bulletStyle + '>' + item + '</li>\n';
4287  
4288        return item;
4289      });
4290  
4291      // attacklab: strip sentinel
4292      listStr = listStr.replace(/¨0/g, '');
4293  
4294      globals.gListLevel--;
4295  
4296      if (trimTrailing) {
4297        listStr = listStr.replace(/\s+$/, '');
4298      }
4299  
4300      return listStr;
4301    }
4302  
4303    function styleStartNumber (list, listType) {
4304      // check if ol and starts by a number different than 1
4305      if (listType === 'ol') {
4306        var res = list.match(/^ *(\d+)\./);
4307        if (res && res[1] !== '1') {
4308          return ' start="' + res[1] + '"';
4309        }
4310      }
4311      return '';
4312    }
4313  
4314    /**
4315     * Check and parse consecutive lists (better fix for issue #142)
4316     * @param {string} list
4317     * @param {string} listType
4318     * @param {boolean} trimTrailing
4319     * @returns {string}
4320     */
4321    function parseConsecutiveLists (list, listType, trimTrailing) {
4322      // check if we caught 2 or more consecutive lists by mistake
4323      // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
4324      var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
4325          ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
4326          counterRxg = (listType === 'ul') ? olRgx : ulRgx,
4327          result = '';
4328  
4329      if (list.search(counterRxg) !== -1) {
4330        (function parseCL (txt) {
4331          var pos = txt.search(counterRxg),
4332              style = styleStartNumber(list, listType);
4333          if (pos !== -1) {
4334            // slice
4335            result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
4336  
4337            // invert counterType and listType
4338            listType = (listType === 'ul') ? 'ol' : 'ul';
4339            counterRxg = (listType === 'ul') ? olRgx : ulRgx;
4340  
4341            //recurse
4342            parseCL(txt.slice(pos));
4343          } else {
4344            result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
4345          }
4346        })(list);
4347      } else {
4348        var style = styleStartNumber(list, listType);
4349        result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
4350      }
4351  
4352      return result;
4353    }
4354  
4355    /** Start of list parsing **/
4356    text = globals.converter._dispatch('lists.before', text, options, globals);
4357    // add sentinel to hack around khtml/safari bug:
4358    // http://bugs.webkit.org/show_bug.cgi?id=11231
4359    text += '¨0';
4360  
4361    if (globals.gListLevel) {
4362      text = text.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4363        function (wholeMatch, list, m2) {
4364          var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4365          return parseConsecutiveLists(list, listType, true);
4366        }
4367      );
4368    } else {
4369      text = text.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,
4370        function (wholeMatch, m1, list, m3) {
4371          var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
4372          return parseConsecutiveLists(list, listType, false);
4373        }
4374      );
4375    }
4376  
4377    // strip sentinel
4378    text = text.replace(/¨0/, '');
4379    text = globals.converter._dispatch('lists.after', text, options, globals);
4380    return text;
4381  });
4382  
4383  /**
4384   * Parse metadata at the top of the document
4385   */
4386  showdown.subParser('metadata', function (text, options, globals) {
4387    'use strict';
4388  
4389    if (!options.metadata) {
4390      return text;
4391    }
4392  
4393    text = globals.converter._dispatch('metadata.before', text, options, globals);
4394  
4395    function parseMetadataContents (content) {
4396      // raw is raw so it's not changed in any way
4397      globals.metadata.raw = content;
4398  
4399      // escape chars forbidden in html attributes
4400      // double quotes
4401      content = content
4402        // ampersand first
4403        .replace(/&/g, '&amp;')
4404        // double quotes
4405        .replace(/"/g, '&quot;');
4406  
4407      content = content.replace(/\n {4}/g, ' ');
4408      content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
4409        globals.metadata.parsed[key] = value;
4410        return '';
4411      });
4412    }
4413  
4414    text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
4415      parseMetadataContents(content);
4416      return '¨M';
4417    });
4418  
4419    text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
4420      if (format) {
4421        globals.metadata.format = format;
4422      }
4423      parseMetadataContents(content);
4424      return '¨M';
4425    });
4426  
4427    text = text.replace(/¨M/g, '');
4428  
4429    text = globals.converter._dispatch('metadata.after', text, options, globals);
4430    return text;
4431  });
4432  
4433  /**
4434   * Remove one level of line-leading tabs or spaces
4435   */
4436  showdown.subParser('outdent', function (text, options, globals) {
4437    'use strict';
4438    text = globals.converter._dispatch('outdent.before', text, options, globals);
4439  
4440    // attacklab: hack around Konqueror 3.5.4 bug:
4441    // "----------bug".replace(/^-/g,"") == "bug"
4442    text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
4443  
4444    // attacklab: clean up hack
4445    text = text.replace(/¨0/g, '');
4446  
4447    text = globals.converter._dispatch('outdent.after', text, options, globals);
4448    return text;
4449  });
4450  
4451  /**
4452   *
4453   */
4454  showdown.subParser('paragraphs', function (text, options, globals) {
4455    'use strict';
4456  
4457    text = globals.converter._dispatch('paragraphs.before', text, options, globals);
4458    // Strip leading and trailing lines:
4459    text = text.replace(/^\n+/g, '');
4460    text = text.replace(/\n+$/g, '');
4461  
4462    var grafs = text.split(/\n{2,}/g),
4463        grafsOut = [],
4464        end = grafs.length; // Wrap <p> tags
4465  
4466    for (var i = 0; i < end; i++) {
4467      var str = grafs[i];
4468      // if this is an HTML marker, copy it
4469      if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
4470        grafsOut.push(str);
4471  
4472      // test for presence of characters to prevent empty lines being parsed
4473      // as paragraphs (resulting in undesired extra empty paragraphs)
4474      } else if (str.search(/\S/) >= 0) {
4475        str = showdown.subParser('spanGamut')(str, options, globals);
4476        str = str.replace(/^([ \t]*)/g, '<p>');
4477        str += '</p>';
4478        grafsOut.push(str);
4479      }
4480    }
4481  
4482    /** Unhashify HTML blocks */
4483    end = grafsOut.length;
4484    for (i = 0; i < end; i++) {
4485      var blockText = '',
4486          grafsOutIt = grafsOut[i],
4487          codeFlag = false;
4488      // if this is a marker for an html block...
4489      // use RegExp.test instead of string.search because of QML bug
4490      while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
4491        var delim = RegExp.$1,
4492            num   = RegExp.$2;
4493  
4494        if (delim === 'K') {
4495          blockText = globals.gHtmlBlocks[num];
4496        } else {
4497          // we need to check if ghBlock is a false positive
4498          if (codeFlag) {
4499            // use encoded version of all text
4500            blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4501          } else {
4502            blockText = globals.ghCodeBlocks[num].codeblock;
4503          }
4504        }
4505        blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4506  
4507        grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4508        // Check if grafsOutIt is a pre->code
4509        if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4510          codeFlag = true;
4511        }
4512      }
4513      grafsOut[i] = grafsOutIt;
4514    }
4515    text = grafsOut.join('\n');
4516    // Strip leading and trailing lines:
4517    text = text.replace(/^\n+/g, '');
4518    text = text.replace(/\n+$/g, '');
4519    return globals.converter._dispatch('paragraphs.after', text, options, globals);
4520  });
4521  
4522  /**
4523   * Run extension
4524   */
4525  showdown.subParser('runExtension', function (ext, text, options, globals) {
4526    'use strict';
4527  
4528    if (ext.filter) {
4529      text = ext.filter(text, globals.converter, options);
4530  
4531    } else if (ext.regex) {
4532      // TODO remove this when old extension loading mechanism is deprecated
4533      var re = ext.regex;
4534      if (!(re instanceof RegExp)) {
4535        re = new RegExp(re, 'g');
4536      }
4537      text = text.replace(re, ext.replace);
4538    }
4539  
4540    return text;
4541  });
4542  
4543  /**
4544   * These are all the transformations that occur *within* block-level
4545   * tags like paragraphs, headers, and list items.
4546   */
4547  showdown.subParser('spanGamut', function (text, options, globals) {
4548    'use strict';
4549  
4550    text = globals.converter._dispatch('spanGamut.before', text, options, globals);
4551    text = showdown.subParser('codeSpans')(text, options, globals);
4552    text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4553    text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
4554  
4555    // Process anchor and image tags. Images must come first,
4556    // because ![foo][f] looks like an anchor.
4557    text = showdown.subParser('images')(text, options, globals);
4558    text = showdown.subParser('anchors')(text, options, globals);
4559  
4560    // Make links out of things like `<http://example.com/>`
4561    // Must come after anchors, because you can use < and >
4562    // delimiters in inline links like [this](<url>).
4563    text = showdown.subParser('autoLinks')(text, options, globals);
4564    text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
4565    text = showdown.subParser('emoji')(text, options, globals);
4566    text = showdown.subParser('underline')(text, options, globals);
4567    text = showdown.subParser('italicsAndBold')(text, options, globals);
4568    text = showdown.subParser('strikethrough')(text, options, globals);
4569    text = showdown.subParser('ellipsis')(text, options, globals);
4570  
4571    // we need to hash HTML tags inside spans
4572    text = showdown.subParser('hashHTMLSpans')(text, options, globals);
4573  
4574    // now we encode amps and angles
4575    text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
4576  
4577    // Do hard breaks
4578    if (options.simpleLineBreaks) {
4579      // GFM style hard breaks
4580      // only add line breaks if the text does not contain a block (special case for lists)
4581      if (!/\n\n¨K/.test(text)) {
4582        text = text.replace(/\n+/g, '<br />\n');
4583      }
4584    } else {
4585      // Vanilla hard breaks
4586      text = text.replace(/  +\n/g, '<br />\n');
4587    }
4588  
4589    text = globals.converter._dispatch('spanGamut.after', text, options, globals);
4590    return text;
4591  });
4592  
4593  showdown.subParser('strikethrough', function (text, options, globals) {
4594    'use strict';
4595  
4596    function parseInside (txt) {
4597      if (options.simplifiedAutoLink) {
4598        txt = showdown.subParser('simplifiedAutoLinks')(txt, options, globals);
4599      }
4600      return '<del>' + txt + '</del>';
4601    }
4602  
4603    if (options.strikethrough) {
4604      text = globals.converter._dispatch('strikethrough.before', text, options, globals);
4605      text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return parseInside(txt); });
4606      text = globals.converter._dispatch('strikethrough.after', text, options, globals);
4607    }
4608  
4609    return text;
4610  });
4611  
4612  /**
4613   * Strips link definitions from text, stores the URLs and titles in
4614   * hash references.
4615   * Link defs are in the form: ^[id]: url "optional title"
4616   */
4617  showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
4618    'use strict';
4619  
4620    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,
4621        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;
4622  
4623    // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
4624    text += '¨0';
4625  
4626    var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
4627      linkId = linkId.toLowerCase();
4628      if (url.match(/^data:.+?\/.+?;base64,/)) {
4629        // remove newlines
4630        globals.gUrls[linkId] = url.replace(/\s/g, '');
4631      } else {
4632        globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url, options, globals);  // Link IDs are case-insensitive
4633      }
4634  
4635      if (blankLines) {
4636        // Oops, found blank lines, so it's not a title.
4637        // Put back the parenthetical statement we stole.
4638        return blankLines + title;
4639  
4640      } else {
4641        if (title) {
4642          globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
4643        }
4644        if (options.parseImgDimensions && width && height) {
4645          globals.gDimensions[linkId] = {
4646            width:  width,
4647            height: height
4648          };
4649        }
4650      }
4651      // Completely remove the definition from the text
4652      return '';
4653    };
4654  
4655    // first we try to find base64 link references
4656    text = text.replace(base64Regex, replaceFunc);
4657  
4658    text = text.replace(regex, replaceFunc);
4659  
4660    // attacklab: strip sentinel
4661    text = text.replace(/¨0/, '');
4662  
4663    return text;
4664  });
4665  
4666  showdown.subParser('tables', function (text, options, globals) {
4667    'use strict';
4668  
4669    if (!options.tables) {
4670      return text;
4671    }
4672  
4673    var tableRgx       = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
4674      //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
4675        singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
4676  
4677    function parseStyles (sLine) {
4678      if (/^:[ \t]*--*$/.test(sLine)) {
4679        return ' style="text-align:left;"';
4680      } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
4681        return ' style="text-align:right;"';
4682      } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
4683        return ' style="text-align:center;"';
4684      } else {
4685        return '';
4686      }
4687    }
4688  
4689    function parseHeaders (header, style) {
4690      var id = '';
4691      header = header.trim();
4692      // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
4693      if (options.tablesHeaderId || options.tableHeaderId) {
4694        id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
4695      }
4696      header = showdown.subParser('spanGamut')(header, options, globals);
4697  
4698      return '<th' + id + style + '>' + header + '</th>\n';
4699    }
4700  
4701    function parseCells (cell, style) {
4702      var subText = showdown.subParser('spanGamut')(cell, options, globals);
4703      return '<td' + style + '>' + subText + '</td>\n';
4704    }
4705  
4706    function buildTable (headers, cells) {
4707      var tb = '<table>\n<thead>\n<tr>\n',
4708          tblLgn = headers.length;
4709  
4710      for (var i = 0; i < tblLgn; ++i) {
4711        tb += headers[i];
4712      }
4713      tb += '</tr>\n</thead>\n<tbody>\n';
4714  
4715      for (i = 0; i < cells.length; ++i) {
4716        tb += '<tr>\n';
4717        for (var ii = 0; ii < tblLgn; ++ii) {
4718          tb += cells[i][ii];
4719        }
4720        tb += '</tr>\n';
4721      }
4722      tb += '</tbody>\n</table>\n';
4723      return tb;
4724    }
4725  
4726    function parseTable (rawTable) {
4727      var i, tableLines = rawTable.split('\n');
4728  
4729      for (i = 0; i < tableLines.length; ++i) {
4730        // strip wrong first and last column if wrapped tables are used
4731        if (/^ {0,3}\|/.test(tableLines[i])) {
4732          tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
4733        }
4734        if (/\|[ \t]*$/.test(tableLines[i])) {
4735          tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
4736        }
4737        // parse code spans first, but we only support one line code spans
4738        tableLines[i] = showdown.subParser('codeSpans')(tableLines[i], options, globals);
4739      }
4740  
4741      var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
4742          rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
4743          rawCells = [],
4744          headers = [],
4745          styles = [],
4746          cells = [];
4747  
4748      tableLines.shift();
4749      tableLines.shift();
4750  
4751      for (i = 0; i < tableLines.length; ++i) {
4752        if (tableLines[i].trim() === '') {
4753          continue;
4754        }
4755        rawCells.push(
4756          tableLines[i]
4757            .split('|')
4758            .map(function (s) {
4759              return s.trim();
4760            })
4761        );
4762      }
4763  
4764      if (rawHeaders.length < rawStyles.length) {
4765        return rawTable;
4766      }
4767  
4768      for (i = 0; i < rawStyles.length; ++i) {
4769        styles.push(parseStyles(rawStyles[i]));
4770      }
4771  
4772      for (i = 0; i < rawHeaders.length; ++i) {
4773        if (showdown.helper.isUndefined(styles[i])) {
4774          styles[i] = '';
4775        }
4776        headers.push(parseHeaders(rawHeaders[i], styles[i]));
4777      }
4778  
4779      for (i = 0; i < rawCells.length; ++i) {
4780        var row = [];
4781        for (var ii = 0; ii < headers.length; ++ii) {
4782          if (showdown.helper.isUndefined(rawCells[i][ii])) {
4783  
4784          }
4785          row.push(parseCells(rawCells[i][ii], styles[ii]));
4786        }
4787        cells.push(row);
4788      }
4789  
4790      return buildTable(headers, cells);
4791    }
4792  
4793    text = globals.converter._dispatch('tables.before', text, options, globals);
4794  
4795    // find escaped pipe characters
4796    text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
4797  
4798    // parse multi column tables
4799    text = text.replace(tableRgx, parseTable);
4800  
4801    // parse one column tables
4802    text = text.replace(singeColTblRgx, parseTable);
4803  
4804    text = globals.converter._dispatch('tables.after', text, options, globals);
4805  
4806    return text;
4807  });
4808  
4809  showdown.subParser('underline', function (text, options, globals) {
4810    'use strict';
4811  
4812    if (!options.underline) {
4813      return text;
4814    }
4815  
4816    text = globals.converter._dispatch('underline.before', text, options, globals);
4817  
4818    if (options.literalMidWordUnderscores) {
4819      text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4820        return '<u>' + txt + '</u>';
4821      });
4822      text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4823        return '<u>' + txt + '</u>';
4824      });
4825    } else {
4826      text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4827        return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4828      });
4829      text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4830        return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4831      });
4832    }
4833  
4834    // escape remaining underscores to prevent them being parsed by italic and bold
4835    text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
4836  
4837    text = globals.converter._dispatch('underline.after', text, options, globals);
4838  
4839    return text;
4840  });
4841  
4842  /**
4843   * Swap back in all the special characters we've hidden.
4844   */
4845  showdown.subParser('unescapeSpecialChars', function (text, options, globals) {
4846    'use strict';
4847    text = globals.converter._dispatch('unescapeSpecialChars.before', text, options, globals);
4848  
4849    text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
4850      var charCodeToReplace = parseInt(m1);
4851      return String.fromCharCode(charCodeToReplace);
4852    });
4853  
4854    text = globals.converter._dispatch('unescapeSpecialChars.after', text, options, globals);
4855    return text;
4856  });
4857  
4858  showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
4859    'use strict';
4860  
4861    var txt = '';
4862    if (node.hasChildNodes()) {
4863      var children = node.childNodes,
4864          childrenLength = children.length;
4865  
4866      for (var i = 0; i < childrenLength; ++i) {
4867        var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
4868  
4869        if (innerTxt === '') {
4870          continue;
4871        }
4872        txt += innerTxt;
4873      }
4874    }
4875    // cleanup
4876    txt = txt.trim();
4877    txt = '> ' + txt.split('\n').join('\n> ');
4878    return txt;
4879  });
4880  
4881  showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
4882    'use strict';
4883  
4884    var lang = node.getAttribute('language'),
4885        num  = node.getAttribute('precodenum');
4886    return '```' + lang + '\n' + globals.preList[num] + '\n```';
4887  });
4888  
4889  showdown.subParser('makeMarkdown.codeSpan', function (node) {
4890    'use strict';
4891  
4892    return '`' + node.innerHTML + '`';
4893  });
4894  
4895  showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
4896    'use strict';
4897  
4898    var txt = '';
4899    if (node.hasChildNodes()) {
4900      txt += '*';
4901      var children = node.childNodes,
4902          childrenLength = children.length;
4903      for (var i = 0; i < childrenLength; ++i) {
4904        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4905      }
4906      txt += '*';
4907    }
4908    return txt;
4909  });
4910  
4911  showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
4912    'use strict';
4913  
4914    var headerMark = new Array(headerLevel + 1).join('#'),
4915        txt = '';
4916  
4917    if (node.hasChildNodes()) {
4918      txt = headerMark + ' ';
4919      var children = node.childNodes,
4920          childrenLength = children.length;
4921  
4922      for (var i = 0; i < childrenLength; ++i) {
4923        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4924      }
4925    }
4926    return txt;
4927  });
4928  
4929  showdown.subParser('makeMarkdown.hr', function () {
4930    'use strict';
4931  
4932    return '---';
4933  });
4934  
4935  showdown.subParser('makeMarkdown.image', function (node) {
4936    'use strict';
4937  
4938    var txt = '';
4939    if (node.hasAttribute('src')) {
4940      txt += '![' + node.getAttribute('alt') + '](';
4941      txt += '<' + node.getAttribute('src') + '>';
4942      if (node.hasAttribute('width') && node.hasAttribute('height')) {
4943        txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
4944      }
4945  
4946      if (node.hasAttribute('title')) {
4947        txt += ' "' + node.getAttribute('title') + '"';
4948      }
4949      txt += ')';
4950    }
4951    return txt;
4952  });
4953  
4954  showdown.subParser('makeMarkdown.links', function (node, globals) {
4955    'use strict';
4956  
4957    var txt = '';
4958    if (node.hasChildNodes() && node.hasAttribute('href')) {
4959      var children = node.childNodes,
4960          childrenLength = children.length;
4961      txt = '[';
4962      for (var i = 0; i < childrenLength; ++i) {
4963        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4964      }
4965      txt += '](';
4966      txt += '<' + node.getAttribute('href') + '>';
4967      if (node.hasAttribute('title')) {
4968        txt += ' "' + node.getAttribute('title') + '"';
4969      }
4970      txt += ')';
4971    }
4972    return txt;
4973  });
4974  
4975  showdown.subParser('makeMarkdown.list', function (node, globals, type) {
4976    'use strict';
4977  
4978    var txt = '';
4979    if (!node.hasChildNodes()) {
4980      return '';
4981    }
4982    var listItems       = node.childNodes,
4983        listItemsLenght = listItems.length,
4984        listNum = node.getAttribute('start') || 1;
4985  
4986    for (var i = 0; i < listItemsLenght; ++i) {
4987      if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
4988        continue;
4989      }
4990  
4991      // define the bullet to use in list
4992      var bullet = '';
4993      if (type === 'ol') {
4994        bullet = listNum.toString() + '. ';
4995      } else {
4996        bullet = '- ';
4997      }
4998  
4999      // parse list item
5000      txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
5001      ++listNum;
5002    }
5003  
5004    // add comment at the end to prevent consecutive lists to be parsed as one
5005    txt += '\n<!-- -->\n';
5006    return txt.trim();
5007  });
5008  
5009  showdown.subParser('makeMarkdown.listItem', function (node, globals) {
5010    'use strict';
5011  
5012    var listItemTxt = '';
5013  
5014    var children = node.childNodes,
5015        childrenLenght = children.length;
5016  
5017    for (var i = 0; i < childrenLenght; ++i) {
5018      listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5019    }
5020    // if it's only one liner, we need to add a newline at the end
5021    if (!/\n$/.test(listItemTxt)) {
5022      listItemTxt += '\n';
5023    } else {
5024      // it's multiparagraph, so we need to indent
5025      listItemTxt = listItemTxt
5026        .split('\n')
5027        .join('\n    ')
5028        .replace(/^ {4}$/gm, '')
5029        .replace(/\n\n+/g, '\n\n');
5030    }
5031  
5032    return listItemTxt;
5033  });
5034  
5035  
5036  
5037  showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
5038    'use strict';
5039  
5040    spansOnly = spansOnly || false;
5041  
5042    var txt = '';
5043  
5044    // edge case of text without wrapper paragraph
5045    if (node.nodeType === 3) {
5046      return showdown.subParser('makeMarkdown.txt')(node, globals);
5047    }
5048  
5049    // HTML comment
5050    if (node.nodeType === 8) {
5051      return '<!--' + node.data + '-->\n\n';
5052    }
5053  
5054    // process only node elements
5055    if (node.nodeType !== 1) {
5056      return '';
5057    }
5058  
5059    var tagName = node.tagName.toLowerCase();
5060  
5061    switch (tagName) {
5062  
5063      //
5064      // BLOCKS
5065      //
5066      case 'h1':
5067        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
5068        break;
5069      case 'h2':
5070        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
5071        break;
5072      case 'h3':
5073        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
5074        break;
5075      case 'h4':
5076        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
5077        break;
5078      case 'h5':
5079        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
5080        break;
5081      case 'h6':
5082        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
5083        break;
5084  
5085      case 'p':
5086        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
5087        break;
5088  
5089      case 'blockquote':
5090        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
5091        break;
5092  
5093      case 'hr':
5094        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
5095        break;
5096  
5097      case 'ol':
5098        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
5099        break;
5100  
5101      case 'ul':
5102        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
5103        break;
5104  
5105      case 'precode':
5106        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
5107        break;
5108  
5109      case 'pre':
5110        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
5111        break;
5112  
5113      case 'table':
5114        if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
5115        break;
5116  
5117      //
5118      // SPANS
5119      //
5120      case 'code':
5121        txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
5122        break;
5123  
5124      case 'em':
5125      case 'i':
5126        txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
5127        break;
5128  
5129      case 'strong':
5130      case 'b':
5131        txt = showdown.subParser('makeMarkdown.strong')(node, globals);
5132        break;
5133  
5134      case 'del':
5135        txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
5136        break;
5137  
5138      case 'a':
5139        txt = showdown.subParser('makeMarkdown.links')(node, globals);
5140        break;
5141  
5142      case 'img':
5143        txt = showdown.subParser('makeMarkdown.image')(node, globals);
5144        break;
5145  
5146      default:
5147        txt = node.outerHTML + '\n\n';
5148    }
5149  
5150    // common normalization
5151    // TODO eventually
5152  
5153    return txt;
5154  });
5155  
5156  showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
5157    'use strict';
5158  
5159    var txt = '';
5160    if (node.hasChildNodes()) {
5161      var children = node.childNodes,
5162          childrenLength = children.length;
5163      for (var i = 0; i < childrenLength; ++i) {
5164        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5165      }
5166    }
5167  
5168    // some text normalization
5169    txt = txt.trim();
5170  
5171    return txt;
5172  });
5173  
5174  showdown.subParser('makeMarkdown.pre', function (node, globals) {
5175    'use strict';
5176  
5177    var num  = node.getAttribute('prenum');
5178    return '<pre>' + globals.preList[num] + '</pre>';
5179  });
5180  
5181  showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
5182    'use strict';
5183  
5184    var txt = '';
5185    if (node.hasChildNodes()) {
5186      txt += '~~';
5187      var children = node.childNodes,
5188          childrenLength = children.length;
5189      for (var i = 0; i < childrenLength; ++i) {
5190        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5191      }
5192      txt += '~~';
5193    }
5194    return txt;
5195  });
5196  
5197  showdown.subParser('makeMarkdown.strong', function (node, globals) {
5198    'use strict';
5199  
5200    var txt = '';
5201    if (node.hasChildNodes()) {
5202      txt += '**';
5203      var children = node.childNodes,
5204          childrenLength = children.length;
5205      for (var i = 0; i < childrenLength; ++i) {
5206        txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
5207      }
5208      txt += '**';
5209    }
5210    return txt;
5211  });
5212  
5213  showdown.subParser('makeMarkdown.table', function (node, globals) {
5214    'use strict';
5215  
5216    var txt = '',
5217        tableArray = [[], []],
5218        headings   = node.querySelectorAll('thead>tr>th'),
5219        rows       = node.querySelectorAll('tbody>tr'),
5220        i, ii;
5221    for (i = 0; i < headings.length; ++i) {
5222      var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
5223          allign = '---';
5224  
5225      if (headings[i].hasAttribute('style')) {
5226        var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
5227        switch (style) {
5228          case 'text-align:left;':
5229            allign = ':---';
5230            break;
5231          case 'text-align:right;':
5232            allign = '---:';
5233            break;
5234          case 'text-align:center;':
5235            allign = ':---:';
5236            break;
5237        }
5238      }
5239      tableArray[0][i] = headContent.trim();
5240      tableArray[1][i] = allign;
5241    }
5242  
5243    for (i = 0; i < rows.length; ++i) {
5244      var r = tableArray.push([]) - 1,
5245          cols = rows[i].getElementsByTagName('td');
5246  
5247      for (ii = 0; ii < headings.length; ++ii) {
5248        var cellContent = ' ';
5249        if (typeof cols[ii] !== 'undefined') {
5250          cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
5251        }
5252        tableArray[r].push(cellContent);
5253      }
5254    }
5255  
5256    var cellSpacesCount = 3;
5257    for (i = 0; i < tableArray.length; ++i) {
5258      for (ii = 0; ii < tableArray[i].length; ++ii) {
5259        var strLen = tableArray[i][ii].length;
5260        if (strLen > cellSpacesCount) {
5261          cellSpacesCount = strLen;
5262        }
5263      }
5264    }
5265  
5266    for (i = 0; i < tableArray.length; ++i) {
5267      for (ii = 0; ii < tableArray[i].length; ++ii) {
5268        if (i === 1) {
5269          if (tableArray[i][ii].slice(-1) === ':') {
5270            tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
5271          } else {
5272            tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
5273          }
5274        } else {
5275          tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
5276        }
5277      }
5278      txt += '| ' + tableArray[i].join(' | ') + ' |\n';
5279    }
5280  
5281    return txt.trim();
5282  });
5283  
5284  showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
5285    'use strict';
5286  
5287    var txt = '';
5288    if (!node.hasChildNodes()) {
5289      return '';
5290    }
5291    var children = node.childNodes,
5292        childrenLength = children.length;
5293  
5294    for (var i = 0; i < childrenLength; ++i) {
5295      txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
5296    }
5297    return txt.trim();
5298  });
5299  
5300  showdown.subParser('makeMarkdown.txt', function (node) {
5301    'use strict';
5302  
5303    var txt = node.nodeValue;
5304  
5305    // multiple spaces are collapsed
5306    txt = txt.replace(/ +/g, ' ');
5307  
5308    // replace the custom ¨NBSP; with a space
5309    txt = txt.replace(/¨NBSP;/g, ' ');
5310  
5311    // ", <, > and & should replace escaped html entities
5312    txt = showdown.helper.unescapeHTMLEntities(txt);
5313  
5314    // escape markdown magic characters
5315    // emphasis, strong and strikethrough - can appear everywhere
5316    // we also escape pipe (|) because of tables
5317    // and escape ` because of code blocks and spans
5318    txt = txt.replace(/([*_~|`])/g, '\\$1');
5319  
5320    // escape > because of blockquotes
5321    txt = txt.replace(/^(\s*)>/g, '\\$1>');
5322  
5323    // hash character, only troublesome at the beginning of a line because of headers
5324    txt = txt.replace(/^#/gm, '\\#');
5325  
5326    // horizontal rules
5327    txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
5328  
5329    // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
5330    txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
5331  
5332    // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
5333    txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
5334  
5335    // images and links, ] followed by ( is problematic, so we escape it
5336    txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
5337  
5338    // reference URIs must also be escaped
5339    txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
5340  
5341    return txt;
5342  });
5343  
5344  var root = this;
5345  
5346  // AMD Loader
5347  if (true) {
5348    !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () {
5349      'use strict';
5350      return showdown;
5351    }).call(exports, __webpack_require__, exports, module),
5352                  __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
5353  
5354  // CommonJS/nodeJS Loader
5355  } else {}
5356  }).call(this);
5357  
5358  
5359  
5360  /***/ }),
5361  
5362  /***/ 24:
5363  /***/ (function(module, exports) {
5364  
5365  (function() { module.exports = this["wp"]["dom"]; }());
5366  
5367  /***/ }),
5368  
5369  /***/ 26:
5370  /***/ (function(module, exports) {
5371  
5372  (function() { module.exports = this["wp"]["hooks"]; }());
5373  
5374  /***/ }),
5375  
5376  /***/ 28:
5377  /***/ (function(module, __webpack_exports__, __webpack_require__) {
5378  
5379  "use strict";
5380  
5381  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js
5382  var arrayWithHoles = __webpack_require__(37);
5383  
5384  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js
5385  function _iterableToArrayLimit(arr, i) {
5386    var _arr = [];
5387    var _n = true;
5388    var _d = false;
5389    var _e = undefined;
5390  
5391    try {
5392      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
5393        _arr.push(_s.value);
5394  
5395        if (i && _arr.length === i) break;
5396      }
5397    } catch (err) {
5398      _d = true;
5399      _e = err;
5400    } finally {
5401      try {
5402        if (!_n && _i["return"] != null) _i["return"]();
5403      } finally {
5404        if (_d) throw _e;
5405      }
5406    }
5407  
5408    return _arr;
5409  }
5410  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js
5411  var nonIterableRest = __webpack_require__(38);
5412  
5413  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/slicedToArray.js
5414  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _slicedToArray; });
5415  
5416  
5417  
5418  function _slicedToArray(arr, i) {
5419    return Object(arrayWithHoles["a" /* default */])(arr) || _iterableToArrayLimit(arr, i) || Object(nonIterableRest["a" /* default */])();
5420  }
5421  
5422  /***/ }),
5423  
5424  /***/ 30:
5425  /***/ (function(module, __webpack_exports__, __webpack_require__) {
5426  
5427  "use strict";
5428  
5429  
5430  var LEAF_KEY, hasWeakMap;
5431  
5432  /**
5433   * Arbitrary value used as key for referencing cache object in WeakMap tree.
5434   *
5435   * @type {Object}
5436   */
5437  LEAF_KEY = {};
5438  
5439  /**
5440   * Whether environment supports WeakMap.
5441   *
5442   * @type {boolean}
5443   */
5444  hasWeakMap = typeof WeakMap !== 'undefined';
5445  
5446  /**
5447   * Returns the first argument as the sole entry in an array.
5448   *
5449   * @param {*} value Value to return.
5450   *
5451   * @return {Array} Value returned as entry in array.
5452   */
5453  function arrayOf( value ) {
5454      return [ value ];
5455  }
5456  
5457  /**
5458   * Returns true if the value passed is object-like, or false otherwise. A value
5459   * is object-like if it can support property assignment, e.g. object or array.
5460   *
5461   * @param {*} value Value to test.
5462   *
5463   * @return {boolean} Whether value is object-like.
5464   */
5465  function isObjectLike( value ) {
5466      return !! value && 'object' === typeof value;
5467  }
5468  
5469  /**
5470   * Creates and returns a new cache object.
5471   *
5472   * @return {Object} Cache object.
5473   */
5474  function createCache() {
5475      var cache = {
5476          clear: function() {
5477              cache.head = null;
5478          },
5479      };
5480  
5481      return cache;
5482  }
5483  
5484  /**
5485   * Returns true if entries within the two arrays are strictly equal by
5486   * reference from a starting index.
5487   *
5488   * @param {Array}  a         First array.
5489   * @param {Array}  b         Second array.
5490   * @param {number} fromIndex Index from which to start comparison.
5491   *
5492   * @return {boolean} Whether arrays are shallowly equal.
5493   */
5494  function isShallowEqual( a, b, fromIndex ) {
5495      var i;
5496  
5497      if ( a.length !== b.length ) {
5498          return false;
5499      }
5500  
5501      for ( i = fromIndex; i < a.length; i++ ) {
5502          if ( a[ i ] !== b[ i ] ) {
5503              return false;
5504          }
5505      }
5506  
5507      return true;
5508  }
5509  
5510  /**
5511   * Returns a memoized selector function. The getDependants function argument is
5512   * called before the memoized selector and is expected to return an immutable
5513   * reference or array of references on which the selector depends for computing
5514   * its own return value. The memoize cache is preserved only as long as those
5515   * dependant references remain the same. If getDependants returns a different
5516   * reference(s), the cache is cleared and the selector value regenerated.
5517   *
5518   * @param {Function} selector      Selector function.
5519   * @param {Function} getDependants Dependant getter returning an immutable
5520   *                                 reference or array of reference used in
5521   *                                 cache bust consideration.
5522   *
5523   * @return {Function} Memoized selector.
5524   */
5525  /* harmony default export */ __webpack_exports__["a"] = (function( selector, getDependants ) {
5526      var rootCache, getCache;
5527  
5528      // Use object source as dependant if getter not provided
5529      if ( ! getDependants ) {
5530          getDependants = arrayOf;
5531      }
5532  
5533      /**
5534       * Returns the root cache. If WeakMap is supported, this is assigned to the
5535       * root WeakMap cache set, otherwise it is a shared instance of the default
5536       * cache object.
5537       *
5538       * @return {(WeakMap|Object)} Root cache object.
5539       */
5540  	function getRootCache() {
5541          return rootCache;
5542      }
5543  
5544      /**
5545       * Returns the cache for a given dependants array. When possible, a WeakMap
5546       * will be used to create a unique cache for each set of dependants. This
5547       * is feasible due to the nature of WeakMap in allowing garbage collection
5548       * to occur on entries where the key object is no longer referenced. Since
5549       * WeakMap requires the key to be an object, this is only possible when the
5550       * dependant is object-like. The root cache is created as a hierarchy where
5551       * each top-level key is the first entry in a dependants set, the value a
5552       * WeakMap where each key is the next dependant, and so on. This continues
5553       * so long as the dependants are object-like. If no dependants are object-
5554       * like, then the cache is shared across all invocations.
5555       *
5556       * @see isObjectLike
5557       *
5558       * @param {Array} dependants Selector dependants.
5559       *
5560       * @return {Object} Cache object.
5561       */
5562  	function getWeakMapCache( dependants ) {
5563          var caches = rootCache,
5564              isUniqueByDependants = true,
5565              i, dependant, map, cache;
5566  
5567          for ( i = 0; i < dependants.length; i++ ) {
5568              dependant = dependants[ i ];
5569  
5570              // Can only compose WeakMap from object-like key.
5571              if ( ! isObjectLike( dependant ) ) {
5572                  isUniqueByDependants = false;
5573                  break;
5574              }
5575  
5576              // Does current segment of cache already have a WeakMap?
5577              if ( caches.has( dependant ) ) {
5578                  // Traverse into nested WeakMap.
5579                  caches = caches.get( dependant );
5580              } else {
5581                  // Create, set, and traverse into a new one.
5582                  map = new WeakMap();
5583                  caches.set( dependant, map );
5584                  caches = map;
5585              }
5586          }
5587  
5588          // We use an arbitrary (but consistent) object as key for the last item
5589          // in the WeakMap to serve as our running cache.
5590          if ( ! caches.has( LEAF_KEY ) ) {
5591              cache = createCache();
5592              cache.isUniqueByDependants = isUniqueByDependants;
5593              caches.set( LEAF_KEY, cache );
5594          }
5595  
5596          return caches.get( LEAF_KEY );
5597      }
5598  
5599      // Assign cache handler by availability of WeakMap
5600      getCache = hasWeakMap ? getWeakMapCache : getRootCache;
5601  
5602      /**
5603       * Resets root memoization cache.
5604       */
5605  	function clear() {
5606          rootCache = hasWeakMap ? new WeakMap() : createCache();
5607      }
5608  
5609      // eslint-disable-next-line jsdoc/check-param-names
5610      /**
5611       * The augmented selector call, considering first whether dependants have
5612       * changed before passing it to underlying memoize function.
5613       *
5614       * @param {Object} source    Source object for derivation.
5615       * @param {...*}   extraArgs Additional arguments to pass to selector.
5616       *
5617       * @return {*} Selector result.
5618       */
5619  	function callSelector( /* source, ...extraArgs */ ) {
5620          var len = arguments.length,
5621              cache, node, i, args, dependants;
5622  
5623          // Create copy of arguments (avoid leaking deoptimization).
5624          args = new Array( len );
5625          for ( i = 0; i < len; i++ ) {
5626              args[ i ] = arguments[ i ];
5627          }
5628  
5629          dependants = getDependants.apply( null, args );
5630          cache = getCache( dependants );
5631  
5632          // If not guaranteed uniqueness by dependants (primitive type or lack
5633          // of WeakMap support), shallow compare against last dependants and, if
5634          // references have changed, destroy cache to recalculate result.
5635          if ( ! cache.isUniqueByDependants ) {
5636              if ( cache.lastDependants && ! isShallowEqual( dependants, cache.lastDependants, 0 ) ) {
5637                  cache.clear();
5638              }
5639  
5640              cache.lastDependants = dependants;
5641          }
5642  
5643          node = cache.head;
5644          while ( node ) {
5645              // Check whether node arguments match arguments
5646              if ( ! isShallowEqual( node.args, args, 1 ) ) {
5647                  node = node.next;
5648                  continue;
5649              }
5650  
5651              // At this point we can assume we've found a match
5652  
5653              // Surface matched node to head if not already
5654              if ( node !== cache.head ) {
5655                  // Adjust siblings to point to each other.
5656                  node.prev.next = node.next;
5657                  if ( node.next ) {
5658                      node.next.prev = node.prev;
5659                  }
5660  
5661                  node.next = cache.head;
5662                  node.prev = null;
5663                  cache.head.prev = node;
5664                  cache.head = node;
5665              }
5666  
5667              // Return immediately
5668              return node.val;
5669          }
5670  
5671          // No cached value found. Continue to insertion phase:
5672  
5673          node = {
5674              // Generate the result from original function
5675              val: selector.apply( null, args ),
5676          };
5677  
5678          // Avoid including the source object in the cache.
5679          args[ 0 ] = null;
5680          node.args = args;
5681  
5682          // Don't need to check whether node is already head, since it would
5683          // have been returned above already if it was
5684  
5685          // Shift existing head down list
5686          if ( cache.head ) {
5687              cache.head.prev = node;
5688              node.next = cache.head;
5689          }
5690  
5691          cache.head = node;
5692  
5693          return node.val;
5694      }
5695  
5696      callSelector.getDependants = getDependants;
5697      callSelector.clear = clear;
5698      clear();
5699  
5700      return callSelector;
5701  });
5702  
5703  
5704  /***/ }),
5705  
5706  /***/ 34:
5707  /***/ (function(module, __webpack_exports__, __webpack_require__) {
5708  
5709  "use strict";
5710  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _iterableToArray; });
5711  function _iterableToArray(iter) {
5712    if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
5713  }
5714  
5715  /***/ }),
5716  
5717  /***/ 348:
5718  /***/ (function(module, __webpack_exports__, __webpack_require__) {
5719  
5720  "use strict";
5721  __webpack_require__.r(__webpack_exports__);
5722  var selectors_namespaceObject = {};
5723  __webpack_require__.r(selectors_namespaceObject);
5724  __webpack_require__.d(selectors_namespaceObject, "getBlockTypes", function() { return getBlockTypes; });
5725  __webpack_require__.d(selectors_namespaceObject, "getBlockType", function() { return getBlockType; });
5726  __webpack_require__.d(selectors_namespaceObject, "getBlockStyles", function() { return getBlockStyles; });
5727  __webpack_require__.d(selectors_namespaceObject, "getCategories", function() { return getCategories; });
5728  __webpack_require__.d(selectors_namespaceObject, "getDefaultBlockName", function() { return getDefaultBlockName; });
5729  __webpack_require__.d(selectors_namespaceObject, "getFreeformFallbackBlockName", function() { return getFreeformFallbackBlockName; });
5730  __webpack_require__.d(selectors_namespaceObject, "getUnregisteredFallbackBlockName", function() { return getUnregisteredFallbackBlockName; });
5731  __webpack_require__.d(selectors_namespaceObject, "getChildBlockNames", function() { return selectors_getChildBlockNames; });
5732  __webpack_require__.d(selectors_namespaceObject, "getBlockSupport", function() { return selectors_getBlockSupport; });
5733  __webpack_require__.d(selectors_namespaceObject, "hasBlockSupport", function() { return hasBlockSupport; });
5734  __webpack_require__.d(selectors_namespaceObject, "isMatchingSearchTerm", function() { return isMatchingSearchTerm; });
5735  __webpack_require__.d(selectors_namespaceObject, "hasChildBlocks", function() { return selectors_hasChildBlocks; });
5736  __webpack_require__.d(selectors_namespaceObject, "hasChildBlocksWithInserterSupport", function() { return selectors_hasChildBlocksWithInserterSupport; });
5737  var actions_namespaceObject = {};
5738  __webpack_require__.r(actions_namespaceObject);
5739  __webpack_require__.d(actions_namespaceObject, "addBlockTypes", function() { return addBlockTypes; });
5740  __webpack_require__.d(actions_namespaceObject, "removeBlockTypes", function() { return removeBlockTypes; });
5741  __webpack_require__.d(actions_namespaceObject, "addBlockStyles", function() { return addBlockStyles; });
5742  __webpack_require__.d(actions_namespaceObject, "removeBlockStyles", function() { return removeBlockStyles; });
5743  __webpack_require__.d(actions_namespaceObject, "setDefaultBlockName", function() { return setDefaultBlockName; });
5744  __webpack_require__.d(actions_namespaceObject, "setFreeformFallbackBlockName", function() { return setFreeformFallbackBlockName; });
5745  __webpack_require__.d(actions_namespaceObject, "setUnregisteredFallbackBlockName", function() { return setUnregisteredFallbackBlockName; });
5746  __webpack_require__.d(actions_namespaceObject, "setCategories", function() { return setCategories; });
5747  __webpack_require__.d(actions_namespaceObject, "updateCategory", function() { return updateCategory; });
5748  
5749  // EXTERNAL MODULE: external {"this":["wp","data"]}
5750  var external_this_wp_data_ = __webpack_require__(5);
5751  
5752  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/defineProperty.js
5753  var defineProperty = __webpack_require__(15);
5754  
5755  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js + 2 modules
5756  var toConsumableArray = __webpack_require__(17);
5757  
5758  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/objectSpread.js
5759  var objectSpread = __webpack_require__(7);
5760  
5761  // EXTERNAL MODULE: external "lodash"
5762  var external_lodash_ = __webpack_require__(2);
5763  
5764  // EXTERNAL MODULE: external {"this":["wp","i18n"]}
5765  var external_this_wp_i18n_ = __webpack_require__(1);
5766  
5767  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/store/reducer.js
5768  
5769  
5770  
5771  
5772  /**
5773   * External dependencies
5774   */
5775  
5776  /**
5777   * WordPress dependencies
5778   */
5779  
5780  
5781  
5782  /**
5783   * Module Constants
5784   */
5785  
5786  var DEFAULT_CATEGORIES = [{
5787    slug: 'common',
5788    title: Object(external_this_wp_i18n_["__"])('Common Blocks')
5789  }, {
5790    slug: 'formatting',
5791    title: Object(external_this_wp_i18n_["__"])('Formatting')
5792  }, {
5793    slug: 'layout',
5794    title: Object(external_this_wp_i18n_["__"])('Layout Elements')
5795  }, {
5796    slug: 'widgets',
5797    title: Object(external_this_wp_i18n_["__"])('Widgets')
5798  }, {
5799    slug: 'embed',
5800    title: Object(external_this_wp_i18n_["__"])('Embeds')
5801  }, {
5802    slug: 'reusable',
5803    title: Object(external_this_wp_i18n_["__"])('Reusable Blocks')
5804  }];
5805  /**
5806   * Reducer managing the block types
5807   *
5808   * @param {Object} state  Current state.
5809   * @param {Object} action Dispatched action.
5810   *
5811   * @return {Object} Updated state.
5812   */
5813  
5814  function reducer_blockTypes() {
5815    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5816    var action = arguments.length > 1 ? arguments[1] : undefined;
5817  
5818    switch (action.type) {
5819      case 'ADD_BLOCK_TYPES':
5820        return Object(objectSpread["a" /* default */])({}, state, Object(external_lodash_["keyBy"])(Object(external_lodash_["map"])(action.blockTypes, function (blockType) {
5821          return Object(external_lodash_["omit"])(blockType, 'styles ');
5822        }), 'name'));
5823  
5824      case 'REMOVE_BLOCK_TYPES':
5825        return Object(external_lodash_["omit"])(state, action.names);
5826    }
5827  
5828    return state;
5829  }
5830  /**
5831   * Reducer managing the block style variations.
5832   *
5833   * @param {Object} state  Current state.
5834   * @param {Object} action Dispatched action.
5835   *
5836   * @return {Object} Updated state.
5837   */
5838  
5839  function blockStyles() {
5840    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5841    var action = arguments.length > 1 ? arguments[1] : undefined;
5842  
5843    switch (action.type) {
5844      case 'ADD_BLOCK_TYPES':
5845        return Object(objectSpread["a" /* default */])({}, state, Object(external_lodash_["mapValues"])(Object(external_lodash_["keyBy"])(action.blockTypes, 'name'), function (blockType) {
5846          return Object(external_lodash_["uniqBy"])([].concat(Object(toConsumableArray["a" /* default */])(Object(external_lodash_["get"])(blockType, ['styles'], [])), Object(toConsumableArray["a" /* default */])(Object(external_lodash_["get"])(state, [blockType.name], []))), function (style) {
5847            return style.name;
5848          });
5849        }));
5850  
5851      case 'ADD_BLOCK_STYLES':
5852        return Object(objectSpread["a" /* default */])({}, state, Object(defineProperty["a" /* default */])({}, action.blockName, Object(external_lodash_["uniqBy"])([].concat(Object(toConsumableArray["a" /* default */])(Object(external_lodash_["get"])(state, [action.blockName], [])), Object(toConsumableArray["a" /* default */])(action.styles)), function (style) {
5853          return style.name;
5854        })));
5855  
5856      case 'REMOVE_BLOCK_STYLES':
5857        return Object(objectSpread["a" /* default */])({}, state, Object(defineProperty["a" /* default */])({}, action.blockName, Object(external_lodash_["filter"])(Object(external_lodash_["get"])(state, [action.blockName], []), function (style) {
5858          return action.styleNames.indexOf(style.name) === -1;
5859        })));
5860    }
5861  
5862    return state;
5863  }
5864  /**
5865   * Higher-order Reducer creating a reducer keeping track of given block name.
5866   *
5867   * @param {string} setActionType  Action type.
5868   *
5869   * @return {function} Reducer.
5870   */
5871  
5872  function createBlockNameSetterReducer(setActionType) {
5873    return function () {
5874      var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
5875      var action = arguments.length > 1 ? arguments[1] : undefined;
5876  
5877      switch (action.type) {
5878        case 'REMOVE_BLOCK_TYPES':
5879          if (action.names.indexOf(state) !== -1) {
5880            return null;
5881          }
5882  
5883          return state;
5884  
5885        case setActionType:
5886          return action.name || null;
5887      }
5888  
5889      return state;
5890    };
5891  }
5892  var reducer_defaultBlockName = createBlockNameSetterReducer('SET_DEFAULT_BLOCK_NAME');
5893  var freeformFallbackBlockName = createBlockNameSetterReducer('SET_FREEFORM_FALLBACK_BLOCK_NAME');
5894  var unregisteredFallbackBlockName = createBlockNameSetterReducer('SET_UNREGISTERED_FALLBACK_BLOCK_NAME');
5895  /**
5896   * Reducer managing the categories
5897   *
5898   * @param {Object} state  Current state.
5899   * @param {Object} action Dispatched action.
5900   *
5901   * @return {Object} Updated state.
5902   */
5903  
5904  function reducer_categories() {
5905    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_CATEGORIES;
5906    var action = arguments.length > 1 ? arguments[1] : undefined;
5907  
5908    switch (action.type) {
5909      case 'SET_CATEGORIES':
5910        return action.categories || [];
5911  
5912      case 'UPDATE_CATEGORY':
5913        {
5914          if (!action.category || Object(external_lodash_["isEmpty"])(action.category)) {
5915            return state;
5916          }
5917  
5918          var categoryToChange = Object(external_lodash_["find"])(state, ['slug', action.slug]);
5919  
5920          if (categoryToChange) {
5921            return Object(external_lodash_["map"])(state, function (category) {
5922              if (category.slug === action.slug) {
5923                return Object(objectSpread["a" /* default */])({}, category, action.category);
5924              }
5925  
5926              return category;
5927            });
5928          }
5929        }
5930    }
5931  
5932    return state;
5933  }
5934  /* harmony default export */ var reducer = (Object(external_this_wp_data_["combineReducers"])({
5935    blockTypes: reducer_blockTypes,
5936    blockStyles: blockStyles,
5937    defaultBlockName: reducer_defaultBlockName,
5938    freeformFallbackBlockName: freeformFallbackBlockName,
5939    unregisteredFallbackBlockName: unregisteredFallbackBlockName,
5940    categories: reducer_categories
5941  }));
5942  
5943  // EXTERNAL MODULE: ./node_modules/rememo/es/rememo.js
5944  var rememo = __webpack_require__(30);
5945  
5946  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/store/selectors.js
5947  /**
5948   * External dependencies
5949   */
5950  
5951  
5952  /**
5953   * Given a block name or block type object, returns the corresponding
5954   * normalized block type object.
5955   *
5956   * @param {Object}          state      Blocks state.
5957   * @param {(string|Object)} nameOrType Block name or type object
5958   *
5959   * @return {Object} Block type object.
5960   */
5961  
5962  var getNormalizedBlockType = function getNormalizedBlockType(state, nameOrType) {
5963    return 'string' === typeof nameOrType ? getBlockType(state, nameOrType) : nameOrType;
5964  };
5965  /**
5966   * Returns all the available block types.
5967   *
5968   * @param {Object} state Data state.
5969   *
5970   * @return {Array} Block Types.
5971   */
5972  
5973  
5974  var getBlockTypes = Object(rememo["a" /* default */])(function (state) {
5975    return Object.values(state.blockTypes);
5976  }, function (state) {
5977    return [state.blockTypes];
5978  });
5979  /**
5980   * Returns a block type by name.
5981   *
5982   * @param {Object} state Data state.
5983   * @param {string} name Block type name.
5984   *
5985   * @return {Object?} Block Type.
5986   */
5987  
5988  function getBlockType(state, name) {
5989    return state.blockTypes[name];
5990  }
5991  /**
5992   * Returns block styles by block name.
5993   *
5994   * @param {Object} state Data state.
5995   * @param {string} name  Block type name.
5996   *
5997   * @return {Array?} Block Styles.
5998   */
5999  
6000  function getBlockStyles(state, name) {
6001    return state.blockStyles[name];
6002  }
6003  /**
6004   * Returns all the available categories.
6005   *
6006   * @param {Object} state Data state.
6007   *
6008   * @return {Array} Categories list.
6009   */
6010  
6011  function getCategories(state) {
6012    return state.categories;
6013  }
6014  /**
6015   * Returns the name of the default block name.
6016   *
6017   * @param {Object} state Data state.
6018   *
6019   * @return {string?} Default block name.
6020   */
6021  
6022  function getDefaultBlockName(state) {
6023    return state.defaultBlockName;
6024  }
6025  /**
6026   * Returns the name of the block for handling non-block content.
6027   *
6028   * @param {Object} state Data state.
6029   *
6030   * @return {string?} Name of the block for handling non-block content.
6031   */
6032  
6033  function getFreeformFallbackBlockName(state) {
6034    return state.freeformFallbackBlockName;
6035  }
6036  /**
6037   * Returns the name of the block for handling unregistered blocks.
6038   *
6039   * @param {Object} state Data state.
6040   *
6041   * @return {string?} Name of the block for handling unregistered blocks.
6042   */
6043  
6044  function getUnregisteredFallbackBlockName(state) {
6045    return state.unregisteredFallbackBlockName;
6046  }
6047  /**
6048   * Returns an array with the child blocks of a given block.
6049   *
6050   * @param {Object} state     Data state.
6051   * @param {string} blockName Block type name.
6052   *
6053   * @return {Array} Array of child block names.
6054   */
6055  
6056  var selectors_getChildBlockNames = Object(rememo["a" /* default */])(function (state, blockName) {
6057    return Object(external_lodash_["map"])(Object(external_lodash_["filter"])(state.blockTypes, function (blockType) {
6058      return Object(external_lodash_["includes"])(blockType.parent, blockName);
6059    }), function (_ref) {
6060      var name = _ref.name;
6061      return name;
6062    });
6063  }, function (state) {
6064    return [state.blockTypes];
6065  });
6066  /**
6067   * Returns the block support value for a feature, if defined.
6068   *
6069   * @param  {Object}          state           Data state.
6070   * @param  {(string|Object)} nameOrType      Block name or type object
6071   * @param  {string}          feature         Feature to retrieve
6072   * @param  {*}               defaultSupports Default value to return if not
6073   *                                           explicitly defined
6074   *
6075   * @return {?*} Block support value
6076   */
6077  
6078  var selectors_getBlockSupport = function getBlockSupport(state, nameOrType, feature, defaultSupports) {
6079    var blockType = getNormalizedBlockType(state, nameOrType);
6080    return Object(external_lodash_["get"])(blockType, ['supports', feature], defaultSupports);
6081  };
6082  /**
6083   * Returns true if the block defines support for a feature, or false otherwise.
6084   *
6085   * @param  {Object}         state           Data state.
6086   * @param {(string|Object)} nameOrType      Block name or type object.
6087   * @param {string}          feature         Feature to test.
6088   * @param {boolean}         defaultSupports Whether feature is supported by
6089   *                                          default if not explicitly defined.
6090   *
6091   * @return {boolean} Whether block supports feature.
6092   */
6093  
6094  function hasBlockSupport(state, nameOrType, feature, defaultSupports) {
6095    return !!selectors_getBlockSupport(state, nameOrType, feature, defaultSupports);
6096  }
6097  /**
6098   * Returns true if the block type by the given name or object value matches a
6099   * search term, or false otherwise.
6100   *
6101   * @param {Object}          state      Blocks state.
6102   * @param {(string|Object)} nameOrType Block name or type object.
6103   * @param {string}          searchTerm Search term by which to filter.
6104   *
6105   * @return {Object[]} Wheter block type matches search term.
6106   */
6107  
6108  function isMatchingSearchTerm(state, nameOrType, searchTerm) {
6109    var blockType = getNormalizedBlockType(state, nameOrType);
6110    var getNormalizedSearchTerm = Object(external_lodash_["flow"])([// Disregard diacritics.
6111    //  Input: "média"
6112    external_lodash_["deburr"], // Lowercase.
6113    //  Input: "MEDIA"
6114    function (term) {
6115      return term.toLowerCase();
6116    }, // Strip leading and trailing whitespace.
6117    //  Input: " media "
6118    function (term) {
6119      return term.trim();
6120    }]);
6121    var normalizedSearchTerm = getNormalizedSearchTerm(searchTerm);
6122    var isSearchMatch = Object(external_lodash_["flow"])([getNormalizedSearchTerm, function (normalizedCandidate) {
6123      return Object(external_lodash_["includes"])(normalizedCandidate, normalizedSearchTerm);
6124    }]);
6125    return isSearchMatch(blockType.title) || Object(external_lodash_["some"])(blockType.keywords, isSearchMatch) || isSearchMatch(blockType.category);
6126  }
6127  /**
6128   * Returns a boolean indicating if a block has child blocks or not.
6129   *
6130   * @param {Object} state     Data state.
6131   * @param {string} blockName Block type name.
6132   *
6133   * @return {boolean} True if a block contains child blocks and false otherwise.
6134   */
6135  
6136  var selectors_hasChildBlocks = function hasChildBlocks(state, blockName) {
6137    return selectors_getChildBlockNames(state, blockName).length > 0;
6138  };
6139  /**
6140   * Returns a boolean indicating if a block has at least one child block with inserter support.
6141   *
6142   * @param {Object} state     Data state.
6143   * @param {string} blockName Block type name.
6144   *
6145   * @return {boolean} True if a block contains at least one child blocks with inserter support
6146   *                   and false otherwise.
6147   */
6148  
6149  var selectors_hasChildBlocksWithInserterSupport = function hasChildBlocksWithInserterSupport(state, blockName) {
6150    return Object(external_lodash_["some"])(selectors_getChildBlockNames(state, blockName), function (childBlockName) {
6151      return hasBlockSupport(state, childBlockName, 'inserter', true);
6152    });
6153  };
6154  
6155  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/store/actions.js
6156  /**
6157   * External dependencies
6158   */
6159  
6160  /**
6161   * Returns an action object used in signalling that block types have been added.
6162   *
6163   * @param {Array|Object} blockTypes Block types received.
6164   *
6165   * @return {Object} Action object.
6166   */
6167  
6168  function addBlockTypes(blockTypes) {
6169    return {
6170      type: 'ADD_BLOCK_TYPES',
6171      blockTypes: Object(external_lodash_["castArray"])(blockTypes)
6172    };
6173  }
6174  /**
6175   * Returns an action object used to remove a registered block type.
6176   *
6177   * @param {string|Array} names Block name.
6178   *
6179   * @return {Object} Action object.
6180   */
6181  
6182  function removeBlockTypes(names) {
6183    return {
6184      type: 'REMOVE_BLOCK_TYPES',
6185      names: Object(external_lodash_["castArray"])(names)
6186    };
6187  }
6188  /**
6189   * Returns an action object used in signalling that new block styles have been added.
6190   *
6191   * @param {string}       blockName  Block name.
6192   * @param {Array|Object} styles     Block styles.
6193   *
6194   * @return {Object} Action object.
6195   */
6196  
6197  function addBlockStyles(blockName, styles) {
6198    return {
6199      type: 'ADD_BLOCK_STYLES',
6200      styles: Object(external_lodash_["castArray"])(styles),
6201      blockName: blockName
6202    };
6203  }
6204  /**
6205   * Returns an action object used in signalling that block styles have been removed.
6206   *
6207   * @param {string}       blockName  Block name.
6208   * @param {Array|string} styleNames Block style names.
6209   *
6210   * @return {Object} Action object.
6211   */
6212  
6213  function removeBlockStyles(blockName, styleNames) {
6214    return {
6215      type: 'REMOVE_BLOCK_STYLES',
6216      styleNames: Object(external_lodash_["castArray"])(styleNames),
6217      blockName: blockName
6218    };
6219  }
6220  /**
6221   * Returns an action object used to set the default block name.
6222   *
6223   * @param {string} name Block name.
6224   *
6225   * @return {Object} Action object.
6226   */
6227  
6228  function setDefaultBlockName(name) {
6229    return {
6230      type: 'SET_DEFAULT_BLOCK_NAME',
6231      name: name
6232    };
6233  }
6234  /**
6235   * Returns an action object used to set the name of the block used as a fallback
6236   * for non-block content.
6237   *
6238   * @param {string} name Block name.
6239   *
6240   * @return {Object} Action object.
6241   */
6242  
6243  function setFreeformFallbackBlockName(name) {
6244    return {
6245      type: 'SET_FREEFORM_FALLBACK_BLOCK_NAME',
6246      name: name
6247    };
6248  }
6249  /**
6250   * Returns an action object used to set the name of the block used as a fallback
6251   * for unregistered blocks.
6252   *
6253   * @param {string} name Block name.
6254   *
6255   * @return {Object} Action object.
6256   */
6257  
6258  function setUnregisteredFallbackBlockName(name) {
6259    return {
6260      type: 'SET_UNREGISTERED_FALLBACK_BLOCK_NAME',
6261      name: name
6262    };
6263  }
6264  /**
6265   * Returns an action object used to set block categories.
6266   *
6267   * @param {Object[]} categories Block categories.
6268   *
6269   * @return {Object} Action object.
6270   */
6271  
6272  function setCategories(categories) {
6273    return {
6274      type: 'SET_CATEGORIES',
6275      categories: categories
6276    };
6277  }
6278  /**
6279   * Returns an action object used to update a category.
6280   *
6281   * @param {string} slug     Block category slug.
6282   * @param {Object} category Object containing the category properties that should be updated.
6283   *
6284   * @return {Object} Action object.
6285   */
6286  
6287  function updateCategory(slug, category) {
6288    return {
6289      type: 'UPDATE_CATEGORY',
6290      slug: slug,
6291      category: category
6292    };
6293  }
6294  
6295  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/store/index.js
6296  /**
6297   * WordPress dependencies
6298   */
6299  
6300  /**
6301   * Internal dependencies
6302   */
6303  
6304  
6305  
6306  
6307  Object(external_this_wp_data_["registerStore"])('core/blocks', {
6308    reducer: reducer,
6309    selectors: selectors_namespaceObject,
6310    actions: actions_namespaceObject
6311  });
6312  
6313  // EXTERNAL MODULE: ./node_modules/uuid/v4.js
6314  var v4 = __webpack_require__(65);
6315  var v4_default = /*#__PURE__*/__webpack_require__.n(v4);
6316  
6317  // EXTERNAL MODULE: external {"this":["wp","hooks"]}
6318  var external_this_wp_hooks_ = __webpack_require__(26);
6319  
6320  // EXTERNAL MODULE: ./node_modules/tinycolor2/tinycolor.js
6321  var tinycolor = __webpack_require__(45);
6322  var tinycolor_default = /*#__PURE__*/__webpack_require__.n(tinycolor);
6323  
6324  // EXTERNAL MODULE: external {"this":["wp","element"]}
6325  var external_this_wp_element_ = __webpack_require__(0);
6326  
6327  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/utils.js
6328  
6329  
6330  /**
6331   * External dependencies
6332   */
6333  
6334  
6335  /**
6336   * WordPress dependencies
6337   */
6338  
6339  
6340  /**
6341   * Internal dependencies
6342   */
6343  
6344  
6345  
6346  /**
6347   * Array of icon colors containing a color to be used if the icon color
6348   * was not explicitly set but the icon background color was.
6349   *
6350   * @type {Object}
6351   */
6352  
6353  var ICON_COLORS = ['#191e23', '#f8f9f9'];
6354  /**
6355   * Determines whether the block is a default block
6356   * and its attributes are equal to the default attributes
6357   * which means the block is unmodified.
6358   *
6359   * @param  {WPBlock} block Block Object
6360   *
6361   * @return {boolean}       Whether the block is an unmodified default block
6362   */
6363  
6364  function isUnmodifiedDefaultBlock(block) {
6365    var defaultBlockName = registration_getDefaultBlockName();
6366  
6367    if (block.name !== defaultBlockName) {
6368      return false;
6369    } // Cache a created default block if no cache exists or the default block
6370    // name changed.
6371  
6372  
6373    if (!isUnmodifiedDefaultBlock.block || isUnmodifiedDefaultBlock.block.name !== defaultBlockName) {
6374      isUnmodifiedDefaultBlock.block = createBlock(defaultBlockName);
6375    }
6376  
6377    var newDefaultBlock = isUnmodifiedDefaultBlock.block;
6378    var blockType = registration_getBlockType(defaultBlockName);
6379    return Object(external_lodash_["every"])(blockType.attributes, function (value, key) {
6380      return newDefaultBlock.attributes[key] === block.attributes[key];
6381    });
6382  }
6383  /**
6384   * Function that checks if the parameter is a valid icon.
6385   *
6386   * @param {*} icon  Parameter to be checked.
6387   *
6388   * @return {boolean} True if the parameter is a valid icon and false otherwise.
6389   */
6390  
6391  function isValidIcon(icon) {
6392    return !!icon && (Object(external_lodash_["isString"])(icon) || Object(external_this_wp_element_["isValidElement"])(icon) || Object(external_lodash_["isFunction"])(icon) || icon instanceof external_this_wp_element_["Component"]);
6393  }
6394  /**
6395   * Function that receives an icon as set by the blocks during the registration
6396   * and returns a new icon object that is normalized so we can rely on just on possible icon structure
6397   * in the codebase.
6398   *
6399   * @param {(Object|string|WPElement)} icon  Slug of the Dashicon to be shown
6400   *                                          as the icon for the block in the
6401   *                                          inserter, or element or an object describing the icon.
6402   *
6403   * @return {Object} Object describing the icon.
6404   */
6405  
6406  function normalizeIconObject(icon) {
6407    if (!icon) {
6408      icon = 'block-default';
6409    }
6410  
6411    if (isValidIcon(icon)) {
6412      return {
6413        src: icon
6414      };
6415    }
6416  
6417    if (Object(external_lodash_["has"])(icon, ['background'])) {
6418      var tinyBgColor = tinycolor_default()(icon.background);
6419      return Object(objectSpread["a" /* default */])({}, icon, {
6420        foreground: icon.foreground ? icon.foreground : Object(tinycolor["mostReadable"])(tinyBgColor, ICON_COLORS, {
6421          includeFallbackColors: true,
6422          level: 'AA',
6423          size: 'large'
6424        }).toHexString(),
6425        shadowColor: tinyBgColor.setAlpha(0.3).toRgbString()
6426      });
6427    }
6428  
6429    return icon;
6430  }
6431  /**
6432   * Normalizes block type passed as param. When string is passed then
6433   * it converts it to the matching block type object.
6434   * It passes the original object otherwise.
6435   *
6436   * @param {string|Object} blockTypeOrName  Block type or name.
6437   *
6438   * @return {?Object} Block type.
6439   */
6440  
6441  function normalizeBlockType(blockTypeOrName) {
6442    if (Object(external_lodash_["isString"])(blockTypeOrName)) {
6443      return registration_getBlockType(blockTypeOrName);
6444    }
6445  
6446    return blockTypeOrName;
6447  }
6448  
6449  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/registration.js
6450  
6451  
6452  /* eslint no-console: [ 'error', { allow: [ 'error' ] } ] */
6453  
6454  /**
6455   * External dependencies
6456   */
6457  
6458  /**
6459   * WordPress dependencies
6460   */
6461  
6462  
6463  
6464  /**
6465   * Internal dependencies
6466   */
6467  
6468  
6469  /**
6470   * Defined behavior of a block type.
6471   *
6472   * @typedef {WPBlockType}
6473   *
6474   * @property {string}                    name       Block's namespaced name.
6475   * @property {string}                    title      Human-readable label for a block.
6476   *                                                  Shown in the block inserter.
6477   * @property {string}                    category   Category classification of block,
6478   *                                                  impacting where block is shown in
6479   *                                                  inserter results.
6480   * @property {(Object|string|WPElement)} icon       Slug of the Dashicon to be shown
6481   *                                                  as the icon for the block in the
6482   *                                                  inserter, or element or an object describing the icon.
6483   * @property {?string[]}                 keywords   Additional keywords to produce
6484   *                                                  block as inserter search result.
6485   * @property {?Object}                   attributes Block attributes.
6486   * @property {Function}                  save       Serialize behavior of a block,
6487   *                                                  returning an element describing
6488   *                                                  structure of the block's post
6489   *                                                  content markup.
6490   * @property {WPComponent}               edit       Component rendering element to be
6491   *                                                  interacted with in an editor.
6492   */
6493  
6494  var serverSideBlockDefinitions = {};
6495  /**
6496   * Set the server side block definition of blocks.
6497   *
6498   * @param {Object} definitions Server-side block definitions
6499   */
6500  
6501  function unstable__bootstrapServerSideBlockDefinitions(definitions) {
6502    // eslint-disable-line camelcase
6503    serverSideBlockDefinitions = definitions;
6504  }
6505  /**
6506   * Registers a new block provided a unique name and an object defining its
6507   * behavior. Once registered, the block is made available as an option to any
6508   * editor interface where blocks are implemented.
6509   *
6510   * @param {string} name     Block name.
6511   * @param {Object} settings Block settings.
6512   *
6513   * @return {?WPBlock} The block, if it has been successfully registered;
6514   *                     otherwise `undefined`.
6515   */
6516  
6517  function registerBlockType(name, settings) {
6518    settings = Object(objectSpread["a" /* default */])({
6519      name: name
6520    }, Object(external_lodash_["get"])(serverSideBlockDefinitions, name), settings);
6521  
6522    if (typeof name !== 'string') {
6523      console.error('Block names must be strings.');
6524      return;
6525    }
6526  
6527    if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
6528      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');
6529      return;
6530    }
6531  
6532    if (Object(external_this_wp_data_["select"])('core/blocks').getBlockType(name)) {
6533      console.error('Block "' + name + '" is already registered.');
6534      return;
6535    }
6536  
6537    settings = Object(external_this_wp_hooks_["applyFilters"])('blocks.registerBlockType', settings, name);
6538  
6539    if (!settings || !Object(external_lodash_["isFunction"])(settings.save)) {
6540      console.error('The "save" property must be specified and must be a valid function.');
6541      return;
6542    }
6543  
6544    if ('edit' in settings && !Object(external_lodash_["isFunction"])(settings.edit)) {
6545      console.error('The "edit" property must be a valid function.');
6546      return;
6547    }
6548  
6549    if (!('category' in settings)) {
6550      console.error('The block "' + name + '" must have a category.');
6551      return;
6552    }
6553  
6554    if ('category' in settings && !Object(external_lodash_["some"])(Object(external_this_wp_data_["select"])('core/blocks').getCategories(), {
6555      slug: settings.category
6556    })) {
6557      console.error('The block "' + name + '" must have a registered category.');
6558      return;
6559    }
6560  
6561    if (!('title' in settings) || settings.title === '') {
6562      console.error('The block "' + name + '" must have a title.');
6563      return;
6564    }
6565  
6566    if (typeof settings.title !== 'string') {
6567      console.error('Block titles must be strings.');
6568      return;
6569    }
6570  
6571    settings.icon = normalizeIconObject(settings.icon);
6572  
6573    if (!isValidIcon(settings.icon.src)) {
6574      console.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://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-registration/#icon-optional');
6575      return;
6576    }
6577  
6578    Object(external_this_wp_data_["dispatch"])('core/blocks').addBlockTypes(settings);
6579    return settings;
6580  }
6581  /**
6582   * Unregisters a block.
6583   *
6584   * @param {string} name Block name.
6585   *
6586   * @return {?WPBlock} The previous block value, if it has been successfully
6587   *                     unregistered; otherwise `undefined`.
6588   */
6589  
6590  function unregisterBlockType(name) {
6591    var oldBlock = Object(external_this_wp_data_["select"])('core/blocks').getBlockType(name);
6592  
6593    if (!oldBlock) {
6594      console.error('Block "' + name + '" is not registered.');
6595      return;
6596    }
6597  
6598    Object(external_this_wp_data_["dispatch"])('core/blocks').removeBlockTypes(name);
6599    return oldBlock;
6600  }
6601  /**
6602   * Assigns name of block for handling non-block content.
6603   *
6604   * @param {string} blockName Block name.
6605   */
6606  
6607  function setFreeformContentHandlerName(blockName) {
6608    Object(external_this_wp_data_["dispatch"])('core/blocks').setFreeformFallbackBlockName(blockName);
6609  }
6610  /**
6611   * Retrieves name of block handling non-block content, or undefined if no
6612   * handler has been defined.
6613   *
6614   * @return {?string} Blog name.
6615   */
6616  
6617  function getFreeformContentHandlerName() {
6618    return Object(external_this_wp_data_["select"])('core/blocks').getFreeformFallbackBlockName();
6619  }
6620  /**
6621   * Assigns name of block handling unregistered block types.
6622   *
6623   * @param {string} blockName Block name.
6624   */
6625  
6626  function setUnregisteredTypeHandlerName(blockName) {
6627    Object(external_this_wp_data_["dispatch"])('core/blocks').setUnregisteredFallbackBlockName(blockName);
6628  }
6629  /**
6630   * Retrieves name of block handling unregistered block types, or undefined if no
6631   * handler has been defined.
6632   *
6633   * @return {?string} Blog name.
6634   */
6635  
6636  function getUnregisteredTypeHandlerName() {
6637    return Object(external_this_wp_data_["select"])('core/blocks').getUnregisteredFallbackBlockName();
6638  }
6639  /**
6640   * Assigns the default block name.
6641   *
6642   * @param {string} name Block name.
6643   */
6644  
6645  function registration_setDefaultBlockName(name) {
6646    Object(external_this_wp_data_["dispatch"])('core/blocks').setDefaultBlockName(name);
6647  }
6648  /**
6649   * Retrieves the default block name.
6650   *
6651   * @return {?string} Block name.
6652   */
6653  
6654  function registration_getDefaultBlockName() {
6655    return Object(external_this_wp_data_["select"])('core/blocks').getDefaultBlockName();
6656  }
6657  /**
6658   * Returns a registered block type.
6659   *
6660   * @param {string} name Block name.
6661   *
6662   * @return {?Object} Block type.
6663   */
6664  
6665  function registration_getBlockType(name) {
6666    return Object(external_this_wp_data_["select"])('core/blocks').getBlockType(name);
6667  }
6668  /**
6669   * Returns all registered blocks.
6670   *
6671   * @return {Array} Block settings.
6672   */
6673  
6674  function registration_getBlockTypes() {
6675    return Object(external_this_wp_data_["select"])('core/blocks').getBlockTypes();
6676  }
6677  /**
6678   * Returns the block support value for a feature, if defined.
6679   *
6680   * @param  {(string|Object)} nameOrType      Block name or type object
6681   * @param  {string}          feature         Feature to retrieve
6682   * @param  {*}               defaultSupports Default value to return if not
6683   *                                           explicitly defined
6684   *
6685   * @return {?*} Block support value
6686   */
6687  
6688  function registration_getBlockSupport(nameOrType, feature, defaultSupports) {
6689    return Object(external_this_wp_data_["select"])('core/blocks').getBlockSupport(nameOrType, feature, defaultSupports);
6690  }
6691  /**
6692   * Returns true if the block defines support for a feature, or false otherwise.
6693   *
6694   * @param {(string|Object)} nameOrType      Block name or type object.
6695   * @param {string}          feature         Feature to test.
6696   * @param {boolean}         defaultSupports Whether feature is supported by
6697   *                                          default if not explicitly defined.
6698   *
6699   * @return {boolean} Whether block supports feature.
6700   */
6701  
6702  function registration_hasBlockSupport(nameOrType, feature, defaultSupports) {
6703    return Object(external_this_wp_data_["select"])('core/blocks').hasBlockSupport(nameOrType, feature, defaultSupports);
6704  }
6705  /**
6706   * Determines whether or not the given block is a reusable block. This is a
6707   * special block type that is used to point to a global block stored via the
6708   * API.
6709   *
6710   * @param {Object} blockOrType Block or Block Type to test.
6711   *
6712   * @return {boolean} Whether the given block is a reusable block.
6713   */
6714  
6715  function isReusableBlock(blockOrType) {
6716    return blockOrType.name === 'core/block';
6717  }
6718  /**
6719   * Returns an array with the child blocks of a given block.
6720   *
6721   * @param {string} blockName Name of block (example: “latest-posts”).
6722   *
6723   * @return {Array} Array of child block names.
6724   */
6725  
6726  var registration_getChildBlockNames = function getChildBlockNames(blockName) {
6727    return Object(external_this_wp_data_["select"])('core/blocks').getChildBlockNames(blockName);
6728  };
6729  /**
6730   * Returns a boolean indicating if a block has child blocks or not.
6731   *
6732   * @param {string} blockName Name of block (example: “latest-posts”).
6733   *
6734   * @return {boolean} True if a block contains child blocks and false otherwise.
6735   */
6736  
6737  var registration_hasChildBlocks = function hasChildBlocks(blockName) {
6738    return Object(external_this_wp_data_["select"])('core/blocks').hasChildBlocks(blockName);
6739  };
6740  /**
6741   * Returns a boolean indicating if a block has at least one child block with inserter support.
6742   *
6743   * @param {string} blockName Block type name.
6744   *
6745   * @return {boolean} True if a block contains at least one child blocks with inserter support
6746   *                   and false otherwise.
6747   */
6748  
6749  var registration_hasChildBlocksWithInserterSupport = function hasChildBlocksWithInserterSupport(blockName) {
6750    return Object(external_this_wp_data_["select"])('core/blocks').hasChildBlocksWithInserterSupport(blockName);
6751  };
6752  /**
6753   * Registers a new block style variation for the given block.
6754   *
6755   * @param {string} blockName      Name of block (example: “core/latest-posts”).
6756   * @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
6757   */
6758  
6759  var registration_registerBlockStyle = function registerBlockStyle(blockName, styleVariation) {
6760    Object(external_this_wp_data_["dispatch"])('core/blocks').addBlockStyles(blockName, styleVariation);
6761  };
6762  /**
6763   * Unregisters a block style variation for the given block.
6764   *
6765   * @param {string} blockName          Name of block (example: “core/latest-posts”).
6766   * @param {string} styleVariationName Name of class applied to the block.
6767   */
6768  
6769  var registration_unregisterBlockStyle = function unregisterBlockStyle(blockName, styleVariationName) {
6770    Object(external_this_wp_data_["dispatch"])('core/blocks').removeBlockStyles(blockName, styleVariationName);
6771  };
6772  
6773  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/factory.js
6774  
6775  
6776  
6777  /**
6778   * External dependencies
6779   */
6780  
6781  
6782  /**
6783   * WordPress dependencies
6784   */
6785  
6786  
6787  /**
6788   * Internal dependencies
6789   */
6790  
6791  
6792  
6793  /**
6794   * Returns a block object given its type and attributes.
6795   *
6796   * @param {string} name        Block name.
6797   * @param {Object} attributes  Block attributes.
6798   * @param {?Array} innerBlocks Nested blocks.
6799   *
6800   * @return {Object} Block object.
6801   */
6802  
6803  function createBlock(name) {
6804    var attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6805    var innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
6806    // Get the type definition associated with a registered block.
6807    var blockType = registration_getBlockType(name); // Ensure attributes contains only values defined by block type, and merge
6808    // default values for missing attributes.
6809  
6810    var sanitizedAttributes = Object(external_lodash_["reduce"])(blockType.attributes, function (result, schema, key) {
6811      var value = attributes[key];
6812  
6813      if (undefined !== value) {
6814        result[key] = value;
6815      } else if (schema.hasOwnProperty('default')) {
6816        result[key] = schema.default;
6817      }
6818  
6819      if (['node', 'children'].indexOf(schema.source) !== -1) {
6820        // Ensure value passed is always an array, which we're expecting in
6821        // the RichText component to handle the deprecated value.
6822        if (typeof result[key] === 'string') {
6823          result[key] = [result[key]];
6824        } else if (!Array.isArray(result[key])) {
6825          result[key] = [];
6826        }
6827      }
6828  
6829      return result;
6830    }, {});
6831    var clientId = v4_default()(); // Blocks are stored with a unique ID, the assigned type name, the block
6832    // attributes, and their inner blocks.
6833  
6834    return {
6835      clientId: clientId,
6836      name: name,
6837      isValid: true,
6838      attributes: sanitizedAttributes,
6839      innerBlocks: innerBlocks
6840    };
6841  }
6842  /**
6843   * Given a block object, returns a copy of the block object, optionally merging
6844   * new attributes and/or replacing its inner blocks.
6845   *
6846   * @param {Object} block              Block instance.
6847   * @param {Object} mergeAttributes    Block attributes.
6848   * @param {?Array} newInnerBlocks     Nested blocks.
6849   *
6850   * @return {Object} A cloned block.
6851   */
6852  
6853  function cloneBlock(block) {
6854    var mergeAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6855    var newInnerBlocks = arguments.length > 2 ? arguments[2] : undefined;
6856    var clientId = v4_default()();
6857    return Object(objectSpread["a" /* default */])({}, block, {
6858      clientId: clientId,
6859      attributes: Object(objectSpread["a" /* default */])({}, block.attributes, mergeAttributes),
6860      innerBlocks: newInnerBlocks || block.innerBlocks.map(function (innerBlock) {
6861        return cloneBlock(innerBlock);
6862      })
6863    });
6864  }
6865  /**
6866   * Returns a boolean indicating whether a transform is possible based on
6867   * various bits of context.
6868   *
6869   * @param {Object} transform The transform object to validate.
6870   * @param {string} direction Is this a 'from' or 'to' transform.
6871   * @param {Array} blocks The blocks to transform from.
6872   *
6873   * @return {boolean} Is the transform possible?
6874   */
6875  
6876  var factory_isPossibleTransformForSource = function isPossibleTransformForSource(transform, direction, blocks) {
6877    if (Object(external_lodash_["isEmpty"])(blocks)) {
6878      return false;
6879    } // If multiple blocks are selected, only multi block transforms are allowed.
6880  
6881  
6882    var isMultiBlock = blocks.length > 1;
6883    var isValidForMultiBlocks = !isMultiBlock || transform.isMultiBlock;
6884  
6885    if (!isValidForMultiBlocks) {
6886      return false;
6887    } // Only consider 'block' type transforms as valid.
6888  
6889  
6890    var isBlockType = transform.type === 'block';
6891  
6892    if (!isBlockType) {
6893      return false;
6894    } // Check if the transform's block name matches the source block only if this is a transform 'from'.
6895  
6896  
6897    var sourceBlock = Object(external_lodash_["first"])(blocks);
6898    var hasMatchingName = direction !== 'from' || transform.blocks.indexOf(sourceBlock.name) !== -1;
6899  
6900    if (!hasMatchingName) {
6901      return false;
6902    } // If the transform has a `isMatch` function specified, check that it returns true.
6903  
6904  
6905    if (Object(external_lodash_["isFunction"])(transform.isMatch)) {
6906      var attributes = transform.isMultiBlock ? blocks.map(function (block) {
6907        return block.attributes;
6908      }) : sourceBlock.attributes;
6909  
6910      if (!transform.isMatch(attributes)) {
6911        return false;
6912      }
6913    }
6914  
6915    return true;
6916  };
6917  /**
6918   * Returns block types that the 'blocks' can be transformed into, based on
6919   * 'from' transforms on other blocks.
6920   *
6921   * @param {Array}  blocks  The blocks to transform from.
6922   *
6923   * @return {Array} Block types that the blocks can be transformed into.
6924   */
6925  
6926  
6927  var factory_getBlockTypesForPossibleFromTransforms = function getBlockTypesForPossibleFromTransforms(blocks) {
6928    if (Object(external_lodash_["isEmpty"])(blocks)) {
6929      return [];
6930    }
6931  
6932    var allBlockTypes = registration_getBlockTypes(); // filter all blocks to find those with a 'from' transform.
6933  
6934    var blockTypesWithPossibleFromTransforms = Object(external_lodash_["filter"])(allBlockTypes, function (blockType) {
6935      var fromTransforms = getBlockTransforms('from', blockType.name);
6936      return !!findTransform(fromTransforms, function (transform) {
6937        return factory_isPossibleTransformForSource(transform, 'from', blocks);
6938      });
6939    });
6940    return blockTypesWithPossibleFromTransforms;
6941  };
6942  /**
6943   * Returns block types that the 'blocks' can be transformed into, based on
6944   * the source block's own 'to' transforms.
6945   *
6946   * @param {Array} blocks The blocks to transform from.
6947   *
6948   * @return {Array} Block types that the source can be transformed into.
6949   */
6950  
6951  
6952  var factory_getBlockTypesForPossibleToTransforms = function getBlockTypesForPossibleToTransforms(blocks) {
6953    if (Object(external_lodash_["isEmpty"])(blocks)) {
6954      return [];
6955    }
6956  
6957    var sourceBlock = Object(external_lodash_["first"])(blocks);
6958    var blockType = registration_getBlockType(sourceBlock.name);
6959    var transformsTo = getBlockTransforms('to', blockType.name); // filter all 'to' transforms to find those that are possible.
6960  
6961    var possibleTransforms = Object(external_lodash_["filter"])(transformsTo, function (transform) {
6962      return factory_isPossibleTransformForSource(transform, 'to', blocks);
6963    }); // Build a list of block names using the possible 'to' transforms.
6964  
6965    var blockNames = Object(external_lodash_["flatMap"])(possibleTransforms, function (transformation) {
6966      return transformation.blocks;
6967    }); // Map block names to block types.
6968  
6969    return blockNames.map(function (name) {
6970      return registration_getBlockType(name);
6971    });
6972  };
6973  /**
6974   * Returns an array of block types that the set of blocks received as argument
6975   * can be transformed into.
6976   *
6977   * @param {Array} blocks Blocks array.
6978   *
6979   * @return {Array} Block types that the blocks argument can be transformed to.
6980   */
6981  
6982  
6983  function getPossibleBlockTransformations(blocks) {
6984    if (Object(external_lodash_["isEmpty"])(blocks)) {
6985      return [];
6986    }
6987  
6988    var sourceBlock = Object(external_lodash_["first"])(blocks);
6989    var isMultiBlock = blocks.length > 1;
6990  
6991    if (isMultiBlock && !Object(external_lodash_["every"])(blocks, {
6992      name: sourceBlock.name
6993    })) {
6994      return [];
6995    }
6996  
6997    var blockTypesForFromTransforms = factory_getBlockTypesForPossibleFromTransforms(blocks);
6998    var blockTypesForToTransforms = factory_getBlockTypesForPossibleToTransforms(blocks);
6999    return Object(external_lodash_["uniq"])([].concat(Object(toConsumableArray["a" /* default */])(blockTypesForFromTransforms), Object(toConsumableArray["a" /* default */])(blockTypesForToTransforms)));
7000  }
7001  /**
7002   * Given an array of transforms, returns the highest-priority transform where
7003   * the predicate function returns a truthy value. A higher-priority transform
7004   * is one with a lower priority value (i.e. first in priority order). Returns
7005   * null if the transforms set is empty or the predicate function returns a
7006   * falsey value for all entries.
7007   *
7008   * @param {Object[]} transforms Transforms to search.
7009   * @param {Function} predicate  Function returning true on matching transform.
7010   *
7011   * @return {?Object} Highest-priority transform candidate.
7012   */
7013  
7014  function findTransform(transforms, predicate) {
7015    // The hooks library already has built-in mechanisms for managing priority
7016    // queue, so leverage via locally-defined instance.
7017    var hooks = Object(external_this_wp_hooks_["createHooks"])();
7018  
7019    var _loop = function _loop(i) {
7020      var candidate = transforms[i];
7021  
7022      if (predicate(candidate)) {
7023        hooks.addFilter('transform', 'transform/' + i.toString(), function (result) {
7024          return result ? result : candidate;
7025        }, candidate.priority);
7026      }
7027    };
7028  
7029    for (var i = 0; i < transforms.length; i++) {
7030      _loop(i);
7031    } // Filter name is arbitrarily chosen but consistent with above aggregation.
7032  
7033  
7034    return hooks.applyFilters('transform', null);
7035  }
7036  /**
7037   * Returns normal block transforms for a given transform direction, optionally
7038   * for a specific block by name, or an empty array if there are no transforms.
7039   * If no block name is provided, returns transforms for all blocks. A normal
7040   * transform object includes `blockName` as a property.
7041   *
7042   * @param {string}  direction Transform direction ("to", "from").
7043   * @param {string|Object} blockTypeOrName  Block type or name.
7044   *
7045   * @return {Array} Block transforms for direction.
7046   */
7047  
7048  function getBlockTransforms(direction, blockTypeOrName) {
7049    // When retrieving transforms for all block types, recurse into self.
7050    if (blockTypeOrName === undefined) {
7051      return Object(external_lodash_["flatMap"])(registration_getBlockTypes(), function (_ref) {
7052        var name = _ref.name;
7053        return getBlockTransforms(direction, name);
7054      });
7055    } // Validate that block type exists and has array of direction.
7056  
7057  
7058    var blockType = normalizeBlockType(blockTypeOrName);
7059  
7060    var _ref2 = blockType || {},
7061        blockName = _ref2.name,
7062        transforms = _ref2.transforms;
7063  
7064    if (!transforms || !Array.isArray(transforms[direction])) {
7065      return [];
7066    } // Map transforms to normal form.
7067  
7068  
7069    return transforms[direction].map(function (transform) {
7070      return Object(objectSpread["a" /* default */])({}, transform, {
7071        blockName: blockName
7072      });
7073    });
7074  }
7075  /**
7076   * Switch one or more blocks into one or more blocks of the new block type.
7077   *
7078   * @param {Array|Object} blocks Blocks array or block object.
7079   * @param {string}       name   Block name.
7080   *
7081   * @return {Array} Array of blocks.
7082   */
7083  
7084  function switchToBlockType(blocks, name) {
7085    var blocksArray = Object(external_lodash_["castArray"])(blocks);
7086    var isMultiBlock = blocksArray.length > 1;
7087    var firstBlock = blocksArray[0];
7088    var sourceName = firstBlock.name;
7089  
7090    if (isMultiBlock && !Object(external_lodash_["every"])(blocksArray, function (block) {
7091      return block.name === sourceName;
7092    })) {
7093      return null;
7094    } // Find the right transformation by giving priority to the "to"
7095    // transformation.
7096  
7097  
7098    var transformationsFrom = getBlockTransforms('from', name);
7099    var transformationsTo = getBlockTransforms('to', sourceName);
7100    var transformation = findTransform(transformationsTo, function (t) {
7101      return t.type === 'block' && t.blocks.indexOf(name) !== -1 && (!isMultiBlock || t.isMultiBlock);
7102    }) || findTransform(transformationsFrom, function (t) {
7103      return t.type === 'block' && t.blocks.indexOf(sourceName) !== -1 && (!isMultiBlock || t.isMultiBlock);
7104    }); // Stop if there is no valid transformation.
7105  
7106    if (!transformation) {
7107      return null;
7108    }
7109  
7110    var transformationResults;
7111  
7112    if (transformation.isMultiBlock) {
7113      transformationResults = transformation.transform(blocksArray.map(function (currentBlock) {
7114        return currentBlock.attributes;
7115      }), blocksArray.map(function (currentBlock) {
7116        return currentBlock.innerBlocks;
7117      }));
7118    } else {
7119      transformationResults = transformation.transform(firstBlock.attributes, firstBlock.innerBlocks);
7120    } // Ensure that the transformation function returned an object or an array
7121    // of objects.
7122  
7123  
7124    if (!Object(external_lodash_["isObjectLike"])(transformationResults)) {
7125      return null;
7126    } // If the transformation function returned a single object, we want to work
7127    // with an array instead.
7128  
7129  
7130    transformationResults = Object(external_lodash_["castArray"])(transformationResults); // Ensure that every block object returned by the transformation has a
7131    // valid block type.
7132  
7133    if (transformationResults.some(function (result) {
7134      return !registration_getBlockType(result.name);
7135    })) {
7136      return null;
7137    }
7138  
7139    var firstSwitchedBlock = Object(external_lodash_["findIndex"])(transformationResults, function (result) {
7140      return result.name === name;
7141    }); // Ensure that at least one block object returned by the transformation has
7142    // the expected "destination" block type.
7143  
7144    if (firstSwitchedBlock < 0) {
7145      return null;
7146    }
7147  
7148    return transformationResults.map(function (result, index) {
7149      var transformedBlock = Object(objectSpread["a" /* default */])({}, result, {
7150        // The first transformed block whose type matches the "destination"
7151        // type gets to keep the existing client ID of the first block.
7152        clientId: index === firstSwitchedBlock ? firstBlock.clientId : result.clientId
7153      });
7154      /**
7155       * Filters an individual transform result from block transformation.
7156       * All of the original blocks are passed, since transformations are
7157       * many-to-many, not one-to-one.
7158       *
7159       * @param {Object}   transformedBlock The transformed block.
7160       * @param {Object[]} blocks           Original blocks transformed.
7161       */
7162  
7163  
7164      return Object(external_this_wp_hooks_["applyFilters"])('blocks.switchToBlockType.transformedBlock', transformedBlock, blocks);
7165    });
7166  }
7167  
7168  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/slicedToArray.js + 1 modules
7169  var slicedToArray = __webpack_require__(28);
7170  
7171  // CONCATENATED MODULE: ./node_modules/hpq/es/get-path.js
7172  /**
7173   * Given object and string of dot-delimited path segments, returns value at
7174   * path or undefined if path cannot be resolved.
7175   *
7176   * @param  {Object} object Lookup object
7177   * @param  {string} path   Path to resolve
7178   * @return {?*}            Resolved value
7179   */
7180  function getPath(object, path) {
7181    var segments = path.split('.');
7182    var segment;
7183  
7184    while (segment = segments.shift()) {
7185      if (!(segment in object)) {
7186        return;
7187      }
7188  
7189      object = object[segment];
7190    }
7191  
7192    return object;
7193  }
7194  // CONCATENATED MODULE: ./node_modules/hpq/es/index.js
7195  /**
7196   * Internal dependencies
7197   */
7198  
7199  /**
7200   * Function returning a DOM document created by `createHTMLDocument`. The same
7201   * document is returned between invocations.
7202   *
7203   * @return {Document} DOM document.
7204   */
7205  
7206  var getDocument = function () {
7207    var doc;
7208    return function () {
7209      if (!doc) {
7210        doc = document.implementation.createHTMLDocument('');
7211      }
7212  
7213      return doc;
7214    };
7215  }();
7216  /**
7217   * Given a markup string or DOM element, creates an object aligning with the
7218   * shape of the matchers object, or the value returned by the matcher.
7219   *
7220   * @param  {(string|Element)}  source   Source content
7221   * @param  {(Object|Function)} matchers Matcher function or object of matchers
7222   * @return {(Object|*)}                 Matched value(s), shaped by object
7223   */
7224  
7225  
7226  function es_parse(source, matchers) {
7227    if (!matchers) {
7228      return;
7229    } // Coerce to element
7230  
7231  
7232    if ('string' === typeof source) {
7233      var doc = getDocument();
7234      doc.body.innerHTML = source;
7235      source = doc.body;
7236    } // Return singular value
7237  
7238  
7239    if ('function' === typeof matchers) {
7240      return matchers(source);
7241    } // Bail if we can't handle matchers
7242  
7243  
7244    if (Object !== matchers.constructor) {
7245      return;
7246    } // Shape result by matcher object
7247  
7248  
7249    return Object.keys(matchers).reduce(function (memo, key) {
7250      memo[key] = es_parse(source, matchers[key]);
7251      return memo;
7252    }, {});
7253  }
7254  /**
7255   * Generates a function which matches node of type selector, returning an
7256   * attribute by property if the attribute exists. If no selector is passed,
7257   * returns property of the query element.
7258   *
7259   * @param  {?string} selector Optional selector
7260   * @param  {string}  name     Property name
7261   * @return {*}                Property value
7262   */
7263  
7264  function prop(selector, name) {
7265    if (1 === arguments.length) {
7266      name = selector;
7267      selector = undefined;
7268    }
7269  
7270    return function (node) {
7271      var match = node;
7272  
7273      if (selector) {
7274        match = node.querySelector(selector);
7275      }
7276  
7277      if (match) {
7278        return getPath(match, name);
7279      }
7280    };
7281  }
7282  /**
7283   * Generates a function which matches node of type selector, returning an
7284   * attribute by name if the attribute exists. If no selector is passed,
7285   * returns attribute of the query element.
7286   *
7287   * @param  {?string} selector Optional selector
7288   * @param  {string}  name     Attribute name
7289   * @return {?string}          Attribute value
7290   */
7291  
7292  function attr(selector, name) {
7293    if (1 === arguments.length) {
7294      name = selector;
7295      selector = undefined;
7296    }
7297  
7298    return function (node) {
7299      var attributes = prop(selector, 'attributes')(node);
7300  
7301      if (attributes && attributes.hasOwnProperty(name)) {
7302        return attributes[name].value;
7303      }
7304    };
7305  }
7306  /**
7307   * Convenience for `prop( selector, 'innerHTML' )`.
7308   *
7309   * @see prop()
7310   *
7311   * @param  {?string} selector Optional selector
7312   * @return {string}           Inner HTML
7313   */
7314  
7315  function es_html(selector) {
7316    return prop(selector, 'innerHTML');
7317  }
7318  /**
7319   * Convenience for `prop( selector, 'textContent' )`.
7320   *
7321   * @see prop()
7322   *
7323   * @param  {?string} selector Optional selector
7324   * @return {string}           Text content
7325   */
7326  
7327  function es_text(selector) {
7328    return prop(selector, 'textContent');
7329  }
7330  /**
7331   * Creates a new matching context by first finding elements matching selector
7332   * using querySelectorAll before then running another `parse` on `matchers`
7333   * scoped to the matched elements.
7334   *
7335   * @see parse()
7336   *
7337   * @param  {string}            selector Selector to match
7338   * @param  {(Object|Function)} matchers Matcher function or object of matchers
7339   * @return {Array.<*,Object>}           Array of matched value(s)
7340   */
7341  
7342  function query(selector, matchers) {
7343    return function (node) {
7344      var matches = node.querySelectorAll(selector);
7345      return [].map.call(matches, function (match) {
7346        return es_parse(match, matchers);
7347      });
7348    };
7349  }
7350  // EXTERNAL MODULE: external {"this":["wp","autop"]}
7351  var external_this_wp_autop_ = __webpack_require__(66);
7352  
7353  // EXTERNAL MODULE: external {"this":["wp","blockSerializationDefaultParser"]}
7354  var external_this_wp_blockSerializationDefaultParser_ = __webpack_require__(199);
7355  
7356  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js
7357  var arrayWithHoles = __webpack_require__(37);
7358  
7359  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/iterableToArray.js
7360  var iterableToArray = __webpack_require__(34);
7361  
7362  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js
7363  var nonIterableRest = __webpack_require__(38);
7364  
7365  // CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/toArray.js
7366  
7367  
7368  
7369  function _toArray(arr) {
7370    return Object(arrayWithHoles["a" /* default */])(arr) || Object(iterableToArray["a" /* default */])(arr) || Object(nonIterableRest["a" /* default */])();
7371  }
7372  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/classCallCheck.js
7373  var classCallCheck = __webpack_require__(10);
7374  
7375  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/createClass.js
7376  var createClass = __webpack_require__(9);
7377  
7378  // CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/utils.js
7379  var WSP = /[\t\n\f ]/;
7380  var ALPHA = /[A-Za-z]/;
7381  var CRLF = /\r\n?/g;
7382  function isSpace(char) {
7383      return WSP.test(char);
7384  }
7385  function isAlpha(char) {
7386      return ALPHA.test(char);
7387  }
7388  function preprocessInput(input) {
7389      return input.replace(CRLF, "\n");
7390  }
7391  function unwrap(maybe, msg) {
7392      if (!maybe)
7393          throw new Error((msg || 'value') + " was null");
7394      return maybe;
7395  }
7396  function or(maybe, otherwise) {
7397      return maybe || otherwise;
7398  }
7399  
7400  // CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/evented-tokenizer.js
7401  
7402  var evented_tokenizer_EventedTokenizer = /** @class */ (function () {
7403      function EventedTokenizer(delegate, entityParser) {
7404          this.delegate = delegate;
7405          this.entityParser = entityParser;
7406          this.state = null;
7407          this.input = null;
7408          this.index = -1;
7409          this.tagLine = -1;
7410          this.tagColumn = -1;
7411          this.line = -1;
7412          this.column = -1;
7413          this.states = {
7414              beforeData: function () {
7415                  var char = this.peek();
7416                  if (char === "<") {
7417                      this.state = 'tagOpen';
7418                      this.markTagStart();
7419                      this.consume();
7420                  }
7421                  else {
7422                      this.state = 'data';
7423                      this.delegate.beginData();
7424                  }
7425              },
7426              data: function () {
7427                  var char = this.peek();
7428                  if (char === "<") {
7429                      this.delegate.finishData();
7430                      this.state = 'tagOpen';
7431                      this.markTagStart();
7432                      this.consume();
7433                  }
7434                  else if (char === "&") {
7435                      this.consume();
7436                      this.delegate.appendToData(this.consumeCharRef() || "&");
7437                  }
7438                  else {
7439                      this.consume();
7440                      this.delegate.appendToData(char);
7441                  }
7442              },
7443              tagOpen: function () {
7444                  var char = this.consume();
7445                  if (char === "!") {
7446                      this.state = 'markupDeclaration';
7447                  }
7448                  else if (char === "/") {
7449                      this.state = 'endTagOpen';
7450                  }
7451                  else if (isAlpha(char)) {
7452                      this.state = 'tagName';
7453                      this.delegate.beginStartTag();
7454                      this.delegate.appendToTagName(char.toLowerCase());
7455                  }
7456              },
7457              markupDeclaration: function () {
7458                  var char = this.consume();
7459                  if (char === "-" && this.input.charAt(this.index) === "-") {
7460                      this.consume();
7461                      this.state = 'commentStart';
7462                      this.delegate.beginComment();
7463                  }
7464              },
7465              commentStart: function () {
7466                  var char = this.consume();
7467                  if (char === "-") {
7468                      this.state = 'commentStartDash';
7469                  }
7470                  else if (char === ">") {
7471                      this.delegate.finishComment();
7472                      this.state = 'beforeData';
7473                  }
7474                  else {
7475                      this.delegate.appendToCommentData(char);
7476                      this.state = 'comment';
7477                  }
7478              },
7479              commentStartDash: function () {
7480                  var char = this.consume();
7481                  if (char === "-") {
7482                      this.state = 'commentEnd';
7483                  }
7484                  else if (char === ">") {
7485                      this.delegate.finishComment();
7486                      this.state = 'beforeData';
7487                  }
7488                  else {
7489                      this.delegate.appendToCommentData("-");
7490                      this.state = 'comment';
7491                  }
7492              },
7493              comment: function () {
7494                  var char = this.consume();
7495                  if (char === "-") {
7496                      this.state = 'commentEndDash';
7497                  }
7498                  else {
7499                      this.delegate.appendToCommentData(char);
7500                  }
7501              },
7502              commentEndDash: function () {
7503                  var char = this.consume();
7504                  if (char === "-") {
7505                      this.state = 'commentEnd';
7506                  }
7507                  else {
7508                      this.delegate.appendToCommentData("-" + char);
7509                      this.state = 'comment';
7510                  }
7511              },
7512              commentEnd: function () {
7513                  var char = this.consume();
7514                  if (char === ">") {
7515                      this.delegate.finishComment();
7516                      this.state = 'beforeData';
7517                  }
7518                  else {
7519                      this.delegate.appendToCommentData("--" + char);
7520                      this.state = 'comment';
7521                  }
7522              },
7523              tagName: function () {
7524                  var char = this.consume();
7525                  if (isSpace(char)) {
7526                      this.state = 'beforeAttributeName';
7527                  }
7528                  else if (char === "/") {
7529                      this.state = 'selfClosingStartTag';
7530                  }
7531                  else if (char === ">") {
7532                      this.delegate.finishTag();
7533                      this.state = 'beforeData';
7534                  }
7535                  else {
7536                      this.delegate.appendToTagName(char);
7537                  }
7538              },
7539              beforeAttributeName: function () {
7540                  var char = this.peek();
7541                  if (isSpace(char)) {
7542                      this.consume();
7543                      return;
7544                  }
7545                  else if (char === "/") {
7546                      this.state = 'selfClosingStartTag';
7547                      this.consume();
7548                  }
7549                  else if (char === ">") {
7550                      this.consume();
7551                      this.delegate.finishTag();
7552                      this.state = 'beforeData';
7553                  }
7554                  else if (char === '=') {
7555                      this.delegate.reportSyntaxError("attribute name cannot start with equals sign");
7556                      this.state = 'attributeName';
7557                      this.delegate.beginAttribute();
7558                      this.consume();
7559                      this.delegate.appendToAttributeName(char);
7560                  }
7561                  else {
7562                      this.state = 'attributeName';
7563                      this.delegate.beginAttribute();
7564                  }
7565              },
7566              attributeName: function () {
7567                  var char = this.peek();
7568                  if (isSpace(char)) {
7569                      this.state = 'afterAttributeName';
7570                      this.consume();
7571                  }
7572                  else if (char === "/") {
7573                      this.delegate.beginAttributeValue(false);
7574                      this.delegate.finishAttributeValue();
7575                      this.consume();
7576                      this.state = 'selfClosingStartTag';
7577                  }
7578                  else if (char === "=") {
7579                      this.state = 'beforeAttributeValue';
7580                      this.consume();
7581                  }
7582                  else if (char === ">") {
7583                      this.delegate.beginAttributeValue(false);
7584                      this.delegate.finishAttributeValue();
7585                      this.consume();
7586                      this.delegate.finishTag();
7587                      this.state = 'beforeData';
7588                  }
7589                  else if (char === '"' || char === "'" || char === '<') {
7590                      this.delegate.reportSyntaxError(char + " is not a valid character within attribute names");
7591                      this.consume();
7592                      this.delegate.appendToAttributeName(char);
7593                  }
7594                  else {
7595                      this.consume();
7596                      this.delegate.appendToAttributeName(char);
7597                  }
7598              },
7599              afterAttributeName: function () {
7600                  var char = this.peek();
7601                  if (isSpace(char)) {
7602                      this.consume();
7603                      return;
7604                  }
7605                  else if (char === "/") {
7606                      this.delegate.beginAttributeValue(false);
7607                      this.delegate.finishAttributeValue();
7608                      this.consume();
7609                      this.state = 'selfClosingStartTag';
7610                  }
7611                  else if (char === "=") {
7612                      this.consume();
7613                      this.state = 'beforeAttributeValue';
7614                  }
7615                  else if (char === ">") {
7616                      this.delegate.beginAttributeValue(false);
7617                      this.delegate.finishAttributeValue();
7618                      this.consume();
7619                      this.delegate.finishTag();
7620                      this.state = 'beforeData';
7621                  }
7622                  else {
7623                      this.delegate.beginAttributeValue(false);
7624                      this.delegate.finishAttributeValue();
7625                      this.consume();
7626                      this.state = 'attributeName';
7627                      this.delegate.beginAttribute();
7628                      this.delegate.appendToAttributeName(char);
7629                  }
7630              },
7631              beforeAttributeValue: function () {
7632                  var char = this.peek();
7633                  if (isSpace(char)) {
7634                      this.consume();
7635                  }
7636                  else if (char === '"') {
7637                      this.state = 'attributeValueDoubleQuoted';
7638                      this.delegate.beginAttributeValue(true);
7639                      this.consume();
7640                  }
7641                  else if (char === "'") {
7642                      this.state = 'attributeValueSingleQuoted';
7643                      this.delegate.beginAttributeValue(true);
7644                      this.consume();
7645                  }
7646                  else if (char === ">") {
7647                      this.delegate.beginAttributeValue(false);
7648                      this.delegate.finishAttributeValue();
7649                      this.consume();
7650                      this.delegate.finishTag();
7651                      this.state = 'beforeData';
7652                  }
7653                  else {
7654                      this.state = 'attributeValueUnquoted';
7655                      this.delegate.beginAttributeValue(false);
7656                      this.consume();
7657                      this.delegate.appendToAttributeValue(char);
7658                  }
7659              },
7660              attributeValueDoubleQuoted: function () {
7661                  var char = this.consume();
7662                  if (char === '"') {
7663                      this.delegate.finishAttributeValue();
7664                      this.state = 'afterAttributeValueQuoted';
7665                  }
7666                  else if (char === "&") {
7667                      this.delegate.appendToAttributeValue(this.consumeCharRef('"') || "&");
7668                  }
7669                  else {
7670                      this.delegate.appendToAttributeValue(char);
7671                  }
7672              },
7673              attributeValueSingleQuoted: function () {
7674                  var char = this.consume();
7675                  if (char === "'") {
7676                      this.delegate.finishAttributeValue();
7677                      this.state = 'afterAttributeValueQuoted';
7678                  }
7679                  else if (char === "&") {
7680                      this.delegate.appendToAttributeValue(this.consumeCharRef("'") || "&");
7681                  }
7682                  else {
7683                      this.delegate.appendToAttributeValue(char);
7684                  }
7685              },
7686              attributeValueUnquoted: function () {
7687                  var char = this.peek();
7688                  if (isSpace(char)) {
7689                      this.delegate.finishAttributeValue();
7690                      this.consume();
7691                      this.state = 'beforeAttributeName';
7692                  }
7693                  else if (char === "&") {
7694                      this.consume();
7695                      this.delegate.appendToAttributeValue(this.consumeCharRef(">") || "&");
7696                  }
7697                  else if (char === ">") {
7698                      this.delegate.finishAttributeValue();
7699                      this.consume();
7700                      this.delegate.finishTag();
7701                      this.state = 'beforeData';
7702                  }
7703                  else {
7704                      this.consume();
7705                      this.delegate.appendToAttributeValue(char);
7706                  }
7707              },
7708              afterAttributeValueQuoted: function () {
7709                  var char = this.peek();
7710                  if (isSpace(char)) {
7711                      this.consume();
7712                      this.state = 'beforeAttributeName';
7713                  }
7714                  else if (char === "/") {
7715                      this.consume();
7716                      this.state = 'selfClosingStartTag';
7717                  }
7718                  else if (char === ">") {
7719                      this.consume();
7720                      this.delegate.finishTag();
7721                      this.state = 'beforeData';
7722                  }
7723                  else {
7724                      this.state = 'beforeAttributeName';
7725                  }
7726              },
7727              selfClosingStartTag: function () {
7728                  var char = this.peek();
7729                  if (char === ">") {
7730                      this.consume();
7731                      this.delegate.markTagAsSelfClosing();
7732                      this.delegate.finishTag();
7733                      this.state = 'beforeData';
7734                  }
7735                  else {
7736                      this.state = 'beforeAttributeName';
7737                  }
7738              },
7739              endTagOpen: function () {
7740                  var char = this.consume();
7741                  if (isAlpha(char)) {
7742                      this.state = 'tagName';
7743                      this.delegate.beginEndTag();
7744                      this.delegate.appendToTagName(char.toLowerCase());
7745                  }
7746              }
7747          };
7748          this.reset();
7749      }
7750      EventedTokenizer.prototype.reset = function () {
7751          this.state = 'beforeData';
7752          this.input = '';
7753          this.index = 0;
7754          this.line = 1;
7755          this.column = 0;
7756          this.tagLine = -1;
7757          this.tagColumn = -1;
7758          this.delegate.reset();
7759      };
7760      EventedTokenizer.prototype.tokenize = function (input) {
7761          this.reset();
7762          this.tokenizePart(input);
7763          this.tokenizeEOF();
7764      };
7765      EventedTokenizer.prototype.tokenizePart = function (input) {
7766          this.input += preprocessInput(input);
7767          while (this.index < this.input.length) {
7768              this.states[this.state].call(this);
7769          }
7770      };
7771      EventedTokenizer.prototype.tokenizeEOF = function () {
7772          this.flushData();
7773      };
7774      EventedTokenizer.prototype.flushData = function () {
7775          if (this.state === 'data') {
7776              this.delegate.finishData();
7777              this.state = 'beforeData';
7778          }
7779      };
7780      EventedTokenizer.prototype.peek = function () {
7781          return this.input.charAt(this.index);
7782      };
7783      EventedTokenizer.prototype.consume = function () {
7784          var char = this.peek();
7785          this.index++;
7786          if (char === "\n") {
7787              this.line++;
7788              this.column = 0;
7789          }
7790          else {
7791              this.column++;
7792          }
7793          return char;
7794      };
7795      EventedTokenizer.prototype.consumeCharRef = function () {
7796          var endIndex = this.input.indexOf(';', this.index);
7797          if (endIndex === -1) {
7798              return;
7799          }
7800          var entity = this.input.slice(this.index, endIndex);
7801          var chars = this.entityParser.parse(entity);
7802          if (chars) {
7803              var count = entity.length;
7804              // consume the entity chars
7805              while (count) {
7806                  this.consume();
7807                  count--;
7808              }
7809              // consume the `;`
7810              this.consume();
7811              return chars;
7812          }
7813      };
7814      EventedTokenizer.prototype.markTagStart = function () {
7815          // these properties to be removed in next major bump
7816          this.tagLine = this.line;
7817          this.tagColumn = this.column;
7818          if (this.delegate.tagOpen) {
7819              this.delegate.tagOpen();
7820          }
7821      };
7822      return EventedTokenizer;
7823  }());
7824  /* harmony default export */ var evented_tokenizer = (evented_tokenizer_EventedTokenizer);
7825  
7826  // CONCATENATED MODULE: ./node_modules/simple-html-tokenizer/dist/es6/tokenizer.js
7827  
7828  
7829  ;
7830  var tokenizer_Tokenizer = /** @class */ (function () {
7831      function Tokenizer(entityParser, options) {
7832          if (options === void 0) { options = {}; }
7833          this.options = options;
7834          this._token = null;
7835          this.startLine = 1;
7836          this.startColumn = 0;
7837          this.tokens = [];
7838          this.currentAttribute = null;
7839          this.tokenizer = new evented_tokenizer(this, entityParser);
7840      }
7841      Object.defineProperty(Tokenizer.prototype, "token", {
7842          get: function () {
7843              return unwrap(this._token);
7844          },
7845          set: function (value) {
7846              this._token = value;
7847          },
7848          enumerable: true,
7849          configurable: true
7850      });
7851      Tokenizer.prototype.tokenize = function (input) {
7852          this.tokens = [];
7853          this.tokenizer.tokenize(input);
7854          return this.tokens;
7855      };
7856      Tokenizer.prototype.tokenizePart = function (input) {
7857          this.tokens = [];
7858          this.tokenizer.tokenizePart(input);
7859          return this.tokens;
7860      };
7861      Tokenizer.prototype.tokenizeEOF = function () {
7862          this.tokens = [];
7863          this.tokenizer.tokenizeEOF();
7864          return this.tokens[0];
7865      };
7866      Tokenizer.prototype.reset = function () {
7867          this._token = null;
7868          this.startLine = 1;
7869          this.startColumn = 0;
7870      };
7871      Tokenizer.prototype.addLocInfo = function () {
7872          if (this.options.loc) {
7873              this.token.loc = {
7874                  start: {
7875                      line: this.startLine,
7876                      column: this.startColumn
7877                  },
7878                  end: {
7879                      line: this.tokenizer.line,
7880                      column: this.tokenizer.column
7881                  }
7882              };
7883          }
7884          this.startLine = this.tokenizer.line;
7885          this.startColumn = this.tokenizer.column;
7886      };
7887      // Data
7888      Tokenizer.prototype.beginData = function () {
7889          this.token = {
7890              type: 'Chars',
7891              chars: ''
7892          };
7893          this.tokens.push(this.token);
7894      };
7895      Tokenizer.prototype.appendToData = function (char) {
7896          this.token.chars += char;
7897      };
7898      Tokenizer.prototype.finishData = function () {
7899          this.addLocInfo();
7900      };
7901      // Comment
7902      Tokenizer.prototype.beginComment = function () {
7903          this.token = {
7904              type: 'Comment',
7905              chars: ''
7906          };
7907          this.tokens.push(this.token);
7908      };
7909      Tokenizer.prototype.appendToCommentData = function (char) {
7910          this.token.chars += char;
7911      };
7912      Tokenizer.prototype.finishComment = function () {
7913          this.addLocInfo();
7914      };
7915      // Tags - basic
7916      Tokenizer.prototype.beginStartTag = function () {
7917          this.token = {
7918              type: 'StartTag',
7919              tagName: '',
7920              attributes: [],
7921              selfClosing: false
7922          };
7923          this.tokens.push(this.token);
7924      };
7925      Tokenizer.prototype.beginEndTag = function () {
7926          this.token = {
7927              type: 'EndTag',
7928              tagName: ''
7929          };
7930          this.tokens.push(this.token);
7931      };
7932      Tokenizer.prototype.finishTag = function () {
7933          this.addLocInfo();
7934      };
7935      Tokenizer.prototype.markTagAsSelfClosing = function () {
7936          this.token.selfClosing = true;
7937      };
7938      // Tags - name
7939      Tokenizer.prototype.appendToTagName = function (char) {
7940          this.token.tagName += char;
7941      };
7942      // Tags - attributes
7943      Tokenizer.prototype.beginAttribute = function () {
7944          var attributes = unwrap(this.token.attributes, "current token's attributs");
7945          this.currentAttribute = ["", "", false];
7946          attributes.push(this.currentAttribute);
7947      };
7948      Tokenizer.prototype.appendToAttributeName = function (char) {
7949          var currentAttribute = unwrap(this.currentAttribute);
7950          currentAttribute[0] += char;
7951      };
7952      Tokenizer.prototype.beginAttributeValue = function (isQuoted) {
7953          var currentAttribute = unwrap(this.currentAttribute);
7954          currentAttribute[2] = isQuoted;
7955      };
7956      Tokenizer.prototype.appendToAttributeValue = function (char) {
7957          var currentAttribute = unwrap(this.currentAttribute);
7958          currentAttribute[1] = currentAttribute[1] || "";
7959          currentAttribute[1] += char;
7960      };
7961      Tokenizer.prototype.finishAttributeValue = function () {
7962      };
7963      Tokenizer.prototype.reportSyntaxError = function (message) {
7964          this.token.syntaxError = message;
7965      };
7966      return Tokenizer;
7967  }());
7968  /* harmony default export */ var tokenizer = (tokenizer_Tokenizer);
7969  
7970  // EXTERNAL MODULE: external {"this":["wp","htmlEntities"]}
7971  var external_this_wp_htmlEntities_ = __webpack_require__(56);
7972  
7973  // EXTERNAL MODULE: external {"this":["wp","isShallowEqual"]}
7974  var external_this_wp_isShallowEqual_ = __webpack_require__(42);
7975  var external_this_wp_isShallowEqual_default = /*#__PURE__*/__webpack_require__.n(external_this_wp_isShallowEqual_);
7976  
7977  // EXTERNAL MODULE: ./node_modules/@babel/runtime/helpers/esm/extends.js
7978  var esm_extends = __webpack_require__(19);
7979  
7980  // EXTERNAL MODULE: external {"this":["wp","compose"]}
7981  var external_this_wp_compose_ = __webpack_require__(6);
7982  
7983  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/block-content-provider/index.js
7984  
7985  
7986  
7987  /**
7988   * WordPress dependencies
7989   */
7990  
7991  
7992  /**
7993   * Internal dependencies
7994   */
7995  
7996  
7997  
7998  var _createContext = Object(external_this_wp_element_["createContext"])(function () {}),
7999      Consumer = _createContext.Consumer,
8000      Provider = _createContext.Provider;
8001  /**
8002   * An internal block component used in block content serialization to inject
8003   * nested block content within the `save` implementation of the ancestor
8004   * component in which it is nested. The component provides a pre-bound
8005   * `BlockContent` component via context, which is used by the developer-facing
8006   * `InnerBlocks.Content` component to render block content.
8007   *
8008   * @example
8009   *
8010   * ```jsx
8011   * <BlockContentProvider innerBlocks={ innerBlocks }>
8012   *     { blockSaveElement }
8013   * </BlockContentProvider>
8014   * ```
8015   *
8016   * @return {WPElement} Element with BlockContent injected via context.
8017   */
8018  
8019  
8020  var block_content_provider_BlockContentProvider = function BlockContentProvider(_ref) {
8021    var children = _ref.children,
8022        innerBlocks = _ref.innerBlocks;
8023  
8024    var BlockContent = function BlockContent() {
8025      // Value is an array of blocks, so defer to block serializer
8026      var html = serialize(innerBlocks); // Use special-cased raw HTML tag to avoid default escaping
8027  
8028      return Object(external_this_wp_element_["createElement"])(external_this_wp_element_["RawHTML"], null, html);
8029    };
8030  
8031    return Object(external_this_wp_element_["createElement"])(Provider, {
8032      value: BlockContent
8033    }, children);
8034  };
8035  /**
8036   * A Higher Order Component used to inject BlockContent using context to the
8037   * wrapped component.
8038   *
8039   * @return {Component} Enhanced component with injected BlockContent as prop.
8040   */
8041  
8042  
8043  var withBlockContentContext = Object(external_this_wp_compose_["createHigherOrderComponent"])(function (OriginalComponent) {
8044    return function (props) {
8045      return Object(external_this_wp_element_["createElement"])(Consumer, null, function (context) {
8046        return Object(external_this_wp_element_["createElement"])(OriginalComponent, Object(esm_extends["a" /* default */])({}, props, {
8047          BlockContent: context
8048        }));
8049      });
8050    };
8051  }, 'withBlockContentContext');
8052  /* harmony default export */ var block_content_provider = (block_content_provider_BlockContentProvider);
8053  
8054  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/serializer.js
8055  
8056  
8057  
8058  /**
8059   * External dependencies
8060   */
8061  
8062  /**
8063   * WordPress dependencies
8064   */
8065  
8066  
8067  
8068  
8069  /**
8070   * Internal dependencies
8071   */
8072  
8073  
8074  
8075  
8076  /**
8077   * Returns the block's default classname from its name.
8078   *
8079   * @param {string} blockName The block name.
8080   *
8081   * @return {string} The block's default class.
8082   */
8083  
8084  function getBlockDefaultClassName(blockName) {
8085    // Generated HTML classes for blocks follow the `wp-block-{name}` nomenclature.
8086    // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (used in 'core-embed/').
8087    var className = 'wp-block-' + blockName.replace(/\//, '-').replace(/^core-/, '');
8088    return Object(external_this_wp_hooks_["applyFilters"])('blocks.getBlockDefaultClassName', className, blockName);
8089  }
8090  /**
8091   * Returns the block's default menu item classname from its name.
8092   *
8093   * @param {string} blockName The block name.
8094   *
8095   * @return {string} The block's default menu item class.
8096   */
8097  
8098  function getBlockMenuDefaultClassName(blockName) {
8099    // Generated HTML classes for blocks follow the `editor-block-list-item-{name}` nomenclature.
8100    // Blocks provided by WordPress drop the prefixes 'core/' or 'core-' (used in 'core-embed/').
8101    var className = 'editor-block-list-item-' + blockName.replace(/\//, '-').replace(/^core-/, '');
8102    return Object(external_this_wp_hooks_["applyFilters"])('blocks.getBlockMenuDefaultClassName', className, blockName);
8103  }
8104  /**
8105   * Given a block type containing a save render implementation and attributes, returns the
8106   * enhanced element to be saved or string when raw HTML expected.
8107   *
8108   * @param {string|Object} blockTypeOrName   Block type or name.
8109   * @param {Object}        attributes        Block attributes.
8110   * @param {?Array}        innerBlocks       Nested blocks.
8111   *
8112   * @return {Object|string} Save element or raw HTML string.
8113   */
8114  
8115  function getSaveElement(blockTypeOrName, attributes) {
8116    var innerBlocks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
8117    var blockType = normalizeBlockType(blockTypeOrName);
8118    var save = blockType.save; // Component classes are unsupported for save since serialization must
8119    // occur synchronously. For improved interoperability with higher-order
8120    // components which often return component class, emulate basic support.
8121  
8122    if (save.prototype instanceof external_this_wp_element_["Component"]) {
8123      var instance = new save({
8124        attributes: attributes
8125      });
8126      save = instance.render.bind(instance);
8127    }
8128  
8129    var element = save({
8130      attributes: attributes,
8131      innerBlocks: innerBlocks
8132    });
8133  
8134    if (Object(external_lodash_["isObject"])(element) && Object(external_this_wp_hooks_["hasFilter"])('blocks.getSaveContent.extraProps')) {
8135      /**
8136       * Filters the props applied to the block save result element.
8137       *
8138       * @param {Object}      props      Props applied to save element.
8139       * @param {WPBlockType} blockType  Block type definition.
8140       * @param {Object}      attributes Block attributes.
8141       */
8142      var props = Object(external_this_wp_hooks_["applyFilters"])('blocks.getSaveContent.extraProps', Object(objectSpread["a" /* default */])({}, element.props), blockType, attributes);
8143  
8144      if (!external_this_wp_isShallowEqual_default()(props, element.props)) {
8145        element = Object(external_this_wp_element_["cloneElement"])(element, props);
8146      }
8147    }
8148    /**
8149     * Filters the save result of a block during serialization.
8150     *
8151     * @param {WPElement}   element    Block save result.
8152     * @param {WPBlockType} blockType  Block type definition.
8153     * @param {Object}      attributes Block attributes.
8154     */
8155  
8156  
8157    element = Object(external_this_wp_hooks_["applyFilters"])('blocks.getSaveElement', element, blockType, attributes);
8158    return Object(external_this_wp_element_["createElement"])(block_content_provider, {
8159      innerBlocks: innerBlocks
8160    }, element);
8161  }
8162  /**
8163   * Given a block type containing a save render implementation and attributes, returns the
8164   * static markup to be saved.
8165   *
8166   * @param {string|Object} blockTypeOrName Block type or name.
8167   * @param {Object}        attributes      Block attributes.
8168   * @param {?Array}        innerBlocks     Nested blocks.
8169   *
8170   * @return {string} Save content.
8171   */
8172  
8173  function getSaveContent(blockTypeOrName, attributes, innerBlocks) {
8174    var blockType = normalizeBlockType(blockTypeOrName);
8175    return Object(external_this_wp_element_["renderToString"])(getSaveElement(blockType, attributes, innerBlocks));
8176  }
8177  /**
8178   * Returns attributes which are to be saved and serialized into the block
8179   * comment delimiter.
8180   *
8181   * When a block exists in memory it contains as its attributes both those
8182   * parsed the block comment delimiter _and_ those which matched from the
8183   * contents of the block.
8184   *
8185   * This function returns only those attributes which are needed to persist and
8186   * which cannot be matched from the block content.
8187   *
8188   * @param {Object<string,*>} blockType     Block type.
8189   * @param {Object<string,*>} attributes Attributes from in-memory block data.
8190   *
8191   * @return {Object<string,*>} Subset of attributes for comment serialization.
8192   */
8193  
8194  function getCommentAttributes(blockType, attributes) {
8195    return Object(external_lodash_["reduce"])(blockType.attributes, function (result, attributeSchema, key) {
8196      var value = attributes[key]; // Ignore undefined values.
8197  
8198      if (undefined === value) {
8199        return result;
8200      } // Ignore all attributes but the ones with an "undefined" source
8201      // "undefined" source refers to attributes saved in the block comment.
8202  
8203  
8204      if (attributeSchema.source !== undefined) {
8205        return result;
8206      } // Ignore default value.
8207  
8208  
8209      if ('default' in attributeSchema && attributeSchema.default === value) {
8210        return result;
8211      } // Otherwise, include in comment set.
8212  
8213  
8214      result[key] = value;
8215      return result;
8216    }, {});
8217  }
8218  /**
8219   * Given an attributes object, returns a string in the serialized attributes
8220   * format prepared for post content.
8221   *
8222   * @param {Object} attributes Attributes object.
8223   *
8224   * @return {string} Serialized attributes.
8225   */
8226  
8227  function serializeAttributes(attributes) {
8228    return JSON.stringify(attributes) // Don't break HTML comments.
8229    .replace(/--/g, "\\u002d\\u002d") // Don't break non-standard-compliant tools.
8230    .replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026") // Bypass server stripslashes behavior which would unescape stringify's
8231    // escaping of quotation mark.
8232    //
8233    // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
8234    .replace(/\\"/g, "\\u0022");
8235  }
8236  /**
8237   * Given a block object, returns the Block's Inner HTML markup.
8238   *
8239   * @param {Object} block Block instance.
8240   *
8241   * @return {string} HTML.
8242   */
8243  
8244  function getBlockContent(block) {
8245    // @todo why not getBlockInnerHtml?
8246    // If block was parsed as invalid or encounters an error while generating
8247    // save content, use original content instead to avoid content loss. If a
8248    // block contains nested content, exempt it from this condition because we
8249    // otherwise have no access to its original content and content loss would
8250    // still occur.
8251    var saveContent = block.originalContent;
8252  
8253    if (block.isValid || block.innerBlocks.length) {
8254      try {
8255        saveContent = getSaveContent(block.name, block.attributes, block.innerBlocks);
8256      } catch (error) {}
8257    }
8258  
8259    return saveContent;
8260  }
8261  /**
8262   * Returns the content of a block, including comment delimiters.
8263   *
8264   * @param {string} rawBlockName Block name.
8265   * @param {Object} attributes   Block attributes.
8266   * @param {string} content      Block save content.
8267   *
8268   * @return {string} Comment-delimited block content.
8269   */
8270  
8271  function getCommentDelimitedContent(rawBlockName, attributes, content) {
8272    var serializedAttributes = !Object(external_lodash_["isEmpty"])(attributes) ? serializeAttributes(attributes) + ' ' : ''; // Strip core blocks of their namespace prefix.
8273  
8274    var blockName = Object(external_lodash_["startsWith"])(rawBlockName, 'core/') ? rawBlockName.slice(5) : rawBlockName; // @todo make the `wp:` prefix potentially configurable.
8275  
8276    if (!content) {
8277      return "<!-- wp:".concat(blockName, " ").concat(serializedAttributes, "/-->");
8278    }
8279  
8280    return "<!-- wp:".concat(blockName, " ").concat(serializedAttributes, "-->\n") + content + "\n<!-- /wp:".concat(blockName, " -->");
8281  }
8282  /**
8283   * Returns the content of a block, including comment delimiters, determining
8284   * serialized attributes and content form from the current state of the block.
8285   *
8286   * @param {Object} block Block instance.
8287   *
8288   * @return {string} Serialized block.
8289   */
8290  
8291  function serializeBlock(block) {
8292    var blockName = block.name;
8293    var saveContent = getBlockContent(block);
8294  
8295    switch (blockName) {
8296      case getFreeformContentHandlerName():
8297      case getUnregisteredTypeHandlerName():
8298        return saveContent;
8299  
8300      default:
8301        {
8302          var blockType = registration_getBlockType(blockName);
8303          var saveAttributes = getCommentAttributes(blockType, block.attributes);
8304          return getCommentDelimitedContent(blockName, saveAttributes, saveContent);
8305        }
8306    }
8307  }
8308  /**
8309   * Takes a block or set of blocks and returns the serialized post content.
8310   *
8311   * @param {Array} blocks Block(s) to serialize.
8312   *
8313   * @return {string} The post content.
8314   */
8315  
8316  function serialize(blocks) {
8317    return Object(external_lodash_["castArray"])(blocks).map(serializeBlock).join('\n\n');
8318  }
8319  
8320  // CONCATENATED MODULE: ./node_modules/@wordpress/blocks/build-module/api/validation.js
8321  
8322  
8323  
8324  
8325  
8326  
8327  
8328  /**
8329   * External dependencies
8330   */
8331  
8332  
8333  /**
8334   * WordPress dependencies
8335   */
8336  
8337  
8338  /**
8339   * Internal dependencies
8340   */
8341  
8342  
8343  
8344  /**
8345   * Globally matches any consecutive whitespace
8346   *
8347   * @type {RegExp}
8348   */
8349  
8350  var REGEXP_WHITESPACE = /[\t\n\r\v\f ]+/g;
8351  /**
8352   * Matches a string containing only whitespace
8353   *
8354   * @type {RegExp}
8355   */
8356  
8357  var REGEXP_ONLY_WHITESPACE = /^[\t\n\r\v\f ]*$/;
8358  /**
8359   * Matches a CSS URL type value
8360   *
8361   * @type {RegExp}
8362   */
8363  
8364  var REGEXP_STYLE_URL_TYPE = /^url\s*\(['"\s]*(.*?)['"\s]*\)$/;
8365  /**
8366   * Boolean attributes are attributes whose presence as being assigned is
8367   * meaningful, even if only empty.
8368   *
8369   * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
8370   * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
8371   *
8372   * Object.keys( [ ...document.querySelectorAll( '#attributes-1 > tbody > tr' ) ]
8373   *     .filter( ( tr ) => tr.lastChild.textContent.indexOf( 'Boolean attribute' ) !== -1 )
8374   *     .reduce( ( result, tr ) => Object.assign( result, {
8375   *         [ tr.firstChild.textContent.trim() ]: true
8376   *     } ), {} ) ).sort();
8377   *
8378   * @type {Array}
8379   */
8380  
8381  var 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'];
8382  /**
8383   * Enumerated attributes are attributes which must be of a specific value form.
8384   * Like boolean attributes, these are meaningful if specified, even if not of a
8385   * valid enumerated value.
8386   *
8387   * See: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute
8388   * Extracted from: https://html.spec.whatwg.org/multipage/indices.html#attributes-3
8389   *
8390   * Object.keys( [ ...document.querySelectorAll( '#attributes-1 > tbody > tr' ) ]
8391   *     .filter( ( tr ) => /^("(.+?)";?\s*)+/.test( tr.lastChild.textContent.trim() ) )
8392   *     .reduce( ( result, tr ) => Object.assign( result, {
8393   *         [ tr.firstChild.textContent.trim() ]: true
8394   *     } ), {} ) ).sort();
8395   *
8396   * @type {Array}
8397   */
8398  
8399  var 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'];
8400  /**
8401   * Meaningful attributes are those who cannot be safely ignored when omitted in
8402   * one HTML markup string and not another.
8403   *
8404   * @type {Array}
8405   */
8406  
8407  var MEANINGFUL_ATTRIBUTES = [].concat(BOOLEAN_ATTRIBUTES, ENUMERATED_ATTRIBUTES);
8408  /**
8409   * Array of functions which receive a text string on which to apply normalizing
8410   * behavior for consideration in text token equivalence, carefully ordered from
8411   * least-to-most expensive operations.
8412   *
8413   * @type {Array}
8414   */
8415  
8416  var TEXT_NORMALIZATIONS = [external_lodash_["identity"], getTextWithCollapsedWhitespace];
8417  /**
8418   * Regular expression matching a named character reference. In lieu of bundling
8419   * a full set of references, the pattern covers the minimal necessary to test
8420   * positively against the full set.
8421   *
8422   * "The ampersand must be followed by one of the names given in the named
8423   * character references section, using the same case."
8424   *
8425   * Tested aginst "12.5 Named character references":
8426   *
8427   * ```
8428   * const references = [ ...document.querySelectorAll(
8429   *     '#named-character-references-table tr[id^=entity-] td:first-child'
8430   * ) ].map( ( code ) => code.textContent )
8431   * references.every( ( reference ) => /^[\da-z]+$/i.test( reference ) )
8432   * ```
8433   *
8434   * @link https://html.spec.whatwg.org/multipage/syntax.html#character-references
8435   * @link https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
8436   *
8437   * @type {RegExp}
8438   */
8439  
8440  var REGEXP_NAMED_CHARACTER_REFERENCE = /^[\da-z]+$/i;
8441  /**
8442   * Regular expression matching a decimal character reference.
8443   *
8444   * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#),
8445   * followed by one or more ASCII digits, representing a base-ten integer"
8446   *
8447   * @link https://html.spec.whatwg.org/multipage/syntax.html#character-references
8448   *
8449   * @type {RegExp}
8450   */
8451  
8452  var REGEXP_DECIMAL_CHARACTER_REFERENCE = /^#\d+$/;
8453  /**
8454   * Regular expression matching a hexadecimal character reference.
8455   *
8456   * "The ampersand must be followed by a U+0023 NUMBER SIGN character (#), which
8457   * must be followed by either a U+0078 LATIN SMALL LETTER X character (x) or a
8458   * U+0058 LATIN CAPITAL LETTER X character (X), which must then be followed by
8459   * one or more ASCII hex digits, representing a hexadecimal integer"
8460   *
8461   * @link https://html.spec.whatwg.org/multipage/syntax.html#character-references
8462   *
8463   * @type {RegExp}
8464   */
8465  
8466  var REGEXP_HEXADECIMAL_CHARACTER_REFERENCE = /^#x[\da-f]+$/i;
8467  /**
8468   * Returns true if the given string is a valid character reference segment, or
8469   * false otherwise. The text should be stripped of `&` and `;` demarcations.
8470   *
8471   * @param {string} text Text to test.
8472   *
8473   * @return {boolean} Whether text is valid character reference.
8474   */
8475  
8476  function isValidCharacterReference(text) {
8477    return REGEXP_NAMED_CHARACTER_REFERENCE.test(text) || REGEXP_DECIMAL_CHARACTER_REFERENCE.test(text) || REGEXP_HEXADECIMAL_CHARACTER_REFERENCE.test(text);
8478  }
8479  /**
8480   * Subsitute EntityParser class for `simple-html-tokenizer` which uses the
8481   * implementation of `decodeEntities` from `html-entities`, in order to avoid
8482   * bundling a massive named character reference.
8483   *
8484   * @see https://github.com/tildeio/simple-html-tokenizer/tree/master/src/entity-parser.ts
8485   */
8486  
8487  var validation_DecodeEntityParser =
8488  /*#__PURE__*/
8489  function () {
8490    function DecodeEntityParser() {
8491      Object(classCallCheck["a" /* default */])(this, DecodeEntityParser);
8492    }
8493  
8494    Object(createClass["a" /* default */])(DecodeEntityParser, [{
8495      key: "parse",
8496  
8497      /**
8498       * Returns a substitute string for an entity string sequence between `&`
8499       * and `;`, or undefined if no substitution should occur.
8500       *
8501       * @param {string} entity Entity fragment discovered in HTML.
8502       *
8503       * @return {?string} Entity substitute value.
8504       */
8505      value: function parse(entity) {
8506        if (isValidCharacterReference(entity)) {
8507          return Object(external_this_wp_htmlEntities_["decodeEntities"])('&' + entity + ';');
8508        }
8509      }
8510    }]);
8511  
8512    return DecodeEntityParser;
8513  }();
8514  /**
8515   * Object of logger functions.
8516   */
8517  
8518  var log = function () {
8519    /**
8520     * Creates a logger with block validation prefix.
8521     *
8522     * @param {Function} logger Original logger function.
8523     *
8524     * @return {Function} Augmented logger function.
8525     */
8526    function createLogger(logger) {
8527      // In test environments, pre-process the sprintf message to improve
8528      // readability of error messages. We'd prefer to avoid pulling in this
8529      // dependency in runtime environments, and it can be dropped by a combo
8530      // of Webpack env substitution + UglifyJS dead code elimination.
8531      if (false) {}
8532  
8533      return function (message) {
8534        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
8535          args[_key - 1] = arguments[_key];
8536        }
8537  
8538        return logger.apply(void 0, ['Block validation: ' + message].concat(args));
8539      };
8540    }
8541  
8542    return {
8543      /* eslint-disable no-console */
8544      error: createLogger(console.error),
8545      warning: createLogger(console.warn)
8546      /* eslint-enable no-console */
8547  
8548    };
8549  }();
8550  /**
8551   * Given a specified string, returns an array of strings split by consecutive
8552   * whitespace, ignoring leading or trailing whitespace.
8553   *
8554   * @param {string} text Original text.
8555   *
8556   * @return {string[]} Text pieces split on whitespace.
8557   */
8558  
8559  
8560  function getTextPiecesSplitOnWhitespace(text) {
8561    return text.trim().split(REGEXP_WHITESPACE);
8562  }
8563  /**
8564   * Given a specified string, returns a new trimmed string where all consecutive
8565   * whitespace is collapsed to a single space.
8566   *
8567   * @param {string} text Original text.
8568   *
8569   * @return {string} Trimmed text with consecutive whitespace collapsed.
8570   */
8571  
8572  function getTextWithCollapsedWhitespace(text) {
8573    // This is an overly simplified whitespace comparison. The specification is
8574    // more prescriptive of whitespace behavior in inline and block contexts.
8575    //
8576    // See: https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33
8577    return getTextPiecesSplitOnWhitespace(text).join(' ');
8578  }
8579  /**
8580   * Returns attribute pairs of the given StartTag token, including only pairs
8581   * where the value is non-empty or the attribute is a boolean attribute, an
8582   * enumerated attribute, or a custom data- attribute.
8583   *
8584   * @see MEANINGFUL_ATTRIBUTES
8585   *
8586   * @param {Object} token StartTag token.
8587   *
8588   * @return {Array[]} Attribute pairs.
8589   */
8590  
8591  function getMeaningfulAttributePairs(token) {
8592    return token.attributes.filter(function (pair) {
8593      var _pair = Object(slicedToArray["a" /* default */])(pair, 2),
8594          key = _pair[0],
8595          value = _pair[1];
8596  
8597      return value || key.indexOf('data-') === 0 || Object(external_lodash_["includes"])(MEANINGFUL_ATTRIBUTES, key);
8598    });
8599  }
8600  /**
8601   * Returns true if two text tokens (with `chars` property) are equivalent, or
8602   * false otherwise.
8603   *
8604   * @param {Object} actual   Actual token.
8605   * @param {Object} expected Expected token.
8606   *
8607   * @return {boolean} Whether two text tokens are equivalent.
8608   */
8609  
8610  function isEquivalentTextTokens(actual, expected) {
8611    // This function is intentionally written as syntactically "ugly" as a hot
8612    // path optimization. Text is progressively normalized in order from least-
8613    // to-most operationally expensive, until the earliest point at which text
8614    // can be confidently inferred as being equal.
8615    var actualChars = actual.chars;
8616    var expectedChars = expected.chars;
8617  
8618    for (var i = 0; i < TEXT_NORMALIZATIONS.length; i++) {
8619      var normalize = TEXT_NORMALIZATIONS[i];
8620      actualChars = normalize(actualChars);
8621      expectedChars = normalize(expectedChars);
8622  
8623      if (actualChars === expectedChars) {
8624        return true;
8625      }
8626    }
8627  
8628    log.warning('Expected text `%s`, saw `%s`.', expected.chars, actual.chars);
8629    return false;
8630  }
8631  /**
8632   * Given a style value, returns a normalized style value for strict equality
8633   * comparison.
8634   *
8635   * @param {string} value Style value.
8636   *
8637   * @return {string} Normalized style value.
8638   */
8639  
8640  function getNormalizedStyleValue(value) {
8641    return value // Normalize URL type to omit whitespace or quotes
8642    .replace(REGEXP_STYLE_URL_TYPE, 'url($1)');
8643  }
8644  /**
8645   * Given a style attribute string, returns an object of style properties.
8646   *
8647   * @param {string} text Style attribute.
8648   *
8649   * @return {Object} Style properties.
8650   */
8651  
8652  function getStyleProperties(text) {
8653    var pairs = text // Trim ending semicolon (avoid including in split)
8654    .replace(/;?\s*$/, '') // Split on property assignment
8655    .split(';') // For each property assignment...
8656    .map(function (style) {
8657      // ...split further into key-value pairs
8658      var _style$split = style.split(':'),
8659          _style$split2 = _toArray(_style$split),
8660          key = _style$split2[0],
8661          valueParts = _style$split2.slice(1);
8662  
8663      var value = valueParts.join(':');
8664      return [key.trim(), getNormalizedStyleValue(value.trim())];
8665    });
8666    return Object(external_lodash_["fromPairs"])(pairs);
8667  }
8668  /**
8669   * Attribute-specific equality handlers
8670   *
8671   * @type {Object}
8672   */
8673  
8674  var isEqualAttributesOfName = Object(objectSpread["a" /* default */])({
8675    class: function _class(actual, expected) {
8676      // Class matches if members are the same, even if out of order or
8677      // superfluous whitespace between.
8678      return !external_lodash_["xor"].apply(void 0, Object(toConsumableArray["a" /* default */])([actual, expected].map(getTextPiecesSplitOnWhitespace))).length;
8679    },
8680    style: function style(actual, expected) {
8681      return external_lodash_["isEqual"].apply(void 0, Object(toConsumableArray["a" /* default */])([actual, expected].map(getStyleProperties)));
8682    }
8683  }, Object(external_lodash_["fromPairs"])(BOOLEAN_ATTRIBUTES.map(function (attribute) {
8684    return [attribute, external_lodash_["stubTrue"]];
8685  })));
8686  /**
8687   * Given two sets of attribute tuples, returns true if the attribute sets are
8688   * equivalent.
8689   *
8690   * @param {Array[]} actual   Actual attributes tuples.
8691   * @param {Array[]} expected Expected attributes tuples.
8692   *
8693   * @return {boolean} Whether attributes are equivalent.
8694   */
8695  
8696  function isEqualTagAttributePairs(actual, expected) {
8697    // Attributes is tokenized as tuples. Their lengths should match. This also
8698    // avoids us needing to check both attributes sets, since if A has any keys
8699    // which do not exist in B, we know the sets to be different.
8700    if (actual.length !== expected.length) {
8701      log.warning('Expected attributes %o, instead saw %o.', expected, actual);
8702      return false;
8703    } // Convert tuples to object for ease of lookup
8704  
8705  
8706    var _map = [actual, expected].map(external_lodash_["fromPairs"]),
8707        _map2 = Object(slicedToArray["a" /* default */])(_map, 2),
8708        actualAttributes = _map2[0],
8709        expectedAttributes = _map2[1];
8710  
8711    for (var name in actualAttributes) {
8712      // As noted above, if missing member in B, assume different
8713      if (!expectedAttributes.hasOwnProperty(name)) {
8714        log.warning('Encountered unexpected attribute `%s`.', name);
8715        return false;
8716      }
8717  
8718      var actualValue = actualAttributes[name];
8719      var expectedValue = expectedAttributes[name];
8720      var isEqualAttributes = isEqualAttributesOfName[name];
8721  
8722      if (isEqualAttributes) {
8723        // Defer custom attribute equality handling
8724        if (!isEqualAttributes(actualValue, expectedValue)) {
8725          log.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
8726          return false;
8727        }
8728      } else if (actualValue !== expectedValue) {
8729        // Otherwise strict inequality should bail
8730        log.warning('Expected attribute `%s` of value `%s`, saw `%s`.', name, expectedValue, actualValue);
8731        return false;
8732      }
8733    }
8734  
8735    return true;
8736  }
8737  /**
8738   * Token-type-specific equality handlers
8739   *
8740   * @type {Object}
8741   */
8742  
8743  var isEqualTokensOfType = {
8744    StartTag: function StartTag(actual, expected) {
8745      if (actual.tagName !== expected.tagName) {
8746        log.warning('Expected tag name `%s`, instead saw `%s`.', expected.tagName, actual.tagName);
8747        return false;
8748      }
8749  
8750      return isEqualTagAttributePairs.apply(void 0, Object(toConsumableArray["a" /* default */])([actual, expected].map(getMeaningfulAttributePairs)));
8751    },
8752    Chars: isEquivalentTextTokens,
8753    Comment: isEquivalentTextTokens
8754  };
8755  /**
8756   * Given an array of tokens, returns the first token which is not purely
8757   * whitespace.
8758   *
8759   * Mutates the tokens array.
8760   *
8761   * @param {Object[]} tokens Set of tokens to search.
8762   *
8763   * @return {Object} Next non-whitespace token.
8764   */
8765  
8766  function getNextNonWhitespaceToken(tokens) {
8767    var token;
8768  
8769    while (token = tokens.shift()) {
8770