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


Generated : Mon Oct 12 08:20:33 2026 Cross-referenced by PHPXref