[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/ -> rich-text.js (source)

   1  /******/ (() => { // webpackBootstrap
   2  /******/     "use strict";
   3  /******/     // The require scope
   4  /******/     var __webpack_require__ = {};
   5  /******/     
   6  /************************************************************************/
   7  /******/     /* webpack/runtime/compat get default export */
   8  /******/     (() => {
   9  /******/         // getDefaultExport function for compatibility with non-harmony modules
  10  /******/         __webpack_require__.n = (module) => {
  11  /******/             var getter = module && module.__esModule ?
  12  /******/                 () => (module['default']) :
  13  /******/                 () => (module);
  14  /******/             __webpack_require__.d(getter, { a: getter });
  15  /******/             return getter;
  16  /******/         };
  17  /******/     })();
  18  /******/     
  19  /******/     /* webpack/runtime/define property getters */
  20  /******/     (() => {
  21  /******/         // define getter functions for harmony exports
  22  /******/         __webpack_require__.d = (exports, definition) => {
  23  /******/             for(var key in definition) {
  24  /******/                 if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  25  /******/                     Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  26  /******/                 }
  27  /******/             }
  28  /******/         };
  29  /******/     })();
  30  /******/     
  31  /******/     /* webpack/runtime/hasOwnProperty shorthand */
  32  /******/     (() => {
  33  /******/         __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  34  /******/     })();
  35  /******/     
  36  /******/     /* webpack/runtime/make namespace object */
  37  /******/     (() => {
  38  /******/         // define __esModule on exports
  39  /******/         __webpack_require__.r = (exports) => {
  40  /******/             if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  41  /******/                 Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  42  /******/             }
  43  /******/             Object.defineProperty(exports, '__esModule', { value: true });
  44  /******/         };
  45  /******/     })();
  46  /******/     
  47  /************************************************************************/
  48  var __webpack_exports__ = {};
  49  // ESM COMPAT FLAG
  50  __webpack_require__.r(__webpack_exports__);
  51  
  52  // EXPORTS
  53  __webpack_require__.d(__webpack_exports__, {
  54    RichTextData: () => (/* reexport */ RichTextData),
  55    __experimentalRichText: () => (/* reexport */ __experimentalRichText),
  56    __unstableCreateElement: () => (/* reexport */ createElement),
  57    __unstableToDom: () => (/* reexport */ toDom),
  58    __unstableUseRichText: () => (/* reexport */ useRichText),
  59    applyFormat: () => (/* reexport */ applyFormat),
  60    concat: () => (/* reexport */ concat),
  61    create: () => (/* reexport */ create),
  62    getActiveFormat: () => (/* reexport */ getActiveFormat),
  63    getActiveFormats: () => (/* reexport */ getActiveFormats),
  64    getActiveObject: () => (/* reexport */ getActiveObject),
  65    getTextContent: () => (/* reexport */ getTextContent),
  66    insert: () => (/* reexport */ insert),
  67    insertObject: () => (/* reexport */ insertObject),
  68    isCollapsed: () => (/* reexport */ isCollapsed),
  69    isEmpty: () => (/* reexport */ isEmpty),
  70    join: () => (/* reexport */ join),
  71    registerFormatType: () => (/* reexport */ registerFormatType),
  72    remove: () => (/* reexport */ remove_remove),
  73    removeFormat: () => (/* reexport */ removeFormat),
  74    replace: () => (/* reexport */ replace_replace),
  75    slice: () => (/* reexport */ slice),
  76    split: () => (/* reexport */ split),
  77    store: () => (/* reexport */ store),
  78    toHTMLString: () => (/* reexport */ toHTMLString),
  79    toggleFormat: () => (/* reexport */ toggleFormat),
  80    unregisterFormatType: () => (/* reexport */ unregisterFormatType),
  81    useAnchor: () => (/* reexport */ useAnchor),
  82    useAnchorRef: () => (/* reexport */ useAnchorRef)
  83  });
  84  
  85  // NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
  86  var selectors_namespaceObject = {};
  87  __webpack_require__.r(selectors_namespaceObject);
  88  __webpack_require__.d(selectors_namespaceObject, {
  89    getFormatType: () => (getFormatType),
  90    getFormatTypeForBareElement: () => (getFormatTypeForBareElement),
  91    getFormatTypeForClassName: () => (getFormatTypeForClassName),
  92    getFormatTypes: () => (getFormatTypes)
  93  });
  94  
  95  // NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
  96  var actions_namespaceObject = {};
  97  __webpack_require__.r(actions_namespaceObject);
  98  __webpack_require__.d(actions_namespaceObject, {
  99    addFormatTypes: () => (addFormatTypes),
 100    removeFormatTypes: () => (removeFormatTypes)
 101  });
 102  
 103  ;// CONCATENATED MODULE: external ["wp","data"]
 104  const external_wp_data_namespaceObject = window["wp"]["data"];
 105  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/reducer.js
 106  /**
 107   * WordPress dependencies
 108   */
 109  
 110  
 111  /**
 112   * Reducer managing the format types
 113   *
 114   * @param {Object} state  Current state.
 115   * @param {Object} action Dispatched action.
 116   *
 117   * @return {Object} Updated state.
 118   */
 119  function formatTypes(state = {}, action) {
 120    switch (action.type) {
 121      case 'ADD_FORMAT_TYPES':
 122        return {
 123          ...state,
 124          // Key format types by their name.
 125          ...action.formatTypes.reduce((newFormatTypes, type) => ({
 126            ...newFormatTypes,
 127            [type.name]: type
 128          }), {})
 129        };
 130      case 'REMOVE_FORMAT_TYPES':
 131        return Object.fromEntries(Object.entries(state).filter(([key]) => !action.names.includes(key)));
 132    }
 133    return state;
 134  }
 135  /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
 136    formatTypes
 137  }));
 138  
 139  ;// CONCATENATED MODULE: ./node_modules/rememo/rememo.js
 140  
 141  
 142  /** @typedef {(...args: any[]) => *[]} GetDependants */
 143  
 144  /** @typedef {() => void} Clear */
 145  
 146  /**
 147   * @typedef {{
 148   *   getDependants: GetDependants,
 149   *   clear: Clear
 150   * }} EnhancedSelector
 151   */
 152  
 153  /**
 154   * Internal cache entry.
 155   *
 156   * @typedef CacheNode
 157   *
 158   * @property {?CacheNode|undefined} [prev] Previous node.
 159   * @property {?CacheNode|undefined} [next] Next node.
 160   * @property {*[]} args Function arguments for cache entry.
 161   * @property {*} val Function result.
 162   */
 163  
 164  /**
 165   * @typedef Cache
 166   *
 167   * @property {Clear} clear Function to clear cache.
 168   * @property {boolean} [isUniqueByDependants] Whether dependants are valid in
 169   * considering cache uniqueness. A cache is unique if dependents are all arrays
 170   * or objects.
 171   * @property {CacheNode?} [head] Cache head.
 172   * @property {*[]} [lastDependants] Dependants from previous invocation.
 173   */
 174  
 175  /**
 176   * Arbitrary value used as key for referencing cache object in WeakMap tree.
 177   *
 178   * @type {{}}
 179   */
 180  var LEAF_KEY = {};
 181  
 182  /**
 183   * Returns the first argument as the sole entry in an array.
 184   *
 185   * @template T
 186   *
 187   * @param {T} value Value to return.
 188   *
 189   * @return {[T]} Value returned as entry in array.
 190   */
 191  function arrayOf(value) {
 192      return [value];
 193  }
 194  
 195  /**
 196   * Returns true if the value passed is object-like, or false otherwise. A value
 197   * is object-like if it can support property assignment, e.g. object or array.
 198   *
 199   * @param {*} value Value to test.
 200   *
 201   * @return {boolean} Whether value is object-like.
 202   */
 203  function isObjectLike(value) {
 204      return !!value && 'object' === typeof value;
 205  }
 206  
 207  /**
 208   * Creates and returns a new cache object.
 209   *
 210   * @return {Cache} Cache object.
 211   */
 212  function createCache() {
 213      /** @type {Cache} */
 214      var cache = {
 215          clear: function () {
 216              cache.head = null;
 217          },
 218      };
 219  
 220      return cache;
 221  }
 222  
 223  /**
 224   * Returns true if entries within the two arrays are strictly equal by
 225   * reference from a starting index.
 226   *
 227   * @param {*[]} a First array.
 228   * @param {*[]} b Second array.
 229   * @param {number} fromIndex Index from which to start comparison.
 230   *
 231   * @return {boolean} Whether arrays are shallowly equal.
 232   */
 233  function isShallowEqual(a, b, fromIndex) {
 234      var i;
 235  
 236      if (a.length !== b.length) {
 237          return false;
 238      }
 239  
 240      for (i = fromIndex; i < a.length; i++) {
 241          if (a[i] !== b[i]) {
 242              return false;
 243          }
 244      }
 245  
 246      return true;
 247  }
 248  
 249  /**
 250   * Returns a memoized selector function. The getDependants function argument is
 251   * called before the memoized selector and is expected to return an immutable
 252   * reference or array of references on which the selector depends for computing
 253   * its own return value. The memoize cache is preserved only as long as those
 254   * dependant references remain the same. If getDependants returns a different
 255   * reference(s), the cache is cleared and the selector value regenerated.
 256   *
 257   * @template {(...args: *[]) => *} S
 258   *
 259   * @param {S} selector Selector function.
 260   * @param {GetDependants=} getDependants Dependant getter returning an array of
 261   * references used in cache bust consideration.
 262   */
 263  /* harmony default export */ function rememo(selector, getDependants) {
 264      /** @type {WeakMap<*,*>} */
 265      var rootCache;
 266  
 267      /** @type {GetDependants} */
 268      var normalizedGetDependants = getDependants ? getDependants : arrayOf;
 269  
 270      /**
 271       * Returns the cache for a given dependants array. When possible, a WeakMap
 272       * will be used to create a unique cache for each set of dependants. This
 273       * is feasible due to the nature of WeakMap in allowing garbage collection
 274       * to occur on entries where the key object is no longer referenced. Since
 275       * WeakMap requires the key to be an object, this is only possible when the
 276       * dependant is object-like. The root cache is created as a hierarchy where
 277       * each top-level key is the first entry in a dependants set, the value a
 278       * WeakMap where each key is the next dependant, and so on. This continues
 279       * so long as the dependants are object-like. If no dependants are object-
 280       * like, then the cache is shared across all invocations.
 281       *
 282       * @see isObjectLike
 283       *
 284       * @param {*[]} dependants Selector dependants.
 285       *
 286       * @return {Cache} Cache object.
 287       */
 288  	function getCache(dependants) {
 289          var caches = rootCache,
 290              isUniqueByDependants = true,
 291              i,
 292              dependant,
 293              map,
 294              cache;
 295  
 296          for (i = 0; i < dependants.length; i++) {
 297              dependant = dependants[i];
 298  
 299              // Can only compose WeakMap from object-like key.
 300              if (!isObjectLike(dependant)) {
 301                  isUniqueByDependants = false;
 302                  break;
 303              }
 304  
 305              // Does current segment of cache already have a WeakMap?
 306              if (caches.has(dependant)) {
 307                  // Traverse into nested WeakMap.
 308                  caches = caches.get(dependant);
 309              } else {
 310                  // Create, set, and traverse into a new one.
 311                  map = new WeakMap();
 312                  caches.set(dependant, map);
 313                  caches = map;
 314              }
 315          }
 316  
 317          // We use an arbitrary (but consistent) object as key for the last item
 318          // in the WeakMap to serve as our running cache.
 319          if (!caches.has(LEAF_KEY)) {
 320              cache = createCache();
 321              cache.isUniqueByDependants = isUniqueByDependants;
 322              caches.set(LEAF_KEY, cache);
 323          }
 324  
 325          return caches.get(LEAF_KEY);
 326      }
 327  
 328      /**
 329       * Resets root memoization cache.
 330       */
 331  	function clear() {
 332          rootCache = new WeakMap();
 333      }
 334  
 335      /* eslint-disable jsdoc/check-param-names */
 336      /**
 337       * The augmented selector call, considering first whether dependants have
 338       * changed before passing it to underlying memoize function.
 339       *
 340       * @param {*}    source    Source object for derivation.
 341       * @param {...*} extraArgs Additional arguments to pass to selector.
 342       *
 343       * @return {*} Selector result.
 344       */
 345      /* eslint-enable jsdoc/check-param-names */
 346  	function callSelector(/* source, ...extraArgs */) {
 347          var len = arguments.length,
 348              cache,
 349              node,
 350              i,
 351              args,
 352              dependants;
 353  
 354          // Create copy of arguments (avoid leaking deoptimization).
 355          args = new Array(len);
 356          for (i = 0; i < len; i++) {
 357              args[i] = arguments[i];
 358          }
 359  
 360          dependants = normalizedGetDependants.apply(null, args);
 361          cache = getCache(dependants);
 362  
 363          // If not guaranteed uniqueness by dependants (primitive type), shallow
 364          // compare against last dependants and, if references have changed,
 365          // destroy cache to recalculate result.
 366          if (!cache.isUniqueByDependants) {
 367              if (
 368                  cache.lastDependants &&
 369                  !isShallowEqual(dependants, cache.lastDependants, 0)
 370              ) {
 371                  cache.clear();
 372              }
 373  
 374              cache.lastDependants = dependants;
 375          }
 376  
 377          node = cache.head;
 378          while (node) {
 379              // Check whether node arguments match arguments
 380              if (!isShallowEqual(node.args, args, 1)) {
 381                  node = node.next;
 382                  continue;
 383              }
 384  
 385              // At this point we can assume we've found a match
 386  
 387              // Surface matched node to head if not already
 388              if (node !== cache.head) {
 389                  // Adjust siblings to point to each other.
 390                  /** @type {CacheNode} */ (node.prev).next = node.next;
 391                  if (node.next) {
 392                      node.next.prev = node.prev;
 393                  }
 394  
 395                  node.next = cache.head;
 396                  node.prev = null;
 397                  /** @type {CacheNode} */ (cache.head).prev = node;
 398                  cache.head = node;
 399              }
 400  
 401              // Return immediately
 402              return node.val;
 403          }
 404  
 405          // No cached value found. Continue to insertion phase:
 406  
 407          node = /** @type {CacheNode} */ ({
 408              // Generate the result from original function
 409              val: selector.apply(null, args),
 410          });
 411  
 412          // Avoid including the source object in the cache.
 413          args[0] = null;
 414          node.args = args;
 415  
 416          // Don't need to check whether node is already head, since it would
 417          // have been returned above already if it was
 418  
 419          // Shift existing head down list
 420          if (cache.head) {
 421              cache.head.prev = node;
 422              node.next = cache.head;
 423          }
 424  
 425          cache.head = node;
 426  
 427          return node.val;
 428      }
 429  
 430      callSelector.getDependants = normalizedGetDependants;
 431      callSelector.clear = clear;
 432      clear();
 433  
 434      return /** @type {S & EnhancedSelector} */ (callSelector);
 435  }
 436  
 437  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
 438  /**
 439   * External dependencies
 440   */
 441  
 442  
 443  /**
 444   * Returns all the available format types.
 445   *
 446   * @param {Object} state Data state.
 447   *
 448   * @example
 449   * ```js
 450   * import { __, sprintf } from '@wordpress/i18n';
 451   * import { store as richTextStore } from '@wordpress/rich-text';
 452   * import { useSelect } from '@wordpress/data';
 453   *
 454   * const ExampleComponent = () => {
 455   *    const { getFormatTypes } = useSelect(
 456   *        ( select ) => select( richTextStore ),
 457   *        []
 458   *    );
 459   *
 460   *    const availableFormats = getFormatTypes();
 461   *
 462   *    return availableFormats ? (
 463   *        <ul>
 464   *            { availableFormats?.map( ( format ) => (
 465   *                <li>{ format.name }</li>
 466   *           ) ) }
 467   *        </ul>
 468   *    ) : (
 469   *        __( 'No Formats available' )
 470   *    );
 471   * };
 472   * ```
 473   *
 474   * @return {Array} Format types.
 475   */
 476  const getFormatTypes = rememo(state => Object.values(state.formatTypes), state => [state.formatTypes]);
 477  
 478  /**
 479   * Returns a format type by name.
 480   *
 481   * @param {Object} state Data state.
 482   * @param {string} name  Format type name.
 483   *
 484   * @example
 485   * ```js
 486   * import { __, sprintf } from '@wordpress/i18n';
 487   * import { store as richTextStore } from '@wordpress/rich-text';
 488   * import { useSelect } from '@wordpress/data';
 489   *
 490   * const ExampleComponent = () => {
 491   *    const { getFormatType } = useSelect(
 492   *        ( select ) => select( richTextStore ),
 493   *        []
 494   *    );
 495   *
 496   *    const boldFormat = getFormatType( 'core/bold' );
 497   *
 498   *    return boldFormat ? (
 499   *        <ul>
 500   *            { Object.entries( boldFormat )?.map( ( [ key, value ] ) => (
 501   *                <li>
 502   *                    { key } : { value }
 503   *                </li>
 504   *           ) ) }
 505   *       </ul>
 506   *    ) : (
 507   *        __( 'Not Found' )
 508   *    ;
 509   * };
 510   * ```
 511   *
 512   * @return {Object?} Format type.
 513   */
 514  function getFormatType(state, name) {
 515    return state.formatTypes[name];
 516  }
 517  
 518  /**
 519   * Gets the format type, if any, that can handle a bare element (without a
 520   * data-format-type attribute), given the tag name of this element.
 521   *
 522   * @param {Object} state              Data state.
 523   * @param {string} bareElementTagName The tag name of the element to find a
 524   *                                    format type for.
 525   *
 526   * @example
 527   * ```js
 528   * import { __, sprintf } from '@wordpress/i18n';
 529   * import { store as richTextStore } from '@wordpress/rich-text';
 530   * import { useSelect } from '@wordpress/data';
 531   *
 532   * const ExampleComponent = () => {
 533   *    const { getFormatTypeForBareElement } = useSelect(
 534   *        ( select ) => select( richTextStore ),
 535   *        []
 536   *    );
 537   *
 538   *    const format = getFormatTypeForBareElement( 'strong' );
 539   *
 540   *    return format && <p>{ sprintf( __( 'Format name: %s' ), format.name ) }</p>;
 541   * }
 542   * ```
 543   *
 544   * @return {?Object} Format type.
 545   */
 546  function getFormatTypeForBareElement(state, bareElementTagName) {
 547    const formatTypes = getFormatTypes(state);
 548    return formatTypes.find(({
 549      className,
 550      tagName
 551    }) => {
 552      return className === null && bareElementTagName === tagName;
 553    }) || formatTypes.find(({
 554      className,
 555      tagName
 556    }) => {
 557      return className === null && '*' === tagName;
 558    });
 559  }
 560  
 561  /**
 562   * Gets the format type, if any, that can handle an element, given its classes.
 563   *
 564   * @param {Object} state            Data state.
 565   * @param {string} elementClassName The classes of the element to find a format
 566   *                                  type for.
 567   *
 568   * @example
 569   * ```js
 570   * import { __, sprintf } from '@wordpress/i18n';
 571   * import { store as richTextStore } from '@wordpress/rich-text';
 572   * import { useSelect } from '@wordpress/data';
 573   *
 574   * const ExampleComponent = () => {
 575   *    const { getFormatTypeForClassName } = useSelect(
 576   *        ( select ) => select( richTextStore ),
 577   *        []
 578   *    );
 579   *
 580   *    const format = getFormatTypeForClassName( 'has-inline-color' );
 581   *
 582   *    return format && <p>{ sprintf( __( 'Format name: %s' ), format.name ) }</p>;
 583   * };
 584   * ```
 585   *
 586   * @return {?Object} Format type.
 587   */
 588  function getFormatTypeForClassName(state, elementClassName) {
 589    return getFormatTypes(state).find(({
 590      className
 591    }) => {
 592      if (className === null) {
 593        return false;
 594      }
 595      return ` $elementClassName} `.indexOf(` $className} `) >= 0;
 596    });
 597  }
 598  
 599  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
 600  /**
 601   * Returns an action object used in signalling that format types have been
 602   * added.
 603   * Ignored from documentation as registerFormatType should be used instead from @wordpress/rich-text
 604   *
 605   * @ignore
 606   *
 607   * @param {Array|Object} formatTypes Format types received.
 608   *
 609   * @return {Object} Action object.
 610   */
 611  function addFormatTypes(formatTypes) {
 612    return {
 613      type: 'ADD_FORMAT_TYPES',
 614      formatTypes: Array.isArray(formatTypes) ? formatTypes : [formatTypes]
 615    };
 616  }
 617  
 618  /**
 619   * Returns an action object used to remove a registered format type.
 620   *
 621   * Ignored from documentation as unregisterFormatType should be used instead from @wordpress/rich-text
 622   *
 623   * @ignore
 624   *
 625   * @param {string|Array} names Format name.
 626   *
 627   * @return {Object} Action object.
 628   */
 629  function removeFormatTypes(names) {
 630    return {
 631      type: 'REMOVE_FORMAT_TYPES',
 632      names: Array.isArray(names) ? names : [names]
 633    };
 634  }
 635  
 636  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/index.js
 637  /**
 638   * WordPress dependencies
 639   */
 640  
 641  
 642  /**
 643   * Internal dependencies
 644   */
 645  
 646  
 647  
 648  const STORE_NAME = 'core/rich-text';
 649  
 650  /**
 651   * Store definition for the rich-text namespace.
 652   *
 653   * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
 654   *
 655   * @type {Object}
 656   */
 657  const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
 658    reducer: reducer,
 659    selectors: selectors_namespaceObject,
 660    actions: actions_namespaceObject
 661  });
 662  (0,external_wp_data_namespaceObject.register)(store);
 663  
 664  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-format-equal.js
 665  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
 666  
 667  /**
 668   * Optimised equality check for format objects.
 669   *
 670   * @param {?RichTextFormat} format1 Format to compare.
 671   * @param {?RichTextFormat} format2 Format to compare.
 672   *
 673   * @return {boolean} True if formats are equal, false if not.
 674   */
 675  function isFormatEqual(format1, format2) {
 676    // Both not defined.
 677    if (format1 === format2) {
 678      return true;
 679    }
 680  
 681    // Either not defined.
 682    if (!format1 || !format2) {
 683      return false;
 684    }
 685    if (format1.type !== format2.type) {
 686      return false;
 687    }
 688    const attributes1 = format1.attributes;
 689    const attributes2 = format2.attributes;
 690  
 691    // Both not defined.
 692    if (attributes1 === attributes2) {
 693      return true;
 694    }
 695  
 696    // Either not defined.
 697    if (!attributes1 || !attributes2) {
 698      return false;
 699    }
 700    const keys1 = Object.keys(attributes1);
 701    const keys2 = Object.keys(attributes2);
 702    if (keys1.length !== keys2.length) {
 703      return false;
 704    }
 705    const length = keys1.length;
 706  
 707    // Optimise for speed.
 708    for (let i = 0; i < length; i++) {
 709      const name = keys1[i];
 710      if (attributes1[name] !== attributes2[name]) {
 711        return false;
 712      }
 713    }
 714    return true;
 715  }
 716  
 717  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/normalise-formats.js
 718  /**
 719   * Internal dependencies
 720   */
 721  
 722  
 723  
 724  /** @typedef {import('./types').RichTextValue} RichTextValue */
 725  
 726  /**
 727   * Normalises formats: ensures subsequent adjacent equal formats have the same
 728   * reference.
 729   *
 730   * @param {RichTextValue} value Value to normalise formats of.
 731   *
 732   * @return {RichTextValue} New value with normalised formats.
 733   */
 734  function normaliseFormats(value) {
 735    const newFormats = value.formats.slice();
 736    newFormats.forEach((formatsAtIndex, index) => {
 737      const formatsAtPreviousIndex = newFormats[index - 1];
 738      if (formatsAtPreviousIndex) {
 739        const newFormatsAtIndex = formatsAtIndex.slice();
 740        newFormatsAtIndex.forEach((format, formatIndex) => {
 741          const previousFormat = formatsAtPreviousIndex[formatIndex];
 742          if (isFormatEqual(format, previousFormat)) {
 743            newFormatsAtIndex[formatIndex] = previousFormat;
 744          }
 745        });
 746        newFormats[index] = newFormatsAtIndex;
 747      }
 748    });
 749    return {
 750      ...value,
 751      formats: newFormats
 752    };
 753  }
 754  
 755  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/apply-format.js
 756  /**
 757   * Internal dependencies
 758   */
 759  
 760  
 761  
 762  /** @typedef {import('./types').RichTextValue} RichTextValue */
 763  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
 764  
 765  function replace(array, index, value) {
 766    array = array.slice();
 767    array[index] = value;
 768    return array;
 769  }
 770  
 771  /**
 772   * Apply a format object to a Rich Text value from the given `startIndex` to the
 773   * given `endIndex`. Indices are retrieved from the selection if none are
 774   * provided.
 775   *
 776   * @param {RichTextValue}  value        Value to modify.
 777   * @param {RichTextFormat} format       Format to apply.
 778   * @param {number}         [startIndex] Start index.
 779   * @param {number}         [endIndex]   End index.
 780   *
 781   * @return {RichTextValue} A new value with the format applied.
 782   */
 783  function applyFormat(value, format, startIndex = value.start, endIndex = value.end) {
 784    const {
 785      formats,
 786      activeFormats
 787    } = value;
 788    const newFormats = formats.slice();
 789  
 790    // The selection is collapsed.
 791    if (startIndex === endIndex) {
 792      const startFormat = newFormats[startIndex]?.find(({
 793        type
 794      }) => type === format.type);
 795  
 796      // If the caret is at a format of the same type, expand start and end to
 797      // the edges of the format. This is useful to apply new attributes.
 798      if (startFormat) {
 799        const index = newFormats[startIndex].indexOf(startFormat);
 800        while (newFormats[startIndex] && newFormats[startIndex][index] === startFormat) {
 801          newFormats[startIndex] = replace(newFormats[startIndex], index, format);
 802          startIndex--;
 803        }
 804        endIndex++;
 805        while (newFormats[endIndex] && newFormats[endIndex][index] === startFormat) {
 806          newFormats[endIndex] = replace(newFormats[endIndex], index, format);
 807          endIndex++;
 808        }
 809      }
 810    } else {
 811      // Determine the highest position the new format can be inserted at.
 812      let position = +Infinity;
 813      for (let index = startIndex; index < endIndex; index++) {
 814        if (newFormats[index]) {
 815          newFormats[index] = newFormats[index].filter(({
 816            type
 817          }) => type !== format.type);
 818          const length = newFormats[index].length;
 819          if (length < position) {
 820            position = length;
 821          }
 822        } else {
 823          newFormats[index] = [];
 824          position = 0;
 825        }
 826      }
 827      for (let index = startIndex; index < endIndex; index++) {
 828        newFormats[index].splice(position, 0, format);
 829      }
 830    }
 831    return normaliseFormats({
 832      ...value,
 833      formats: newFormats,
 834      // Always revise active formats. This serves as a placeholder for new
 835      // inputs with the format so new input appears with the format applied,
 836      // and ensures a format of the same type uses the latest values.
 837      activeFormats: [...(activeFormats?.filter(({
 838        type
 839      }) => type !== format.type) || []), format]
 840    });
 841  }
 842  
 843  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create-element.js
 844  /**
 845   * Parse the given HTML into a body element.
 846   *
 847   * Note: The current implementation will return a shared reference, reset on
 848   * each call to `createElement`. Therefore, you should not hold a reference to
 849   * the value to operate upon asynchronously, as it may have unexpected results.
 850   *
 851   * @param {HTMLDocument} document The HTML document to use to parse.
 852   * @param {string}       html     The HTML to parse.
 853   *
 854   * @return {HTMLBodyElement} Body element with parsed HTML.
 855   */
 856  function createElement({
 857    implementation
 858  }, html) {
 859    // Because `createHTMLDocument` is an expensive operation, and with this
 860    // function being internal to `rich-text` (full control in avoiding a risk
 861    // of asynchronous operations on the shared reference), a single document
 862    // is reused and reset for each call to the function.
 863    if (!createElement.body) {
 864      createElement.body = implementation.createHTMLDocument('').body;
 865    }
 866    createElement.body.innerHTML = html;
 867    return createElement.body;
 868  }
 869  
 870  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/special-characters.js
 871  /**
 872   * Object replacement character, used as a placeholder for objects.
 873   */
 874  const OBJECT_REPLACEMENT_CHARACTER = '\ufffc';
 875  
 876  /**
 877   * Zero width non-breaking space, used as padding in the editable DOM tree when
 878   * it is empty otherwise.
 879   */
 880  const ZWNBSP = '\ufeff';
 881  
 882  ;// CONCATENATED MODULE: external ["wp","escapeHtml"]
 883  const external_wp_escapeHtml_namespaceObject = window["wp"]["escapeHtml"];
 884  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-formats.js
 885  /** @typedef {import('./types').RichTextValue} RichTextValue */
 886  /** @typedef {import('./types').RichTextFormatList} RichTextFormatList */
 887  
 888  /**
 889   * Internal dependencies
 890   */
 891  
 892  
 893  /**
 894   * Gets the all format objects at the start of the selection.
 895   *
 896   * @param {RichTextValue} value                Value to inspect.
 897   * @param {Array}         EMPTY_ACTIVE_FORMATS Array to return if there are no
 898   *                                             active formats.
 899   *
 900   * @return {RichTextFormatList} Active format objects.
 901   */
 902  function getActiveFormats(value, EMPTY_ACTIVE_FORMATS = []) {
 903    const {
 904      formats,
 905      start,
 906      end,
 907      activeFormats
 908    } = value;
 909    if (start === undefined) {
 910      return EMPTY_ACTIVE_FORMATS;
 911    }
 912    if (start === end) {
 913      // For a collapsed caret, it is possible to override the active formats.
 914      if (activeFormats) {
 915        return activeFormats;
 916      }
 917      const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS;
 918      const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS;
 919  
 920      // By default, select the lowest amount of formats possible (which means
 921      // the caret is positioned outside the format boundary). The user can
 922      // then use arrow keys to define `activeFormats`.
 923      if (formatsBefore.length < formatsAfter.length) {
 924        return formatsBefore;
 925      }
 926      return formatsAfter;
 927    }
 928  
 929    // If there's no formats at the start index, there are not active formats.
 930    if (!formats[start]) {
 931      return EMPTY_ACTIVE_FORMATS;
 932    }
 933    const selectedFormats = formats.slice(start, end);
 934  
 935    // Clone the formats so we're not mutating the live value.
 936    const _activeFormats = [...selectedFormats[0]];
 937    let i = selectedFormats.length;
 938  
 939    // For performance reasons, start from the end where it's much quicker to
 940    // realise that there are no active formats.
 941    while (i--) {
 942      const formatsAtIndex = selectedFormats[i];
 943  
 944      // If we run into any index without formats, we're sure that there's no
 945      // active formats.
 946      if (!formatsAtIndex) {
 947        return EMPTY_ACTIVE_FORMATS;
 948      }
 949      let ii = _activeFormats.length;
 950  
 951      // Loop over the active formats and remove any that are not present at
 952      // the current index.
 953      while (ii--) {
 954        const format = _activeFormats[ii];
 955        if (!formatsAtIndex.find(_format => isFormatEqual(format, _format))) {
 956          _activeFormats.splice(ii, 1);
 957        }
 958      }
 959  
 960      // If there are no active formats, we can stop.
 961      if (_activeFormats.length === 0) {
 962        return EMPTY_ACTIVE_FORMATS;
 963      }
 964    }
 965    return _activeFormats || EMPTY_ACTIVE_FORMATS;
 966  }
 967  
 968  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-format-type.js
 969  /**
 970   * WordPress dependencies
 971   */
 972  
 973  /**
 974   * Internal dependencies
 975   */
 976  
 977  
 978  /** @typedef {import('./register-format-type').RichTextFormatType} RichTextFormatType */
 979  
 980  /**
 981   * Returns a registered format type.
 982   *
 983   * @param {string} name Format name.
 984   *
 985   * @return {RichTextFormatType|undefined} Format type.
 986   */
 987  function get_format_type_getFormatType(name) {
 988    return (0,external_wp_data_namespaceObject.select)(store).getFormatType(name);
 989  }
 990  
 991  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-tree.js
 992  /**
 993   * Internal dependencies
 994   */
 995  
 996  
 997  
 998  
 999  function restoreOnAttributes(attributes, isEditableTree) {
1000    if (isEditableTree) {
1001      return attributes;
1002    }
1003    const newAttributes = {};
1004    for (const key in attributes) {
1005      let newKey = key;
1006      if (key.startsWith('data-disable-rich-text-')) {
1007        newKey = key.slice('data-disable-rich-text-'.length);
1008      }
1009      newAttributes[newKey] = attributes[key];
1010    }
1011    return newAttributes;
1012  }
1013  
1014  /**
1015   * Converts a format object to information that can be used to create an element
1016   * from (type, attributes and object).
1017   *
1018   * @param {Object}  $1                        Named parameters.
1019   * @param {string}  $1.type                   The format type.
1020   * @param {string}  $1.tagName                The tag name.
1021   * @param {Object}  $1.attributes             The format attributes.
1022   * @param {Object}  $1.unregisteredAttributes The unregistered format
1023   *                                            attributes.
1024   * @param {boolean} $1.object                 Whether or not it is an object
1025   *                                            format.
1026   * @param {boolean} $1.boundaryClass          Whether or not to apply a boundary
1027   *                                            class.
1028   * @param {boolean} $1.isEditableTree
1029   *
1030   * @return {Object} Information to be used for element creation.
1031   */
1032  function fromFormat({
1033    type,
1034    tagName,
1035    attributes,
1036    unregisteredAttributes,
1037    object,
1038    boundaryClass,
1039    isEditableTree
1040  }) {
1041    const formatType = get_format_type_getFormatType(type);
1042    let elementAttributes = {};
1043    if (boundaryClass && isEditableTree) {
1044      elementAttributes['data-rich-text-format-boundary'] = 'true';
1045    }
1046    if (!formatType) {
1047      if (attributes) {
1048        elementAttributes = {
1049          ...attributes,
1050          ...elementAttributes
1051        };
1052      }
1053      return {
1054        type,
1055        attributes: restoreOnAttributes(elementAttributes, isEditableTree),
1056        object
1057      };
1058    }
1059    elementAttributes = {
1060      ...unregisteredAttributes,
1061      ...elementAttributes
1062    };
1063    for (const name in attributes) {
1064      const key = formatType.attributes ? formatType.attributes[name] : false;
1065      if (key) {
1066        elementAttributes[key] = attributes[name];
1067      } else {
1068        elementAttributes[name] = attributes[name];
1069      }
1070    }
1071    if (formatType.className) {
1072      if (elementAttributes.class) {
1073        elementAttributes.class = `$formatType.className} $elementAttributes.class}`;
1074      } else {
1075        elementAttributes.class = formatType.className;
1076      }
1077    }
1078  
1079    // When a format is declared as non editable, make it non editable in the
1080    // editor.
1081    if (isEditableTree && formatType.contentEditable === false) {
1082      elementAttributes.contenteditable = 'false';
1083    }
1084    return {
1085      type: tagName || formatType.tagName,
1086      object: formatType.object,
1087      attributes: restoreOnAttributes(elementAttributes, isEditableTree)
1088    };
1089  }
1090  
1091  /**
1092   * Checks if both arrays of formats up until a certain index are equal.
1093   *
1094   * @param {Array}  a     Array of formats to compare.
1095   * @param {Array}  b     Array of formats to compare.
1096   * @param {number} index Index to check until.
1097   */
1098  function isEqualUntil(a, b, index) {
1099    do {
1100      if (a[index] !== b[index]) {
1101        return false;
1102      }
1103    } while (index--);
1104    return true;
1105  }
1106  function toTree({
1107    value,
1108    preserveWhiteSpace,
1109    createEmpty,
1110    append,
1111    getLastChild,
1112    getParent,
1113    isText,
1114    getText,
1115    remove,
1116    appendText,
1117    onStartIndex,
1118    onEndIndex,
1119    isEditableTree,
1120    placeholder
1121  }) {
1122    const {
1123      formats,
1124      replacements,
1125      text,
1126      start,
1127      end
1128    } = value;
1129    const formatsLength = formats.length + 1;
1130    const tree = createEmpty();
1131    const activeFormats = getActiveFormats(value);
1132    const deepestActiveFormat = activeFormats[activeFormats.length - 1];
1133    let lastCharacterFormats;
1134    let lastCharacter;
1135    append(tree, '');
1136    for (let i = 0; i < formatsLength; i++) {
1137      const character = text.charAt(i);
1138      const shouldInsertPadding = isEditableTree && (
1139      // Pad the line if the line is empty.
1140      !lastCharacter ||
1141      // Pad the line if the previous character is a line break, otherwise
1142      // the line break won't be visible.
1143      lastCharacter === '\n');
1144      const characterFormats = formats[i];
1145      let pointer = getLastChild(tree);
1146      if (characterFormats) {
1147        characterFormats.forEach((format, formatIndex) => {
1148          if (pointer && lastCharacterFormats &&
1149          // Reuse the last element if all formats remain the same.
1150          isEqualUntil(characterFormats, lastCharacterFormats, formatIndex)) {
1151            pointer = getLastChild(pointer);
1152            return;
1153          }
1154          const {
1155            type,
1156            tagName,
1157            attributes,
1158            unregisteredAttributes
1159          } = format;
1160          const boundaryClass = isEditableTree && format === deepestActiveFormat;
1161          const parent = getParent(pointer);
1162          const newNode = append(parent, fromFormat({
1163            type,
1164            tagName,
1165            attributes,
1166            unregisteredAttributes,
1167            boundaryClass,
1168            isEditableTree
1169          }));
1170          if (isText(pointer) && getText(pointer).length === 0) {
1171            remove(pointer);
1172          }
1173          pointer = append(newNode, '');
1174        });
1175      }
1176  
1177      // If there is selection at 0, handle it before characters are inserted.
1178      if (i === 0) {
1179        if (onStartIndex && start === 0) {
1180          onStartIndex(tree, pointer);
1181        }
1182        if (onEndIndex && end === 0) {
1183          onEndIndex(tree, pointer);
1184        }
1185      }
1186      if (character === OBJECT_REPLACEMENT_CHARACTER) {
1187        const replacement = replacements[i];
1188        if (!replacement) continue;
1189        const {
1190          type,
1191          attributes,
1192          innerHTML
1193        } = replacement;
1194        const formatType = get_format_type_getFormatType(type);
1195        if (!isEditableTree && type === 'script') {
1196          pointer = append(getParent(pointer), fromFormat({
1197            type: 'script',
1198            isEditableTree
1199          }));
1200          append(pointer, {
1201            html: decodeURIComponent(attributes['data-rich-text-script'])
1202          });
1203        } else if (formatType?.contentEditable === false) {
1204          // For non editable formats, render the stored inner HTML.
1205          pointer = append(getParent(pointer), fromFormat({
1206            ...replacement,
1207            isEditableTree,
1208            boundaryClass: start === i && end === i + 1
1209          }));
1210          if (innerHTML) {
1211            append(pointer, {
1212              html: innerHTML
1213            });
1214          }
1215        } else {
1216          pointer = append(getParent(pointer), fromFormat({
1217            ...replacement,
1218            object: true,
1219            isEditableTree
1220          }));
1221        }
1222        // Ensure pointer is text node.
1223        pointer = append(getParent(pointer), '');
1224      } else if (!preserveWhiteSpace && character === '\n') {
1225        pointer = append(getParent(pointer), {
1226          type: 'br',
1227          attributes: isEditableTree ? {
1228            'data-rich-text-line-break': 'true'
1229          } : undefined,
1230          object: true
1231        });
1232        // Ensure pointer is text node.
1233        pointer = append(getParent(pointer), '');
1234      } else if (!isText(pointer)) {
1235        pointer = append(getParent(pointer), character);
1236      } else {
1237        appendText(pointer, character);
1238      }
1239      if (onStartIndex && start === i + 1) {
1240        onStartIndex(tree, pointer);
1241      }
1242      if (onEndIndex && end === i + 1) {
1243        onEndIndex(tree, pointer);
1244      }
1245      if (shouldInsertPadding && i === text.length) {
1246        append(getParent(pointer), ZWNBSP);
1247        if (placeholder && text.length === 0) {
1248          append(getParent(pointer), {
1249            type: 'span',
1250            attributes: {
1251              'data-rich-text-placeholder': placeholder,
1252              // Necessary to prevent the placeholder from catching
1253              // selection and being editable.
1254              style: 'pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;'
1255            }
1256          });
1257        }
1258      }
1259      lastCharacterFormats = characterFormats;
1260      lastCharacter = character;
1261    }
1262    return tree;
1263  }
1264  
1265  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-html-string.js
1266  /**
1267   * WordPress dependencies
1268   */
1269  
1270  
1271  
1272  /**
1273   * Internal dependencies
1274   */
1275  
1276  
1277  
1278  /** @typedef {import('./types').RichTextValue} RichTextValue */
1279  
1280  /**
1281   * Create an HTML string from a Rich Text value.
1282   *
1283   * @param {Object}        $1                      Named argements.
1284   * @param {RichTextValue} $1.value                Rich text value.
1285   * @param {boolean}       [$1.preserveWhiteSpace] Preserves newlines if true.
1286   *
1287   * @return {string} HTML string.
1288   */
1289  function toHTMLString({
1290    value,
1291    preserveWhiteSpace
1292  }) {
1293    const tree = toTree({
1294      value,
1295      preserveWhiteSpace,
1296      createEmpty,
1297      append,
1298      getLastChild,
1299      getParent,
1300      isText,
1301      getText,
1302      remove,
1303      appendText
1304    });
1305    return createChildrenHTML(tree.children);
1306  }
1307  function createEmpty() {
1308    return {};
1309  }
1310  function getLastChild({
1311    children
1312  }) {
1313    return children && children[children.length - 1];
1314  }
1315  function append(parent, object) {
1316    if (typeof object === 'string') {
1317      object = {
1318        text: object
1319      };
1320    }
1321    object.parent = parent;
1322    parent.children = parent.children || [];
1323    parent.children.push(object);
1324    return object;
1325  }
1326  function appendText(object, text) {
1327    object.text += text;
1328  }
1329  function getParent({
1330    parent
1331  }) {
1332    return parent;
1333  }
1334  function isText({
1335    text
1336  }) {
1337    return typeof text === 'string';
1338  }
1339  function getText({
1340    text
1341  }) {
1342    return text;
1343  }
1344  function remove(object) {
1345    const index = object.parent.children.indexOf(object);
1346    if (index !== -1) {
1347      object.parent.children.splice(index, 1);
1348    }
1349    return object;
1350  }
1351  function createElementHTML({
1352    type,
1353    attributes,
1354    object,
1355    children
1356  }) {
1357    let attributeString = '';
1358    for (const key in attributes) {
1359      if (!(0,external_wp_escapeHtml_namespaceObject.isValidAttributeName)(key)) {
1360        continue;
1361      }
1362      attributeString += ` $key}="${(0,external_wp_escapeHtml_namespaceObject.escapeAttribute)(attributes[key])}"`;
1363    }
1364    if (object) {
1365      return `<$type}$attributeString}>`;
1366    }
1367    return `<$type}$attributeString}>$createChildrenHTML(children)}</$type}>`;
1368  }
1369  function createChildrenHTML(children = []) {
1370    return children.map(child => {
1371      if (child.html !== undefined) {
1372        return child.html;
1373      }
1374      return child.text === undefined ? createElementHTML(child) : (0,external_wp_escapeHtml_namespaceObject.escapeEditableHTML)(child.text);
1375    }).join('');
1376  }
1377  
1378  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-text-content.js
1379  /**
1380   * Internal dependencies
1381   */
1382  
1383  
1384  /** @typedef {import('./types').RichTextValue} RichTextValue */
1385  
1386  /**
1387   * Get the textual content of a Rich Text value. This is similar to
1388   * `Element.textContent`.
1389   *
1390   * @param {RichTextValue} value Value to use.
1391   *
1392   * @return {string} The text content.
1393   */
1394  function getTextContent({
1395    text
1396  }) {
1397    return text.replace(OBJECT_REPLACEMENT_CHARACTER, '');
1398  }
1399  
1400  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create.js
1401  /**
1402   * WordPress dependencies
1403   */
1404  
1405  
1406  /**
1407   * Internal dependencies
1408   */
1409  
1410  
1411  
1412  
1413  
1414  
1415  
1416  /** @typedef {import('./types').RichTextValue} RichTextValue */
1417  
1418  function createEmptyValue() {
1419    return {
1420      formats: [],
1421      replacements: [],
1422      text: ''
1423    };
1424  }
1425  function toFormat({
1426    tagName,
1427    attributes
1428  }) {
1429    let formatType;
1430    if (attributes && attributes.class) {
1431      formatType = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForClassName(attributes.class);
1432      if (formatType) {
1433        // Preserve any additional classes.
1434        attributes.class = ` $attributes.class} `.replace(` $formatType.className} `, ' ').trim();
1435        if (!attributes.class) {
1436          delete attributes.class;
1437        }
1438      }
1439    }
1440    if (!formatType) {
1441      formatType = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForBareElement(tagName);
1442    }
1443    if (!formatType) {
1444      return attributes ? {
1445        type: tagName,
1446        attributes
1447      } : {
1448        type: tagName
1449      };
1450    }
1451    if (formatType.__experimentalCreatePrepareEditableTree && !formatType.__experimentalCreateOnChangeEditableValue) {
1452      return null;
1453    }
1454    if (!attributes) {
1455      return {
1456        formatType,
1457        type: formatType.name,
1458        tagName
1459      };
1460    }
1461    const registeredAttributes = {};
1462    const unregisteredAttributes = {};
1463    const _attributes = {
1464      ...attributes
1465    };
1466    for (const key in formatType.attributes) {
1467      const name = formatType.attributes[key];
1468      registeredAttributes[key] = _attributes[name];
1469  
1470      // delete the attribute and what's left is considered
1471      // to be unregistered.
1472      delete _attributes[name];
1473      if (typeof registeredAttributes[key] === 'undefined') {
1474        delete registeredAttributes[key];
1475      }
1476    }
1477    for (const name in _attributes) {
1478      unregisteredAttributes[name] = attributes[name];
1479    }
1480    if (formatType.contentEditable === false) {
1481      delete unregisteredAttributes.contenteditable;
1482    }
1483    return {
1484      formatType,
1485      type: formatType.name,
1486      tagName,
1487      attributes: registeredAttributes,
1488      unregisteredAttributes
1489    };
1490  }
1491  
1492  /**
1493   * The RichTextData class is used to instantiate a wrapper around rich text
1494   * values, with methods that can be used to transform or manipulate the data.
1495   *
1496   * - Create an empty instance: `new RichTextData()`.
1497   * - Create one from an HTML string: `RichTextData.fromHTMLString(
1498   *   '<em>hello</em>' )`.
1499   * - Create one from a wrapper HTMLElement: `RichTextData.fromHTMLElement(
1500   *   document.querySelector( 'p' ) )`.
1501   * - Create one from plain text: `RichTextData.fromPlainText( '1\n2' )`.
1502   * - Create one from a rich text value: `new RichTextData( { text: '...',
1503   *   formats: [ ... ] } )`.
1504   *
1505   * @todo Add methods to manipulate the data, such as applyFormat, slice etc.
1506   */
1507  class RichTextData {
1508    #value;
1509    static empty() {
1510      return new RichTextData();
1511    }
1512    static fromPlainText(text) {
1513      return new RichTextData(create({
1514        text
1515      }));
1516    }
1517    static fromHTMLString(html) {
1518      return new RichTextData(create({
1519        html
1520      }));
1521    }
1522    static fromHTMLElement(htmlElement, options = {}) {
1523      const {
1524        preserveWhiteSpace = false
1525      } = options;
1526      const element = preserveWhiteSpace ? htmlElement : collapseWhiteSpace(htmlElement);
1527      const richTextData = new RichTextData(create({
1528        element
1529      }));
1530      Object.defineProperty(richTextData, 'originalHTML', {
1531        value: htmlElement.innerHTML
1532      });
1533      return richTextData;
1534    }
1535    constructor(init = createEmptyValue()) {
1536      this.#value = init;
1537    }
1538    toPlainText() {
1539      return getTextContent(this.#value);
1540    }
1541    // We could expose `toHTMLElement` at some point as well, but we'd only use
1542    // it internally.
1543    toHTMLString({
1544      preserveWhiteSpace
1545    } = {}) {
1546      return this.originalHTML || toHTMLString({
1547        value: this.#value,
1548        preserveWhiteSpace
1549      });
1550    }
1551    valueOf() {
1552      return this.toHTMLString();
1553    }
1554    toString() {
1555      return this.toHTMLString();
1556    }
1557    toJSON() {
1558      return this.toHTMLString();
1559    }
1560    get length() {
1561      return this.text.length;
1562    }
1563    get formats() {
1564      return this.#value.formats;
1565    }
1566    get replacements() {
1567      return this.#value.replacements;
1568    }
1569    get text() {
1570      return this.#value.text;
1571    }
1572  }
1573  for (const name of Object.getOwnPropertyNames(String.prototype)) {
1574    if (RichTextData.prototype.hasOwnProperty(name)) {
1575      continue;
1576    }
1577    Object.defineProperty(RichTextData.prototype, name, {
1578      value(...args) {
1579        // Should we convert back to RichTextData?
1580        return this.toHTMLString()[name](...args);
1581      }
1582    });
1583  }
1584  
1585  /**
1586   * Create a RichText value from an `Element` tree (DOM), an HTML string or a
1587   * plain text string, with optionally a `Range` object to set the selection. If
1588   * called without any input, an empty value will be created. The optional
1589   * functions can be used to filter out content.
1590   *
1591   * A value will have the following shape, which you are strongly encouraged not
1592   * to modify without the use of helper functions:
1593   *
1594   * ```js
1595   * {
1596   *   text: string,
1597   *   formats: Array,
1598   *   replacements: Array,
1599   *   ?start: number,
1600   *   ?end: number,
1601   * }
1602   * ```
1603   *
1604   * As you can see, text and formatting are separated. `text` holds the text,
1605   * including any replacement characters for objects and lines. `formats`,
1606   * `objects` and `lines` are all sparse arrays of the same length as `text`. It
1607   * holds information about the formatting at the relevant text indices. Finally
1608   * `start` and `end` state which text indices are selected. They are only
1609   * provided if a `Range` was given.
1610   *
1611   * @param {Object}  [$1]                          Optional named arguments.
1612   * @param {Element} [$1.element]                  Element to create value from.
1613   * @param {string}  [$1.text]                     Text to create value from.
1614   * @param {string}  [$1.html]                     HTML to create value from.
1615   * @param {Range}   [$1.range]                    Range to create value from.
1616   * @param {boolean} [$1.__unstableIsEditableTree]
1617   * @return {RichTextValue} A rich text value.
1618   */
1619  function create({
1620    element,
1621    text,
1622    html,
1623    range,
1624    __unstableIsEditableTree: isEditableTree
1625  } = {}) {
1626    if (html instanceof RichTextData) {
1627      return {
1628        text: html.text,
1629        formats: html.formats,
1630        replacements: html.replacements
1631      };
1632    }
1633    if (typeof text === 'string' && text.length > 0) {
1634      return {
1635        formats: Array(text.length),
1636        replacements: Array(text.length),
1637        text
1638      };
1639    }
1640    if (typeof html === 'string' && html.length > 0) {
1641      // It does not matter which document this is, we're just using it to
1642      // parse.
1643      element = createElement(document, html);
1644    }
1645    if (typeof element !== 'object') {
1646      return createEmptyValue();
1647    }
1648    return createFromElement({
1649      element,
1650      range,
1651      isEditableTree
1652    });
1653  }
1654  
1655  /**
1656   * Helper to accumulate the value's selection start and end from the current
1657   * node and range.
1658   *
1659   * @param {Object} accumulator Object to accumulate into.
1660   * @param {Node}   node        Node to create value with.
1661   * @param {Range}  range       Range to create value with.
1662   * @param {Object} value       Value that is being accumulated.
1663   */
1664  function accumulateSelection(accumulator, node, range, value) {
1665    if (!range) {
1666      return;
1667    }
1668    const {
1669      parentNode
1670    } = node;
1671    const {
1672      startContainer,
1673      startOffset,
1674      endContainer,
1675      endOffset
1676    } = range;
1677    const currentLength = accumulator.text.length;
1678  
1679    // Selection can be extracted from value.
1680    if (value.start !== undefined) {
1681      accumulator.start = currentLength + value.start;
1682      // Range indicates that the current node has selection.
1683    } else if (node === startContainer && node.nodeType === node.TEXT_NODE) {
1684      accumulator.start = currentLength + startOffset;
1685      // Range indicates that the current node is selected.
1686    } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset]) {
1687      accumulator.start = currentLength;
1688      // Range indicates that the selection is after the current node.
1689    } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset - 1]) {
1690      accumulator.start = currentLength + value.text.length;
1691      // Fallback if no child inside handled the selection.
1692    } else if (node === startContainer) {
1693      accumulator.start = currentLength;
1694    }
1695  
1696    // Selection can be extracted from value.
1697    if (value.end !== undefined) {
1698      accumulator.end = currentLength + value.end;
1699      // Range indicates that the current node has selection.
1700    } else if (node === endContainer && node.nodeType === node.TEXT_NODE) {
1701      accumulator.end = currentLength + endOffset;
1702      // Range indicates that the current node is selected.
1703    } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset - 1]) {
1704      accumulator.end = currentLength + value.text.length;
1705      // Range indicates that the selection is before the current node.
1706    } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset]) {
1707      accumulator.end = currentLength;
1708      // Fallback if no child inside handled the selection.
1709    } else if (node === endContainer) {
1710      accumulator.end = currentLength + endOffset;
1711    }
1712  }
1713  
1714  /**
1715   * Adjusts the start and end offsets from a range based on a text filter.
1716   *
1717   * @param {Node}     node   Node of which the text should be filtered.
1718   * @param {Range}    range  The range to filter.
1719   * @param {Function} filter Function to use to filter the text.
1720   *
1721   * @return {Object|void} Object containing range properties.
1722   */
1723  function filterRange(node, range, filter) {
1724    if (!range) {
1725      return;
1726    }
1727    const {
1728      startContainer,
1729      endContainer
1730    } = range;
1731    let {
1732      startOffset,
1733      endOffset
1734    } = range;
1735    if (node === startContainer) {
1736      startOffset = filter(node.nodeValue.slice(0, startOffset)).length;
1737    }
1738    if (node === endContainer) {
1739      endOffset = filter(node.nodeValue.slice(0, endOffset)).length;
1740    }
1741    return {
1742      startContainer,
1743      startOffset,
1744      endContainer,
1745      endOffset
1746    };
1747  }
1748  
1749  /**
1750   * Collapse any whitespace used for HTML formatting to one space character,
1751   * because it will also be displayed as such by the browser.
1752   *
1753   * We need to strip it from the content because we use white-space: pre-wrap for
1754   * displaying editable rich text. Without using white-space: pre-wrap, the
1755   * browser will litter the content with non breaking spaces, among other issues.
1756   * See packages/rich-text/src/component/use-default-style.js.
1757   *
1758   * @see
1759   * https://developer.mozilla.org/en-US/docs/Web/CSS/white-space-collapse#collapsing_of_white_space
1760   *
1761   * @param {HTMLElement} element
1762   * @param {boolean}     isRoot
1763   *
1764   * @return {HTMLElement} New element with collapsed whitespace.
1765   */
1766  function collapseWhiteSpace(element, isRoot = true) {
1767    const clone = element.cloneNode(true);
1768    clone.normalize();
1769    Array.from(clone.childNodes).forEach((node, i, nodes) => {
1770      if (node.nodeType === node.TEXT_NODE) {
1771        let newNodeValue = node.nodeValue;
1772        if (/[\n\t\r\f]/.test(newNodeValue)) {
1773          newNodeValue = newNodeValue.replace(/[\n\t\r\f]+/g, ' ');
1774        }
1775        if (newNodeValue.indexOf('  ') !== -1) {
1776          newNodeValue = newNodeValue.replace(/ {2,}/g, ' ');
1777        }
1778        if (i === 0 && newNodeValue.startsWith(' ')) {
1779          newNodeValue = newNodeValue.slice(1);
1780        } else if (isRoot && i === nodes.length - 1 && newNodeValue.endsWith(' ')) {
1781          newNodeValue = newNodeValue.slice(0, -1);
1782        }
1783        node.nodeValue = newNodeValue;
1784      } else if (node.nodeType === node.ELEMENT_NODE) {
1785        collapseWhiteSpace(node, false);
1786      }
1787    });
1788    return clone;
1789  }
1790  
1791  /**
1792   * We need to normalise line breaks to `\n` so they are consistent across
1793   * platforms and serialised properly. Not removing \r would cause it to
1794   * linger and result in double line breaks when whitespace is preserved.
1795   */
1796  const CARRIAGE_RETURN = '\r';
1797  
1798  /**
1799   * Removes reserved characters used by rich-text (zero width non breaking spaces
1800   * added by `toTree` and object replacement characters).
1801   *
1802   * @param {string} string
1803   */
1804  function removeReservedCharacters(string) {
1805    // with the global flag, note that we should create a new regex each time OR
1806    // reset lastIndex state.
1807    return string.replace(new RegExp(`[$ZWNBSP}$OBJECT_REPLACEMENT_CHARACTER}$CARRIAGE_RETURN}]`, 'gu'), '');
1808  }
1809  
1810  /**
1811   * Creates a Rich Text value from a DOM element and range.
1812   *
1813   * @param {Object}  $1                  Named argements.
1814   * @param {Element} [$1.element]        Element to create value from.
1815   * @param {Range}   [$1.range]          Range to create value from.
1816   * @param {boolean} [$1.isEditableTree]
1817   *
1818   * @return {RichTextValue} A rich text value.
1819   */
1820  function createFromElement({
1821    element,
1822    range,
1823    isEditableTree
1824  }) {
1825    const accumulator = createEmptyValue();
1826    if (!element) {
1827      return accumulator;
1828    }
1829    if (!element.hasChildNodes()) {
1830      accumulateSelection(accumulator, element, range, createEmptyValue());
1831      return accumulator;
1832    }
1833    const length = element.childNodes.length;
1834  
1835    // Optimise for speed.
1836    for (let index = 0; index < length; index++) {
1837      const node = element.childNodes[index];
1838      const tagName = node.nodeName.toLowerCase();
1839      if (node.nodeType === node.TEXT_NODE) {
1840        const text = removeReservedCharacters(node.nodeValue);
1841        range = filterRange(node, range, removeReservedCharacters);
1842        accumulateSelection(accumulator, node, range, {
1843          text
1844        });
1845        // Create a sparse array of the same length as `text`, in which
1846        // formats can be added.
1847        accumulator.formats.length += text.length;
1848        accumulator.replacements.length += text.length;
1849        accumulator.text += text;
1850        continue;
1851      }
1852      if (node.nodeType !== node.ELEMENT_NODE) {
1853        continue;
1854      }
1855      if (isEditableTree &&
1856      // Ignore any line breaks that are not inserted by us.
1857      tagName === 'br' && !node.getAttribute('data-rich-text-line-break')) {
1858        accumulateSelection(accumulator, node, range, createEmptyValue());
1859        continue;
1860      }
1861      if (tagName === 'script') {
1862        const value = {
1863          formats: [,],
1864          replacements: [{
1865            type: tagName,
1866            attributes: {
1867              'data-rich-text-script': node.getAttribute('data-rich-text-script') || encodeURIComponent(node.innerHTML)
1868            }
1869          }],
1870          text: OBJECT_REPLACEMENT_CHARACTER
1871        };
1872        accumulateSelection(accumulator, node, range, value);
1873        mergePair(accumulator, value);
1874        continue;
1875      }
1876      if (tagName === 'br') {
1877        accumulateSelection(accumulator, node, range, createEmptyValue());
1878        mergePair(accumulator, create({
1879          text: '\n'
1880        }));
1881        continue;
1882      }
1883      const format = toFormat({
1884        tagName,
1885        attributes: getAttributes({
1886          element: node
1887        })
1888      });
1889  
1890      // When a format type is declared as not editable, replace it with an
1891      // object replacement character and preserve the inner HTML.
1892      if (format?.formatType?.contentEditable === false) {
1893        delete format.formatType;
1894        accumulateSelection(accumulator, node, range, createEmptyValue());
1895        mergePair(accumulator, {
1896          formats: [,],
1897          replacements: [{
1898            ...format,
1899            innerHTML: node.innerHTML
1900          }],
1901          text: OBJECT_REPLACEMENT_CHARACTER
1902        });
1903        continue;
1904      }
1905      if (format) delete format.formatType;
1906      const value = createFromElement({
1907        element: node,
1908        range,
1909        isEditableTree
1910      });
1911      accumulateSelection(accumulator, node, range, value);
1912  
1913      // Ignore any placeholders, but keep their content since the browser
1914      // might insert text inside them when the editable element is flex.
1915      if (!format || node.getAttribute('data-rich-text-placeholder')) {
1916        mergePair(accumulator, value);
1917      } else if (value.text.length === 0) {
1918        if (format.attributes) {
1919          mergePair(accumulator, {
1920            formats: [,],
1921            replacements: [format],
1922            text: OBJECT_REPLACEMENT_CHARACTER
1923          });
1924        }
1925      } else {
1926        // Indices should share a reference to the same formats array.
1927        // Only create a new reference if `formats` changes.
1928        function mergeFormats(formats) {
1929          if (mergeFormats.formats === formats) {
1930            return mergeFormats.newFormats;
1931          }
1932          const newFormats = formats ? [format, ...formats] : [format];
1933          mergeFormats.formats = formats;
1934          mergeFormats.newFormats = newFormats;
1935          return newFormats;
1936        }
1937  
1938        // Since the formats parameter can be `undefined`, preset
1939        // `mergeFormats` with a new reference.
1940        mergeFormats.newFormats = [format];
1941        mergePair(accumulator, {
1942          ...value,
1943          formats: Array.from(value.formats, mergeFormats)
1944        });
1945      }
1946    }
1947    return accumulator;
1948  }
1949  
1950  /**
1951   * Gets the attributes of an element in object shape.
1952   *
1953   * @param {Object}  $1         Named argements.
1954   * @param {Element} $1.element Element to get attributes from.
1955   *
1956   * @return {Object|void} Attribute object or `undefined` if the element has no
1957   *                       attributes.
1958   */
1959  function getAttributes({
1960    element
1961  }) {
1962    if (!element.hasAttributes()) {
1963      return;
1964    }
1965    const length = element.attributes.length;
1966    let accumulator;
1967  
1968    // Optimise for speed.
1969    for (let i = 0; i < length; i++) {
1970      const {
1971        name,
1972        value
1973      } = element.attributes[i];
1974      if (name.indexOf('data-rich-text-') === 0) {
1975        continue;
1976      }
1977      const safeName = /^on/i.test(name) ? 'data-disable-rich-text-' + name : name;
1978      accumulator = accumulator || {};
1979      accumulator[safeName] = value;
1980    }
1981    return accumulator;
1982  }
1983  
1984  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/concat.js
1985  /**
1986   * Internal dependencies
1987   */
1988  
1989  
1990  
1991  
1992  /** @typedef {import('./types').RichTextValue} RichTextValue */
1993  
1994  /**
1995   * Concats a pair of rich text values. Not that this mutates `a` and does NOT
1996   * normalise formats!
1997   *
1998   * @param {Object} a Value to mutate.
1999   * @param {Object} b Value to add read from.
2000   *
2001   * @return {Object} `a`, mutated.
2002   */
2003  function mergePair(a, b) {
2004    a.formats = a.formats.concat(b.formats);
2005    a.replacements = a.replacements.concat(b.replacements);
2006    a.text += b.text;
2007    return a;
2008  }
2009  
2010  /**
2011   * Combine all Rich Text values into one. This is similar to
2012   * `String.prototype.concat`.
2013   *
2014   * @param {...RichTextValue} values Objects to combine.
2015   *
2016   * @return {RichTextValue} A new value combining all given records.
2017   */
2018  function concat(...values) {
2019    return normaliseFormats(values.reduce(mergePair, create()));
2020  }
2021  
2022  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-format.js
2023  /**
2024   * Internal dependencies
2025   */
2026  
2027  
2028  /** @typedef {import('./types').RichTextValue} RichTextValue */
2029  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
2030  
2031  /**
2032   * Gets the format object by type at the start of the selection. This can be
2033   * used to get e.g. the URL of a link format at the current selection, but also
2034   * to check if a format is active at the selection. Returns undefined if there
2035   * is no format at the selection.
2036   *
2037   * @param {RichTextValue} value      Value to inspect.
2038   * @param {string}        formatType Format type to look for.
2039   *
2040   * @return {RichTextFormat|undefined} Active format object of the specified
2041   *                                    type, or undefined.
2042   */
2043  function getActiveFormat(value, formatType) {
2044    return getActiveFormats(value).find(({
2045      type
2046    }) => type === formatType);
2047  }
2048  
2049  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-object.js
2050  /**
2051   * Internal dependencies
2052   */
2053  
2054  
2055  
2056  /** @typedef {import('./types').RichTextValue} RichTextValue */
2057  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
2058  
2059  /**
2060   * Gets the active object, if there is any.
2061   *
2062   * @param {RichTextValue} value Value to inspect.
2063   *
2064   * @return {RichTextFormat|void} Active object, or undefined.
2065   */
2066  function getActiveObject({
2067    start,
2068    end,
2069    replacements,
2070    text
2071  }) {
2072    if (start + 1 !== end || text[start] !== OBJECT_REPLACEMENT_CHARACTER) {
2073      return;
2074    }
2075    return replacements[start];
2076  }
2077  
2078  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-collapsed.js
2079  /**
2080   * Internal dependencies
2081   */
2082  
2083  /**
2084   * Check if the selection of a Rich Text value is collapsed or not. Collapsed
2085   * means that no characters are selected, but there is a caret present. If there
2086   * is no selection, `undefined` will be returned. This is similar to
2087   * `window.getSelection().isCollapsed()`.
2088   *
2089   * @param props       The rich text value to check.
2090   * @param props.start
2091   * @param props.end
2092   * @return True if the selection is collapsed, false if not, undefined if there is no selection.
2093   */
2094  function isCollapsed({
2095    start,
2096    end
2097  }) {
2098    if (start === undefined || end === undefined) {
2099      return;
2100    }
2101    return start === end;
2102  }
2103  
2104  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-empty.js
2105  /** @typedef {import('./types').RichTextValue} RichTextValue */
2106  
2107  /**
2108   * Check if a Rich Text value is Empty, meaning it contains no text or any
2109   * objects (such as images).
2110   *
2111   * @param {RichTextValue} value Value to use.
2112   *
2113   * @return {boolean} True if the value is empty, false if not.
2114   */
2115  function isEmpty({
2116    text
2117  }) {
2118    return text.length === 0;
2119  }
2120  
2121  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/join.js
2122  /**
2123   * Internal dependencies
2124   */
2125  
2126  
2127  
2128  
2129  /** @typedef {import('./types').RichTextValue} RichTextValue */
2130  
2131  /**
2132   * Combine an array of Rich Text values into one, optionally separated by
2133   * `separator`, which can be a Rich Text value, HTML string, or plain text
2134   * string. This is similar to `Array.prototype.join`.
2135   *
2136   * @param {Array<RichTextValue>} values      An array of values to join.
2137   * @param {string|RichTextValue} [separator] Separator string or value.
2138   *
2139   * @return {RichTextValue} A new combined value.
2140   */
2141  function join(values, separator = '') {
2142    if (typeof separator === 'string') {
2143      separator = create({
2144        text: separator
2145      });
2146    }
2147    return normaliseFormats(values.reduce((accumlator, {
2148      formats,
2149      replacements,
2150      text
2151    }) => ({
2152      formats: accumlator.formats.concat(separator.formats, formats),
2153      replacements: accumlator.replacements.concat(separator.replacements, replacements),
2154      text: accumlator.text + separator.text + text
2155    })));
2156  }
2157  
2158  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/register-format-type.js
2159  /**
2160   * WordPress dependencies
2161   */
2162  
2163  /**
2164   * Internal dependencies
2165   */
2166  
2167  /**
2168   * @typedef {Object} WPFormat
2169   *
2170   * @property {string}        name        A string identifying the format. Must be
2171   *                                       unique across all registered formats.
2172   * @property {string}        tagName     The HTML tag this format will wrap the
2173   *                                       selection with.
2174   * @property {boolean}       interactive Whether format makes content interactive or not.
2175   * @property {string | null} [className] A class to match the format.
2176   * @property {string}        title       Name of the format.
2177   * @property {Function}      edit        Should return a component for the user to
2178   *                                       interact with the new registered format.
2179   */
2180  
2181  /**
2182   * Registers a new format provided a unique name and an object defining its
2183   * behavior.
2184   *
2185   * @param {string}   name     Format name.
2186   * @param {WPFormat} settings Format settings.
2187   *
2188   * @return {WPFormat|undefined} The format, if it has been successfully
2189   *                              registered; otherwise `undefined`.
2190   */
2191  function registerFormatType(name, settings) {
2192    settings = {
2193      name,
2194      ...settings
2195    };
2196    if (typeof settings.name !== 'string') {
2197      window.console.error('Format names must be strings.');
2198      return;
2199    }
2200    if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(settings.name)) {
2201      window.console.error('Format names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-format');
2202      return;
2203    }
2204    if ((0,external_wp_data_namespaceObject.select)(store).getFormatType(settings.name)) {
2205      window.console.error('Format "' + settings.name + '" is already registered.');
2206      return;
2207    }
2208    if (typeof settings.tagName !== 'string' || settings.tagName === '') {
2209      window.console.error('Format tag names must be a string.');
2210      return;
2211    }
2212    if ((typeof settings.className !== 'string' || settings.className === '') && settings.className !== null) {
2213      window.console.error('Format class names must be a string, or null to handle bare elements.');
2214      return;
2215    }
2216    if (!/^[_a-zA-Z]+[a-zA-Z0-9_-]*$/.test(settings.className)) {
2217      window.console.error('A class name must begin with a letter, followed by any number of hyphens, underscores, letters, or numbers.');
2218      return;
2219    }
2220    if (settings.className === null) {
2221      const formatTypeForBareElement = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForBareElement(settings.tagName);
2222      if (formatTypeForBareElement && formatTypeForBareElement.name !== 'core/unknown') {
2223        window.console.error(`Format "$formatTypeForBareElement.name}" is already registered to handle bare tag name "$settings.tagName}".`);
2224        return;
2225      }
2226    } else {
2227      const formatTypeForClassName = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForClassName(settings.className);
2228      if (formatTypeForClassName) {
2229        window.console.error(`Format "$formatTypeForClassName.name}" is already registered to handle class name "$settings.className}".`);
2230        return;
2231      }
2232    }
2233    if (!('title' in settings) || settings.title === '') {
2234      window.console.error('The format "' + settings.name + '" must have a title.');
2235      return;
2236    }
2237    if ('keywords' in settings && settings.keywords.length > 3) {
2238      window.console.error('The format "' + settings.name + '" can have a maximum of 3 keywords.');
2239      return;
2240    }
2241    if (typeof settings.title !== 'string') {
2242      window.console.error('Format titles must be strings.');
2243      return;
2244    }
2245    (0,external_wp_data_namespaceObject.dispatch)(store).addFormatTypes(settings);
2246    return settings;
2247  }
2248  
2249  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove-format.js
2250  /**
2251   * Internal dependencies
2252   */
2253  
2254  
2255  
2256  /** @typedef {import('./types').RichTextValue} RichTextValue */
2257  
2258  /**
2259   * Remove any format object from a Rich Text value by type from the given
2260   * `startIndex` to the given `endIndex`. Indices are retrieved from the
2261   * selection if none are provided.
2262   *
2263   * @param {RichTextValue} value        Value to modify.
2264   * @param {string}        formatType   Format type to remove.
2265   * @param {number}        [startIndex] Start index.
2266   * @param {number}        [endIndex]   End index.
2267   *
2268   * @return {RichTextValue} A new value with the format applied.
2269   */
2270  function removeFormat(value, formatType, startIndex = value.start, endIndex = value.end) {
2271    const {
2272      formats,
2273      activeFormats
2274    } = value;
2275    const newFormats = formats.slice();
2276  
2277    // If the selection is collapsed, expand start and end to the edges of the
2278    // format.
2279    if (startIndex === endIndex) {
2280      const format = newFormats[startIndex]?.find(({
2281        type
2282      }) => type === formatType);
2283      if (format) {
2284        while (newFormats[startIndex]?.find(newFormat => newFormat === format)) {
2285          filterFormats(newFormats, startIndex, formatType);
2286          startIndex--;
2287        }
2288        endIndex++;
2289        while (newFormats[endIndex]?.find(newFormat => newFormat === format)) {
2290          filterFormats(newFormats, endIndex, formatType);
2291          endIndex++;
2292        }
2293      }
2294    } else {
2295      for (let i = startIndex; i < endIndex; i++) {
2296        if (newFormats[i]) {
2297          filterFormats(newFormats, i, formatType);
2298        }
2299      }
2300    }
2301    return normaliseFormats({
2302      ...value,
2303      formats: newFormats,
2304      activeFormats: activeFormats?.filter(({
2305        type
2306      }) => type !== formatType) || []
2307    });
2308  }
2309  function filterFormats(formats, index, formatType) {
2310    const newFormats = formats[index].filter(({
2311      type
2312    }) => type !== formatType);
2313    if (newFormats.length) {
2314      formats[index] = newFormats;
2315    } else {
2316      delete formats[index];
2317    }
2318  }
2319  
2320  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert.js
2321  /**
2322   * Internal dependencies
2323   */
2324  
2325  
2326  
2327  
2328  /** @typedef {import('./types').RichTextValue} RichTextValue */
2329  
2330  /**
2331   * Insert a Rich Text value, an HTML string, or a plain text string, into a
2332   * Rich Text value at the given `startIndex`. Any content between `startIndex`
2333   * and `endIndex` will be removed. Indices are retrieved from the selection if
2334   * none are provided.
2335   *
2336   * @param {RichTextValue}        value         Value to modify.
2337   * @param {RichTextValue|string} valueToInsert Value to insert.
2338   * @param {number}               [startIndex]  Start index.
2339   * @param {number}               [endIndex]    End index.
2340   *
2341   * @return {RichTextValue} A new value with the value inserted.
2342   */
2343  function insert(value, valueToInsert, startIndex = value.start, endIndex = value.end) {
2344    const {
2345      formats,
2346      replacements,
2347      text
2348    } = value;
2349    if (typeof valueToInsert === 'string') {
2350      valueToInsert = create({
2351        text: valueToInsert
2352      });
2353    }
2354    const index = startIndex + valueToInsert.text.length;
2355    return normaliseFormats({
2356      formats: formats.slice(0, startIndex).concat(valueToInsert.formats, formats.slice(endIndex)),
2357      replacements: replacements.slice(0, startIndex).concat(valueToInsert.replacements, replacements.slice(endIndex)),
2358      text: text.slice(0, startIndex) + valueToInsert.text + text.slice(endIndex),
2359      start: index,
2360      end: index
2361    });
2362  }
2363  
2364  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove.js
2365  /**
2366   * Internal dependencies
2367   */
2368  
2369  
2370  
2371  
2372  /** @typedef {import('./types').RichTextValue} RichTextValue */
2373  
2374  /**
2375   * Remove content from a Rich Text value between the given `startIndex` and
2376   * `endIndex`. Indices are retrieved from the selection if none are provided.
2377   *
2378   * @param {RichTextValue} value        Value to modify.
2379   * @param {number}        [startIndex] Start index.
2380   * @param {number}        [endIndex]   End index.
2381   *
2382   * @return {RichTextValue} A new value with the content removed.
2383   */
2384  function remove_remove(value, startIndex, endIndex) {
2385    return insert(value, create(), startIndex, endIndex);
2386  }
2387  
2388  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/replace.js
2389  /**
2390   * Internal dependencies
2391   */
2392  
2393  
2394  
2395  /** @typedef {import('./types').RichTextValue} RichTextValue */
2396  
2397  /**
2398   * Search a Rich Text value and replace the match(es) with `replacement`. This
2399   * is similar to `String.prototype.replace`.
2400   *
2401   * @param {RichTextValue}   value       The value to modify.
2402   * @param {RegExp|string}   pattern     A RegExp object or literal. Can also be
2403   *                                      a string. It is treated as a verbatim
2404   *                                      string and is not interpreted as a
2405   *                                      regular expression. Only the first
2406   *                                      occurrence will be replaced.
2407   * @param {Function|string} replacement The match or matches are replaced with
2408   *                                      the specified or the value returned by
2409   *                                      the specified function.
2410   *
2411   * @return {RichTextValue} A new value with replacements applied.
2412   */
2413  function replace_replace({
2414    formats,
2415    replacements,
2416    text,
2417    start,
2418    end
2419  }, pattern, replacement) {
2420    text = text.replace(pattern, (match, ...rest) => {
2421      const offset = rest[rest.length - 2];
2422      let newText = replacement;
2423      let newFormats;
2424      let newReplacements;
2425      if (typeof newText === 'function') {
2426        newText = replacement(match, ...rest);
2427      }
2428      if (typeof newText === 'object') {
2429        newFormats = newText.formats;
2430        newReplacements = newText.replacements;
2431        newText = newText.text;
2432      } else {
2433        newFormats = Array(newText.length);
2434        newReplacements = Array(newText.length);
2435        if (formats[offset]) {
2436          newFormats = newFormats.fill(formats[offset]);
2437        }
2438      }
2439      formats = formats.slice(0, offset).concat(newFormats, formats.slice(offset + match.length));
2440      replacements = replacements.slice(0, offset).concat(newReplacements, replacements.slice(offset + match.length));
2441      if (start) {
2442        start = end = offset + newText.length;
2443      }
2444      return newText;
2445    });
2446    return normaliseFormats({
2447      formats,
2448      replacements,
2449      text,
2450      start,
2451      end
2452    });
2453  }
2454  
2455  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert-object.js
2456  /**
2457   * Internal dependencies
2458   */
2459  
2460  
2461  
2462  
2463  /** @typedef {import('./types').RichTextValue} RichTextValue */
2464  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
2465  
2466  /**
2467   * Insert a format as an object into a Rich Text value at the given
2468   * `startIndex`. Any content between `startIndex` and `endIndex` will be
2469   * removed. Indices are retrieved from the selection if none are provided.
2470   *
2471   * @param {RichTextValue}  value          Value to modify.
2472   * @param {RichTextFormat} formatToInsert Format to insert as object.
2473   * @param {number}         [startIndex]   Start index.
2474   * @param {number}         [endIndex]     End index.
2475   *
2476   * @return {RichTextValue} A new value with the object inserted.
2477   */
2478  function insertObject(value, formatToInsert, startIndex, endIndex) {
2479    const valueToInsert = {
2480      formats: [,],
2481      replacements: [formatToInsert],
2482      text: OBJECT_REPLACEMENT_CHARACTER
2483    };
2484    return insert(value, valueToInsert, startIndex, endIndex);
2485  }
2486  
2487  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/slice.js
2488  /** @typedef {import('./types').RichTextValue} RichTextValue */
2489  
2490  /**
2491   * Slice a Rich Text value from `startIndex` to `endIndex`. Indices are
2492   * retrieved from the selection if none are provided. This is similar to
2493   * `String.prototype.slice`.
2494   *
2495   * @param {RichTextValue} value        Value to modify.
2496   * @param {number}        [startIndex] Start index.
2497   * @param {number}        [endIndex]   End index.
2498   *
2499   * @return {RichTextValue} A new extracted value.
2500   */
2501  function slice(value, startIndex = value.start, endIndex = value.end) {
2502    const {
2503      formats,
2504      replacements,
2505      text
2506    } = value;
2507    if (startIndex === undefined || endIndex === undefined) {
2508      return {
2509        ...value
2510      };
2511    }
2512    return {
2513      formats: formats.slice(startIndex, endIndex),
2514      replacements: replacements.slice(startIndex, endIndex),
2515      text: text.slice(startIndex, endIndex)
2516    };
2517  }
2518  
2519  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/split.js
2520  /**
2521   * Internal dependencies
2522   */
2523  
2524  /** @typedef {import('./types').RichTextValue} RichTextValue */
2525  
2526  /**
2527   * Split a Rich Text value in two at the given `startIndex` and `endIndex`, or
2528   * split at the given separator. This is similar to `String.prototype.split`.
2529   * Indices are retrieved from the selection if none are provided.
2530   *
2531   * @param {RichTextValue} value
2532   * @param {number|string} [string] Start index, or string at which to split.
2533   *
2534   * @return {Array<RichTextValue>|undefined} An array of new values.
2535   */
2536  function split({
2537    formats,
2538    replacements,
2539    text,
2540    start,
2541    end
2542  }, string) {
2543    if (typeof string !== 'string') {
2544      return splitAtSelection(...arguments);
2545    }
2546    let nextStart = 0;
2547    return text.split(string).map(substring => {
2548      const startIndex = nextStart;
2549      const value = {
2550        formats: formats.slice(startIndex, startIndex + substring.length),
2551        replacements: replacements.slice(startIndex, startIndex + substring.length),
2552        text: substring
2553      };
2554      nextStart += string.length + substring.length;
2555      if (start !== undefined && end !== undefined) {
2556        if (start >= startIndex && start < nextStart) {
2557          value.start = start - startIndex;
2558        } else if (start < startIndex && end > startIndex) {
2559          value.start = 0;
2560        }
2561        if (end >= startIndex && end < nextStart) {
2562          value.end = end - startIndex;
2563        } else if (start < nextStart && end > nextStart) {
2564          value.end = substring.length;
2565        }
2566      }
2567      return value;
2568    });
2569  }
2570  function splitAtSelection({
2571    formats,
2572    replacements,
2573    text,
2574    start,
2575    end
2576  }, startIndex = start, endIndex = end) {
2577    if (start === undefined || end === undefined) {
2578      return;
2579    }
2580    const before = {
2581      formats: formats.slice(0, startIndex),
2582      replacements: replacements.slice(0, startIndex),
2583      text: text.slice(0, startIndex)
2584    };
2585    const after = {
2586      formats: formats.slice(endIndex),
2587      replacements: replacements.slice(endIndex),
2588      text: text.slice(endIndex),
2589      start: 0,
2590      end: 0
2591    };
2592    return [before, after];
2593  }
2594  
2595  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-range-equal.js
2596  /**
2597   * Returns true if two ranges are equal, or false otherwise. Ranges are
2598   * considered equal if their start and end occur in the same container and
2599   * offset.
2600   *
2601   * @param {Range|null} a First range object to test.
2602   * @param {Range|null} b First range object to test.
2603   *
2604   * @return {boolean} Whether the two ranges are equal.
2605   */
2606  function isRangeEqual(a, b) {
2607    return a === b || a && b && a.startContainer === b.startContainer && a.startOffset === b.startOffset && a.endContainer === b.endContainer && a.endOffset === b.endOffset;
2608  }
2609  
2610  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-dom.js
2611  /**
2612   * Internal dependencies
2613   */
2614  
2615  
2616  
2617  
2618  
2619  /** @typedef {import('./types').RichTextValue} RichTextValue */
2620  
2621  /**
2622   * Creates a path as an array of indices from the given root node to the given
2623   * node.
2624   *
2625   * @param {Node}        node     Node to find the path of.
2626   * @param {HTMLElement} rootNode Root node to find the path from.
2627   * @param {Array}       path     Initial path to build on.
2628   *
2629   * @return {Array} The path from the root node to the node.
2630   */
2631  function createPathToNode(node, rootNode, path) {
2632    const parentNode = node.parentNode;
2633    let i = 0;
2634    while (node = node.previousSibling) {
2635      i++;
2636    }
2637    path = [i, ...path];
2638    if (parentNode !== rootNode) {
2639      path = createPathToNode(parentNode, rootNode, path);
2640    }
2641    return path;
2642  }
2643  
2644  /**
2645   * Gets a node given a path (array of indices) from the given node.
2646   *
2647   * @param {HTMLElement} node Root node to find the wanted node in.
2648   * @param {Array}       path Path (indices) to the wanted node.
2649   *
2650   * @return {Object} Object with the found node and the remaining offset (if any).
2651   */
2652  function getNodeByPath(node, path) {
2653    path = [...path];
2654    while (node && path.length > 1) {
2655      node = node.childNodes[path.shift()];
2656    }
2657    return {
2658      node,
2659      offset: path[0]
2660    };
2661  }
2662  function to_dom_append(element, child) {
2663    if (child.html !== undefined) {
2664      return element.innerHTML += child.html;
2665    }
2666    if (typeof child === 'string') {
2667      child = element.ownerDocument.createTextNode(child);
2668    }
2669    const {
2670      type,
2671      attributes
2672    } = child;
2673    if (type) {
2674      child = element.ownerDocument.createElement(type);
2675      for (const key in attributes) {
2676        child.setAttribute(key, attributes[key]);
2677      }
2678    }
2679    return element.appendChild(child);
2680  }
2681  function to_dom_appendText(node, text) {
2682    node.appendData(text);
2683  }
2684  function to_dom_getLastChild({
2685    lastChild
2686  }) {
2687    return lastChild;
2688  }
2689  function to_dom_getParent({
2690    parentNode
2691  }) {
2692    return parentNode;
2693  }
2694  function to_dom_isText(node) {
2695    return node.nodeType === node.TEXT_NODE;
2696  }
2697  function to_dom_getText({
2698    nodeValue
2699  }) {
2700    return nodeValue;
2701  }
2702  function to_dom_remove(node) {
2703    return node.parentNode.removeChild(node);
2704  }
2705  function toDom({
2706    value,
2707    prepareEditableTree,
2708    isEditableTree = true,
2709    placeholder,
2710    doc = document
2711  }) {
2712    let startPath = [];
2713    let endPath = [];
2714    if (prepareEditableTree) {
2715      value = {
2716        ...value,
2717        formats: prepareEditableTree(value)
2718      };
2719    }
2720  
2721    /**
2722     * Returns a new instance of a DOM tree upon which RichText operations can be
2723     * applied.
2724     *
2725     * Note: The current implementation will return a shared reference, reset on
2726     * each call to `createEmpty`. Therefore, you should not hold a reference to
2727     * the value to operate upon asynchronously, as it may have unexpected results.
2728     *
2729     * @return {Object} RichText tree.
2730     */
2731    const createEmpty = () => createElement(doc, '');
2732    const tree = toTree({
2733      value,
2734      createEmpty,
2735      append: to_dom_append,
2736      getLastChild: to_dom_getLastChild,
2737      getParent: to_dom_getParent,
2738      isText: to_dom_isText,
2739      getText: to_dom_getText,
2740      remove: to_dom_remove,
2741      appendText: to_dom_appendText,
2742      onStartIndex(body, pointer) {
2743        startPath = createPathToNode(pointer, body, [pointer.nodeValue.length]);
2744      },
2745      onEndIndex(body, pointer) {
2746        endPath = createPathToNode(pointer, body, [pointer.nodeValue.length]);
2747      },
2748      isEditableTree,
2749      placeholder
2750    });
2751    return {
2752      body: tree,
2753      selection: {
2754        startPath,
2755        endPath
2756      }
2757    };
2758  }
2759  
2760  /**
2761   * Create an `Element` tree from a Rich Text value and applies the difference to
2762   * the `Element` tree contained by `current`.
2763   *
2764   * @param {Object}        $1                       Named arguments.
2765   * @param {RichTextValue} $1.value                 Value to apply.
2766   * @param {HTMLElement}   $1.current               The live root node to apply the element tree to.
2767   * @param {Function}      [$1.prepareEditableTree] Function to filter editorable formats.
2768   * @param {boolean}       [$1.__unstableDomOnly]   Only apply elements, no selection.
2769   * @param {string}        [$1.placeholder]         Placeholder text.
2770   */
2771  function apply({
2772    value,
2773    current,
2774    prepareEditableTree,
2775    __unstableDomOnly,
2776    placeholder
2777  }) {
2778    // Construct a new element tree in memory.
2779    const {
2780      body,
2781      selection
2782    } = toDom({
2783      value,
2784      prepareEditableTree,
2785      placeholder,
2786      doc: current.ownerDocument
2787    });
2788    applyValue(body, current);
2789    if (value.start !== undefined && !__unstableDomOnly) {
2790      applySelection(selection, current);
2791    }
2792  }
2793  function applyValue(future, current) {
2794    let i = 0;
2795    let futureChild;
2796    while (futureChild = future.firstChild) {
2797      const currentChild = current.childNodes[i];
2798      if (!currentChild) {
2799        current.appendChild(futureChild);
2800      } else if (!currentChild.isEqualNode(futureChild)) {
2801        if (currentChild.nodeName !== futureChild.nodeName || currentChild.nodeType === currentChild.TEXT_NODE && currentChild.data !== futureChild.data) {
2802          current.replaceChild(futureChild, currentChild);
2803        } else {
2804          const currentAttributes = currentChild.attributes;
2805          const futureAttributes = futureChild.attributes;
2806          if (currentAttributes) {
2807            let ii = currentAttributes.length;
2808  
2809            // Reverse loop because `removeAttribute` on `currentChild`
2810            // changes `currentAttributes`.
2811            while (ii--) {
2812              const {
2813                name
2814              } = currentAttributes[ii];
2815              if (!futureChild.getAttribute(name)) {
2816                currentChild.removeAttribute(name);
2817              }
2818            }
2819          }
2820          if (futureAttributes) {
2821            for (let ii = 0; ii < futureAttributes.length; ii++) {
2822              const {
2823                name,
2824                value
2825              } = futureAttributes[ii];
2826              if (currentChild.getAttribute(name) !== value) {
2827                currentChild.setAttribute(name, value);
2828              }
2829            }
2830          }
2831          applyValue(futureChild, currentChild);
2832          future.removeChild(futureChild);
2833        }
2834      } else {
2835        future.removeChild(futureChild);
2836      }
2837      i++;
2838    }
2839    while (current.childNodes[i]) {
2840      current.removeChild(current.childNodes[i]);
2841    }
2842  }
2843  function applySelection({
2844    startPath,
2845    endPath
2846  }, current) {
2847    const {
2848      node: startContainer,
2849      offset: startOffset
2850    } = getNodeByPath(current, startPath);
2851    const {
2852      node: endContainer,
2853      offset: endOffset
2854    } = getNodeByPath(current, endPath);
2855    const {
2856      ownerDocument
2857    } = current;
2858    const {
2859      defaultView
2860    } = ownerDocument;
2861    const selection = defaultView.getSelection();
2862    const range = ownerDocument.createRange();
2863    range.setStart(startContainer, startOffset);
2864    range.setEnd(endContainer, endOffset);
2865    const {
2866      activeElement
2867    } = ownerDocument;
2868    if (selection.rangeCount > 0) {
2869      // If the to be added range and the live range are the same, there's no
2870      // need to remove the live range and add the equivalent range.
2871      if (isRangeEqual(range, selection.getRangeAt(0))) {
2872        return;
2873      }
2874      selection.removeAllRanges();
2875    }
2876    selection.addRange(range);
2877  
2878    // This function is not intended to cause a shift in focus. Since the above
2879    // selection manipulations may shift focus, ensure that focus is restored to
2880    // its previous state.
2881    if (activeElement !== ownerDocument.activeElement) {
2882      // The `instanceof` checks protect against edge cases where the focused
2883      // element is not of the interface HTMLElement (does not have a `focus`
2884      // or `blur` property).
2885      //
2886      // See: https://github.com/Microsoft/TypeScript/issues/5901#issuecomment-431649653
2887      if (activeElement instanceof defaultView.HTMLElement) {
2888        activeElement.focus();
2889      }
2890    }
2891  }
2892  
2893  ;// CONCATENATED MODULE: external ["wp","a11y"]
2894  const external_wp_a11y_namespaceObject = window["wp"]["a11y"];
2895  ;// CONCATENATED MODULE: external ["wp","i18n"]
2896  const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
2897  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/toggle-format.js
2898  /**
2899   * WordPress dependencies
2900   */
2901  
2902  
2903  
2904  
2905  /**
2906   * Internal dependencies
2907   */
2908  
2909  
2910  
2911  
2912  
2913  /** @typedef {import('./types').RichTextValue} RichTextValue */
2914  /** @typedef {import('./types').RichTextFormat} RichTextFormat */
2915  
2916  /**
2917   * Toggles a format object to a Rich Text value at the current selection.
2918   *
2919   * @param {RichTextValue}  value  Value to modify.
2920   * @param {RichTextFormat} format Format to apply or remove.
2921   *
2922   * @return {RichTextValue} A new value with the format applied or removed.
2923   */
2924  function toggleFormat(value, format) {
2925    if (getActiveFormat(value, format.type)) {
2926      // For screen readers, will announce if formatting control is disabled.
2927      if (format.title) {
2928        // translators: %s: title of the formatting control
2929        (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)((0,external_wp_i18n_namespaceObject.__)('%s removed.'), format.title), 'assertive');
2930      }
2931      return removeFormat(value, format.type);
2932    }
2933    // For screen readers, will announce if formatting control is enabled.
2934    if (format.title) {
2935      // translators: %s: title of the formatting control
2936      (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)((0,external_wp_i18n_namespaceObject.__)('%s applied.'), format.title), 'assertive');
2937    }
2938    return applyFormat(value, format);
2939  }
2940  
2941  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/unregister-format-type.js
2942  /**
2943   * WordPress dependencies
2944   */
2945  
2946  
2947  /**
2948   * Internal dependencies
2949   */
2950  
2951  
2952  /** @typedef {import('./register-format-type').WPFormat} WPFormat */
2953  
2954  /**
2955   * Unregisters a format.
2956   *
2957   * @param {string} name Format name.
2958   *
2959   * @return {WPFormat|undefined} The previous format value, if it has
2960   *                                        been successfully unregistered;
2961   *                                        otherwise `undefined`.
2962   */
2963  function unregisterFormatType(name) {
2964    const oldFormat = (0,external_wp_data_namespaceObject.select)(store).getFormatType(name);
2965    if (!oldFormat) {
2966      window.console.error(`Format $name} is not registered.`);
2967      return;
2968    }
2969    (0,external_wp_data_namespaceObject.dispatch)(store).removeFormatTypes(name);
2970    return oldFormat;
2971  }
2972  
2973  ;// CONCATENATED MODULE: external ["wp","element"]
2974  const external_wp_element_namespaceObject = window["wp"]["element"];
2975  ;// CONCATENATED MODULE: external ["wp","deprecated"]
2976  const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
2977  var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
2978  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor-ref.js
2979  /**
2980   * WordPress dependencies
2981   */
2982  
2983  
2984  
2985  /**
2986   * Internal dependencies
2987   */
2988  
2989  
2990  /**
2991   * @template T
2992   * @typedef {import('@wordpress/element').RefObject<T>} RefObject<T>
2993   */
2994  /** @typedef {import('../register-format-type').WPFormat} WPFormat */
2995  /** @typedef {import('../types').RichTextValue} RichTextValue */
2996  
2997  /**
2998   * This hook, to be used in a format type's Edit component, returns the active
2999   * element that is formatted, or the selection range if no format is active.
3000   * The returned value is meant to be used for positioning UI, e.g. by passing it
3001   * to the `Popover` component.
3002   *
3003   * @param {Object}                 $1          Named parameters.
3004   * @param {RefObject<HTMLElement>} $1.ref      React ref of the element
3005   *                                             containing  the editable content.
3006   * @param {RichTextValue}          $1.value    Value to check for selection.
3007   * @param {WPFormat}               $1.settings The format type's settings.
3008   *
3009   * @return {Element|Range} The active element or selection range.
3010   */
3011  function useAnchorRef({
3012    ref,
3013    value,
3014    settings = {}
3015  }) {
3016    external_wp_deprecated_default()('`useAnchorRef` hook', {
3017      since: '6.1',
3018      alternative: '`useAnchor` hook'
3019    });
3020    const {
3021      tagName,
3022      className,
3023      name
3024    } = settings;
3025    const activeFormat = name ? getActiveFormat(value, name) : undefined;
3026    return (0,external_wp_element_namespaceObject.useMemo)(() => {
3027      if (!ref.current) return;
3028      const {
3029        ownerDocument: {
3030          defaultView
3031        }
3032      } = ref.current;
3033      const selection = defaultView.getSelection();
3034      if (!selection.rangeCount) {
3035        return;
3036      }
3037      const range = selection.getRangeAt(0);
3038      if (!activeFormat) {
3039        return range;
3040      }
3041      let element = range.startContainer;
3042  
3043      // If the caret is right before the element, select the next element.
3044      element = element.nextElementSibling || element;
3045      while (element.nodeType !== element.ELEMENT_NODE) {
3046        element = element.parentNode;
3047      }
3048      return element.closest(tagName + (className ? '.' + className : ''));
3049    }, [activeFormat, value.start, value.end, tagName, className]);
3050  }
3051  
3052  ;// CONCATENATED MODULE: external ["wp","compose"]
3053  const external_wp_compose_namespaceObject = window["wp"]["compose"];
3054  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor.js
3055  /**
3056   * WordPress dependencies
3057   */
3058  
3059  
3060  
3061  /** @typedef {import('../register-format-type').WPFormat} WPFormat */
3062  /** @typedef {import('../types').RichTextValue} RichTextValue */
3063  
3064  /**
3065   * Given a range and a format tag name and class name, returns the closest
3066   * format element.
3067   *
3068   * @param {Range}       range                  The Range to check.
3069   * @param {HTMLElement} editableContentElement The editable wrapper.
3070   * @param {string}      tagName                The tag name of the format element.
3071   * @param {string}      className              The class name of the format element.
3072   *
3073   * @return {HTMLElement|undefined} The format element, if found.
3074   */
3075  function getFormatElement(range, editableContentElement, tagName, className) {
3076    let element = range.startContainer;
3077  
3078    // Even if the active format is defined, the actualy DOM range's start
3079    // container may be outside of the format's DOM element:
3080    // `a‸<strong>b</strong>` (DOM) while visually it's `a<strong>‸b</strong>`.
3081    // So at a given selection index, start with the deepest format DOM element.
3082    if (element.nodeType === element.TEXT_NODE && range.startOffset === element.length && element.nextSibling) {
3083      element = element.nextSibling;
3084      while (element.firstChild) {
3085        element = element.firstChild;
3086      }
3087    }
3088    if (element.nodeType !== element.ELEMENT_NODE) {
3089      element = element.parentElement;
3090    }
3091    if (!element) return;
3092    if (element === editableContentElement) return;
3093    if (!editableContentElement.contains(element)) return;
3094    const selector = tagName + (className ? '.' + className : '');
3095  
3096    // .closest( selector ), but with a boundary. Check if the element matches
3097    // the selector. If it doesn't match, try the parent element if it's not the
3098    // editable wrapper. We don't want to try to match ancestors of the editable
3099    // wrapper, which is what .closest( selector ) would do. When the element is
3100    // the editable wrapper (which is most likely the case because most text is
3101    // unformatted), this never runs.
3102    while (element !== editableContentElement) {
3103      if (element.matches(selector)) {
3104        return element;
3105      }
3106      element = element.parentElement;
3107    }
3108  }
3109  
3110  /**
3111   * @typedef {Object} VirtualAnchorElement
3112   * @property {() => DOMRect} getBoundingClientRect A function returning a DOMRect
3113   * @property {HTMLElement}   contextElement        The actual DOM element
3114   */
3115  
3116  /**
3117   * Creates a virtual anchor element for a range.
3118   *
3119   * @param {Range}       range                  The range to create a virtual anchor element for.
3120   * @param {HTMLElement} editableContentElement The editable wrapper.
3121   *
3122   * @return {VirtualAnchorElement} The virtual anchor element.
3123   */
3124  function createVirtualAnchorElement(range, editableContentElement) {
3125    return {
3126      contextElement: editableContentElement,
3127      getBoundingClientRect() {
3128        return editableContentElement.contains(range.startContainer) ? range.getBoundingClientRect() : editableContentElement.getBoundingClientRect();
3129      }
3130    };
3131  }
3132  
3133  /**
3134   * Get the anchor: a format element if there is a matching one based on the
3135   * tagName and className or a range otherwise.
3136   *
3137   * @param {HTMLElement} editableContentElement The editable wrapper.
3138   * @param {string}      tagName                The tag name of the format
3139   *                                             element.
3140   * @param {string}      className              The class name of the format
3141   *                                             element.
3142   *
3143   * @return {HTMLElement|VirtualAnchorElement|undefined} The anchor.
3144   */
3145  function getAnchor(editableContentElement, tagName, className) {
3146    if (!editableContentElement) return;
3147    const {
3148      ownerDocument
3149    } = editableContentElement;
3150    const {
3151      defaultView
3152    } = ownerDocument;
3153    const selection = defaultView.getSelection();
3154    if (!selection) return;
3155    if (!selection.rangeCount) return;
3156    const range = selection.getRangeAt(0);
3157    if (!range || !range.startContainer) return;
3158    const formatElement = getFormatElement(range, editableContentElement, tagName, className);
3159    if (formatElement) return formatElement;
3160    return createVirtualAnchorElement(range, editableContentElement);
3161  }
3162  
3163  /**
3164   * This hook, to be used in a format type's Edit component, returns the active
3165   * element that is formatted, or a virtual element for the selection range if
3166   * no format is active. The returned value is meant to be used for positioning
3167   * UI, e.g. by passing it to the `Popover` component via the `anchor` prop.
3168   *
3169   * @param {Object}           $1                        Named parameters.
3170   * @param {HTMLElement|null} $1.editableContentElement The element containing
3171   *                                                     the editable content.
3172   * @param {WPFormat=}        $1.settings               The format type's settings.
3173   * @return {Element|VirtualAnchorElement|undefined|null} The active element or selection range.
3174   */
3175  function useAnchor({
3176    editableContentElement,
3177    settings = {}
3178  }) {
3179    const {
3180      tagName,
3181      className,
3182      isActive
3183    } = settings;
3184    const [anchor, setAnchor] = (0,external_wp_element_namespaceObject.useState)(() => getAnchor(editableContentElement, tagName, className));
3185    const wasActive = (0,external_wp_compose_namespaceObject.usePrevious)(isActive);
3186    (0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
3187      if (!editableContentElement) return;
3188      function callback() {
3189        setAnchor(getAnchor(editableContentElement, tagName, className));
3190      }
3191      function attach() {
3192        ownerDocument.addEventListener('selectionchange', callback);
3193      }
3194      function detach() {
3195        ownerDocument.removeEventListener('selectionchange', callback);
3196      }
3197      const {
3198        ownerDocument
3199      } = editableContentElement;
3200      if (editableContentElement === ownerDocument.activeElement ||
3201      // When a link is created, we need to attach the popover to the newly created anchor.
3202      !wasActive && isActive ||
3203      // Sometimes we're _removing_ an active anchor, such as the inline color popover.
3204      // When we add the color, it switches from a virtual anchor to a `<mark>` element.
3205      // When we _remove_ the color, it switches from a `<mark>` element to a virtual anchor.
3206      wasActive && !isActive) {
3207        setAnchor(getAnchor(editableContentElement, tagName, className));
3208        attach();
3209      }
3210      editableContentElement.addEventListener('focusin', attach);
3211      editableContentElement.addEventListener('focusout', detach);
3212      return () => {
3213        detach();
3214        editableContentElement.removeEventListener('focusin', attach);
3215        editableContentElement.removeEventListener('focusout', detach);
3216      };
3217    }, [editableContentElement, tagName, className, isActive, wasActive]);
3218    return anchor;
3219  }
3220  
3221  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-default-style.js
3222  /**
3223   * WordPress dependencies
3224   */
3225  
3226  
3227  /**
3228   * In HTML, leading and trailing spaces are not visible, and multiple spaces
3229   * elsewhere are visually reduced to one space. This rule prevents spaces from
3230   * collapsing so all space is visible in the editor and can be removed. It also
3231   * prevents some browsers from inserting non-breaking spaces at the end of a
3232   * line to prevent the space from visually disappearing. Sometimes these non
3233   * breaking spaces can linger in the editor causing unwanted non breaking spaces
3234   * in between words. If also prevent Firefox from inserting a trailing `br` node
3235   * to visualise any trailing space, causing the element to be saved.
3236   *
3237   * > Authors are encouraged to set the 'white-space' property on editing hosts
3238   * > and on markup that was originally created through these editing mechanisms
3239   * > to the value 'pre-wrap'. Default HTML whitespace handling is not well
3240   * > suited to WYSIWYG editing, and line wrapping will not work correctly in
3241   * > some corner cases if 'white-space' is left at its default value.
3242   *
3243   * https://html.spec.whatwg.org/multipage/interaction.html#best-practices-for-in-page-editors
3244   *
3245   * @type {string}
3246   */
3247  const whiteSpace = 'pre-wrap';
3248  
3249  /**
3250   * A minimum width of 1px will prevent the rich text container from collapsing
3251   * to 0 width and hiding the caret. This is useful for inline containers.
3252   */
3253  const minWidth = '1px';
3254  function useDefaultStyle() {
3255    return (0,external_wp_element_namespaceObject.useCallback)(element => {
3256      if (!element) return;
3257      element.style.whiteSpace = whiteSpace;
3258      element.style.minWidth = minWidth;
3259    }, []);
3260  }
3261  
3262  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-boundary-style.js
3263  /**
3264   * WordPress dependencies
3265   */
3266  
3267  
3268  /*
3269   * Calculates and renders the format boundary style when the active formats
3270   * change.
3271   */
3272  function useBoundaryStyle({
3273    record
3274  }) {
3275    const ref = (0,external_wp_element_namespaceObject.useRef)();
3276    const {
3277      activeFormats = [],
3278      replacements,
3279      start
3280    } = record.current;
3281    const activeReplacement = replacements[start];
3282    (0,external_wp_element_namespaceObject.useEffect)(() => {
3283      // There's no need to recalculate the boundary styles if no formats are
3284      // active, because no boundary styles will be visible.
3285      if ((!activeFormats || !activeFormats.length) && !activeReplacement) {
3286        return;
3287      }
3288      const boundarySelector = '*[data-rich-text-format-boundary]';
3289      const element = ref.current.querySelector(boundarySelector);
3290      if (!element) {
3291        return;
3292      }
3293      const {
3294        ownerDocument
3295      } = element;
3296      const {
3297        defaultView
3298      } = ownerDocument;
3299      const computedStyle = defaultView.getComputedStyle(element);
3300      const newColor = computedStyle.color.replace(')', ', 0.2)').replace('rgb', 'rgba');
3301      const selector = `.rich-text:focus $boundarySelector}`;
3302      const rule = `background-color: $newColor}`;
3303      const style = `$selector} {$rule}}`;
3304      const globalStyleId = 'rich-text-boundary-style';
3305      let globalStyle = ownerDocument.getElementById(globalStyleId);
3306      if (!globalStyle) {
3307        globalStyle = ownerDocument.createElement('style');
3308        globalStyle.id = globalStyleId;
3309        ownerDocument.head.appendChild(globalStyle);
3310      }
3311      if (globalStyle.innerHTML !== style) {
3312        globalStyle.innerHTML = style;
3313      }
3314    }, [activeFormats, activeReplacement]);
3315    return ref;
3316  }
3317  
3318  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-copy-handler.js
3319  /**
3320   * WordPress dependencies
3321   */
3322  
3323  
3324  
3325  /**
3326   * Internal dependencies
3327   */
3328  
3329  
3330  
3331  
3332  function useCopyHandler(props) {
3333    const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
3334    propsRef.current = props;
3335    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3336      function onCopy(event) {
3337        const {
3338          record
3339        } = propsRef.current;
3340        const {
3341          ownerDocument
3342        } = element;
3343        if (isCollapsed(record.current) || !element.contains(ownerDocument.activeElement)) {
3344          return;
3345        }
3346        const selectedRecord = slice(record.current);
3347        const plainText = getTextContent(selectedRecord);
3348        const html = toHTMLString({
3349          value: selectedRecord
3350        });
3351        event.clipboardData.setData('text/plain', plainText);
3352        event.clipboardData.setData('text/html', html);
3353        event.clipboardData.setData('rich-text', 'true');
3354        event.preventDefault();
3355        if (event.type === 'cut') {
3356          ownerDocument.execCommand('delete');
3357        }
3358      }
3359      element.addEventListener('copy', onCopy);
3360      element.addEventListener('cut', onCopy);
3361      return () => {
3362        element.removeEventListener('copy', onCopy);
3363        element.removeEventListener('cut', onCopy);
3364      };
3365    }, []);
3366  }
3367  
3368  ;// CONCATENATED MODULE: external ["wp","keycodes"]
3369  const external_wp_keycodes_namespaceObject = window["wp"]["keycodes"];
3370  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-format-boundaries.js
3371  /**
3372   * WordPress dependencies
3373   */
3374  
3375  
3376  
3377  
3378  /**
3379   * Internal dependencies
3380   */
3381  
3382  const EMPTY_ACTIVE_FORMATS = [];
3383  function useFormatBoundaries(props) {
3384    const [, forceRender] = (0,external_wp_element_namespaceObject.useReducer)(() => ({}));
3385    const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
3386    propsRef.current = props;
3387    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3388      function onKeyDown(event) {
3389        const {
3390          keyCode,
3391          shiftKey,
3392          altKey,
3393          metaKey,
3394          ctrlKey
3395        } = event;
3396        if (
3397        // Only override left and right keys without modifiers pressed.
3398        shiftKey || altKey || metaKey || ctrlKey || keyCode !== external_wp_keycodes_namespaceObject.LEFT && keyCode !== external_wp_keycodes_namespaceObject.RIGHT) {
3399          return;
3400        }
3401        const {
3402          record,
3403          applyRecord
3404        } = propsRef.current;
3405        const {
3406          text,
3407          formats,
3408          start,
3409          end,
3410          activeFormats: currentActiveFormats = []
3411        } = record.current;
3412        const collapsed = isCollapsed(record.current);
3413        const {
3414          ownerDocument
3415        } = element;
3416        const {
3417          defaultView
3418        } = ownerDocument;
3419        // To do: ideally, we should look at visual position instead.
3420        const {
3421          direction
3422        } = defaultView.getComputedStyle(element);
3423        const reverseKey = direction === 'rtl' ? external_wp_keycodes_namespaceObject.RIGHT : external_wp_keycodes_namespaceObject.LEFT;
3424        const isReverse = event.keyCode === reverseKey;
3425  
3426        // If the selection is collapsed and at the very start, do nothing if
3427        // navigating backward.
3428        // If the selection is collapsed and at the very end, do nothing if
3429        // navigating forward.
3430        if (collapsed && currentActiveFormats.length === 0) {
3431          if (start === 0 && isReverse) {
3432            return;
3433          }
3434          if (end === text.length && !isReverse) {
3435            return;
3436          }
3437        }
3438  
3439        // If the selection is not collapsed, let the browser handle collapsing
3440        // the selection for now. Later we could expand this logic to set
3441        // boundary positions if needed.
3442        if (!collapsed) {
3443          return;
3444        }
3445        const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS;
3446        const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS;
3447        const destination = isReverse ? formatsBefore : formatsAfter;
3448        const isIncreasing = currentActiveFormats.every((format, index) => format === destination[index]);
3449        let newActiveFormatsLength = currentActiveFormats.length;
3450        if (!isIncreasing) {
3451          newActiveFormatsLength--;
3452        } else if (newActiveFormatsLength < destination.length) {
3453          newActiveFormatsLength++;
3454        }
3455        if (newActiveFormatsLength === currentActiveFormats.length) {
3456          record.current._newActiveFormats = destination;
3457          return;
3458        }
3459        event.preventDefault();
3460        const origin = isReverse ? formatsAfter : formatsBefore;
3461        const source = isIncreasing ? destination : origin;
3462        const newActiveFormats = source.slice(0, newActiveFormatsLength);
3463        const newValue = {
3464          ...record.current,
3465          activeFormats: newActiveFormats
3466        };
3467        record.current = newValue;
3468        applyRecord(newValue);
3469        forceRender();
3470      }
3471      element.addEventListener('keydown', onKeyDown);
3472      return () => {
3473        element.removeEventListener('keydown', onKeyDown);
3474      };
3475    }, []);
3476  }
3477  
3478  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-select-object.js
3479  /**
3480   * WordPress dependencies
3481   */
3482  
3483  function useSelectObject() {
3484    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3485      function onClick(event) {
3486        const {
3487          target
3488        } = event;
3489  
3490        // If the child element has no text content, it must be an object.
3491        if (target === element || target.textContent && target.isContentEditable) {
3492          return;
3493        }
3494        const {
3495          ownerDocument
3496        } = target;
3497        const {
3498          defaultView
3499        } = ownerDocument;
3500        const selection = defaultView.getSelection();
3501  
3502        // If it's already selected, do nothing and let default behavior
3503        // happen. This means it's "click-through".
3504        if (selection.containsNode(target)) return;
3505        const range = ownerDocument.createRange();
3506        // If the target is within a non editable element, select the non
3507        // editable element.
3508        const nodeToSelect = target.isContentEditable ? target : target.closest('[contenteditable]');
3509        range.selectNode(nodeToSelect);
3510        selection.removeAllRanges();
3511        selection.addRange(range);
3512        event.preventDefault();
3513      }
3514      function onFocusIn(event) {
3515        // When there is incoming focus from a link, select the object.
3516        if (event.relatedTarget && !element.contains(event.relatedTarget) && event.relatedTarget.tagName === 'A') {
3517          onClick(event);
3518        }
3519      }
3520      element.addEventListener('click', onClick);
3521      element.addEventListener('focusin', onFocusIn);
3522      return () => {
3523        element.removeEventListener('click', onClick);
3524        element.removeEventListener('focusin', onFocusIn);
3525      };
3526    }, []);
3527  }
3528  
3529  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/update-formats.js
3530  /**
3531   * Internal dependencies
3532   */
3533  
3534  
3535  
3536  /** @typedef {import('./types').RichTextValue} RichTextValue */
3537  
3538  /**
3539   * Efficiently updates all the formats from `start` (including) until `end`
3540   * (excluding) with the active formats. Mutates `value`.
3541   *
3542   * @param {Object}        $1         Named paramentes.
3543   * @param {RichTextValue} $1.value   Value te update.
3544   * @param {number}        $1.start   Index to update from.
3545   * @param {number}        $1.end     Index to update until.
3546   * @param {Array}         $1.formats Replacement formats.
3547   *
3548   * @return {RichTextValue} Mutated value.
3549   */
3550  function updateFormats({
3551    value,
3552    start,
3553    end,
3554    formats
3555  }) {
3556    // Start and end may be switched in case of delete.
3557    const min = Math.min(start, end);
3558    const max = Math.max(start, end);
3559    const formatsBefore = value.formats[min - 1] || [];
3560    const formatsAfter = value.formats[max] || [];
3561  
3562    // First, fix the references. If any format right before or after are
3563    // equal, the replacement format should use the same reference.
3564    value.activeFormats = formats.map((format, index) => {
3565      if (formatsBefore[index]) {
3566        if (isFormatEqual(format, formatsBefore[index])) {
3567          return formatsBefore[index];
3568        }
3569      } else if (formatsAfter[index]) {
3570        if (isFormatEqual(format, formatsAfter[index])) {
3571          return formatsAfter[index];
3572        }
3573      }
3574      return format;
3575    });
3576    while (--end >= start) {
3577      if (value.activeFormats.length > 0) {
3578        value.formats[end] = value.activeFormats;
3579      } else {
3580        delete value.formats[end];
3581      }
3582    }
3583    return value;
3584  }
3585  
3586  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-input-and-selection.js
3587  /**
3588   * WordPress dependencies
3589   */
3590  
3591  
3592  
3593  /**
3594   * Internal dependencies
3595   */
3596  
3597  
3598  
3599  /**
3600   * All inserting input types that would insert HTML into the DOM.
3601   *
3602   * @see https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes
3603   *
3604   * @type {Set}
3605   */
3606  const INSERTION_INPUT_TYPES_TO_IGNORE = new Set(['insertParagraph', 'insertOrderedList', 'insertUnorderedList', 'insertHorizontalRule', 'insertLink']);
3607  const use_input_and_selection_EMPTY_ACTIVE_FORMATS = [];
3608  const PLACEHOLDER_ATTR_NAME = 'data-rich-text-placeholder';
3609  
3610  /**
3611   * If the selection is set on the placeholder element, collapse the selection to
3612   * the start (before the placeholder).
3613   *
3614   * @param {Window} defaultView
3615   */
3616  function fixPlaceholderSelection(defaultView) {
3617    const selection = defaultView.getSelection();
3618    const {
3619      anchorNode,
3620      anchorOffset
3621    } = selection;
3622    if (anchorNode.nodeType !== anchorNode.ELEMENT_NODE) {
3623      return;
3624    }
3625    const targetNode = anchorNode.childNodes[anchorOffset];
3626    if (!targetNode || targetNode.nodeType !== targetNode.ELEMENT_NODE || !targetNode.hasAttribute(PLACEHOLDER_ATTR_NAME)) {
3627      return;
3628    }
3629    selection.collapseToStart();
3630  }
3631  function useInputAndSelection(props) {
3632    const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
3633    propsRef.current = props;
3634    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3635      const {
3636        ownerDocument
3637      } = element;
3638      const {
3639        defaultView
3640      } = ownerDocument;
3641      let isComposing = false;
3642      function onInput(event) {
3643        // Do not trigger a change if characters are being composed.
3644        // Browsers  will usually emit a final `input` event when the
3645        // characters are composed.
3646        // As of December 2019, Safari doesn't support
3647        // nativeEvent.isComposing.
3648        if (isComposing) {
3649          return;
3650        }
3651        let inputType;
3652        if (event) {
3653          inputType = event.inputType;
3654        }
3655        const {
3656          record,
3657          applyRecord,
3658          createRecord,
3659          handleChange
3660        } = propsRef.current;
3661  
3662        // The browser formatted something or tried to insert HTML.
3663        // Overwrite it. It will be handled later by the format library if
3664        // needed.
3665        if (inputType && (inputType.indexOf('format') === 0 || INSERTION_INPUT_TYPES_TO_IGNORE.has(inputType))) {
3666          applyRecord(record.current);
3667          return;
3668        }
3669        const currentValue = createRecord();
3670        const {
3671          start,
3672          activeFormats: oldActiveFormats = []
3673        } = record.current;
3674  
3675        // Update the formats between the last and new caret position.
3676        const change = updateFormats({
3677          value: currentValue,
3678          start,
3679          end: currentValue.start,
3680          formats: oldActiveFormats
3681        });
3682        handleChange(change);
3683      }
3684  
3685      /**
3686       * Syncs the selection to local state. A callback for the
3687       * `selectionchange` event.
3688       */
3689      function handleSelectionChange() {
3690        const {
3691          record,
3692          applyRecord,
3693          createRecord,
3694          onSelectionChange
3695        } = propsRef.current;
3696  
3697        // Check if the implementor disabled editing. `contentEditable`
3698        // does disable input, but not text selection, so we must ignore
3699        // selection changes.
3700        if (element.contentEditable !== 'true') {
3701          return;
3702        }
3703  
3704        // Ensure the active element is the rich text element.
3705        if (ownerDocument.activeElement !== element) {
3706          // If it is not, we can stop listening for selection changes.
3707          // We resume listening when the element is focused.
3708          ownerDocument.removeEventListener('selectionchange', handleSelectionChange);
3709          return;
3710        }
3711  
3712        // In case of a keyboard event, ignore selection changes during
3713        // composition.
3714        if (isComposing) {
3715          return;
3716        }
3717        const {
3718          start,
3719          end,
3720          text
3721        } = createRecord();
3722        const oldRecord = record.current;
3723  
3724        // Fallback mechanism for IE11, which doesn't support the input event.
3725        // Any input results in a selection change.
3726        if (text !== oldRecord.text) {
3727          onInput();
3728          return;
3729        }
3730        if (start === oldRecord.start && end === oldRecord.end) {
3731          // Sometimes the browser may set the selection on the placeholder
3732          // element, in which case the caret is not visible. We need to set
3733          // the caret before the placeholder if that's the case.
3734          if (oldRecord.text.length === 0 && start === 0) {
3735            fixPlaceholderSelection(defaultView);
3736          }
3737          return;
3738        }
3739        const newValue = {
3740          ...oldRecord,
3741          start,
3742          end,
3743          // _newActiveFormats may be set on arrow key navigation to control
3744          // the right boundary position. If undefined, getActiveFormats will
3745          // give the active formats according to the browser.
3746          activeFormats: oldRecord._newActiveFormats,
3747          _newActiveFormats: undefined
3748        };
3749        const newActiveFormats = getActiveFormats(newValue, use_input_and_selection_EMPTY_ACTIVE_FORMATS);
3750  
3751        // Update the value with the new active formats.
3752        newValue.activeFormats = newActiveFormats;
3753  
3754        // It is important that the internal value is updated first,
3755        // otherwise the value will be wrong on render!
3756        record.current = newValue;
3757        applyRecord(newValue, {
3758          domOnly: true
3759        });
3760        onSelectionChange(start, end);
3761      }
3762      function onCompositionStart() {
3763        isComposing = true;
3764        // Do not update the selection when characters are being composed as
3765        // this rerenders the component and might destroy internal browser
3766        // editing state.
3767        ownerDocument.removeEventListener('selectionchange', handleSelectionChange);
3768        // Remove the placeholder. Since the rich text value doesn't update
3769        // during composition, the placeholder doesn't get removed. There's
3770        // no need to re-add it, when the value is updated on compositionend
3771        // it will be re-added when the value is empty.
3772        element.querySelector(`[$PLACEHOLDER_ATTR_NAME}]`)?.remove();
3773      }
3774      function onCompositionEnd() {
3775        isComposing = false;
3776        // Ensure the value is up-to-date for browsers that don't emit a final
3777        // input event after composition.
3778        onInput({
3779          inputType: 'insertText'
3780        });
3781        // Tracking selection changes can be resumed.
3782        ownerDocument.addEventListener('selectionchange', handleSelectionChange);
3783      }
3784      function onFocus() {
3785        const {
3786          record,
3787          isSelected,
3788          onSelectionChange,
3789          applyRecord
3790        } = propsRef.current;
3791  
3792        // When the whole editor is editable, let writing flow handle
3793        // selection.
3794        if (element.parentElement.closest('[contenteditable="true"]')) {
3795          return;
3796        }
3797        if (!isSelected) {
3798          // We know for certain that on focus, the old selection is invalid.
3799          // It will be recalculated on the next mouseup, keyup, or touchend
3800          // event.
3801          const index = undefined;
3802          record.current = {
3803            ...record.current,
3804            start: index,
3805            end: index,
3806            activeFormats: use_input_and_selection_EMPTY_ACTIVE_FORMATS
3807          };
3808        } else {
3809          applyRecord(record.current, {
3810            domOnly: true
3811          });
3812        }
3813        onSelectionChange(record.current.start, record.current.end);
3814        ownerDocument.addEventListener('selectionchange', handleSelectionChange);
3815      }
3816      element.addEventListener('input', onInput);
3817      element.addEventListener('compositionstart', onCompositionStart);
3818      element.addEventListener('compositionend', onCompositionEnd);
3819      element.addEventListener('focus', onFocus);
3820      return () => {
3821        element.removeEventListener('input', onInput);
3822        element.removeEventListener('compositionstart', onCompositionStart);
3823        element.removeEventListener('compositionend', onCompositionEnd);
3824        element.removeEventListener('focus', onFocus);
3825      };
3826    }, []);
3827  }
3828  
3829  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-selection-change-compat.js
3830  /**
3831   * WordPress dependencies
3832   */
3833  
3834  
3835  /**
3836   * Internal dependencies
3837   */
3838  
3839  
3840  /**
3841   * Sometimes some browsers are not firing a `selectionchange` event when
3842   * changing the selection by mouse or keyboard. This hook makes sure that, if we
3843   * detect no `selectionchange` or `input` event between the up and down events,
3844   * we fire a `selectionchange` event.
3845   *
3846   * @return {import('@wordpress/compose').RefEffect} A ref effect attaching the
3847   *                                                  listeners.
3848   */
3849  function useSelectionChangeCompat() {
3850    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3851      const {
3852        ownerDocument
3853      } = element;
3854      const {
3855        defaultView
3856      } = ownerDocument;
3857      const selection = defaultView?.getSelection();
3858      let range;
3859      function getRange() {
3860        return selection.rangeCount ? selection.getRangeAt(0) : null;
3861      }
3862      function onDown(event) {
3863        const type = event.type === 'keydown' ? 'keyup' : 'pointerup';
3864        function onCancel() {
3865          ownerDocument.removeEventListener(type, onUp);
3866          ownerDocument.removeEventListener('selectionchange', onCancel);
3867          ownerDocument.removeEventListener('input', onCancel);
3868        }
3869        function onUp() {
3870          onCancel();
3871          if (isRangeEqual(range, getRange())) return;
3872          ownerDocument.dispatchEvent(new Event('selectionchange'));
3873        }
3874        ownerDocument.addEventListener(type, onUp);
3875        ownerDocument.addEventListener('selectionchange', onCancel);
3876        ownerDocument.addEventListener('input', onCancel);
3877        range = getRange();
3878      }
3879      element.addEventListener('pointerdown', onDown);
3880      element.addEventListener('keydown', onDown);
3881      return () => {
3882        element.removeEventListener('pointerdown', onDown);
3883        element.removeEventListener('keydown', onDown);
3884      };
3885    }, []);
3886  }
3887  
3888  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-delete.js
3889  /**
3890   * WordPress dependencies
3891   */
3892  
3893  
3894  
3895  
3896  /**
3897   * Internal dependencies
3898   */
3899  
3900  function useDelete(props) {
3901    const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
3902    propsRef.current = props;
3903    return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
3904      function onKeyDown(event) {
3905        const {
3906          keyCode
3907        } = event;
3908        const {
3909          createRecord,
3910          handleChange
3911        } = propsRef.current;
3912        if (event.defaultPrevented) {
3913          return;
3914        }
3915        if (keyCode !== external_wp_keycodes_namespaceObject.DELETE && keyCode !== external_wp_keycodes_namespaceObject.BACKSPACE) {
3916          return;
3917        }
3918        const currentValue = createRecord();
3919        const {
3920          start,
3921          end,
3922          text
3923        } = currentValue;
3924  
3925        // Always handle full content deletion ourselves.
3926        if (start === 0 && end !== 0 && end === text.length) {
3927          handleChange(remove_remove(currentValue));
3928          event.preventDefault();
3929        }
3930      }
3931      element.addEventListener('keydown', onKeyDown);
3932      return () => {
3933        element.removeEventListener('keydown', onKeyDown);
3934      };
3935    }, []);
3936  }
3937  
3938  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/index.js
3939  /**
3940   * WordPress dependencies
3941   */
3942  
3943  
3944  
3945  
3946  /**
3947   * Internal dependencies
3948   */
3949  
3950  
3951  
3952  
3953  
3954  
3955  
3956  
3957  
3958  
3959  
3960  function useRichText({
3961    value = '',
3962    selectionStart,
3963    selectionEnd,
3964    placeholder,
3965    onSelectionChange,
3966    preserveWhiteSpace,
3967    onChange,
3968    __unstableDisableFormats: disableFormats,
3969    __unstableIsSelected: isSelected,
3970    __unstableDependencies = [],
3971    __unstableAfterParse,
3972    __unstableBeforeSerialize,
3973    __unstableAddInvisibleFormats
3974  }) {
3975    const registry = (0,external_wp_data_namespaceObject.useRegistry)();
3976    const [, forceRender] = (0,external_wp_element_namespaceObject.useReducer)(() => ({}));
3977    const ref = (0,external_wp_element_namespaceObject.useRef)();
3978    function createRecord() {
3979      const {
3980        ownerDocument: {
3981          defaultView
3982        }
3983      } = ref.current;
3984      const selection = defaultView.getSelection();
3985      const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
3986      return create({
3987        element: ref.current,
3988        range,
3989        __unstableIsEditableTree: true
3990      });
3991    }
3992    function applyRecord(newRecord, {
3993      domOnly
3994    } = {}) {
3995      apply({
3996        value: newRecord,
3997        current: ref.current,
3998        prepareEditableTree: __unstableAddInvisibleFormats,
3999        __unstableDomOnly: domOnly,
4000        placeholder
4001      });
4002    }
4003  
4004    // Internal values are updated synchronously, unlike props and state.
4005    const _value = (0,external_wp_element_namespaceObject.useRef)(value);
4006    const record = (0,external_wp_element_namespaceObject.useRef)();
4007    function setRecordFromProps() {
4008      _value.current = value;
4009      record.current = value;
4010      if (!(value instanceof RichTextData)) {
4011        record.current = value ? RichTextData.fromHTMLString(value, {
4012          preserveWhiteSpace
4013        }) : RichTextData.empty();
4014      }
4015      // To do: make rich text internally work with RichTextData.
4016      record.current = {
4017        text: record.current.text,
4018        formats: record.current.formats,
4019        replacements: record.current.replacements
4020      };
4021      if (disableFormats) {
4022        record.current.formats = Array(value.length);
4023        record.current.replacements = Array(value.length);
4024      }
4025      if (__unstableAfterParse) {
4026        record.current.formats = __unstableAfterParse(record.current);
4027      }
4028      record.current.start = selectionStart;
4029      record.current.end = selectionEnd;
4030    }
4031    const hadSelectionUpdate = (0,external_wp_element_namespaceObject.useRef)(false);
4032    if (!record.current) {
4033      hadSelectionUpdate.current = isSelected;
4034      setRecordFromProps();
4035    } else if (selectionStart !== record.current.start || selectionEnd !== record.current.end) {
4036      hadSelectionUpdate.current = isSelected;
4037      record.current = {
4038        ...record.current,
4039        start: selectionStart,
4040        end: selectionEnd,
4041        activeFormats: undefined
4042      };
4043    }
4044  
4045    /**
4046     * Sync the value to global state. The node tree and selection will also be
4047     * updated if differences are found.
4048     *
4049     * @param {Object} newRecord The record to sync and apply.
4050     */
4051    function handleChange(newRecord) {
4052      record.current = newRecord;
4053      applyRecord(newRecord);
4054      if (disableFormats) {
4055        _value.current = newRecord.text;
4056      } else {
4057        const newFormats = __unstableBeforeSerialize ? __unstableBeforeSerialize(newRecord) : newRecord.formats;
4058        newRecord = {
4059          ...newRecord,
4060          formats: newFormats
4061        };
4062        if (typeof value === 'string') {
4063          _value.current = toHTMLString({
4064            value: newRecord,
4065            preserveWhiteSpace
4066          });
4067        } else {
4068          _value.current = new RichTextData(newRecord);
4069        }
4070      }
4071      const {
4072        start,
4073        end,
4074        formats,
4075        text
4076      } = record.current;
4077  
4078      // Selection must be updated first, so it is recorded in history when
4079      // the content change happens.
4080      // We batch both calls to only attempt to rerender once.
4081      registry.batch(() => {
4082        onSelectionChange(start, end);
4083        onChange(_value.current, {
4084          __unstableFormats: formats,
4085          __unstableText: text
4086        });
4087      });
4088      forceRender();
4089    }
4090    function applyFromProps() {
4091      setRecordFromProps();
4092      applyRecord(record.current);
4093    }
4094    const didMount = (0,external_wp_element_namespaceObject.useRef)(false);
4095  
4096    // Value updates must happen synchonously to avoid overwriting newer values.
4097    (0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
4098      if (didMount.current && value !== _value.current) {
4099        applyFromProps();
4100        forceRender();
4101      }
4102    }, [value]);
4103  
4104    // Value updates must happen synchonously to avoid overwriting newer values.
4105    (0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
4106      if (!hadSelectionUpdate.current) {
4107        return;
4108      }
4109      if (ref.current.ownerDocument.activeElement !== ref.current) {
4110        ref.current.focus();
4111      }
4112      applyRecord(record.current);
4113      hadSelectionUpdate.current = false;
4114    }, [hadSelectionUpdate.current]);
4115    const mergedRefs = (0,external_wp_compose_namespaceObject.useMergeRefs)([ref, useDefaultStyle(), useBoundaryStyle({
4116      record
4117    }), useCopyHandler({
4118      record
4119    }), useSelectObject(), useFormatBoundaries({
4120      record,
4121      applyRecord
4122    }), useDelete({
4123      createRecord,
4124      handleChange
4125    }), useInputAndSelection({
4126      record,
4127      applyRecord,
4128      createRecord,
4129      handleChange,
4130      isSelected,
4131      onSelectionChange
4132    }), useSelectionChangeCompat(), (0,external_wp_compose_namespaceObject.useRefEffect)(() => {
4133      applyFromProps();
4134      didMount.current = true;
4135    }, [placeholder, ...__unstableDependencies])]);
4136    return {
4137      value: record.current,
4138      // A function to get the most recent value so event handlers in
4139      // useRichText implementations have access to it. For example when
4140      // listening to input events, we internally update the state, but this
4141      // state is not yet available to the input event handler because React
4142      // may re-render asynchronously.
4143      getValue: () => record.current,
4144      onChange: handleChange,
4145      ref: mergedRefs
4146    };
4147  }
4148  function __experimentalRichText() {}
4149  
4150  ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/index.js
4151  
4152  
4153  
4154  
4155  
4156  
4157  
4158  
4159  
4160  
4161  
4162  
4163  
4164  
4165  
4166  
4167  
4168  
4169  
4170  
4171  
4172  
4173  
4174  
4175  
4176  
4177  
4178  
4179  /**
4180   * An object which represents a formatted string. See main `@wordpress/rich-text`
4181   * documentation for more information.
4182   */
4183  
4184  (window.wp = window.wp || {}).richText = __webpack_exports__;
4185  /******/ })()
4186  ;


Generated : Fri Apr 19 08:20:01 2024 Cross-referenced by PHPXref