1(function() { 2"use strict"; 3var 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
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
141// packages/rich-text/build-module/store/index.mjs 142 var import_data3 = __toESM(require_data(), 1); 143 144
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
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
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
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
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
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
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
360// packages/rich-text/build-module/create.mjs 361 var import_data5 = __toESM(require_data(), 1); 362 363
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
372// packages/rich-text/build-module/special-characters.mjs 373 var OBJECT_REPLACEMENT_CHARACTER = "\uFFFC"; 374 var ZWNBSP = "\uFEFF"; 375 376
376// packages/rich-text/build-module/to-html-string.mjs 377 var import_escape_html = __toESM(require_escape_html(), 1); 378 379
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
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
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
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
766// packages/rich-text/build-module/get-text-content.mjs 767 function getTextContent({ text }) { 768 return text.replace(OBJECT_REPLACEMENT_CHARACTER, ""); 769 } 770 771
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
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
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
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
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
1216// packages/rich-text/build-module/is-empty.mjs 1217 function isEmpty({ text }) { 1218 return text.length === 0; 1219 } 1220 1221
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
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
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
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
1384// packages/rich-text/build-module/remove.mjs 1385 function remove2(value, startIndex, endIndex) { 1386 return insert(value, create(), startIndex, endIndex); 1387 } 1388 1389
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
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
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
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
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
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
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
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
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
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
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
vendor: 8,261 bytes, lines 1770-1941
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
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
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
1981// packages/rich-text/build-module/hook/event-listeners/copy-handler.mjs 1982 var import_compose = __toESM(require_compose(), 1); 1983 1984
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
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
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
2084// packages/rich-text/build-module/hook/event-listeners/format-boundaries.mjs 2085 var import_keycodes = __toESM(require_keycodes(), 1); 2086 2087
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
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
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
2220// packages/rich-text/build-module/hook/event-listeners/input-and-selection.mjs 2221 var import_compose4 = __toESM(require_compose(), 1); 2222 2223
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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})(); 3212//# sourceMappingURL=index.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.