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


Generated : Sun Mar 9 08:20:01 2025 Cross-referenced by PHPXref