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