[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  (function() {
   2  "use strict";
   3  var wp;
   4  (wp ||= {}).richText = (() => {
   5    var __create = Object.create;
   6    var __defProp = Object.defineProperty;
   7    var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
   8    var __getOwnPropNames = Object.getOwnPropertyNames;
   9    var __getProtoOf = Object.getPrototypeOf;
  10    var __hasOwnProp = Object.prototype.hasOwnProperty;
  11    var __commonJS = (cb, mod) => function __require() {
  12      return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  13    };
  14    var __export = (target, all) => {
  15      for (var name in all)
  16        __defProp(target, name, { get: all[name], enumerable: true });
  17    };
  18    var __copyProps = (to, from, except, desc) => {
  19      if (from && typeof from === "object" || typeof from === "function") {
  20        for (let key of __getOwnPropNames(from))
  21          if (!__hasOwnProp.call(to, key) && key !== except)
  22            __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  23      }
  24      return to;
  25    };
  26    var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  27      // If the importer is in node compatibility mode or this is not an ESM
  28      // file that has been converted to a CommonJS file using a Babel-
  29      // compatible transform (i.e. "__esModule" has not been set), then set
  30      // "default" to the CommonJS "module.exports" for node compatibility.
  31      isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  32      mod
  33    ));
  34    var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  35  
  36    // package-external:@wordpress/data
  37    var require_data = __commonJS({
  38      "package-external:@wordpress/data"(exports, module) {
  39        module.exports = window.wp.data;
  40      }
  41    });
  42  
  43    // package-external:@wordpress/escape-html
  44    var require_escape_html = __commonJS({
  45      "package-external:@wordpress/escape-html"(exports, module) {
  46        module.exports = window.wp.escapeHtml;
  47      }
  48    });
  49  
  50    // package-external:@wordpress/a11y
  51    var require_a11y = __commonJS({
  52      "package-external:@wordpress/a11y"(exports, module) {
  53        module.exports = window.wp.a11y;
  54      }
  55    });
  56  
  57    // package-external:@wordpress/i18n
  58    var require_i18n = __commonJS({
  59      "package-external:@wordpress/i18n"(exports, module) {
  60        module.exports = window.wp.i18n;
  61      }
  62    });
  63  
  64    // package-external:@wordpress/private-apis
  65    var require_private_apis = __commonJS({
  66      "package-external:@wordpress/private-apis"(exports, module) {
  67        module.exports = window.wp.privateApis;
  68      }
  69    });
  70  
  71    // package-external:@wordpress/element
  72    var require_element = __commonJS({
  73      "package-external:@wordpress/element"(exports, module) {
  74        module.exports = window.wp.element;
  75      }
  76    });
  77  
  78    // package-external:@wordpress/compose
  79    var require_compose = __commonJS({
  80      "package-external:@wordpress/compose"(exports, module) {
  81        module.exports = window.wp.compose;
  82      }
  83    });
  84  
  85    // package-external:@wordpress/deprecated
  86    var require_deprecated = __commonJS({
  87      "package-external:@wordpress/deprecated"(exports, module) {
  88        module.exports = window.wp.deprecated;
  89      }
  90    });
  91  
  92    // package-external:@wordpress/keycodes
  93    var require_keycodes = __commonJS({
  94      "package-external:@wordpress/keycodes"(exports, module) {
  95        module.exports = window.wp.keycodes;
  96      }
  97    });
  98  
  99    // package-external:@wordpress/dom
 100    var require_dom = __commonJS({
 101      "package-external:@wordpress/dom"(exports, module) {
 102        module.exports = window.wp.dom;
 103      }
 104    });
 105  
 106    // packages/rich-text/build-module/index.mjs
 107    var index_exports = {};
 108    __export(index_exports, {
 109      RichTextData: () => RichTextData,
 110      __experimentalRichText: () => __experimentalRichText,
 111      __unstableCreateElement: () => createElement,
 112      __unstableToDom: () => toDom,
 113      __unstableUseRichText: () => useDeprecatedRichText,
 114      applyFormat: () => applyFormat,
 115      concat: () => concat,
 116      create: () => create,
 117      getActiveFormat: () => getActiveFormat,
 118      getActiveFormats: () => getActiveFormats,
 119      getActiveObject: () => getActiveObject,
 120      getTextContent: () => getTextContent,
 121      insert: () => insert,
 122      insertObject: () => insertObject,
 123      isCollapsed: () => isCollapsed,
 124      isEmpty: () => isEmpty,
 125      join: () => join,
 126      privateApis: () => privateApis,
 127      registerFormatType: () => registerFormatType,
 128      remove: () => remove2,
 129      removeFormat: () => removeFormat,
 130      replace: () => replace2,
 131      slice: () => slice,
 132      split: () => split,
 133      store: () => store,
 134      toHTMLString: () => toHTMLString,
 135      toggleFormat: () => toggleFormat,
 136      unregisterFormatType: () => unregisterFormatType,
 137      useAnchor: () => useAnchor,
 138      useAnchorRef: () => useAnchorRef
 139    });
 140  
 141    // packages/rich-text/build-module/store/index.mjs
 142    var import_data3 = __toESM(require_data(), 1);
 143  
 144    // packages/rich-text/build-module/store/reducer.mjs
 145    var import_data = __toESM(require_data(), 1);
 146    function formatTypes(state = {}, action) {
 147      switch (action.type) {
 148        case "ADD_FORMAT_TYPES":
 149          return {
 150            ...state,
 151            // Key format types by their name.
 152            ...action.formatTypes.reduce(
 153              (newFormatTypes, type) => ({
 154                ...newFormatTypes,
 155                [type.name]: type
 156              }),
 157              {}
 158            )
 159          };
 160        case "REMOVE_FORMAT_TYPES":
 161          return Object.fromEntries(
 162            Object.entries(state).filter(
 163              ([key]) => !action.names.includes(key)
 164            )
 165          );
 166      }
 167      return state;
 168    }
 169    var reducer_default = (0, import_data.combineReducers)({ formatTypes });
 170  
 171    // packages/rich-text/build-module/store/selectors.mjs
 172    var selectors_exports = {};
 173    __export(selectors_exports, {
 174      getFormatType: () => getFormatType,
 175      getFormatTypeForBareElement: () => getFormatTypeForBareElement,
 176      getFormatTypeForClassName: () => getFormatTypeForClassName,
 177      getFormatTypes: () => getFormatTypes
 178    });
 179    var import_data2 = __toESM(require_data(), 1);
 180    var getFormatTypes = (0, import_data2.createSelector)(
 181      (state) => Object.values(state.formatTypes),
 182      (state) => [state.formatTypes]
 183    );
 184    function getFormatType(state, name) {
 185      return state.formatTypes[name];
 186    }
 187    function getFormatTypeForBareElement(state, bareElementTagName) {
 188      const formatTypes2 = getFormatTypes(state);
 189      return formatTypes2.find(({ className, tagName }) => {
 190        return className === null && bareElementTagName === tagName;
 191      }) || formatTypes2.find(({ className, tagName }) => {
 192        return className === null && "*" === tagName;
 193      });
 194    }
 195    function getFormatTypeForClassName(state, elementClassName) {
 196      return getFormatTypes(state).find(({ className }) => {
 197        if (className === null) {
 198          return false;
 199        }
 200        return ` $elementClassName} `.indexOf(` $className} `) >= 0;
 201      });
 202    }
 203  
 204    // packages/rich-text/build-module/store/actions.mjs
 205    var actions_exports = {};
 206    __export(actions_exports, {
 207      addFormatTypes: () => addFormatTypes,
 208      removeFormatTypes: () => removeFormatTypes
 209    });
 210    function addFormatTypes(formatTypes2) {
 211      return {
 212        type: "ADD_FORMAT_TYPES",
 213        formatTypes: Array.isArray(formatTypes2) ? formatTypes2 : [formatTypes2]
 214      };
 215    }
 216    function removeFormatTypes(names) {
 217      return {
 218        type: "REMOVE_FORMAT_TYPES",
 219        names: Array.isArray(names) ? names : [names]
 220      };
 221    }
 222  
 223    // packages/rich-text/build-module/store/index.mjs
 224    var STORE_NAME = "core/rich-text";
 225    var store = (0, import_data3.createReduxStore)(STORE_NAME, {
 226      reducer: reducer_default,
 227      selectors: selectors_exports,
 228      actions: actions_exports
 229    });
 230    (0, import_data3.register)(store);
 231  
 232    // packages/rich-text/build-module/is-format-equal.mjs
 233    function isFormatEqual(format1, format2) {
 234      if (format1 === format2) {
 235        return true;
 236      }
 237      if (!format1 || !format2) {
 238        return false;
 239      }
 240      if (format1.type !== format2.type) {
 241        return false;
 242      }
 243      let attributes1 = format1.attributes;
 244      let attributes2 = format2.attributes;
 245      if (format1.unregisteredAttributes || format2.unregisteredAttributes) {
 246        attributes1 = { ...attributes1, ...format1.unregisteredAttributes };
 247        attributes2 = { ...attributes2, ...format2.unregisteredAttributes };
 248      }
 249      if (attributes1 === attributes2) {
 250        return true;
 251      }
 252      if (!attributes1 || !attributes2) {
 253        return false;
 254      }
 255      const keys1 = Object.keys(attributes1);
 256      const keys2 = Object.keys(attributes2);
 257      if (keys1.length !== keys2.length) {
 258        return false;
 259      }
 260      const length = keys1.length;
 261      for (let i = 0; i < length; i++) {
 262        const name = keys1[i];
 263        if (attributes1[name] !== attributes2[name]) {
 264          return false;
 265        }
 266      }
 267      return true;
 268    }
 269  
 270    // packages/rich-text/build-module/normalise-formats.mjs
 271    function normaliseFormats(value) {
 272      const newFormats = value.formats.slice();
 273      newFormats.forEach((formatsAtIndex, index) => {
 274        const formatsAtPreviousIndex = newFormats[index - 1];
 275        if (formatsAtPreviousIndex) {
 276          const newFormatsAtIndex = formatsAtIndex.slice();
 277          newFormatsAtIndex.forEach((format, formatIndex) => {
 278            const previousFormat = formatsAtPreviousIndex[formatIndex];
 279            if (isFormatEqual(format, previousFormat)) {
 280              newFormatsAtIndex[formatIndex] = previousFormat;
 281            }
 282          });
 283          newFormats[index] = newFormatsAtIndex;
 284        }
 285      });
 286      return {
 287        ...value,
 288        formats: newFormats
 289      };
 290    }
 291  
 292    // packages/rich-text/build-module/apply-format.mjs
 293    function replace(array, index, value) {
 294      array = array.slice();
 295      array[index] = value;
 296      return array;
 297    }
 298    function applyFormat(value, format, startIndex = value.start, endIndex = value.end) {
 299      const { formats, activeFormats } = value;
 300      const newFormats = formats.slice();
 301      const newActiveFormats = [
 302        ...activeFormats?.filter(({ type }) => type !== format.type) || [],
 303        format
 304      ];
 305      if (startIndex === void 0 || endIndex === void 0) {
 306        return normaliseFormats({
 307          ...value,
 308          formats: newFormats,
 309          activeFormats: newActiveFormats
 310        });
 311      }
 312      if (startIndex === endIndex) {
 313        const startFormat = newFormats[startIndex]?.find(
 314          ({ type }) => type === format.type
 315        );
 316        if (startFormat) {
 317          const index = newFormats[startIndex].indexOf(startFormat);
 318          while (newFormats[startIndex] && newFormats[startIndex][index] === startFormat) {
 319            newFormats[startIndex] = replace(
 320              newFormats[startIndex],
 321              index,
 322              format
 323            );
 324            startIndex--;
 325          }
 326          endIndex++;
 327          while (newFormats[endIndex] && newFormats[endIndex][index] === startFormat) {
 328            newFormats[endIndex] = replace(
 329              newFormats[endIndex],
 330              index,
 331              format
 332            );
 333            endIndex++;
 334          }
 335        }
 336      } else {
 337        let position = Infinity;
 338        for (let index = startIndex; index < endIndex; index++) {
 339          if (newFormats[index]) {
 340            newFormats[index] = newFormats[index].filter(
 341              ({ type }) => type !== format.type
 342            );
 343            const length = newFormats[index].length;
 344            if (length < position) {
 345              position = length;
 346            }
 347          } else {
 348            newFormats[index] = [];
 349            position = 0;
 350          }
 351        }
 352        for (let index = startIndex; index < endIndex; index++) {
 353          newFormats[index].splice(position, 0, format);
 354        }
 355      }
 356      return normaliseFormats({
 357        ...value,
 358        formats: newFormats,
 359        activeFormats: newActiveFormats
 360      });
 361    }
 362  
 363    // packages/rich-text/build-module/create.mjs
 364    var import_data5 = __toESM(require_data(), 1);
 365  
 366    // packages/rich-text/build-module/create-element.mjs
 367    var body;
 368    function createElement({ implementation }, html) {
 369      if (!body) {
 370        body = implementation.createHTMLDocument("").body;
 371      }
 372      body.innerHTML = html;
 373      return body;
 374    }
 375  
 376    // packages/rich-text/build-module/special-characters.mjs
 377    var OBJECT_REPLACEMENT_CHARACTER = "\uFFFC";
 378    var ZWNBSP = "\uFEFF";
 379  
 380    // packages/rich-text/build-module/to-html-string.mjs
 381    var import_escape_html = __toESM(require_escape_html(), 1);
 382  
 383    // packages/rich-text/build-module/get-active-formats.mjs
 384    function getActiveFormats(value, EMPTY_ACTIVE_FORMATS3 = []) {
 385      const { formats, start, end, activeFormats } = value;
 386      if (start === void 0 || end === void 0) {
 387        return EMPTY_ACTIVE_FORMATS3;
 388      }
 389      if (start === end) {
 390        if (activeFormats) {
 391          return activeFormats;
 392        }
 393        const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS3;
 394        const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS3;
 395        if (formatsBefore.length < formatsAfter.length) {
 396          return formatsBefore;
 397        }
 398        return formatsAfter;
 399      }
 400      if (!formats[start]) {
 401        return EMPTY_ACTIVE_FORMATS3;
 402      }
 403      const selectedFormats = formats.slice(start, end);
 404      const _activeFormats = [...selectedFormats[0]];
 405      let i = selectedFormats.length;
 406      while (i--) {
 407        const formatsAtIndex = selectedFormats[i];
 408        if (!formatsAtIndex) {
 409          return EMPTY_ACTIVE_FORMATS3;
 410        }
 411        let ii = _activeFormats.length;
 412        while (ii--) {
 413          const format = _activeFormats[ii];
 414          if (!formatsAtIndex.find(
 415            (_format) => isFormatEqual(format, _format)
 416          )) {
 417            _activeFormats.splice(ii, 1);
 418          }
 419        }
 420        if (_activeFormats.length === 0) {
 421          return EMPTY_ACTIVE_FORMATS3;
 422        }
 423      }
 424      return _activeFormats || EMPTY_ACTIVE_FORMATS3;
 425    }
 426  
 427    // packages/rich-text/build-module/get-format-type.mjs
 428    var import_data4 = __toESM(require_data(), 1);
 429    function getFormatType2(name) {
 430      return (0, import_data4.select)(store).getFormatType(name);
 431    }
 432  
 433    // packages/rich-text/build-module/to-tree.mjs
 434    function restoreOnAttributes(attributes, isEditableTree) {
 435      if (isEditableTree) {
 436        return attributes;
 437      }
 438      const newAttributes = {};
 439      for (const key in attributes) {
 440        let newKey = key;
 441        if (key.startsWith("data-disable-rich-text-")) {
 442          newKey = key.slice("data-disable-rich-text-".length);
 443        }
 444        newAttributes[newKey] = attributes[key];
 445      }
 446      return newAttributes;
 447    }
 448    function fromFormat({
 449      type,
 450      tagName,
 451      attributes,
 452      unregisteredAttributes,
 453      object,
 454      boundaryClass,
 455      isEditableTree
 456    }) {
 457      const formatType = getFormatType2(type);
 458      let elementAttributes = {};
 459      if (boundaryClass && isEditableTree) {
 460        elementAttributes["data-rich-text-format-boundary"] = "true";
 461      }
 462      if (!formatType) {
 463        if (attributes) {
 464          elementAttributes = { ...attributes, ...elementAttributes };
 465        }
 466        return {
 467          type,
 468          attributes: restoreOnAttributes(
 469            elementAttributes,
 470            isEditableTree
 471          ),
 472          object
 473        };
 474      }
 475      elementAttributes = { ...unregisteredAttributes, ...elementAttributes };
 476      for (const name in attributes) {
 477        const key = formatType.attributes ? formatType.attributes[name] : false;
 478        if (key) {
 479          elementAttributes[key] = attributes[name];
 480        } else {
 481          elementAttributes[name] = attributes[name];
 482        }
 483      }
 484      if (formatType.className) {
 485        if (elementAttributes.class) {
 486          elementAttributes.class = `$formatType.className} $elementAttributes.class}`;
 487        } else {
 488          elementAttributes.class = formatType.className;
 489        }
 490      }
 491      return {
 492        type: tagName || formatType.tagName,
 493        object: formatType.object,
 494        attributes: restoreOnAttributes(elementAttributes, isEditableTree)
 495      };
 496    }
 497    function isEqualUntil(a, b, index) {
 498      do {
 499        if (a[index] !== b[index]) {
 500          return false;
 501        }
 502      } while (index--);
 503      return true;
 504    }
 505    function toTree({
 506      value,
 507      preserveWhiteSpace,
 508      createEmpty: createEmpty2,
 509      append: append3,
 510      getLastChild: getLastChild3,
 511      getParent: getParent3,
 512      isText: isText3,
 513      getText: getText3,
 514      remove: remove4,
 515      appendText: appendText3,
 516      onStartIndex,
 517      onEndIndex,
 518      isEditableTree,
 519      placeholder
 520    }) {
 521      const { formats, replacements, text, start, end } = value;
 522      const formatsLength = formats.length + 1;
 523      const tree = createEmpty2();
 524      const activeFormats = getActiveFormats(value);
 525      const deepestActiveFormat = activeFormats[activeFormats.length - 1];
 526      let lastCharacterFormats;
 527      let lastCharacter;
 528      append3(tree, "");
 529      for (let i = 0; i < formatsLength; i++) {
 530        const character = text.charAt(i);
 531        const shouldInsertPadding = isEditableTree && // Pad the line if the line is empty.
 532        (!lastCharacter || // Pad the line if the previous character is a line break, otherwise
 533        // the line break won't be visible.
 534        lastCharacter === "\n");
 535        const characterFormats = formats[i];
 536        let pointer = getLastChild3(tree);
 537        if (characterFormats) {
 538          characterFormats.forEach((format, formatIndex) => {
 539            if (pointer && lastCharacterFormats && // Reuse the last element if all formats remain the same.
 540            isEqualUntil(
 541              characterFormats,
 542              lastCharacterFormats,
 543              formatIndex
 544            )) {
 545              pointer = getLastChild3(pointer);
 546              return;
 547            }
 548            const { type, tagName, attributes, unregisteredAttributes } = format;
 549            const boundaryClass = isEditableTree && format === deepestActiveFormat;
 550            const parent = getParent3(pointer);
 551            const newNode = append3(
 552              parent,
 553              fromFormat({
 554                type,
 555                tagName,
 556                attributes,
 557                unregisteredAttributes,
 558                boundaryClass,
 559                isEditableTree
 560              })
 561            );
 562            if (isText3(pointer) && getText3(pointer).length === 0) {
 563              remove4(pointer);
 564            }
 565            pointer = append3(newNode, "");
 566          });
 567        }
 568        if (i === 0) {
 569          if (onStartIndex && start === 0) {
 570            onStartIndex(tree, pointer);
 571          }
 572          if (onEndIndex && end === 0) {
 573            onEndIndex(tree, pointer);
 574          }
 575        }
 576        if (character === OBJECT_REPLACEMENT_CHARACTER) {
 577          const replacement = replacements[i];
 578          if (!replacement) {
 579            continue;
 580          }
 581          const { type, attributes, innerHTML } = replacement;
 582          const formatType = getFormatType2(type);
 583          if (isEditableTree && type === "#comment") {
 584            pointer = append3(getParent3(pointer), {
 585              type: "span",
 586              attributes: {
 587                contenteditable: "false",
 588                "data-rich-text-comment": attributes["data-rich-text-comment"]
 589              }
 590            });
 591            append3(
 592              append3(pointer, { type: "span" }),
 593              attributes["data-rich-text-comment"].trim()
 594            );
 595          } else if (!isEditableTree && type === "script") {
 596            pointer = append3(
 597              getParent3(pointer),
 598              fromFormat({
 599                type: "script",
 600                isEditableTree
 601              })
 602            );
 603            append3(pointer, {
 604              html: decodeURIComponent(
 605                attributes["data-rich-text-script"]
 606              )
 607            });
 608          } else if (formatType?.contentEditable === false) {
 609            if (innerHTML || isEditableTree) {
 610              pointer = getParent3(pointer);
 611              if (isEditableTree) {
 612                const attrs = {
 613                  contenteditable: "false",
 614                  "data-rich-text-bogus": true
 615                };
 616                if (start === i && end === i + 1) {
 617                  attrs["data-rich-text-format-boundary"] = true;
 618                }
 619                pointer = append3(pointer, {
 620                  type: "span",
 621                  attributes: attrs
 622                });
 623                if (isEditableTree && i + 1 === text.length) {
 624                  append3(getParent3(pointer), ZWNBSP);
 625                }
 626              }
 627              pointer = append3(
 628                pointer,
 629                fromFormat({
 630                  ...replacement,
 631                  isEditableTree
 632                })
 633              );
 634              if (innerHTML) {
 635                append3(pointer, {
 636                  html: innerHTML
 637                });
 638              }
 639            }
 640          } else {
 641            pointer = append3(
 642              getParent3(pointer),
 643              fromFormat({
 644                ...replacement,
 645                object: true,
 646                isEditableTree
 647              })
 648            );
 649          }
 650          pointer = append3(getParent3(pointer), "");
 651        } else if (!preserveWhiteSpace && character === "\n") {
 652          pointer = append3(getParent3(pointer), {
 653            type: "br",
 654            attributes: isEditableTree ? {
 655              "data-rich-text-line-break": "true"
 656            } : void 0,
 657            object: true
 658          });
 659          pointer = append3(getParent3(pointer), "");
 660        } else if (!isText3(pointer)) {
 661          pointer = append3(getParent3(pointer), character);
 662        } else {
 663          appendText3(pointer, character);
 664        }
 665        if (onStartIndex && start === i + 1) {
 666          onStartIndex(tree, pointer);
 667        }
 668        if (onEndIndex && end === i + 1) {
 669          onEndIndex(tree, pointer);
 670        }
 671        if (shouldInsertPadding && i === text.length) {
 672          appendText3(pointer, ZWNBSP);
 673          if (placeholder && text.length === 0) {
 674            append3(getParent3(pointer), {
 675              type: "span",
 676              attributes: {
 677                "data-rich-text-placeholder": placeholder,
 678                // Necessary to prevent the placeholder from catching
 679                // selection and being editable.
 680                style: "pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;"
 681              }
 682            });
 683          }
 684        }
 685        lastCharacterFormats = characterFormats;
 686        lastCharacter = character;
 687      }
 688      return tree;
 689    }
 690  
 691    // packages/rich-text/build-module/to-html-string.mjs
 692    function toHTMLString({
 693      value,
 694      preserveWhiteSpace
 695    }) {
 696      const tree = toTree({
 697        value,
 698        preserveWhiteSpace,
 699        createEmpty,
 700        append,
 701        getLastChild,
 702        getParent,
 703        isText,
 704        getText,
 705        remove,
 706        appendText
 707      });
 708      return createChildrenHTML(tree.children);
 709    }
 710    function createEmpty() {
 711      return {};
 712    }
 713    function getLastChild({ children }) {
 714      return children && children[children.length - 1];
 715    }
 716    function append(parent, object) {
 717      if (typeof object === "string") {
 718        object = { text: object };
 719      }
 720      object.parent = parent;
 721      parent.children = parent.children || [];
 722      parent.children.push(object);
 723      return object;
 724    }
 725    function appendText(object, text) {
 726      object.text += text;
 727    }
 728    function getParent({ parent }) {
 729      return parent;
 730    }
 731    function isText({ text }) {
 732      return typeof text === "string";
 733    }
 734    function getText({ text }) {
 735      return text;
 736    }
 737    function remove(object) {
 738      const index = object.parent.children.indexOf(object);
 739      if (index !== -1) {
 740        object.parent.children.splice(index, 1);
 741      }
 742      return object;
 743    }
 744    function createElementHTML({
 745      type,
 746      attributes,
 747      object,
 748      children
 749    }) {
 750      if (type === "#comment") {
 751        return `<!--$attributes["data-rich-text-comment"]}-->`;
 752      }
 753      let attributeString = "";
 754      for (const key in attributes) {
 755        if (!(0, import_escape_html.isValidAttributeName)(key)) {
 756          continue;
 757        }
 758        attributeString += ` $key}="${(0, import_escape_html.escapeAttribute)(
 759          attributes[key]
 760        )}"`;
 761      }
 762      if (object) {
 763        return `<$type}$attributeString}>`;
 764      }
 765      return `<$type}$attributeString}>$createChildrenHTML(
 766        children
 767      )}</$type}>`;
 768    }
 769    function createChildrenHTML(children = []) {
 770      return children.map((child) => {
 771        if (child.html !== void 0) {
 772          return child.html;
 773        }
 774        return child.text === void 0 ? createElementHTML(child) : (0, import_escape_html.escapeEditableHTML)(child.text);
 775      }).join("");
 776    }
 777  
 778    // packages/rich-text/build-module/get-text-content.mjs
 779    function getTextContent({ text }) {
 780      return text.replaceAll(OBJECT_REPLACEMENT_CHARACTER, "");
 781    }
 782  
 783    // packages/rich-text/build-module/create.mjs
 784    function createEmptyValue() {
 785      return {
 786        formats: [],
 787        replacements: [],
 788        text: ""
 789      };
 790    }
 791    function toFormat({
 792      tagName,
 793      attributes
 794    }) {
 795      let formatType;
 796      if (attributes && attributes.class) {
 797        formatType = (0, import_data5.select)(store).getFormatTypeForClassName(
 798          attributes.class
 799        );
 800        if (formatType) {
 801          attributes.class = ` $attributes.class} `.replace(` $formatType.className} `, " ").trim();
 802          if (!attributes.class) {
 803            delete attributes.class;
 804          }
 805        }
 806      }
 807      if (!formatType) {
 808        formatType = (0, import_data5.select)(store).getFormatTypeForBareElement(tagName);
 809      }
 810      if (!formatType) {
 811        return attributes ? { type: tagName, attributes } : { type: tagName };
 812      }
 813      if (formatType.__experimentalCreatePrepareEditableTree && !formatType.__experimentalCreateOnChangeEditableValue) {
 814        return null;
 815      }
 816      if (!attributes) {
 817        return { formatType, type: formatType.name, tagName };
 818      }
 819      const registeredAttributes = {};
 820      const unregisteredAttributes = {};
 821      const _attributes = { ...attributes };
 822      for (const key in formatType.attributes) {
 823        const name = formatType.attributes[key];
 824        registeredAttributes[key] = _attributes[name];
 825        delete _attributes[name];
 826        if (typeof registeredAttributes[key] === "undefined") {
 827          delete registeredAttributes[key];
 828        }
 829      }
 830      for (const name in _attributes) {
 831        unregisteredAttributes[name] = attributes[name];
 832      }
 833      if (formatType.contentEditable === false) {
 834        delete unregisteredAttributes.contenteditable;
 835      }
 836      const format = {
 837        formatType,
 838        type: formatType.name,
 839        tagName
 840      };
 841      if (Object.keys(registeredAttributes).length) {
 842        format.attributes = registeredAttributes;
 843      }
 844      if (Object.keys(unregisteredAttributes).length) {
 845        format.unregisteredAttributes = unregisteredAttributes;
 846      }
 847      return format;
 848    }
 849    var RichTextData = class _RichTextData {
 850      #value;
 851      static empty() {
 852        return new _RichTextData();
 853      }
 854      static fromPlainText(text) {
 855        return new _RichTextData(create({ text }));
 856      }
 857      static fromHTMLString(html) {
 858        return new _RichTextData(create({ html }));
 859      }
 860      /**
 861       * Create a RichTextData instance from an HTML element.
 862       *
 863       * @param htmlElement                The HTML element to create the instance from.
 864       * @param options                    Options.
 865       * @param options.preserveWhiteSpace Whether to preserve white space.
 866       * @return The RichTextData instance.
 867       */
 868      static fromHTMLElement(htmlElement, options = {}) {
 869        const { preserveWhiteSpace = false } = options;
 870        const element = preserveWhiteSpace ? htmlElement : collapseWhiteSpace(htmlElement);
 871        const richTextData = new _RichTextData(create({ element }));
 872        Object.defineProperty(richTextData, "originalHTML", {
 873          value: htmlElement.innerHTML
 874        });
 875        return richTextData;
 876      }
 877      constructor(init = createEmptyValue()) {
 878        this.#value = init;
 879      }
 880      toPlainText() {
 881        return getTextContent(this.#value);
 882      }
 883      // We could expose `toHTMLElement` at some point as well, but we'd only use
 884      // it internally.
 885      /**
 886       * Convert the rich text value to an HTML string.
 887       *
 888       * @param options                    Options.
 889       * @param options.preserveWhiteSpace Whether to preserve white space.
 890       * @return The HTML string.
 891       */
 892      toHTMLString({
 893        preserveWhiteSpace
 894      } = {}) {
 895        return this.originalHTML || toHTMLString({
 896          value: this.#value,
 897          preserveWhiteSpace
 898        });
 899      }
 900      valueOf() {
 901        return this.toHTMLString();
 902      }
 903      toString() {
 904        return this.toHTMLString();
 905      }
 906      toJSON() {
 907        return this.toHTMLString();
 908      }
 909      get length() {
 910        return this.text.length;
 911      }
 912      get formats() {
 913        return this.#value.formats;
 914      }
 915      get replacements() {
 916        return this.#value.replacements;
 917      }
 918      get text() {
 919        return this.#value.text;
 920      }
 921    };
 922    for (const name of Object.getOwnPropertyNames(String.prototype)) {
 923      if (RichTextData.prototype.hasOwnProperty(name)) {
 924        continue;
 925      }
 926      Object.defineProperty(RichTextData.prototype, name, {
 927        value(...args) {
 928          return this.toHTMLString()[name](...args);
 929        }
 930      });
 931    }
 932    function create({
 933      element,
 934      text,
 935      html,
 936      range,
 937      __unstableIsEditableTree: isEditableTree
 938    } = {}) {
 939      if (html instanceof RichTextData) {
 940        return {
 941          text: html.text,
 942          formats: html.formats,
 943          replacements: html.replacements
 944        };
 945      }
 946      if (typeof text === "string" && text.length > 0) {
 947        return {
 948          formats: Array(text.length),
 949          replacements: Array(text.length),
 950          text
 951        };
 952      }
 953      if (typeof html === "string" && html.length > 0) {
 954        element = createElement(document, html);
 955      }
 956      if (typeof element !== "object") {
 957        return createEmptyValue();
 958      }
 959      return createFromElement({
 960        element,
 961        range,
 962        isEditableTree
 963      });
 964    }
 965    function accumulateSelection(accumulator, node, range, value) {
 966      if (!range) {
 967        return;
 968      }
 969      const { parentNode } = node;
 970      const { startContainer, startOffset, endContainer, endOffset } = range;
 971      const currentLength = accumulator.text.length;
 972      if (value.start !== void 0) {
 973        accumulator.start = currentLength + value.start;
 974      } else if (node === startContainer && node.nodeType === node.TEXT_NODE) {
 975        accumulator.start = currentLength + startOffset;
 976      } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset]) {
 977        accumulator.start = currentLength;
 978      } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset - 1]) {
 979        accumulator.start = currentLength + value.text.length;
 980      } else if (node === startContainer) {
 981        accumulator.start = currentLength;
 982      }
 983      if (value.end !== void 0) {
 984        accumulator.end = currentLength + value.end;
 985      } else if (node === endContainer && node.nodeType === node.TEXT_NODE) {
 986        accumulator.end = currentLength + endOffset;
 987      } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset - 1]) {
 988        accumulator.end = currentLength + value.text.length;
 989      } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset]) {
 990        accumulator.end = currentLength;
 991      } else if (node === endContainer) {
 992        accumulator.end = currentLength + endOffset;
 993      }
 994    }
 995    function filterRange(node, range, filter) {
 996      if (!range) {
 997        return;
 998      }
 999      const { startContainer, endContainer } = range;
1000      let { startOffset, endOffset } = range;
1001      if (node === startContainer) {
1002        startOffset = filter(node.nodeValue.slice(0, startOffset)).length;
1003      }
1004      if (node === endContainer) {
1005        endOffset = filter(node.nodeValue.slice(0, endOffset)).length;
1006      }
1007      return { startContainer, startOffset, endContainer, endOffset };
1008    }
1009    function collapseWhiteSpace(element, isRoot = true, hasPrecedingSpace = false, hasTrailingSpace = false) {
1010      const clone = element.cloneNode(true);
1011      clone.normalize();
1012      Array.from(clone.childNodes).forEach((node, i, nodes) => {
1013        if (node.nodeType === node.TEXT_NODE) {
1014          let newNodeValue = node.nodeValue;
1015          if (/[\n\t\r\f]/.test(newNodeValue)) {
1016            newNodeValue = newNodeValue.replace(/[\n\t\r\f]+/g, " ");
1017          }
1018          if (newNodeValue.indexOf("  ") !== -1) {
1019            newNodeValue = newNodeValue.replace(/ {2,}/g, " ");
1020          }
1021          if (i === 0 && newNodeValue.startsWith(" ") && (isRoot || hasPrecedingSpace)) {
1022            newNodeValue = newNodeValue.slice(1);
1023          }
1024          if (i === nodes.length - 1 && newNodeValue.endsWith(" ") && (isRoot || hasTrailingSpace)) {
1025            newNodeValue = newNodeValue.slice(0, -1);
1026          }
1027          node.nodeValue = newNodeValue;
1028        } else if (node.nodeType === node.ELEMENT_NODE) {
1029          const { previousSibling, nextSibling } = node;
1030          const prevHasSpace = previousSibling?.textContent.endsWith(" ");
1031          const nextHasSpace = nextSibling?.textContent.startsWith(" ");
1032          node.replaceWith(
1033            collapseWhiteSpace(
1034              node,
1035              false,
1036              previousSibling ? prevHasSpace : isRoot || hasPrecedingSpace,
1037              nextSibling ? nextHasSpace : isRoot || hasTrailingSpace
1038            )
1039          );
1040        }
1041      });
1042      return clone;
1043    }
1044    var CARRIAGE_RETURN = "\r";
1045    function removeReservedCharacters(string) {
1046      return string.replace(
1047        new RegExp(
1048          `[$ZWNBSP}$OBJECT_REPLACEMENT_CHARACTER}$CARRIAGE_RETURN}]`,
1049          "gu"
1050        ),
1051        ""
1052      );
1053    }
1054    function createFromElement({
1055      element,
1056      range,
1057      isEditableTree
1058    }) {
1059      const accumulator = createEmptyValue();
1060      if (!element) {
1061        return accumulator;
1062      }
1063      if (!element.hasChildNodes()) {
1064        accumulateSelection(accumulator, element, range, createEmptyValue());
1065        return accumulator;
1066      }
1067      const length = element.childNodes.length;
1068      for (let index = 0; index < length; index++) {
1069        const node = element.childNodes[index];
1070        const tagName = node.nodeName.toLowerCase();
1071        if (node.nodeType === node.TEXT_NODE) {
1072          const text = removeReservedCharacters(node.nodeValue);
1073          range = filterRange(node, range, removeReservedCharacters);
1074          accumulateSelection(accumulator, node, range, { text });
1075          accumulator.formats.length += text.length;
1076          accumulator.replacements.length += text.length;
1077          accumulator.text += text;
1078          continue;
1079        }
1080        if (node.nodeType === node.COMMENT_NODE || node.nodeType === node.ELEMENT_NODE && node.tagName === "SPAN" && node.hasAttribute("data-rich-text-comment")) {
1081          const value2 = {
1082            formats: Array(1),
1083            replacements: [
1084              {
1085                type: "#comment",
1086                attributes: {
1087                  "data-rich-text-comment": node.nodeType === node.COMMENT_NODE ? node.nodeValue : node.getAttribute(
1088                    "data-rich-text-comment"
1089                  )
1090                }
1091              }
1092            ],
1093            text: OBJECT_REPLACEMENT_CHARACTER
1094          };
1095          accumulateSelection(accumulator, node, range, value2);
1096          mergePair(accumulator, value2);
1097          continue;
1098        }
1099        if (node.nodeType !== node.ELEMENT_NODE) {
1100          continue;
1101        }
1102        if (isEditableTree && // Ignore any line breaks that are not inserted by us.
1103        tagName === "br" && !node.getAttribute("data-rich-text-line-break")) {
1104          accumulateSelection(accumulator, node, range, createEmptyValue());
1105          continue;
1106        }
1107        if (tagName === "script") {
1108          const value2 = {
1109            formats: Array(1),
1110            replacements: [
1111              {
1112                type: tagName,
1113                attributes: {
1114                  "data-rich-text-script": node.getAttribute(
1115                    "data-rich-text-script"
1116                  ) || encodeURIComponent(
1117                    node.innerHTML
1118                  )
1119                }
1120              }
1121            ],
1122            text: OBJECT_REPLACEMENT_CHARACTER
1123          };
1124          accumulateSelection(accumulator, node, range, value2);
1125          mergePair(accumulator, value2);
1126          continue;
1127        }
1128        if (tagName === "br") {
1129          accumulateSelection(accumulator, node, range, createEmptyValue());
1130          mergePair(accumulator, create({ text: "\n" }));
1131          continue;
1132        }
1133        const format = toFormat({
1134          tagName,
1135          attributes: getAttributes({ element: node })
1136        });
1137        if (format?.formatType?.contentEditable === false) {
1138          delete format.formatType;
1139          accumulateSelection(accumulator, node, range, createEmptyValue());
1140          mergePair(accumulator, {
1141            formats: Array(1),
1142            replacements: [
1143              {
1144                ...format,
1145                innerHTML: node.innerHTML
1146              }
1147            ],
1148            text: OBJECT_REPLACEMENT_CHARACTER
1149          });
1150          continue;
1151        }
1152        if (format) {
1153          delete format.formatType;
1154        }
1155        const value = createFromElement({
1156          element: node,
1157          range,
1158          isEditableTree
1159        });
1160        accumulateSelection(accumulator, node, range, value);
1161        if (!format || node.getAttribute("data-rich-text-placeholder") || node.getAttribute("data-rich-text-bogus")) {
1162          mergePair(accumulator, value);
1163        } else if (value.text.length === 0) {
1164          if (format.attributes) {
1165            mergePair(accumulator, {
1166              formats: Array(1),
1167              replacements: [format],
1168              text: OBJECT_REPLACEMENT_CHARACTER
1169            });
1170          }
1171        } else {
1172          let mergeFormats2 = function(formats) {
1173            if (mergeFormats2.formats === formats) {
1174              return mergeFormats2.newFormats;
1175            }
1176            const newFormats = formats ? [format, ...formats] : [format];
1177            mergeFormats2.formats = formats;
1178            mergeFormats2.newFormats = newFormats;
1179            return newFormats;
1180          };
1181          var mergeFormats = mergeFormats2;
1182          mergeFormats2.newFormats = [format];
1183          mergePair(accumulator, {
1184            ...value,
1185            formats: Array.from(value.formats, mergeFormats2)
1186          });
1187        }
1188      }
1189      return accumulator;
1190    }
1191    function getAttributes({ element }) {
1192      if (!element.hasAttributes()) {
1193        return;
1194      }
1195      const length = element.attributes.length;
1196      let accumulator;
1197      for (let i = 0; i < length; i++) {
1198        const { name, value } = element.attributes[i];
1199        if (name.indexOf("data-rich-text-") === 0) {
1200          continue;
1201        }
1202        const safeName = /^on/i.test(name) ? "data-disable-rich-text-" + name : name;
1203        accumulator = accumulator || {};
1204        accumulator[safeName] = value;
1205      }
1206      return accumulator;
1207    }
1208  
1209    // packages/rich-text/build-module/concat.mjs
1210    function mergePair(a, b) {
1211      a.formats = a.formats.concat(b.formats);
1212      a.replacements = a.replacements.concat(b.replacements);
1213      a.text += b.text;
1214      return a;
1215    }
1216    function concat(...values) {
1217      return normaliseFormats(
1218        values.reduce(mergePair, create())
1219      );
1220    }
1221  
1222    // packages/rich-text/build-module/get-active-format.mjs
1223    function getActiveFormat(value, formatType) {
1224      return getActiveFormats(value).find(
1225        ({ type }) => type === formatType
1226      );
1227    }
1228  
1229    // packages/rich-text/build-module/get-active-object.mjs
1230    function getActiveObject({
1231      start,
1232      end,
1233      replacements,
1234      text
1235    }) {
1236      if (start === void 0 || start + 1 !== end || text[start] !== OBJECT_REPLACEMENT_CHARACTER) {
1237        return;
1238      }
1239      return replacements[start];
1240    }
1241  
1242    // packages/rich-text/build-module/is-collapsed.mjs
1243    function isCollapsed({
1244      start,
1245      end
1246    }) {
1247      if (start === void 0 || end === void 0) {
1248        return;
1249      }
1250      return start === end;
1251    }
1252  
1253    // packages/rich-text/build-module/is-empty.mjs
1254    function isEmpty({ text }) {
1255      return text.length === 0;
1256    }
1257  
1258    // packages/rich-text/build-module/join.mjs
1259    function join(values, separator = "") {
1260      if (typeof separator === "string") {
1261        separator = create({ text: separator });
1262      }
1263      return normaliseFormats(
1264        values.reduce((accumulator, { formats, replacements, text }) => ({
1265          formats: accumulator.formats.concat(separator.formats, formats),
1266          replacements: accumulator.replacements.concat(
1267            separator.replacements,
1268            replacements
1269          ),
1270          text: accumulator.text + separator.text + text
1271        }))
1272      );
1273    }
1274  
1275    // packages/rich-text/build-module/register-format-type.mjs
1276    var import_data6 = __toESM(require_data(), 1);
1277    function registerFormatType(name, settings) {
1278      const formatType = {
1279        name,
1280        ...settings
1281      };
1282      if (typeof formatType.name !== "string") {
1283        window.console.error("Format names must be strings.");
1284        return;
1285      }
1286      if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(formatType.name)) {
1287        window.console.error(
1288          "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"
1289        );
1290        return;
1291      }
1292      if ((0, import_data6.select)(store).getFormatType(formatType.name)) {
1293        window.console.error(
1294          'Format "' + formatType.name + '" is already registered.'
1295        );
1296        return;
1297      }
1298      if (typeof formatType.tagName !== "string" || formatType.tagName === "") {
1299        window.console.error("Format tag names must be a string.");
1300        return;
1301      }
1302      if ((typeof formatType.className !== "string" || formatType.className === "") && formatType.className !== null) {
1303        window.console.error(
1304          "Format class names must be a string, or null to handle bare elements."
1305        );
1306        return;
1307      }
1308      if (formatType.className !== null && !/^[_a-zA-Z]+[a-zA-Z0-9_-]*$/.test(formatType.className)) {
1309        window.console.error(
1310          "A class name must begin with a letter, followed by any number of hyphens, underscores, letters, or numbers."
1311        );
1312        return;
1313      }
1314      if (formatType.className === null) {
1315        const formatTypeForBareElement = (0, import_data6.select)(
1316          store
1317        ).getFormatTypeForBareElement(formatType.tagName);
1318        if (formatTypeForBareElement && formatTypeForBareElement.name !== "core/unknown") {
1319          window.console.error(
1320            `Format "$formatTypeForBareElement.name}" is already registered to handle bare tag name "$formatType.tagName}".`
1321          );
1322          return;
1323        }
1324      } else {
1325        const formatTypeForClassName = (0, import_data6.select)(
1326          store
1327        ).getFormatTypeForClassName(formatType.className);
1328        if (formatTypeForClassName) {
1329          window.console.error(
1330            `Format "$formatTypeForClassName.name}" is already registered to handle class name "$formatType.className}".`
1331          );
1332          return;
1333        }
1334      }
1335      if (!("title" in formatType) || formatType.title === "") {
1336        window.console.error(
1337          'The format "' + formatType.name + '" must have a title.'
1338        );
1339        return;
1340      }
1341      if ((formatType.keywords?.length ?? 0) > 3) {
1342        window.console.error(
1343          'The format "' + formatType.name + '" can have a maximum of 3 keywords.'
1344        );
1345        return;
1346      }
1347      if (typeof formatType.title !== "string") {
1348        window.console.error("Format titles must be strings.");
1349        return;
1350      }
1351      (0, import_data6.dispatch)(store).addFormatTypes(formatType);
1352      return formatType;
1353    }
1354  
1355    // packages/rich-text/build-module/remove-format.mjs
1356    function removeFormat(value, formatType, startIndex = value.start, endIndex = value.end) {
1357      const { formats, activeFormats } = value;
1358      const newFormats = formats.slice();
1359      const newActiveFormats = activeFormats?.filter(({ type }) => type !== formatType) || [];
1360      if (startIndex === void 0 || endIndex === void 0) {
1361        return normaliseFormats({
1362          ...value,
1363          formats: newFormats,
1364          activeFormats: newActiveFormats
1365        });
1366      }
1367      if (startIndex === endIndex) {
1368        const format = newFormats[startIndex]?.find(
1369          ({ type }) => type === formatType
1370        );
1371        if (format) {
1372          while (newFormats[startIndex]?.find(
1373            (newFormat) => newFormat === format
1374          )) {
1375            filterFormats(newFormats, startIndex, formatType);
1376            startIndex--;
1377          }
1378          endIndex++;
1379          while (newFormats[endIndex]?.find(
1380            (newFormat) => newFormat === format
1381          )) {
1382            filterFormats(newFormats, endIndex, formatType);
1383            endIndex++;
1384          }
1385        }
1386      } else {
1387        for (let i = startIndex; i < endIndex; i++) {
1388          if (newFormats[i]) {
1389            filterFormats(newFormats, i, formatType);
1390          }
1391        }
1392      }
1393      return normaliseFormats({
1394        ...value,
1395        formats: newFormats,
1396        activeFormats: newActiveFormats
1397      });
1398    }
1399    function filterFormats(formats, index, formatType) {
1400      const newFormats = formats[index].filter(
1401        ({ type }) => type !== formatType
1402      );
1403      if (newFormats.length) {
1404        formats[index] = newFormats;
1405      } else {
1406        delete formats[index];
1407      }
1408    }
1409  
1410    // packages/rich-text/build-module/insert.mjs
1411    function insert(value, valueToInsert, startIndex = value.start ?? value.text.length, endIndex = value.end ?? startIndex) {
1412      const { formats, replacements, text } = value;
1413      if (typeof valueToInsert === "string") {
1414        valueToInsert = create({ text: valueToInsert });
1415      }
1416      const index = startIndex + valueToInsert.text.length;
1417      return normaliseFormats({
1418        formats: formats.slice(0, startIndex).concat(valueToInsert.formats, formats.slice(endIndex)),
1419        replacements: replacements.slice(0, startIndex).concat(
1420          valueToInsert.replacements,
1421          replacements.slice(endIndex)
1422        ),
1423        text: text.slice(0, startIndex) + valueToInsert.text + text.slice(endIndex),
1424        start: index,
1425        end: index
1426      });
1427    }
1428  
1429    // packages/rich-text/build-module/remove.mjs
1430    function remove2(value, startIndex, endIndex) {
1431      return insert(value, create(), startIndex, endIndex);
1432    }
1433  
1434    // packages/rich-text/build-module/replace.mjs
1435    function replace2({ formats, replacements, text, start, end }, pattern, replacement) {
1436      text = text.replace(pattern, (match, ...rest) => {
1437        const hasGroups = typeof rest[rest.length - 1] === "object";
1438        const offset = rest[rest.length - (hasGroups ? 3 : 2)];
1439        let newText = replacement;
1440        let newFormats;
1441        let newReplacements;
1442        if (typeof newText === "function") {
1443          newText = newText(match, ...rest);
1444        }
1445        if (typeof newText === "object") {
1446          newFormats = newText.formats;
1447          newReplacements = newText.replacements;
1448          newText = newText.text;
1449        } else {
1450          newFormats = Array(newText.length);
1451          newReplacements = Array(newText.length);
1452          if (formats[offset]) {
1453            newFormats = newFormats.fill(formats[offset]);
1454          }
1455        }
1456        formats = formats.slice(0, offset).concat(newFormats, formats.slice(offset + match.length));
1457        replacements = replacements.slice(0, offset).concat(
1458          newReplacements,
1459          replacements.slice(offset + match.length)
1460        );
1461        if (start !== void 0) {
1462          start = end = offset + newText.length;
1463        }
1464        return newText;
1465      });
1466      return normaliseFormats({ formats, replacements, text, start, end });
1467    }
1468  
1469    // packages/rich-text/build-module/insert-object.mjs
1470    function insertObject(value, formatToInsert, startIndex, endIndex) {
1471      const valueToInsert = {
1472        formats: Array(1),
1473        replacements: [formatToInsert],
1474        text: OBJECT_REPLACEMENT_CHARACTER
1475      };
1476      return insert(value, valueToInsert, startIndex, endIndex);
1477    }
1478  
1479    // packages/rich-text/build-module/slice.mjs
1480    function slice(value, startIndex = value.start, endIndex = value.end) {
1481      const { formats, replacements, text } = value;
1482      if (startIndex === void 0 || endIndex === void 0) {
1483        return { ...value };
1484      }
1485      return {
1486        formats: formats.slice(startIndex, endIndex),
1487        replacements: replacements.slice(startIndex, endIndex),
1488        text: text.slice(startIndex, endIndex)
1489      };
1490    }
1491  
1492    // packages/rich-text/build-module/split.mjs
1493    function split(richTextValue, string, endIndex) {
1494      if (typeof string !== "string") {
1495        return splitAtSelection(richTextValue, string, endIndex);
1496      }
1497      const { formats, replacements, text, start, end } = richTextValue;
1498      let nextStart = 0;
1499      return text.split(string).map((substring) => {
1500        const startIndex = nextStart;
1501        const value = {
1502          formats: formats.slice(startIndex, startIndex + substring.length),
1503          replacements: replacements.slice(
1504            startIndex,
1505            startIndex + substring.length
1506          ),
1507          text: substring
1508        };
1509        nextStart += string.length + substring.length;
1510        if (start !== void 0 && end !== void 0) {
1511          if (start >= startIndex && start < nextStart) {
1512            value.start = start - startIndex;
1513          } else if (start < startIndex && end > startIndex) {
1514            value.start = 0;
1515          }
1516          if (end >= startIndex && end < nextStart) {
1517            value.end = end - startIndex;
1518          } else if (start < nextStart && end > nextStart) {
1519            value.end = substring.length;
1520          }
1521        }
1522        return value;
1523      });
1524    }
1525    function splitAtSelection({ formats, replacements, text, start, end }, startIndex = start, endIndex = end) {
1526      if (startIndex === void 0 || endIndex === void 0) {
1527        return;
1528      }
1529      const before = {
1530        formats: formats.slice(0, startIndex),
1531        replacements: replacements.slice(0, startIndex),
1532        text: text.slice(0, startIndex)
1533      };
1534      const after = {
1535        formats: formats.slice(endIndex),
1536        replacements: replacements.slice(endIndex),
1537        text: text.slice(endIndex),
1538        start: 0,
1539        end: 0
1540      };
1541      return [before, after];
1542    }
1543  
1544    // packages/rich-text/build-module/is-range-equal.mjs
1545    function isRangeEqual(a, b) {
1546      return a === b || a && b && a.startContainer === b.startContainer && a.startOffset === b.startOffset && a.endContainer === b.endContainer && a.endOffset === b.endOffset;
1547    }
1548  
1549    // packages/rich-text/build-module/to-dom.mjs
1550    var MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
1551    function createPathToNode(node, rootNode, path) {
1552      const parentNode = node.parentNode;
1553      let i = 0;
1554      while (node = node.previousSibling) {
1555        i++;
1556      }
1557      path = [i, ...path];
1558      if (parentNode !== rootNode) {
1559        path = createPathToNode(parentNode, rootNode, path);
1560      }
1561      return path;
1562    }
1563    function getNodeByPath(node, path) {
1564      path = [...path];
1565      while (node && path.length > 1) {
1566        node = node.childNodes[path.shift()];
1567      }
1568      return {
1569        node,
1570        offset: path[0]
1571      };
1572    }
1573    function append2(element, child) {
1574      if (child.html !== void 0) {
1575        return element.innerHTML += child.html;
1576      }
1577      if (typeof child === "string") {
1578        child = element.ownerDocument.createTextNode(child);
1579      }
1580      const { type, attributes } = child;
1581      if (type) {
1582        if (type === "#comment") {
1583          child = element.ownerDocument.createComment(
1584            attributes["data-rich-text-comment"]
1585          );
1586        } else {
1587          const parentNamespace = element.namespaceURI;
1588          if (type === "math") {
1589            child = element.ownerDocument.createElementNS(
1590              MATHML_NAMESPACE,
1591              type
1592            );
1593          } else if (parentNamespace === MATHML_NAMESPACE) {
1594            if (element.tagName === "MTEXT") {
1595              child = element.ownerDocument.createElement(type);
1596            } else {
1597              child = element.ownerDocument.createElementNS(
1598                MATHML_NAMESPACE,
1599                type
1600              );
1601            }
1602          } else {
1603            child = element.ownerDocument.createElement(type);
1604          }
1605          for (const key in attributes) {
1606            child.setAttribute(
1607              key,
1608              attributes[key]
1609            );
1610          }
1611        }
1612      }
1613      return element.appendChild(child);
1614    }
1615    function appendText2(node, text) {
1616      node.appendData(text);
1617    }
1618    function getLastChild2({ lastChild }) {
1619      return lastChild;
1620    }
1621    function getParent2({ parentNode }) {
1622      return parentNode;
1623    }
1624    function isText2(node) {
1625      return node.nodeType === node.TEXT_NODE;
1626    }
1627    function getText2({ nodeValue }) {
1628      return nodeValue;
1629    }
1630    function remove3(node) {
1631      return node.parentNode.removeChild(node);
1632    }
1633    function toDom({
1634      value,
1635      prepareEditableTree,
1636      isEditableTree = true,
1637      placeholder,
1638      doc = document
1639    }) {
1640      let startPath = [];
1641      let endPath = [];
1642      if (prepareEditableTree) {
1643        value = {
1644          ...value,
1645          formats: prepareEditableTree(value)
1646        };
1647      }
1648      const createEmpty2 = () => createElement(doc, "");
1649      const tree = toTree({
1650        value,
1651        createEmpty: createEmpty2,
1652        // `toTree` only appends to elements, and appends text to text nodes.
1653        append: append2,
1654        getLastChild: getLastChild2,
1655        getParent: getParent2,
1656        isText: isText2,
1657        getText: getText2,
1658        remove: remove3,
1659        appendText: appendText2,
1660        onStartIndex(body2, pointer) {
1661          startPath = createPathToNode(pointer, body2, [
1662            pointer.nodeValue.length
1663          ]);
1664        },
1665        onEndIndex(body2, pointer) {
1666          endPath = createPathToNode(pointer, body2, [
1667            pointer.nodeValue.length
1668          ]);
1669        },
1670        isEditableTree,
1671        placeholder
1672      });
1673      return {
1674        body: tree,
1675        selection: { startPath, endPath }
1676      };
1677    }
1678    function getDomPosition({
1679      value,
1680      offset,
1681      element,
1682      prepareEditableTree,
1683      placeholder
1684    }) {
1685      const { selection } = toDom({
1686        value: { ...value, start: offset, end: offset },
1687        prepareEditableTree,
1688        placeholder,
1689        doc: element.ownerDocument
1690      });
1691      return getNodeByPath(element, selection.startPath);
1692    }
1693    function apply({
1694      value,
1695      current,
1696      prepareEditableTree,
1697      __unstableDomOnly,
1698      placeholder
1699    }) {
1700      const { body: body2, selection } = toDom({
1701        value,
1702        prepareEditableTree,
1703        placeholder,
1704        doc: current.ownerDocument
1705      });
1706      applyValue(body2, current);
1707      if (value.start !== void 0 && !__unstableDomOnly) {
1708        applySelection(selection, current);
1709      }
1710    }
1711    function applyValue(future, current) {
1712      let i = 0;
1713      let futureChild;
1714      while (futureChild = future.firstChild) {
1715        const currentChild = current.childNodes[i];
1716        if (!currentChild) {
1717          current.appendChild(futureChild);
1718        } else if (!currentChild.isEqualNode(futureChild)) {
1719          if (currentChild.nodeName !== futureChild.nodeName || currentChild.nodeType === currentChild.TEXT_NODE && currentChild.data !== futureChild.data) {
1720            current.replaceChild(futureChild, currentChild);
1721          } else {
1722            const currentAttributes = currentChild.attributes;
1723            const futureAttributes = futureChild.attributes;
1724            if (currentAttributes) {
1725              let ii = currentAttributes.length;
1726              while (ii--) {
1727                const { name } = currentAttributes[ii];
1728                if (!futureChild.getAttribute(name)) {
1729                  currentChild.removeAttribute(name);
1730                }
1731              }
1732            }
1733            if (futureAttributes) {
1734              for (let ii = 0; ii < futureAttributes.length; ii++) {
1735                const { name, value } = futureAttributes[ii];
1736                if (currentChild.getAttribute(name) !== value) {
1737                  currentChild.setAttribute(
1738                    name,
1739                    value
1740                  );
1741                }
1742              }
1743            }
1744            applyValue(futureChild, currentChild);
1745            future.removeChild(futureChild);
1746          }
1747        } else {
1748          future.removeChild(futureChild);
1749        }
1750        i++;
1751      }
1752      while (current.childNodes[i]) {
1753        current.removeChild(current.childNodes[i]);
1754      }
1755    }
1756    function applySelection({ startPath, endPath }, current) {
1757      const { node: startContainer, offset: startOffset } = getNodeByPath(
1758        current,
1759        startPath
1760      );
1761      const { node: endContainer, offset: endOffset } = getNodeByPath(
1762        current,
1763        endPath
1764      );
1765      const { ownerDocument } = current;
1766      const { defaultView } = ownerDocument;
1767      const selection = defaultView.getSelection();
1768      const range = ownerDocument.createRange();
1769      range.setStart(startContainer, startOffset);
1770      range.setEnd(endContainer, endOffset);
1771      const { activeElement } = ownerDocument;
1772      if (selection.rangeCount > 0) {
1773        if (isRangeEqual(range, selection.getRangeAt(0))) {
1774          return;
1775        }
1776        selection.removeAllRanges();
1777      }
1778      selection.addRange(range);
1779      if (activeElement !== ownerDocument.activeElement) {
1780        if (activeElement instanceof defaultView.HTMLElement) {
1781          activeElement.focus();
1782        }
1783      }
1784    }
1785  
1786    // packages/rich-text/build-module/toggle-format.mjs
1787    var import_a11y = __toESM(require_a11y(), 1);
1788    var import_i18n = __toESM(require_i18n(), 1);
1789    function toggleFormat(value, format) {
1790      if (getActiveFormat(value, format.type)) {
1791        if (format.title) {
1792          (0, import_a11y.speak)((0, import_i18n.sprintf)((0, import_i18n.__)("%s removed."), format.title), "assertive");
1793        }
1794        return removeFormat(value, format.type);
1795      }
1796      if (format.title) {
1797        (0, import_a11y.speak)((0, import_i18n.sprintf)((0, import_i18n.__)("%s applied."), format.title), "assertive");
1798      }
1799      return applyFormat(value, format);
1800    }
1801  
1802    // packages/rich-text/build-module/unregister-format-type.mjs
1803    var import_data7 = __toESM(require_data(), 1);
1804    function unregisterFormatType(name) {
1805      const oldFormat = (0, import_data7.select)(store).getFormatType(name);
1806      if (!oldFormat) {
1807        window.console.error(`Format $name} is not registered.`);
1808        return;
1809      }
1810      (0, import_data7.dispatch)(store).removeFormatTypes(name);
1811      return oldFormat;
1812    }
1813  
1814    // packages/rich-text/build-module/lock-unlock.mjs
1815    var import_private_apis = __toESM(require_private_apis(), 1);
1816    var { lock, unlock } = (0, import_private_apis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)(
1817      "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.",
1818      "@wordpress/rich-text"
1819    );
1820  
1821    // packages/rich-text/build-module/hook/index.mjs
1822    var import_element5 = __toESM(require_element(), 1);
1823    var import_compose8 = __toESM(require_compose(), 1);
1824    var import_data9 = __toESM(require_data(), 1);
1825    var import_deprecated = __toESM(require_deprecated(), 1);
1826  
1827    // packages/rich-text/build-module/hook/use-default-style.mjs
1828    var import_element = __toESM(require_element(), 1);
1829    var whiteSpace = "pre-wrap";
1830    function useDefaultStyle() {
1831      return (0, import_element.useCallback)((element) => {
1832        if (!element) {
1833          return;
1834        }
1835        element.style.whiteSpace = element.style.whiteSpace || whiteSpace;
1836      }, []);
1837    }
1838  
1839    // node_modules/.store/colord@2.10.0-Qx66Amv6c9C3nDPQDizV6Q/node_modules/colord/index.mjs
1840    for (r = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, t = function(r2) {
1841      return "string" == typeof r2 ? r2.length > 0 : "number" == typeof r2;
1842    }, n = function(r2, t2, n2) {
1843      return void 0 === t2 && (t2 = 0), void 0 === n2 && (n2 = Math.pow(10, t2)), Math.round(n2 * r2) / n2 + 0;
1844    }, u = function(r2, t2, n2) {
1845      return void 0 === t2 && (t2 = 0), void 0 === n2 && (n2 = 1), r2 > n2 ? n2 : r2 > t2 ? r2 : t2;
1846    }, e = function(r2) {
1847      return (r2 = isFinite(r2) ? r2 % 360 : 0) < 0 ? r2 + 360 : r2;
1848    }, o = function(r2, t2) {
1849      return void 0 === t2 && (t2 = 0), n(r2, t2) % 360;
1850    }, a = function(r2) {
1851      return { r: u(r2.r, 0, 255), g: u(r2.g, 0, 255), b: u(r2.b, 0, 255), a: u(r2.a) };
1852    }, i = function(r2) {
1853      return { r: n(r2.r), g: n(r2.g), b: n(r2.b), a: n(r2.a, 3) };
1854    }, s = /^#([0-9a-f]{3,8})$/i, d = function(r2, t2) {
1855      var n2 = r2.charCodeAt(t2);
1856      return (15 & n2) + 9 * (n2 >> 6);
1857    }, h = function(r2, t2) {
1858      return d(r2, t2) << 4 | d(r2, t2 + 1);
1859    }, b = [], f = 0; f < 256; f++) b.push((f < 16 ? "0" : "") + f.toString(16));
1860    var r;
1861    var t;
1862    var n;
1863    var u;
1864    var e;
1865    var o;
1866    var a;
1867    var i;
1868    var s;
1869    var d;
1870    var h;
1871    var b;
1872    var f;
1873    var g = function(r) {
1874      return b[u(r, 0, 255)];
1875    };
1876    var c = function(r) {
1877      var t = r.r, n = r.g, u = r.b, e = r.a, o = Math.max(t, n, u), a = o - Math.min(t, n, u), i = a ? o === t ? (n - u) / a : o === n ? 2 + (u - t) / a : 4 + (t - n) / a : 0;
1878      return { h: 60 * (i < 0 ? i + 6 : i), s: o ? a / o * 100 : 0, v: o / 255 * 100, a: e };
1879    };
1880    var v = function(r) {
1881      var t = r.h, n = r.s, u = r.v, e = r.a;
1882      t = t / 360 * 6, n /= 100, u /= 100;
1883      var o = Math.floor(t), a = u * (1 - n), i = u * (1 - (t - o) * n), s = u * (1 - (1 - t + o) * n), d = o % 6;
1884      return { r: 255 * [u, i, a, a, s, u][d], g: 255 * [s, u, u, i, a, a][d], b: 255 * [a, a, s, u, u, i][d], a: e };
1885    };
1886    var l = function(r) {
1887      return { h: e(r.h), s: u(r.s, 0, 100), l: u(r.l, 0, 100), a: u(r.a) };
1888    };
1889    var p = function(r) {
1890      return { h: o(r.h), s: n(r.s), l: n(r.l), a: n(r.a, 3) };
1891    };
1892    var m = function(r) {
1893      return v((n = (t = r).s, { h: t.h, s: (n *= ((u = t.l) < 50 ? u : 100 - u) / 100) > 0 ? 2 * n / (u + n) * 100 : 0, v: u + n, a: t.a }));
1894      var t, n, u;
1895    };
1896    var y = function(r) {
1897      return { h: (t = c(r)).h, s: (e = (200 - (n = t.s)) * (u = t.v) / 100) > 0 && e < 200 ? n * u / 100 / (e <= 100 ? e : 200 - e) * 100 : 0, l: e / 2, a: t.a };
1898      var t, n, u, e;
1899    };
1900    var N = /^hsla?\(\s*([+-]?(?:\d*\.\d+|\d+))(deg|rad|grad|turn)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))%\s*,\s*([+-]?(?:\d*\.\d+|\d+))%\s*(?:,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
1901    var x = /^hsla?\(\s*([+-]?(?:\d*\.\d+|\d+))(deg|rad|grad|turn)?\s+([+-]?(?:\d*\.\d+|\d+))%\s+([+-]?(?:\d*\.\d+|\d+))%\s*(?:\/\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
1902    var M = /^rgba?\(\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*(?:,\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
1903    var H = /^rgba?\(\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s+([+-]?(?:\d*\.\d+|\d+))(%)?\s+([+-]?(?:\d*\.\d+|\d+))(%)?\s*(?:\/\s*([+-]?(?:\d*\.\d+|\d+))(%)?\s*)?\)$/i;
1904    var $ = { string: [[function(r) {
1905      if (!s.test(r)) return null;
1906      var t = r.length;
1907      return t <= 5 ? { r: 17 * d(r, 1), g: 17 * d(r, 2), b: 17 * d(r, 3), a: 5 === t ? n(17 * d(r, 4) / 255, 2) : 1 } : 7 === t || 9 === t ? { r: h(r, 1), g: h(r, 3), b: h(r, 5), a: 9 === t ? n(h(r, 7) / 255, 2) : 1 } : null;
1908    }, "hex"], [function(r) {
1909      var t = M.exec(r) || H.exec(r);
1910      return t ? t[2] !== t[4] || t[4] !== t[6] ? null : a({ r: Number(t[1]) / (t[2] ? 100 / 255 : 1), g: Number(t[3]) / (t[4] ? 100 / 255 : 1), b: Number(t[5]) / (t[6] ? 100 / 255 : 1), a: void 0 === t[7] ? 1 : Number(t[7]) / (t[8] ? 100 : 1) }) : null;
1911    }, "rgb"], [function(t) {
1912      var n = N.exec(t) || x.exec(t);
1913      if (!n) return null;
1914      var u, e, o = l({ h: (u = n[1], e = n[2], void 0 === e && (e = "deg"), Number(u) * (r[e] || 1)), s: Number(n[3]), l: Number(n[4]), a: void 0 === n[5] ? 1 : Number(n[5]) / (n[6] ? 100 : 1) });
1915      return m(o);
1916    }, "hsl"]], object: [[function(r) {
1917      var n = r.r, u = r.g, e = r.b, o = r.a, i = void 0 === o ? 1 : o;
1918      return t(n) && t(u) && t(e) ? a({ r: Number(n), g: Number(u), b: Number(e), a: Number(i) }) : null;
1919    }, "rgb"], [function(r) {
1920      var n = r.h, u = r.s, e = r.l, o = r.a, a = void 0 === o ? 1 : o;
1921      if (!t(n) || !t(u) || !t(e)) return null;
1922      var i = l({ h: Number(n), s: Number(u), l: Number(e), a: Number(a) });
1923      return m(i);
1924    }, "hsl"], [function(r) {
1925      var n = r.h, o = r.s, a = r.v, i = r.a, s = void 0 === i ? 1 : i;
1926      if (!t(n) || !t(o) || !t(a)) return null;
1927      var d = (function(r2) {
1928        return { h: e(r2.h), s: u(r2.s, 0, 100), v: u(r2.v, 0, 100), a: u(r2.a) };
1929      })({ h: Number(n), s: Number(o), v: Number(a), a: Number(s) });
1930      return v(d);
1931    }, "hsv"]] };
1932    var j = function(r, t) {
1933      for (var n = 0; n < t.length; n++) {
1934        var u = t[n][0](r);
1935        if (u) return [u, t[n][1]];
1936      }
1937      return [null, void 0];
1938    };
1939    var w = function(r) {
1940      return "string" == typeof r ? j(r.trim(), $.string) : "object" == typeof r && null !== r ? j(r, $.object) : [null, void 0];
1941    };
1942    var k = function(r, t) {
1943      var n = y(r);
1944      return { h: n.h, s: u(n.s + 100 * t, 0, 100), l: n.l, a: n.a };
1945    };
1946    var E = function(r) {
1947      return (299 * r.r + 587 * r.g + 114 * r.b) / 1e3 / 255;
1948    };
1949    var R = function(r, t) {
1950      var n = y(r);
1951      return { h: n.h, s: n.s, l: u(n.l + 100 * t, 0, 100), a: n.a };
1952    };
1953    var q = (function() {
1954      function r(r2) {
1955        this.parsed = w(r2)[0], this.rgba = this.parsed || { r: 0, g: 0, b: 0, a: 1 };
1956      }
1957      return r.prototype.isValid = function() {
1958        return null !== this.parsed;
1959      }, r.prototype.brightness = function() {
1960        return n(E(this.rgba), 2);
1961      }, r.prototype.isDark = function() {
1962        return E(this.rgba) < 0.5;
1963      }, r.prototype.isLight = function() {
1964        return E(this.rgba) >= 0.5;
1965      }, r.prototype.toHex = function() {
1966        return r2 = i(this.rgba), t = r2.r, u = r2.g, e = r2.b, a = (o = r2.a) < 1 ? g(n(255 * o)) : "", "#" + g(t) + g(u) + g(e) + a;
1967        var r2, t, u, e, o, a;
1968      }, r.prototype.toRgb = function() {
1969        return i(this.rgba);
1970      }, r.prototype.toRgbString = function() {
1971        return r2 = i(this.rgba), t = r2.r, n = r2.g, u = r2.b, (e = r2.a) < 1 ? "rgba(" + t + ", " + n + ", " + u + ", " + e + ")" : "rgb(" + t + ", " + n + ", " + u + ")";
1972        var r2, t, n, u, e;
1973      }, r.prototype.toHsl = function() {
1974        return p(y(this.rgba));
1975      }, r.prototype.toHslString = function() {
1976        return r2 = p(y(this.rgba)), t = r2.h, n = r2.s, u = r2.l, (e = r2.a) < 1 ? "hsla(" + t + ", " + n + "%, " + u + "%, " + e + ")" : "hsl(" + t + ", " + n + "%, " + u + "%)";
1977        var r2, t, n, u, e;
1978      }, r.prototype.toHsv = function() {
1979        return r2 = c(this.rgba), { h: o(r2.h), s: n(r2.s), v: n(r2.v), a: n(r2.a, 3) };
1980        var r2;
1981      }, r.prototype.invert = function() {
1982        return A({ r: 255 - (r2 = this.rgba).r, g: 255 - r2.g, b: 255 - r2.b, a: r2.a });
1983        var r2;
1984      }, r.prototype.saturate = function(r2) {
1985        return void 0 === r2 && (r2 = 0.1), A(k(this.rgba, r2));
1986      }, r.prototype.desaturate = function(r2) {
1987        return void 0 === r2 && (r2 = 0.1), A(k(this.rgba, -r2));
1988      }, r.prototype.grayscale = function() {
1989        return A(k(this.rgba, -1));
1990      }, r.prototype.lighten = function(r2) {
1991        return void 0 === r2 && (r2 = 0.1), A(R(this.rgba, r2));
1992      }, r.prototype.darken = function(r2) {
1993        return void 0 === r2 && (r2 = 0.1), A(R(this.rgba, -r2));
1994      }, r.prototype.rotate = function(r2) {
1995        return void 0 === r2 && (r2 = 15), this.hue(y(this.rgba).h + r2);
1996      }, r.prototype.alpha = function(r2) {
1997        return "number" == typeof r2 ? A({ r: (t = this.rgba).r, g: t.g, b: t.b, a: r2 }) : n(this.rgba.a, 3);
1998        var t;
1999      }, r.prototype.hue = function(r2) {
2000        var t = y(this.rgba);
2001        return "number" == typeof r2 ? A({ h: r2, s: t.s, l: t.l, a: t.a }) : o(t.h);
2002      }, r.prototype.isEqual = function(r2) {
2003        return this.toHex() === A(r2).toHex();
2004      }, r;
2005    })();
2006    var A = function(r) {
2007      return r instanceof q ? r : new q(r);
2008    };
2009  
2010    // packages/rich-text/build-module/hook/use-boundary-style.mjs
2011    var import_element2 = __toESM(require_element(), 1);
2012    function useBoundaryStyle({
2013      record
2014    }) {
2015      const ref = (0, import_element2.useRef)(void 0);
2016      const { activeFormats = [], replacements, start } = record.current;
2017      const activeReplacement = start === void 0 ? void 0 : replacements[start];
2018      (0, import_element2.useEffect)(() => {
2019        if ((!activeFormats || !activeFormats.length) && !activeReplacement) {
2020          return;
2021        }
2022        const boundarySelector = "*[data-rich-text-format-boundary]";
2023        const element = ref.current.querySelector(boundarySelector);
2024        if (!element) {
2025          return;
2026        }
2027        const { ownerDocument } = element;
2028        const { defaultView } = ownerDocument;
2029        const computedStyle = defaultView.getComputedStyle(element);
2030        const newColor = A(computedStyle.color).alpha(0.2).toRgbString();
2031        const selector = `[contenteditable="true"]:focus $boundarySelector}`;
2032        const rule = `background-color: $newColor}`;
2033        const style = `$selector} {$rule}}`;
2034        const globalStyleId = "rich-text-boundary-style";
2035        let globalStyle = ownerDocument.getElementById(globalStyleId);
2036        if (!globalStyle) {
2037          globalStyle = ownerDocument.createElement("style");
2038          globalStyle.id = globalStyleId;
2039          ownerDocument.head.appendChild(globalStyle);
2040        }
2041        if (globalStyle.innerHTML !== style) {
2042          globalStyle.innerHTML = style;
2043        }
2044      }, [activeFormats, activeReplacement]);
2045      return ref;
2046    }
2047  
2048    // packages/rich-text/build-module/hook/event-listeners/index.mjs
2049    var import_element3 = __toESM(require_element(), 1);
2050    var import_compose7 = __toESM(require_compose(), 1);
2051  
2052    // packages/rich-text/build-module/hook/event-listeners/copy-handler.mjs
2053    var import_compose = __toESM(require_compose(), 1);
2054  
2055    // packages/rich-text/build-module/owns-selection.mjs
2056    function ownsSelection(element) {
2057      const { ownerDocument } = element;
2058      const { activeElement } = ownerDocument;
2059      if (activeElement === element) {
2060        return true;
2061      }
2062      if (!activeElement || activeElement.contentEditable !== "true" || element.contentEditable !== "true" || !activeElement.contains(element)) {
2063        return false;
2064      }
2065      const selection = ownerDocument.defaultView?.getSelection();
2066      if (!selection) {
2067        return false;
2068      }
2069      const { anchorNode, focusNode } = selection;
2070      return !!anchorNode && !!focusNode && element.contains(anchorNode) && element.contains(focusNode);
2071    }
2072  
2073    // packages/rich-text/build-module/hook/event-listeners/copy-handler.mjs
2074    var { subscribeDelegatedListener } = unlock(import_compose.privateApis);
2075    var copyHandler = (props) => (element) => {
2076      function onCopy(event) {
2077        const { record, handleChange } = props.current;
2078        const { ownerDocument } = element;
2079        if (
2080          // Another handler may have already claimed the clipboard, e.g.
2081          // the block editor copying the whole block when its entire
2082          // text is selected.
2083          event.defaultPrevented || isCollapsed(record.current) || !element.contains(ownerDocument.activeElement) && !ownsSelection(element)
2084        ) {
2085          return;
2086        }
2087        const selectedRecord = slice(record.current);
2088        const plainText = getTextContent(selectedRecord);
2089        const html = toHTMLString({ value: selectedRecord });
2090        event.clipboardData.setData("text/plain", plainText);
2091        event.clipboardData.setData("text/html", html);
2092        event.clipboardData.setData("rich-text", "true");
2093        event.preventDefault();
2094        if (event.type === "cut") {
2095          handleChange(remove2(record.current));
2096        }
2097      }
2098      const { defaultView } = element.ownerDocument;
2099      const unsubscribeCopy = subscribeDelegatedListener(
2100        defaultView,
2101        "copy",
2102        onCopy
2103      );
2104      const unsubscribeCut = subscribeDelegatedListener(
2105        defaultView,
2106        "cut",
2107        onCopy
2108      );
2109      return () => {
2110        unsubscribeCopy();
2111        unsubscribeCut();
2112      };
2113    };
2114    var copy_handler_default = copyHandler;
2115  
2116    // packages/rich-text/build-module/hook/event-listeners/select-object.mjs
2117    var import_compose2 = __toESM(require_compose(), 1);
2118    var { subscribeDelegatedListener: subscribeDelegatedListener2 } = unlock(import_compose2.privateApis);
2119    var selectObject = () => (element) => {
2120      function onClick(event) {
2121        const target = event.target;
2122        if (target === element || target.textContent && target.isContentEditable) {
2123          return;
2124        }
2125        const { ownerDocument } = target;
2126        const { defaultView } = ownerDocument;
2127        const selection = defaultView.getSelection();
2128        if (selection.containsNode(target)) {
2129          return;
2130        }
2131        const range = ownerDocument.createRange();
2132        const nodeToSelect = target.isContentEditable ? target : target.closest("[contenteditable]");
2133        range.selectNode(nodeToSelect);
2134        selection.removeAllRanges();
2135        selection.addRange(range);
2136        event.preventDefault();
2137      }
2138      function onFocusIn(event) {
2139        if (event.relatedTarget && !element.contains(event.relatedTarget)) {
2140          onClick(event);
2141        }
2142      }
2143      const unsubscribeClick = subscribeDelegatedListener2(
2144        element,
2145        "click",
2146        onClick
2147      );
2148      const unsubscribeFocusIn = subscribeDelegatedListener2(
2149        element,
2150        "focusin",
2151        onFocusIn
2152      );
2153      return () => {
2154        unsubscribeClick();
2155        unsubscribeFocusIn();
2156      };
2157    };
2158    var select_object_default = selectObject;
2159  
2160    // packages/rich-text/build-module/hook/event-listeners/format-boundaries.mjs
2161    var import_keycodes = __toESM(require_keycodes(), 1);
2162  
2163    // packages/rich-text/build-module/subscribe-owned-listener.mjs
2164    var import_compose3 = __toESM(require_compose(), 1);
2165    var { subscribeDelegatedListener: subscribeDelegatedListener3 } = unlock(import_compose3.privateApis);
2166    var registries = /* @__PURE__ */ new WeakMap();
2167    function subscribeOwnedListener(element, eventType, callback, capture = false) {
2168      const { ownerDocument } = element;
2169      let byEvent = registries.get(ownerDocument);
2170      if (!byEvent) {
2171        byEvent = /* @__PURE__ */ new Map();
2172        registries.set(ownerDocument, byEvent);
2173      }
2174      const key = capture ? `$eventType}:capture` : eventType;
2175      const elements = byEvent.get(key) ?? /* @__PURE__ */ new WeakMap();
2176      if (!byEvent.has(key)) {
2177        byEvent.set(key, elements);
2178        subscribeDelegatedListener3(
2179          ownerDocument,
2180          eventType,
2181          (event) => {
2182            const { defaultView, activeElement } = ownerDocument;
2183            const anchorNode = defaultView?.getSelection()?.anchorNode;
2184            for (let node = anchorNode ?? activeElement; node; node = node.parentNode) {
2185              const callbacks = elements.get(node);
2186              if (callbacks && ownsSelection(node)) {
2187                for (const cb of callbacks) {
2188                  cb(event);
2189                }
2190              }
2191            }
2192          },
2193          capture
2194        );
2195      }
2196      let set = elements.get(element);
2197      if (!set) {
2198        set = /* @__PURE__ */ new Set();
2199        elements.set(element, set);
2200      }
2201      set.add(callback);
2202      return () => {
2203        set.delete(callback);
2204      };
2205    }
2206  
2207    // packages/rich-text/build-module/hook/event-listeners/format-boundaries.mjs
2208    var EMPTY_ACTIVE_FORMATS = [];
2209    var formatBoundaries = (props) => (element) => {
2210      function onKeyDown(event) {
2211        const { keyCode, shiftKey, altKey, metaKey, ctrlKey } = event;
2212        if (
2213          // Only override left and right keys without modifiers pressed.
2214          shiftKey || altKey || metaKey || ctrlKey || keyCode !== import_keycodes.LEFT && keyCode !== import_keycodes.RIGHT
2215        ) {
2216          return;
2217        }
2218        const { record, applyRecord, forceRender } = props.current;
2219        const {
2220          text,
2221          formats,
2222          start,
2223          end,
2224          activeFormats: currentActiveFormats = []
2225        } = record.current;
2226        const collapsed = isCollapsed(record.current);
2227        const { defaultView } = element.ownerDocument;
2228        const { direction } = defaultView.getComputedStyle(element);
2229        const reverseKey = direction === "rtl" ? import_keycodes.RIGHT : import_keycodes.LEFT;
2230        const isReverse = event.keyCode === reverseKey;
2231        if (collapsed && currentActiveFormats.length === 0) {
2232          if (start === 0 && isReverse) {
2233            return;
2234          }
2235          if (end === text.length && !isReverse) {
2236            return;
2237          }
2238        }
2239        if (!collapsed || start === void 0) {
2240          return;
2241        }
2242        const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS;
2243        const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS;
2244        const destination = isReverse ? formatsBefore : formatsAfter;
2245        const isIncreasing = currentActiveFormats.every(
2246          (format, index) => format === destination[index]
2247        );
2248        let newActiveFormatsLength = currentActiveFormats.length;
2249        if (!isIncreasing) {
2250          newActiveFormatsLength--;
2251        } else if (newActiveFormatsLength < destination.length) {
2252          newActiveFormatsLength++;
2253        }
2254        if (newActiveFormatsLength === currentActiveFormats.length) {
2255          record.current._newActiveFormats = destination;
2256          return;
2257        }
2258        event.preventDefault();
2259        const origin = isReverse ? formatsAfter : formatsBefore;
2260        const source = isIncreasing ? destination : origin;
2261        const newActiveFormats = source.slice(0, newActiveFormatsLength);
2262        const newValue = {
2263          ...record.current,
2264          activeFormats: newActiveFormats
2265        };
2266        record.current = newValue;
2267        applyRecord(newValue);
2268        forceRender();
2269      }
2270      return subscribeOwnedListener(
2271        element,
2272        "keydown",
2273        onKeyDown,
2274        true
2275      );
2276    };
2277    var format_boundaries_default = formatBoundaries;
2278  
2279    // packages/rich-text/build-module/hook/event-listeners/delete.mjs
2280    var import_keycodes2 = __toESM(require_keycodes(), 1);
2281    var deleteHandler = (props) => (element) => {
2282      function onKeyDown(event) {
2283        const { keyCode } = event;
2284        if (event.defaultPrevented) {
2285          return;
2286        }
2287        if (keyCode !== import_keycodes2.DELETE && keyCode !== import_keycodes2.BACKSPACE) {
2288          return;
2289        }
2290        const { createRecord, handleChange } = props.current;
2291        const currentValue = createRecord();
2292        const { start, end, text } = currentValue;
2293        if (start === 0 && end !== 0 && end === text.length) {
2294          handleChange(remove2(currentValue));
2295          event.preventDefault();
2296        }
2297      }
2298      return subscribeOwnedListener(
2299        element,
2300        "keydown",
2301        onKeyDown
2302      );
2303    };
2304    var delete_default = deleteHandler;
2305  
2306    // packages/rich-text/build-module/hook/event-listeners/input-and-selection.mjs
2307    var import_compose4 = __toESM(require_compose(), 1);
2308  
2309    // packages/rich-text/build-module/update-formats.mjs
2310    function updateFormats({
2311      value,
2312      start,
2313      end,
2314      formats
2315    }) {
2316      const min = Math.min(start, end);
2317      const max = Math.max(start, end);
2318      const formatsBefore = value.formats[min - 1] || [];
2319      const formatsAfter = value.formats[max] || [];
2320      value.activeFormats = formats.map((format, index) => {
2321        if (formatsBefore[index]) {
2322          if (isFormatEqual(format, formatsBefore[index])) {
2323            return formatsBefore[index];
2324          }
2325        } else if (formatsAfter[index]) {
2326          if (isFormatEqual(format, formatsAfter[index])) {
2327            return formatsAfter[index];
2328          }
2329        }
2330        return format;
2331      });
2332      while (--end >= start) {
2333        if (value.activeFormats.length > 0) {
2334          value.formats[end] = value.activeFormats;
2335        } else {
2336          delete value.formats[end];
2337        }
2338      }
2339      return value;
2340    }
2341  
2342    // packages/rich-text/build-module/hook/event-listeners/input-and-selection.mjs
2343    var { subscribeDelegatedListener: subscribeDelegatedListener4 } = unlock(import_compose4.privateApis);
2344    var INSERTION_INPUT_TYPES_TO_IGNORE = /* @__PURE__ */ new Set([
2345      "insertParagraph",
2346      "insertOrderedList",
2347      "insertUnorderedList",
2348      "insertHorizontalRule",
2349      "insertLink"
2350    ]);
2351    var EMPTY_ACTIVE_FORMATS2 = [];
2352    var PLACEHOLDER_ATTR_NAME = "data-rich-text-placeholder";
2353    var inputAndSelection = (props) => (element) => {
2354      const { ownerDocument } = element;
2355      const { defaultView } = ownerDocument;
2356      let isComposing = false;
2357      let isPointerDown = false;
2358      function onPointerDown() {
2359        isPointerDown = true;
2360      }
2361      function onPointerUp() {
2362        isPointerDown = false;
2363      }
2364      function onInput(event) {
2365        if (isComposing) {
2366          return;
2367        }
2368        let inputType;
2369        if (event && "inputType" in event) {
2370          inputType = event.inputType;
2371        }
2372        const { record, applyRecord, createRecord, handleChange } = props.current;
2373        if (inputType && (inputType.indexOf("format") === 0 || INSERTION_INPUT_TYPES_TO_IGNORE.has(inputType))) {
2374          applyRecord(record.current);
2375          return;
2376        }
2377        const currentValue = createRecord();
2378        const { start } = record.current;
2379        if (start === void 0 || currentValue.start === void 0) {
2380          handleChange(currentValue);
2381          return;
2382        }
2383        const clearFormats = !isCollapsed(record.current) && currentValue.start <= start;
2384        const oldActiveFormats = getActiveFormats(
2385          record.current,
2386          EMPTY_ACTIVE_FORMATS2
2387        );
2388        const change = updateFormats({
2389          value: currentValue,
2390          start,
2391          end: currentValue.start,
2392          formats: clearFormats ? [] : oldActiveFormats
2393        });
2394        handleChange(change);
2395      }
2396      let selectionSnapshot;
2397      function handleSelectionChange() {
2398        const { record, applyRecord, createRecord, onSelectionChange } = props.current;
2399        if (element.contentEditable !== "true") {
2400          return;
2401        }
2402        if (ownerDocument.activeElement !== element && !ownsSelection(element)) {
2403          return;
2404        }
2405        if (isComposing) {
2406          return;
2407        }
2408        const selection = defaultView.getSelection();
2409        if (selectionSnapshot && selectionSnapshot.anchorNode === selection.anchorNode && selectionSnapshot.anchorOffset === selection.anchorOffset && selectionSnapshot.focusNode === selection.focusNode && selectionSnapshot.focusOffset === selection.focusOffset && selectionSnapshot.processedStart === record.current.start && selectionSnapshot.processedEnd === record.current.end) {
2410          return;
2411        }
2412        const { start, end, text } = createRecord();
2413        const oldRecord = record.current;
2414        if (text.length === 0) {
2415          applyRecord({ ...oldRecord, start, end });
2416        }
2417        selectionSnapshot = {
2418          anchorNode: selection.anchorNode,
2419          anchorOffset: selection.anchorOffset,
2420          focusNode: selection.focusNode,
2421          focusOffset: selection.focusOffset,
2422          processedStart: start,
2423          processedEnd: end
2424        };
2425        if (text !== oldRecord.text) {
2426          onInput();
2427          return;
2428        }
2429        if (start === oldRecord.start && end === oldRecord.end) {
2430          return;
2431        }
2432        const newValue = {
2433          ...oldRecord,
2434          start,
2435          end,
2436          // _newActiveFormats may be set on arrow key navigation to control
2437          // the right boundary position. If undefined, getActiveFormats will
2438          // give the active formats according to the browser.
2439          activeFormats: oldRecord._newActiveFormats,
2440          _newActiveFormats: void 0
2441        };
2442        const newActiveFormats = getActiveFormats(
2443          newValue,
2444          EMPTY_ACTIVE_FORMATS2
2445        );
2446        newValue.activeFormats = newActiveFormats;
2447        record.current = newValue;
2448        applyRecord(newValue, { domOnly: true });
2449        onSelectionChange(start, end);
2450      }
2451      function onCompositionStart() {
2452        isComposing = true;
2453        element.querySelector(`[$PLACEHOLDER_ATTR_NAME}]`)?.remove();
2454      }
2455      function onCompositionEnd() {
2456        isComposing = false;
2457        onInput({ inputType: "insertText" });
2458      }
2459      function onFocus(event) {
2460        if (event.target !== element) {
2461          return;
2462        }
2463        if (element.contentEditable !== "true") {
2464          return;
2465        }
2466        const { record, isSelected, onSelectionChange, applyRecord } = props.current;
2467        if (element.parentElement.closest('[contenteditable="true"]')) {
2468          const selection = defaultView.getSelection();
2469          if (!selection.anchorNode || !element.contains(selection.anchorNode)) {
2470            if (isSelected && record.current.start !== void 0) {
2471              applyRecord(record.current);
2472            } else {
2473              selection.collapse(element, 0);
2474            }
2475          }
2476          return;
2477        }
2478        if (!isSelected) {
2479          const index = void 0;
2480          record.current = {
2481            ...record.current,
2482            start: index,
2483            end: index,
2484            activeFormats: EMPTY_ACTIVE_FORMATS2
2485          };
2486          selectionSnapshot = void 0;
2487        } else if (!isPointerDown) {
2488          applyRecord(record.current);
2489        }
2490        onSelectionChange(record.current.start, record.current.end);
2491        window.queueMicrotask(handleSelectionChange);
2492      }
2493      const unsubscribeInput = subscribeOwnedListener(
2494        element,
2495        "input",
2496        onInput,
2497        true
2498      );
2499      const unsubscribeCompositionStart = subscribeOwnedListener(
2500        element,
2501        "compositionstart",
2502        onCompositionStart
2503      );
2504      const unsubscribeCompositionEnd = subscribeOwnedListener(
2505        element,
2506        "compositionend",
2507        onCompositionEnd,
2508        true
2509      );
2510      const unsubscribeFocus = subscribeDelegatedListener4(
2511        element,
2512        "focusin",
2513        onFocus
2514      );
2515      const unsubscribePointerDown = subscribeDelegatedListener4(
2516        element,
2517        "pointerdown",
2518        onPointerDown
2519      );
2520      const unsubscribePointerUp = subscribeDelegatedListener4(
2521        defaultView,
2522        "pointerup",
2523        onPointerUp
2524      );
2525      const unsubscribePointerCancel = subscribeDelegatedListener4(
2526        defaultView,
2527        "pointercancel",
2528        onPointerUp
2529      );
2530      const unsubscribeSelectionChange = subscribeOwnedListener(
2531        element,
2532        "selectionchange",
2533        handleSelectionChange
2534      );
2535      const unsubscribeEnsureSelectionSync = [
2536        "keydown",
2537        "beforeinput",
2538        "copy",
2539        "cut",
2540        "paste"
2541      ].map(
2542        (eventType) => subscribeOwnedListener(
2543          element,
2544          eventType,
2545          handleSelectionChange,
2546          true
2547        )
2548      );
2549      return () => {
2550        unsubscribeInput();
2551        unsubscribeCompositionStart();
2552        unsubscribeCompositionEnd();
2553        unsubscribeFocus();
2554        unsubscribePointerDown();
2555        unsubscribePointerUp();
2556        unsubscribePointerCancel();
2557        unsubscribeSelectionChange();
2558        unsubscribeEnsureSelectionSync.forEach(
2559          (unsubscribe) => unsubscribe()
2560        );
2561      };
2562    };
2563    var input_and_selection_default = inputAndSelection;
2564  
2565    // packages/rich-text/build-module/hook/event-listeners/selection-change-compat.mjs
2566    var import_compose5 = __toESM(require_compose(), 1);
2567    var { subscribeDelegatedListener: subscribeDelegatedListener5 } = unlock(import_compose5.privateApis);
2568    var selectionChangeCompat = () => (element) => {
2569      const { ownerDocument } = element;
2570      const { defaultView } = ownerDocument;
2571      const selection = defaultView?.getSelection();
2572      let range;
2573      function getRange() {
2574        return selection.rangeCount ? selection.getRangeAt(0) : null;
2575      }
2576      function onDown(event) {
2577        const type = event.type === "keydown" ? "keyup" : "pointerup";
2578        function onCancel() {
2579          ownerDocument.removeEventListener(type, onUp);
2580          ownerDocument.removeEventListener("selectionchange", onCancel);
2581          ownerDocument.removeEventListener("input", onCancel);
2582        }
2583        function onUp() {
2584          onCancel();
2585          if (isRangeEqual(range, getRange())) {
2586            return;
2587          }
2588          ownerDocument.dispatchEvent(new Event("selectionchange"));
2589        }
2590        ownerDocument.addEventListener(type, onUp);
2591        ownerDocument.addEventListener("selectionchange", onCancel);
2592        ownerDocument.addEventListener("input", onCancel);
2593        range = getRange();
2594      }
2595      const unsubscribePointerDown = subscribeDelegatedListener5(
2596        element,
2597        "pointerdown",
2598        onDown
2599      );
2600      const unsubscribeKeyDown = subscribeDelegatedListener5(
2601        element,
2602        "keydown",
2603        onDown
2604      );
2605      return () => {
2606        unsubscribePointerDown();
2607        unsubscribeKeyDown();
2608      };
2609    };
2610    var selection_change_compat_default = selectionChangeCompat;
2611  
2612    // packages/rich-text/build-module/hook/event-listeners/prevent-focus-capture.mjs
2613    var import_compose6 = __toESM(require_compose(), 1);
2614    var { subscribeDelegatedListener: subscribeDelegatedListener6 } = unlock(import_compose6.privateApis);
2615    function preventFocusCapture() {
2616      return (element) => {
2617        const { ownerDocument } = element;
2618        const { defaultView } = ownerDocument;
2619        let value = null;
2620        function onPointerDown(event) {
2621          const target = event.target;
2622          if (event.defaultPrevented) {
2623            return;
2624          }
2625          if (target === element) {
2626            return;
2627          }
2628          if (!target.contains(element)) {
2629            return;
2630          }
2631          if (!target.closest("[data-block]")) {
2632            return;
2633          }
2634          value = element.getAttribute("contenteditable");
2635          defaultView.getSelection().removeAllRanges();
2636          element.setAttribute("contenteditable", "false");
2637        }
2638        function onPointerUp() {
2639          if (value !== null) {
2640            element.setAttribute("contenteditable", value);
2641            value = null;
2642            const selection = defaultView.getSelection();
2643            if (selection.isCollapsed && element.contains(selection.anchorNode)) {
2644              selection.removeAllRanges();
2645            }
2646          }
2647        }
2648        const unsubscribePointerDown = subscribeDelegatedListener6(
2649          defaultView,
2650          "pointerdown",
2651          onPointerDown
2652        );
2653        const unsubscribePointerUp = subscribeDelegatedListener6(
2654          defaultView,
2655          "pointerup",
2656          onPointerUp
2657        );
2658        const unsubscribePointerCancel = subscribeDelegatedListener6(
2659          defaultView,
2660          "pointercancel",
2661          onPointerUp
2662        );
2663        return () => {
2664          unsubscribePointerDown();
2665          unsubscribePointerUp();
2666          unsubscribePointerCancel();
2667        };
2668      };
2669    }
2670  
2671    // packages/rich-text/build-module/hook/event-listeners/index.mjs
2672    var allEventListeners = [
2673      input_and_selection_default,
2674      copy_handler_default,
2675      select_object_default,
2676      format_boundaries_default,
2677      delete_default,
2678      selection_change_compat_default,
2679      preventFocusCapture
2680    ];
2681    function useEventListeners(props) {
2682      const propsRef = (0, import_element3.useRef)(props);
2683      (0, import_element3.useInsertionEffect)(() => {
2684        propsRef.current = props;
2685      });
2686      const refEffects = (0, import_element3.useMemo)(
2687        () => allEventListeners.map((refEffect) => refEffect(propsRef)),
2688        [propsRef]
2689      );
2690      return (0, import_compose7.useRefEffect)(
2691        (element) => {
2692          const cleanups = refEffects.map((effect) => effect(element));
2693          return () => {
2694            cleanups.forEach((cleanup) => cleanup());
2695          };
2696        },
2697        [refEffects]
2698      );
2699    }
2700  
2701    // packages/rich-text/build-module/hook/use-format-types.mjs
2702    var import_element4 = __toESM(require_element(), 1);
2703    var import_data8 = __toESM(require_data(), 1);
2704    function formatTypesSelector(select5) {
2705      return select5(store).getFormatTypes();
2706    }
2707    var interactiveContentTags = /* @__PURE__ */ new Set([
2708      "a",
2709      "audio",
2710      "button",
2711      "details",
2712      "embed",
2713      "iframe",
2714      "input",
2715      "label",
2716      "select",
2717      "textarea",
2718      "video"
2719    ]);
2720    function prefixSelectKeys(selected, prefix) {
2721      if (typeof selected !== "object" || selected === null) {
2722        return { [prefix]: selected };
2723      }
2724      return Object.fromEntries(
2725        Object.entries(selected).map(([key, value]) => [
2726          `$prefix}.$key}`,
2727          value
2728        ])
2729      );
2730    }
2731    function getPrefixedSelectKeys(selected, prefix) {
2732      if (selected[prefix]) {
2733        return selected[prefix];
2734      }
2735      return Object.keys(selected).filter((key) => key.startsWith(prefix + ".")).reduce((accumulator, key) => {
2736        accumulator[key.slice(prefix.length + 1)] = selected[key];
2737        return accumulator;
2738      }, {});
2739    }
2740    function useFormatTypes({
2741      allowedFormats,
2742      withoutInteractiveFormatting,
2743      __unstableFormatTypeHandlerContext
2744    }) {
2745      const allFormatTypes = (0, import_data8.useSelect)(formatTypesSelector, []);
2746      const formatTypes2 = (0, import_element4.useMemo)(() => {
2747        return allFormatTypes.filter(({ name, interactive, tagName }) => {
2748          if (allowedFormats && !allowedFormats.includes(name)) {
2749            return false;
2750          }
2751          if (withoutInteractiveFormatting && (interactive || interactiveContentTags.has(tagName))) {
2752            return false;
2753          }
2754          return true;
2755        });
2756      }, [allFormatTypes, allowedFormats, withoutInteractiveFormatting]);
2757      const keyedSelected = (0, import_data8.useSelect)(
2758        (select5) => formatTypes2.reduce(
2759          (accumulator, type) => {
2760            if (!type.__experimentalGetPropsForEditableTreePreparation || !__unstableFormatTypeHandlerContext) {
2761              return accumulator;
2762            }
2763            return {
2764              ...accumulator,
2765              ...prefixSelectKeys(
2766                type.__experimentalGetPropsForEditableTreePreparation(
2767                  select5,
2768                  __unstableFormatTypeHandlerContext
2769                ),
2770                type.name
2771              )
2772            };
2773          },
2774          {}
2775        ),
2776        [formatTypes2, __unstableFormatTypeHandlerContext]
2777      );
2778      const dispatch3 = (0, import_data8.useDispatch)();
2779      const prepareHandlers = [];
2780      const valueHandlers = [];
2781      const changeHandlers = [];
2782      const dependencies = [];
2783      for (const key in keyedSelected) {
2784        dependencies.push(keyedSelected[key]);
2785      }
2786      formatTypes2.forEach((type) => {
2787        if (type.__experimentalCreatePrepareEditableTree && __unstableFormatTypeHandlerContext) {
2788          const handler = type.__experimentalCreatePrepareEditableTree(
2789            getPrefixedSelectKeys(keyedSelected, type.name),
2790            __unstableFormatTypeHandlerContext
2791          );
2792          if (type.__experimentalCreateOnChangeEditableValue) {
2793            valueHandlers.push(handler);
2794          } else {
2795            prepareHandlers.push(handler);
2796          }
2797        }
2798        if (type.__experimentalCreateOnChangeEditableValue && __unstableFormatTypeHandlerContext) {
2799          let dispatchers = {};
2800          if (type.__experimentalGetPropsForEditableTreeChangeHandler) {
2801            dispatchers = type.__experimentalGetPropsForEditableTreeChangeHandler(
2802              dispatch3,
2803              __unstableFormatTypeHandlerContext
2804            );
2805          }
2806          const selected = getPrefixedSelectKeys(keyedSelected, type.name);
2807          changeHandlers.push(
2808            type.__experimentalCreateOnChangeEditableValue(
2809              {
2810                ...typeof selected === "object" ? selected : {},
2811                ...dispatchers
2812              },
2813              __unstableFormatTypeHandlerContext
2814            )
2815          );
2816        }
2817      });
2818      return {
2819        formatTypes: formatTypes2,
2820        prepareHandlers,
2821        valueHandlers,
2822        changeHandlers,
2823        dependencies
2824      };
2825    }
2826  
2827    // packages/rich-text/build-module/hook/index.mjs
2828    var getDomPositionKey = /* @__PURE__ */ Symbol("getDomPosition");
2829    function hasFocus(element) {
2830      const { activeElement } = element.ownerDocument;
2831      return activeElement === element || activeElement?.contentEditable === "true" && activeElement.contains(element);
2832    }
2833    function useRichTextBase({
2834      value = "",
2835      selectionStart,
2836      selectionEnd,
2837      placeholder,
2838      onSelectionChange,
2839      preserveWhiteSpace,
2840      onChange,
2841      __unstableDisableFormats: disableFormats,
2842      __unstableIsSelected: isSelected,
2843      __unstableDependencies = [],
2844      __unstableAfterParse,
2845      __unstableBeforeSerialize,
2846      __unstableAddInvisibleFormats
2847    }) {
2848      const registry = (0, import_data9.useRegistry)();
2849      const [, forceRender] = (0, import_element5.useReducer)(() => ({}), void 0);
2850      const ref = (0, import_element5.useRef)(void 0);
2851      function createRecord() {
2852        const {
2853          ownerDocument: { defaultView }
2854        } = ref.current;
2855        const selection = defaultView.getSelection();
2856        const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
2857        return create({
2858          element: ref.current,
2859          range,
2860          __unstableIsEditableTree: true
2861        });
2862      }
2863      function applyRecord(newRecord, { domOnly } = {}) {
2864        apply({
2865          value: newRecord,
2866          current: ref.current,
2867          prepareEditableTree: __unstableAddInvisibleFormats,
2868          __unstableDomOnly: domOnly,
2869          placeholder
2870        });
2871      }
2872      const _valueRef = (0, import_element5.useRef)(value);
2873      const recordRef = (0, import_element5.useRef)(void 0);
2874      function setRecordFromProps() {
2875        const activeFormats = recordRef.current?.activeFormats;
2876        _valueRef.current = value;
2877        let parsed = value;
2878        if (!(parsed instanceof RichTextData)) {
2879          parsed = parsed ? RichTextData.fromHTMLString(parsed) : RichTextData.empty();
2880        }
2881        recordRef.current = {
2882          text: parsed.text,
2883          formats: parsed.formats,
2884          replacements: parsed.replacements,
2885          activeFormats
2886        };
2887        if (disableFormats) {
2888          recordRef.current.formats = Array(value.length);
2889          recordRef.current.replacements = Array(value.length);
2890        }
2891        if (__unstableAfterParse) {
2892          recordRef.current.formats = __unstableAfterParse(
2893            recordRef.current
2894          );
2895        }
2896        recordRef.current.start = selectionStart;
2897        recordRef.current.end = selectionEnd;
2898      }
2899      if (!recordRef.current) {
2900        setRecordFromProps();
2901      } else if (selectionStart !== recordRef.current.start || selectionEnd !== recordRef.current.end) {
2902        recordRef.current = {
2903          ...recordRef.current,
2904          start: selectionStart,
2905          end: selectionEnd,
2906          activeFormats: void 0
2907        };
2908      }
2909      const sentSelectionRef = (0, import_element5.useRef)([]);
2910      function sendSelection(start, end) {
2911        sentSelectionRef.current = [start, end];
2912        onSelectionChange(start, end);
2913      }
2914      function handleChange(newRecord) {
2915        recordRef.current = newRecord;
2916        applyRecord(newRecord);
2917        if (disableFormats) {
2918          _valueRef.current = newRecord.text;
2919        } else {
2920          const newFormats = __unstableBeforeSerialize ? __unstableBeforeSerialize(newRecord) : newRecord.formats;
2921          newRecord = { ...newRecord, formats: newFormats };
2922          if (typeof value === "string") {
2923            _valueRef.current = toHTMLString({
2924              value: newRecord,
2925              preserveWhiteSpace
2926            });
2927          } else {
2928            _valueRef.current = new RichTextData(newRecord);
2929          }
2930        }
2931        const { start, end, formats, text } = recordRef.current;
2932        registry.batch(() => {
2933          sendSelection(start, end);
2934          onChange(_valueRef.current, {
2935            __unstableFormats: formats,
2936            __unstableText: text
2937          });
2938        });
2939        forceRender();
2940      }
2941      (0, import_element5.useLayoutEffect)(() => {
2942        if (value === _valueRef.current) {
2943          return;
2944        }
2945        setRecordFromProps();
2946        applyRecord(recordRef.current, {
2947          domOnly: !hasFocus(ref.current)
2948        });
2949        forceRender();
2950      }, [value]);
2951      (0, import_element5.useLayoutEffect)(() => {
2952        const [sentStart, sentEnd] = sentSelectionRef.current;
2953        sentSelectionRef.current = [];
2954        if (isSelected && (selectionStart !== sentStart || selectionEnd !== sentEnd) && hasFocus(ref.current)) {
2955          applyRecord(recordRef.current);
2956        }
2957      }, [selectionStart, selectionEnd, isSelected]);
2958      const mergedRefs = (0, import_compose8.useMergeRefs)([
2959        ref,
2960        useDefaultStyle(),
2961        useBoundaryStyle({
2962          record: recordRef
2963        }),
2964        useEventListeners({
2965          record: recordRef,
2966          handleChange,
2967          applyRecord,
2968          createRecord,
2969          isSelected,
2970          onSelectionChange: sendSelection,
2971          forceRender
2972        }),
2973        (0, import_compose8.useRefEffect)(
2974          (element) => {
2975            setRecordFromProps();
2976            applyRecord(recordRef.current, {
2977              domOnly: !hasFocus(element)
2978            });
2979          },
2980          [placeholder, ...__unstableDependencies]
2981        )
2982      ]);
2983      return {
2984        value: recordRef.current,
2985        // A function to get the most recent value so event handlers in
2986        // useRichText implementations have access to it. For example when
2987        // listening to input events, we internally update the state, but this
2988        // state is not yet available to the input event handler because React
2989        // may re-render asynchronously.
2990        getValue: () => recordRef.current,
2991        onChange: handleChange,
2992        ref: mergedRefs,
2993        // The DOM position of an offset in the value, for a selection set
2994        // from outside the element.
2995        [getDomPositionKey]: (0, import_element5.useCallback)(
2996          (offset) => getDomPosition({
2997            value: recordRef.current,
2998            offset: Math.min(offset, recordRef.current.text.length),
2999            element: ref.current,
3000            prepareEditableTree: __unstableAddInvisibleFormats,
3001            placeholder
3002          }),
3003          [__unstableAddInvisibleFormats, placeholder]
3004        )
3005      };
3006    }
3007    function useRichText({
3008      allowedFormats,
3009      withoutInteractiveFormatting,
3010      onChange,
3011      __unstableDependencies = [],
3012      __unstableFormatTypeHandlerContext,
3013      ...props
3014    }) {
3015      const {
3016        formatTypes: formatTypes2,
3017        prepareHandlers,
3018        valueHandlers,
3019        changeHandlers,
3020        dependencies
3021      } = useFormatTypes({
3022        allowedFormats,
3023        withoutInteractiveFormatting,
3024        __unstableFormatTypeHandlerContext
3025      });
3026      function addEditorOnlyFormats(record) {
3027        return valueHandlers.reduce(
3028          (accumulator, fn) => fn(accumulator, record.text),
3029          record.formats
3030        );
3031      }
3032      function removeEditorOnlyFormats(record) {
3033        formatTypes2.forEach((formatType) => {
3034          if (formatType.__experimentalCreatePrepareEditableTree) {
3035            record = removeFormat(
3036              record,
3037              formatType.name,
3038              0,
3039              record.text.length
3040            );
3041          }
3042        });
3043        return record.formats;
3044      }
3045      function addInvisibleFormats(record) {
3046        return prepareHandlers.reduce(
3047          (accumulator, fn) => fn(accumulator, record.text),
3048          record.formats
3049        );
3050      }
3051      const result = useRichTextBase({
3052        ...props,
3053        onChange(value, { __unstableFormats, __unstableText }) {
3054          onChange(value, {
3055            __unstableFormats,
3056            __unstableText
3057          });
3058          Object.values(changeHandlers).forEach((changeHandler) => {
3059            changeHandler(__unstableFormats, __unstableText);
3060          });
3061        },
3062        __unstableDependencies: [...dependencies, ...__unstableDependencies],
3063        __unstableAfterParse: addEditorOnlyFormats,
3064        __unstableBeforeSerialize: removeEditorOnlyFormats,
3065        __unstableAddInvisibleFormats: addInvisibleFormats
3066      });
3067      return { ...result, formatTypes: formatTypes2 };
3068    }
3069    function useDeprecatedRichText(props) {
3070      (0, import_deprecated.default)("`__unstableUseRichText` hook", {
3071        since: "7.0"
3072      });
3073      return useRichTextBase(props);
3074    }
3075  
3076    // packages/rich-text/build-module/contexts.mjs
3077    var import_element6 = __toESM(require_element(), 1);
3078    var KeyboardShortcutContext = (0, import_element6.createContext)(/* @__PURE__ */ new Set());
3079    KeyboardShortcutContext.displayName = "KeyboardShortcutContext";
3080    var InputEventContext = (0, import_element6.createContext)(/* @__PURE__ */ new Set());
3081    InputEventContext.displayName = "InputEventContext";
3082  
3083    // packages/rich-text/build-module/keyboard-shortcut.mjs
3084    var import_keycodes3 = __toESM(require_keycodes(), 1);
3085    var import_element7 = __toESM(require_element(), 1);
3086    var import_compose9 = __toESM(require_compose(), 1);
3087    function RichTextShortcut({
3088      character,
3089      type,
3090      onUse
3091    }) {
3092      const keyboardShortcuts = (0, import_element7.useContext)(KeyboardShortcutContext);
3093      const stableOnUse = (0, import_compose9.useEvent)(onUse);
3094      (0, import_element7.useEffect)(() => {
3095        function callback(event) {
3096          if (import_keycodes3.isKeyboardEvent[type](event, character)) {
3097            stableOnUse();
3098            event.preventDefault();
3099          }
3100        }
3101        keyboardShortcuts.add(callback);
3102        return () => {
3103          keyboardShortcuts.delete(callback);
3104        };
3105      }, [character, type, keyboardShortcuts, stableOnUse]);
3106      return null;
3107    }
3108  
3109    // packages/rich-text/build-module/input-event.mjs
3110    var import_element8 = __toESM(require_element(), 1);
3111    var import_compose10 = __toESM(require_compose(), 1);
3112    function RichTextInputEvent({
3113      inputType,
3114      onInput
3115    }) {
3116      const callbacks = (0, import_element8.useContext)(InputEventContext);
3117      const stableOnInput = (0, import_compose10.useEvent)(onInput);
3118      (0, import_element8.useEffect)(() => {
3119        function callback(event) {
3120          if (event.inputType === inputType) {
3121            stableOnInput();
3122            event.preventDefault();
3123          }
3124        }
3125        callbacks.add(callback);
3126        return () => {
3127          callbacks.delete(callback);
3128        };
3129      }, [inputType, callbacks, stableOnInput]);
3130      return null;
3131    }
3132  
3133    // packages/rich-text/build-module/event-listeners.mjs
3134    var shortcutsListener = (keyboardShortcuts) => (element) => {
3135      function onKeyDown(event) {
3136        for (const keyboardShortcut of keyboardShortcuts) {
3137          keyboardShortcut(event);
3138        }
3139      }
3140      element.addEventListener("keydown", onKeyDown);
3141      return () => {
3142        element.removeEventListener("keydown", onKeyDown);
3143      };
3144    };
3145    var inputEventsListener = (inputEvents) => (element) => {
3146      function onInput(event) {
3147        for (const inputEventHandler of inputEvents) {
3148          inputEventHandler(event);
3149        }
3150      }
3151      element.addEventListener("input", onInput);
3152      return () => {
3153        element.removeEventListener("input", onInput);
3154      };
3155    };
3156  
3157    // packages/rich-text/build-module/private-apis.mjs
3158    var privateApis = {};
3159    lock(privateApis, {
3160      useRichText,
3161      getDomPositionKey,
3162      useFormatTypes,
3163      KeyboardShortcutContext,
3164      InputEventContext,
3165      RichTextShortcut,
3166      RichTextInputEvent,
3167      shortcutsListener,
3168      inputEventsListener,
3169      ownsSelection,
3170      subscribeOwnedListener
3171    });
3172  
3173    // packages/rich-text/build-module/hook/use-anchor-ref.mjs
3174    var import_element9 = __toESM(require_element(), 1);
3175    var import_deprecated2 = __toESM(require_deprecated(), 1);
3176    function useAnchorRef({
3177      ref,
3178      value,
3179      settings = {}
3180    }) {
3181      (0, import_deprecated2.default)("`useAnchorRef` hook", {
3182        since: "6.1",
3183        alternative: "`useAnchor` hook"
3184      });
3185      const { tagName, className, name } = settings;
3186      const activeFormat = name ? getActiveFormat(value, name) : void 0;
3187      return (0, import_element9.useMemo)(() => {
3188        if (!ref.current) {
3189          return;
3190        }
3191        const {
3192          ownerDocument: { defaultView }
3193        } = ref.current;
3194        const selection = defaultView.getSelection();
3195        if (!selection.rangeCount) {
3196          return;
3197        }
3198        const range = selection.getRangeAt(0);
3199        if (!activeFormat) {
3200          return range;
3201        }
3202        let element = range.startContainer;
3203        element = element.nextElementSibling || element;
3204        while (element.nodeType !== element.ELEMENT_NODE) {
3205          element = element.parentNode;
3206        }
3207        return element.closest(
3208          tagName + (className ? "." + className : "")
3209        );
3210      }, [activeFormat, value.start, value.end, tagName, className]);
3211    }
3212  
3213    // packages/rich-text/build-module/hook/use-anchor.mjs
3214    var import_compose11 = __toESM(require_compose(), 1);
3215    var import_element10 = __toESM(require_element(), 1);
3216    var import_dom = __toESM(require_dom(), 1);
3217    function getFormatElement(range, editableContentElement, tagName, className) {
3218      let element = range.startContainer;
3219      if (element.nodeType === element.TEXT_NODE && element instanceof window.Text && range.startOffset === element.length && element.nextSibling) {
3220        element = element.nextSibling;
3221        while (element.firstChild) {
3222          element = element.firstChild;
3223        }
3224      }
3225      if (element.nodeType !== element.ELEMENT_NODE) {
3226        if (!element.parentElement) {
3227          return;
3228        }
3229        element = element.parentElement;
3230      }
3231      if (element === editableContentElement) {
3232        return;
3233      }
3234      if (!editableContentElement.contains(element)) {
3235        return;
3236      }
3237      const selector = tagName + (className ? "." + className : "");
3238      if (!selector) {
3239        return;
3240      }
3241      if (!(element instanceof window.HTMLElement)) {
3242        return;
3243      }
3244      let closestElement = element;
3245      while (closestElement && closestElement !== editableContentElement) {
3246        if (closestElement.matches(selector)) {
3247          return closestElement;
3248        }
3249        closestElement = closestElement.parentElement;
3250      }
3251      return void 0;
3252    }
3253    function createVirtualAnchorElement(range, editableContentElement) {
3254      return {
3255        contextElement: editableContentElement,
3256        getBoundingClientRect() {
3257          if (editableContentElement.contains(range.startContainer)) {
3258            return (0, import_dom.getRectangleFromRange)(range) ?? range.getBoundingClientRect();
3259          }
3260          return editableContentElement.getBoundingClientRect();
3261        }
3262      };
3263    }
3264    function getAnchor(editableContentElement, tagName, className) {
3265      if (!editableContentElement) {
3266        return;
3267      }
3268      const { ownerDocument } = editableContentElement;
3269      const { defaultView } = ownerDocument;
3270      const selection = defaultView?.getSelection();
3271      if (!selection) {
3272        return;
3273      }
3274      if (!selection.rangeCount) {
3275        return;
3276      }
3277      const range = selection.getRangeAt(0);
3278      if (!range || !range.startContainer) {
3279        return;
3280      }
3281      if (!tagName && !className) {
3282        return createVirtualAnchorElement(range, editableContentElement);
3283      }
3284      return getFormatElement(range, editableContentElement, tagName, className) ?? createVirtualAnchorElement(range, editableContentElement);
3285    }
3286    var DEFAULT_SETTINGS = {
3287      tagName: "",
3288      className: ""
3289    };
3290    function useAnchor({
3291      editableContentElement,
3292      settings
3293    }) {
3294      const { tagName, className } = settings ?? DEFAULT_SETTINGS;
3295      const isActive = !!(settings && "isActive" in settings && settings.isActive);
3296      const [anchor, setAnchor] = (0, import_element10.useState)(
3297        () => getAnchor(editableContentElement, tagName, className ?? "")
3298      );
3299      const wasActive = (0, import_compose11.usePrevious)(isActive);
3300      (0, import_element10.useLayoutEffect)(() => {
3301        if (!editableContentElement) {
3302          return;
3303        }
3304        function callback() {
3305          setAnchor(
3306            getAnchor(editableContentElement, tagName, className ?? "")
3307          );
3308        }
3309        function attach() {
3310          ownerDocument.addEventListener("selectionchange", callback);
3311        }
3312        function detach() {
3313          ownerDocument.removeEventListener("selectionchange", callback);
3314        }
3315        const { ownerDocument } = editableContentElement;
3316        if (ownsSelection(editableContentElement) || // When a link is created, we need to attach the popover to the newly created anchor.
3317        !wasActive && isActive || // Sometimes we're _removing_ an active anchor, such as the inline color popover.
3318        // When we add the color, it switches from a virtual anchor to a `<mark>` element.
3319        // When we _remove_ the color, it switches from a `<mark>` element to a virtual anchor.
3320        wasActive && !isActive) {
3321          setAnchor(
3322            getAnchor(editableContentElement, tagName, className ?? "")
3323          );
3324          attach();
3325        }
3326        editableContentElement.addEventListener("focusin", attach);
3327        editableContentElement.addEventListener("focusout", detach);
3328        return () => {
3329          detach();
3330          editableContentElement.removeEventListener("focusin", attach);
3331          editableContentElement.removeEventListener("focusout", detach);
3332        };
3333      }, [editableContentElement, tagName, className, isActive, wasActive]);
3334      return anchor;
3335    }
3336  
3337    // packages/rich-text/build-module/index.mjs
3338    function __experimentalRichText() {
3339    }
3340    return __toCommonJS(index_exports);
3341  })();
3342  (window.wp ||= {}).richText = wp.richText;
3343  })();


Generated : Mon Nov 2 08:20:36 2026 Cross-referenced by PHPXref