[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /******/ (() => { // webpackBootstrap 2 /******/ "use strict"; 3 /******/ // The require scope 4 /******/ var __webpack_require__ = {}; 5 /******/ 6 /************************************************************************/ 7 /******/ /* webpack/runtime/compat get default export */ 8 /******/ (() => { 9 /******/ // getDefaultExport function for compatibility with non-harmony modules 10 /******/ __webpack_require__.n = (module) => { 11 /******/ var getter = module && module.__esModule ? 12 /******/ () => (module['default']) : 13 /******/ () => (module); 14 /******/ __webpack_require__.d(getter, { a: getter }); 15 /******/ return getter; 16 /******/ }; 17 /******/ })(); 18 /******/ 19 /******/ /* webpack/runtime/define property getters */ 20 /******/ (() => { 21 /******/ // define getter functions for harmony exports 22 /******/ __webpack_require__.d = (exports, definition) => { 23 /******/ for(var key in definition) { 24 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 25 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 26 /******/ } 27 /******/ } 28 /******/ }; 29 /******/ })(); 30 /******/ 31 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 32 /******/ (() => { 33 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 34 /******/ })(); 35 /******/ 36 /******/ /* webpack/runtime/make namespace object */ 37 /******/ (() => { 38 /******/ // define __esModule on exports 39 /******/ __webpack_require__.r = (exports) => { 40 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 41 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 42 /******/ } 43 /******/ Object.defineProperty(exports, '__esModule', { value: true }); 44 /******/ }; 45 /******/ })(); 46 /******/ 47 /************************************************************************/ 48 var __webpack_exports__ = {}; 49 // ESM COMPAT FLAG 50 __webpack_require__.r(__webpack_exports__); 51 52 // EXPORTS 53 __webpack_require__.d(__webpack_exports__, { 54 __unstableStripHTML: () => (/* reexport */ stripHTML), 55 computeCaretRect: () => (/* reexport */ computeCaretRect), 56 documentHasSelection: () => (/* reexport */ documentHasSelection), 57 documentHasTextSelection: () => (/* reexport */ documentHasTextSelection), 58 documentHasUncollapsedSelection: () => (/* reexport */ documentHasUncollapsedSelection), 59 focus: () => (/* binding */ build_module_focus), 60 getFilesFromDataTransfer: () => (/* reexport */ getFilesFromDataTransfer), 61 getOffsetParent: () => (/* reexport */ getOffsetParent), 62 getPhrasingContentSchema: () => (/* reexport */ getPhrasingContentSchema), 63 getRectangleFromRange: () => (/* reexport */ getRectangleFromRange), 64 getScrollContainer: () => (/* reexport */ getScrollContainer), 65 insertAfter: () => (/* reexport */ insertAfter), 66 isEmpty: () => (/* reexport */ isEmpty), 67 isEntirelySelected: () => (/* reexport */ isEntirelySelected), 68 isFormElement: () => (/* reexport */ isFormElement), 69 isHorizontalEdge: () => (/* reexport */ isHorizontalEdge), 70 isNumberInput: () => (/* reexport */ isNumberInput), 71 isPhrasingContent: () => (/* reexport */ isPhrasingContent), 72 isRTL: () => (/* reexport */ isRTL), 73 isTextContent: () => (/* reexport */ isTextContent), 74 isTextField: () => (/* reexport */ isTextField), 75 isVerticalEdge: () => (/* reexport */ isVerticalEdge), 76 placeCaretAtHorizontalEdge: () => (/* reexport */ placeCaretAtHorizontalEdge), 77 placeCaretAtVerticalEdge: () => (/* reexport */ placeCaretAtVerticalEdge), 78 remove: () => (/* reexport */ remove), 79 removeInvalidHTML: () => (/* reexport */ removeInvalidHTML), 80 replace: () => (/* reexport */ replace), 81 replaceTag: () => (/* reexport */ replaceTag), 82 safeHTML: () => (/* reexport */ safeHTML), 83 unwrap: () => (/* reexport */ unwrap), 84 wrap: () => (/* reexport */ wrap) 85 }); 86 87 // NAMESPACE OBJECT: ./node_modules/@wordpress/dom/build-module/focusable.js 88 var focusable_namespaceObject = {}; 89 __webpack_require__.r(focusable_namespaceObject); 90 __webpack_require__.d(focusable_namespaceObject, { 91 find: () => (find) 92 }); 93 94 // NAMESPACE OBJECT: ./node_modules/@wordpress/dom/build-module/tabbable.js 95 var tabbable_namespaceObject = {}; 96 __webpack_require__.r(tabbable_namespaceObject); 97 __webpack_require__.d(tabbable_namespaceObject, { 98 find: () => (tabbable_find), 99 findNext: () => (findNext), 100 findPrevious: () => (findPrevious), 101 isTabbableIndex: () => (isTabbableIndex) 102 }); 103 104 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/focusable.js 105 /** 106 * References: 107 * 108 * Focusable: 109 * - https://www.w3.org/TR/html5/editing.html#focus-management 110 * 111 * Sequential focus navigation: 112 * - https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute 113 * 114 * Disabled elements: 115 * - https://www.w3.org/TR/html5/disabled-elements.html#disabled-elements 116 * 117 * getClientRects algorithm (requiring layout box): 118 * - https://www.w3.org/TR/cssom-view-1/#extension-to-the-element-interface 119 * 120 * AREA elements associated with an IMG: 121 * - https://w3c.github.io/html/editing.html#data-model 122 */ 123 124 /** 125 * Returns a CSS selector used to query for focusable elements. 126 * 127 * @param {boolean} sequential If set, only query elements that are sequentially 128 * focusable. Non-interactive elements with a 129 * negative `tabindex` are focusable but not 130 * sequentially focusable. 131 * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute 132 * 133 * @return {string} CSS selector. 134 */ 135 function buildSelector(sequential) { 136 return [sequential ? '[tabindex]:not([tabindex^="-"])' : '[tabindex]', 'a[href]', 'button:not([disabled])', 'input:not([type="hidden"]):not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'iframe:not([tabindex^="-"])', 'object', 'embed', 'area[href]', '[contenteditable]:not([contenteditable=false])'].join(','); 137 } 138 139 /** 140 * Returns true if the specified element is visible (i.e. neither display: none 141 * nor visibility: hidden). 142 * 143 * @param {HTMLElement} element DOM element to test. 144 * 145 * @return {boolean} Whether element is visible. 146 */ 147 function isVisible(element) { 148 return element.offsetWidth > 0 || element.offsetHeight > 0 || element.getClientRects().length > 0; 149 } 150 151 /** 152 * Returns true if the specified area element is a valid focusable element, or 153 * false otherwise. Area is only focusable if within a map where a named map 154 * referenced by an image somewhere in the document. 155 * 156 * @param {HTMLAreaElement} element DOM area element to test. 157 * 158 * @return {boolean} Whether area element is valid for focus. 159 */ 160 function isValidFocusableArea(element) { 161 /** @type {HTMLMapElement | null} */ 162 const map = element.closest('map[name]'); 163 if (!map) { 164 return false; 165 } 166 167 /** @type {HTMLImageElement | null} */ 168 const img = element.ownerDocument.querySelector('img[usemap="#' + map.name + '"]'); 169 return !!img && isVisible(img); 170 } 171 172 /** 173 * Returns all focusable elements within a given context. 174 * 175 * @param {Element} context Element in which to search. 176 * @param {Object} options 177 * @param {boolean} [options.sequential] If set, only return elements that are 178 * sequentially focusable. 179 * Non-interactive elements with a 180 * negative `tabindex` are focusable but 181 * not sequentially focusable. 182 * https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute 183 * 184 * @return {HTMLElement[]} Focusable elements. 185 */ 186 function find(context, { 187 sequential = false 188 } = {}) { 189 /* eslint-disable jsdoc/no-undefined-types */ 190 /** @type {NodeListOf<HTMLElement>} */ 191 /* eslint-enable jsdoc/no-undefined-types */ 192 const elements = context.querySelectorAll(buildSelector(sequential)); 193 return Array.from(elements).filter(element => { 194 if (!isVisible(element)) { 195 return false; 196 } 197 const { 198 nodeName 199 } = element; 200 if ('AREA' === nodeName) { 201 return isValidFocusableArea( /** @type {HTMLAreaElement} */element); 202 } 203 return true; 204 }); 205 } 206 207 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/tabbable.js 208 /** 209 * Internal dependencies 210 */ 211 212 213 /** 214 * Returns the tab index of the given element. In contrast with the tabIndex 215 * property, this normalizes the default (0) to avoid browser inconsistencies, 216 * operating under the assumption that this function is only ever called with a 217 * focusable node. 218 * 219 * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1190261 220 * 221 * @param {Element} element Element from which to retrieve. 222 * 223 * @return {number} Tab index of element (default 0). 224 */ 225 function getTabIndex(element) { 226 const tabIndex = element.getAttribute('tabindex'); 227 return tabIndex === null ? 0 : parseInt(tabIndex, 10); 228 } 229 230 /** 231 * Returns true if the specified element is tabbable, or false otherwise. 232 * 233 * @param {Element} element Element to test. 234 * 235 * @return {boolean} Whether element is tabbable. 236 */ 237 function isTabbableIndex(element) { 238 return getTabIndex(element) !== -1; 239 } 240 241 /** @typedef {Element & { type?: string, checked?: boolean, name?: string }} MaybeHTMLInputElement */ 242 243 /** 244 * Returns a stateful reducer function which constructs a filtered array of 245 * tabbable elements, where at most one radio input is selected for a given 246 * name, giving priority to checked input, falling back to the first 247 * encountered. 248 * 249 * @return {(acc: MaybeHTMLInputElement[], el: MaybeHTMLInputElement) => MaybeHTMLInputElement[]} Radio group collapse reducer. 250 */ 251 function createStatefulCollapseRadioGroup() { 252 /** @type {Record<string, MaybeHTMLInputElement>} */ 253 const CHOSEN_RADIO_BY_NAME = {}; 254 return function collapseRadioGroup( /** @type {MaybeHTMLInputElement[]} */result, /** @type {MaybeHTMLInputElement} */element) { 255 const { 256 nodeName, 257 type, 258 checked, 259 name 260 } = element; 261 262 // For all non-radio tabbables, construct to array by concatenating. 263 if (nodeName !== 'INPUT' || type !== 'radio' || !name) { 264 return result.concat(element); 265 } 266 const hasChosen = CHOSEN_RADIO_BY_NAME.hasOwnProperty(name); 267 268 // Omit by skipping concatenation if the radio element is not chosen. 269 const isChosen = checked || !hasChosen; 270 if (!isChosen) { 271 return result; 272 } 273 274 // At this point, if there had been a chosen element, the current 275 // element is checked and should take priority. Retroactively remove 276 // the element which had previously been considered the chosen one. 277 if (hasChosen) { 278 const hadChosenElement = CHOSEN_RADIO_BY_NAME[name]; 279 result = result.filter(e => e !== hadChosenElement); 280 } 281 CHOSEN_RADIO_BY_NAME[name] = element; 282 return result.concat(element); 283 }; 284 } 285 286 /** 287 * An array map callback, returning an object with the element value and its 288 * array index location as properties. This is used to emulate a proper stable 289 * sort where equal tabIndex should be left in order of their occurrence in the 290 * document. 291 * 292 * @param {Element} element Element. 293 * @param {number} index Array index of element. 294 * 295 * @return {{ element: Element, index: number }} Mapped object with element, index. 296 */ 297 function mapElementToObjectTabbable(element, index) { 298 return { 299 element, 300 index 301 }; 302 } 303 304 /** 305 * An array map callback, returning an element of the given mapped object's 306 * element value. 307 * 308 * @param {{ element: Element }} object Mapped object with element. 309 * 310 * @return {Element} Mapped object element. 311 */ 312 function mapObjectTabbableToElement(object) { 313 return object.element; 314 } 315 316 /** 317 * A sort comparator function used in comparing two objects of mapped elements. 318 * 319 * @see mapElementToObjectTabbable 320 * 321 * @param {{ element: Element, index: number }} a First object to compare. 322 * @param {{ element: Element, index: number }} b Second object to compare. 323 * 324 * @return {number} Comparator result. 325 */ 326 function compareObjectTabbables(a, b) { 327 const aTabIndex = getTabIndex(a.element); 328 const bTabIndex = getTabIndex(b.element); 329 if (aTabIndex === bTabIndex) { 330 return a.index - b.index; 331 } 332 return aTabIndex - bTabIndex; 333 } 334 335 /** 336 * Givin focusable elements, filters out tabbable element. 337 * 338 * @param {Element[]} focusables Focusable elements to filter. 339 * 340 * @return {Element[]} Tabbable elements. 341 */ 342 function filterTabbable(focusables) { 343 return focusables.filter(isTabbableIndex).map(mapElementToObjectTabbable).sort(compareObjectTabbables).map(mapObjectTabbableToElement).reduce(createStatefulCollapseRadioGroup(), []); 344 } 345 346 /** 347 * @param {Element} context 348 * @return {Element[]} Tabbable elements within the context. 349 */ 350 function tabbable_find(context) { 351 return filterTabbable(find(context)); 352 } 353 354 /** 355 * Given a focusable element, find the preceding tabbable element. 356 * 357 * @param {Element} element The focusable element before which to look. Defaults 358 * to the active element. 359 * 360 * @return {Element|undefined} Preceding tabbable element. 361 */ 362 function findPrevious(element) { 363 return filterTabbable(find(element.ownerDocument.body)).reverse().find(focusable => { 364 return ( 365 // eslint-disable-next-line no-bitwise 366 element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_PRECEDING 367 ); 368 }); 369 } 370 371 /** 372 * Given a focusable element, find the next tabbable element. 373 * 374 * @param {Element} element The focusable element after which to look. Defaults 375 * to the active element. 376 * 377 * @return {Element|undefined} Next tabbable element. 378 */ 379 function findNext(element) { 380 return filterTabbable(find(element.ownerDocument.body)).find(focusable => { 381 return ( 382 // eslint-disable-next-line no-bitwise 383 element.compareDocumentPosition(focusable) & element.DOCUMENT_POSITION_FOLLOWING 384 ); 385 }); 386 } 387 388 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/utils/assert-is-defined.js 389 function assertIsDefined(val, name) { 390 if (false) {} 391 } 392 393 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-rectangle-from-range.js 394 /** 395 * Internal dependencies 396 */ 397 398 399 /** 400 * Get the rectangle of a given Range. Returns `null` if no suitable rectangle 401 * can be found. 402 * 403 * @param {Range} range The range. 404 * 405 * @return {DOMRect?} The rectangle. 406 */ 407 function getRectangleFromRange(range) { 408 // For uncollapsed ranges, get the rectangle that bounds the contents of the 409 // range; this a rectangle enclosing the union of the bounding rectangles 410 // for all the elements in the range. 411 if (!range.collapsed) { 412 const rects = Array.from(range.getClientRects()); 413 414 // If there's just a single rect, return it. 415 if (rects.length === 1) { 416 return rects[0]; 417 } 418 419 // Ignore tiny selection at the edge of a range. 420 const filteredRects = rects.filter(({ 421 width 422 }) => width > 1); 423 424 // If it's full of tiny selections, return browser default. 425 if (filteredRects.length === 0) { 426 return range.getBoundingClientRect(); 427 } 428 if (filteredRects.length === 1) { 429 return filteredRects[0]; 430 } 431 let { 432 top: furthestTop, 433 bottom: furthestBottom, 434 left: furthestLeft, 435 right: furthestRight 436 } = filteredRects[0]; 437 for (const { 438 top, 439 bottom, 440 left, 441 right 442 } of filteredRects) { 443 if (top < furthestTop) furthestTop = top; 444 if (bottom > furthestBottom) furthestBottom = bottom; 445 if (left < furthestLeft) furthestLeft = left; 446 if (right > furthestRight) furthestRight = right; 447 } 448 return new window.DOMRect(furthestLeft, furthestTop, furthestRight - furthestLeft, furthestBottom - furthestTop); 449 } 450 const { 451 startContainer 452 } = range; 453 const { 454 ownerDocument 455 } = startContainer; 456 457 // Correct invalid "BR" ranges. The cannot contain any children. 458 if (startContainer.nodeName === 'BR') { 459 const { 460 parentNode 461 } = startContainer; 462 assertIsDefined(parentNode, 'parentNode'); 463 const index = /** @type {Node[]} */Array.from(parentNode.childNodes).indexOf(startContainer); 464 assertIsDefined(ownerDocument, 'ownerDocument'); 465 range = ownerDocument.createRange(); 466 range.setStart(parentNode, index); 467 range.setEnd(parentNode, index); 468 } 469 const rects = range.getClientRects(); 470 471 // If we have multiple rectangles for a collapsed range, there's no way to 472 // know which it is, so don't return anything. 473 if (rects.length > 1) { 474 return null; 475 } 476 let rect = rects[0]; 477 478 // If the collapsed range starts (and therefore ends) at an element node, 479 // `getClientRects` can be empty in some browsers. This can be resolved 480 // by adding a temporary text node with zero-width space to the range. 481 // 482 // See: https://stackoverflow.com/a/6847328/995445 483 if (!rect || rect.height === 0) { 484 assertIsDefined(ownerDocument, 'ownerDocument'); 485 const padNode = ownerDocument.createTextNode('\u200b'); 486 // Do not modify the live range. 487 range = range.cloneRange(); 488 range.insertNode(padNode); 489 rect = range.getClientRects()[0]; 490 assertIsDefined(padNode.parentNode, 'padNode.parentNode'); 491 padNode.parentNode.removeChild(padNode); 492 } 493 return rect; 494 } 495 496 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/compute-caret-rect.js 497 /** 498 * Internal dependencies 499 */ 500 501 502 503 /** 504 * Get the rectangle for the selection in a container. 505 * 506 * @param {Window} win The window of the selection. 507 * 508 * @return {DOMRect | null} The rectangle. 509 */ 510 function computeCaretRect(win) { 511 const selection = win.getSelection(); 512 assertIsDefined(selection, 'selection'); 513 const range = selection.rangeCount ? selection.getRangeAt(0) : null; 514 if (!range) { 515 return null; 516 } 517 return getRectangleFromRange(range); 518 } 519 520 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-text-selection.js 521 /** 522 * Internal dependencies 523 */ 524 525 526 /** 527 * Check whether the current document has selected text. This applies to ranges 528 * of text in the document, and not selection inside `<input>` and `<textarea>` 529 * elements. 530 * 531 * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects. 532 * 533 * @param {Document} doc The document to check. 534 * 535 * @return {boolean} True if there is selection, false if not. 536 */ 537 function documentHasTextSelection(doc) { 538 assertIsDefined(doc.defaultView, 'doc.defaultView'); 539 const selection = doc.defaultView.getSelection(); 540 assertIsDefined(selection, 'selection'); 541 const range = selection.rangeCount ? selection.getRangeAt(0) : null; 542 return !!range && !range.collapsed; 543 } 544 545 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-html-input-element.js 546 /* eslint-disable jsdoc/valid-types */ 547 /** 548 * @param {Node} node 549 * @return {node is HTMLInputElement} Whether the node is an HTMLInputElement. 550 */ 551 function isHTMLInputElement(node) { 552 /* eslint-enable jsdoc/valid-types */ 553 return node?.nodeName === 'INPUT'; 554 } 555 556 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-text-field.js 557 /** 558 * Internal dependencies 559 */ 560 561 562 /* eslint-disable jsdoc/valid-types */ 563 /** 564 * Check whether the given element is a text field, where text field is defined 565 * by the ability to select within the input, or that it is contenteditable. 566 * 567 * See: https://html.spec.whatwg.org/#textFieldSelection 568 * 569 * @param {Node} node The HTML element. 570 * @return {node is HTMLElement} True if the element is an text field, false if not. 571 */ 572 function isTextField(node) { 573 /* eslint-enable jsdoc/valid-types */ 574 const nonTextInputs = ['button', 'checkbox', 'hidden', 'file', 'radio', 'image', 'range', 'reset', 'submit', 'number', 'email', 'time']; 575 return isHTMLInputElement(node) && node.type && !nonTextInputs.includes(node.type) || node.nodeName === 'TEXTAREA' || /** @type {HTMLElement} */node.contentEditable === 'true'; 576 } 577 578 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/input-field-has-uncollapsed-selection.js 579 /** 580 * Internal dependencies 581 */ 582 583 584 585 /** 586 * Check whether the given input field or textarea contains a (uncollapsed) 587 * selection of text. 588 * 589 * CAVEAT: Only specific text-based HTML inputs support the selection APIs 590 * needed to determine whether they have a collapsed or uncollapsed selection. 591 * This function defaults to returning `true` when the selection cannot be 592 * inspected, such as with `<input type="time">`. The rationale is that this 593 * should cause the block editor to defer to the browser's native selection 594 * handling (e.g. copying and pasting), thereby reducing friction for the user. 595 * 596 * See: https://html.spec.whatwg.org/multipage/input.html#do-not-apply 597 * 598 * @param {Element} element The HTML element. 599 * 600 * @return {boolean} Whether the input/textareaa element has some "selection". 601 */ 602 function inputFieldHasUncollapsedSelection(element) { 603 if (!isHTMLInputElement(element) && !isTextField(element)) { 604 return false; 605 } 606 607 // Safari throws a type error when trying to get `selectionStart` and 608 // `selectionEnd` on non-text <input> elements, so a try/catch construct is 609 // necessary. 610 try { 611 const { 612 selectionStart, 613 selectionEnd 614 } = /** @type {HTMLInputElement | HTMLTextAreaElement} */element; 615 return ( 616 // `null` means the input type doesn't implement selection, thus we 617 // cannot determine whether the selection is collapsed, so we 618 // default to true. 619 selectionStart === null || 620 // when not null, compare the two points 621 selectionStart !== selectionEnd 622 ); 623 } catch (error) { 624 // This is Safari's way of saying that the input type doesn't implement 625 // selection, so we default to true. 626 return true; 627 } 628 } 629 630 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-uncollapsed-selection.js 631 /** 632 * Internal dependencies 633 */ 634 635 636 637 /** 638 * Check whether the current document has any sort of (uncollapsed) selection. 639 * This includes ranges of text across elements and any selection inside 640 * textual `<input>` and `<textarea>` elements. 641 * 642 * @param {Document} doc The document to check. 643 * 644 * @return {boolean} Whether there is any recognizable text selection in the document. 645 */ 646 function documentHasUncollapsedSelection(doc) { 647 return documentHasTextSelection(doc) || !!doc.activeElement && inputFieldHasUncollapsedSelection(doc.activeElement); 648 } 649 650 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-selection.js 651 /** 652 * Internal dependencies 653 */ 654 655 656 657 658 /** 659 * Check whether the current document has a selection. This includes focus in 660 * input fields, textareas, and general rich-text selection. 661 * 662 * @param {Document} doc The document to check. 663 * 664 * @return {boolean} True if there is selection, false if not. 665 */ 666 function documentHasSelection(doc) { 667 return !!doc.activeElement && (isHTMLInputElement(doc.activeElement) || isTextField(doc.activeElement) || documentHasTextSelection(doc)); 668 } 669 670 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-computed-style.js 671 /** 672 * Internal dependencies 673 */ 674 675 676 /* eslint-disable jsdoc/valid-types */ 677 /** 678 * @param {Element} element 679 * @return {ReturnType<Window['getComputedStyle']>} The computed style for the element. 680 */ 681 function getComputedStyle(element) { 682 /* eslint-enable jsdoc/valid-types */ 683 assertIsDefined(element.ownerDocument.defaultView, 'element.ownerDocument.defaultView'); 684 return element.ownerDocument.defaultView.getComputedStyle(element); 685 } 686 687 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-scroll-container.js 688 /** 689 * Internal dependencies 690 */ 691 692 693 /** 694 * Given a DOM node, finds the closest scrollable container node or the node 695 * itself, if scrollable. 696 * 697 * @param {Element | null} node Node from which to start. 698 * @param {?string} direction Direction of scrollable container to search for ('vertical', 'horizontal', 'all'). 699 * Defaults to 'vertical'. 700 * @return {Element | undefined} Scrollable container node, if found. 701 */ 702 function getScrollContainer(node, direction = 'vertical') { 703 if (!node) { 704 return undefined; 705 } 706 if (direction === 'vertical' || direction === 'all') { 707 // Scrollable if scrollable height exceeds displayed... 708 if (node.scrollHeight > node.clientHeight) { 709 // ...except when overflow is defined to be hidden or visible 710 const { 711 overflowY 712 } = getComputedStyle(node); 713 if (/(auto|scroll)/.test(overflowY)) { 714 return node; 715 } 716 } 717 } 718 if (direction === 'horizontal' || direction === 'all') { 719 // Scrollable if scrollable width exceeds displayed... 720 if (node.scrollWidth > node.clientWidth) { 721 // ...except when overflow is defined to be hidden or visible 722 const { 723 overflowX 724 } = getComputedStyle(node); 725 if (/(auto|scroll)/.test(overflowX)) { 726 return node; 727 } 728 } 729 } 730 if (node.ownerDocument === node.parentNode) { 731 return node; 732 } 733 734 // Continue traversing. 735 return getScrollContainer( /** @type {Element} */node.parentNode, direction); 736 } 737 738 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-offset-parent.js 739 /** 740 * Internal dependencies 741 */ 742 743 744 /** 745 * Returns the closest positioned element, or null under any of the conditions 746 * of the offsetParent specification. Unlike offsetParent, this function is not 747 * limited to HTMLElement and accepts any Node (e.g. Node.TEXT_NODE). 748 * 749 * @see https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent 750 * 751 * @param {Node} node Node from which to find offset parent. 752 * 753 * @return {Node | null} Offset parent. 754 */ 755 function getOffsetParent(node) { 756 // Cannot retrieve computed style or offset parent only anything other than 757 // an element node, so find the closest element node. 758 let closestElement; 759 while (closestElement = /** @type {Node} */node.parentNode) { 760 if (closestElement.nodeType === closestElement.ELEMENT_NODE) { 761 break; 762 } 763 } 764 if (!closestElement) { 765 return null; 766 } 767 768 // If the closest element is already positioned, return it, as offsetParent 769 // does not otherwise consider the node itself. 770 if (getComputedStyle( /** @type {Element} */closestElement).position !== 'static') { 771 return closestElement; 772 } 773 774 // offsetParent is undocumented/draft. 775 return /** @type {Node & { offsetParent: Node }} */closestElement.offsetParent; 776 } 777 778 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-input-or-text-area.js 779 /* eslint-disable jsdoc/valid-types */ 780 /** 781 * @param {Element} element 782 * @return {element is HTMLInputElement | HTMLTextAreaElement} Whether the element is an input or textarea 783 */ 784 function isInputOrTextArea(element) { 785 /* eslint-enable jsdoc/valid-types */ 786 return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA'; 787 } 788 789 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-entirely-selected.js 790 /** 791 * Internal dependencies 792 */ 793 794 795 796 /** 797 * Check whether the contents of the element have been entirely selected. 798 * Returns true if there is no possibility of selection. 799 * 800 * @param {HTMLElement} element The element to check. 801 * 802 * @return {boolean} True if entirely selected, false if not. 803 */ 804 function isEntirelySelected(element) { 805 if (isInputOrTextArea(element)) { 806 return element.selectionStart === 0 && element.value.length === element.selectionEnd; 807 } 808 if (!element.isContentEditable) { 809 return true; 810 } 811 const { 812 ownerDocument 813 } = element; 814 const { 815 defaultView 816 } = ownerDocument; 817 assertIsDefined(defaultView, 'defaultView'); 818 const selection = defaultView.getSelection(); 819 assertIsDefined(selection, 'selection'); 820 const range = selection.rangeCount ? selection.getRangeAt(0) : null; 821 if (!range) { 822 return true; 823 } 824 const { 825 startContainer, 826 endContainer, 827 startOffset, 828 endOffset 829 } = range; 830 if (startContainer === element && endContainer === element && startOffset === 0 && endOffset === element.childNodes.length) { 831 return true; 832 } 833 const lastChild = element.lastChild; 834 assertIsDefined(lastChild, 'lastChild'); 835 const endContainerContentLength = endContainer.nodeType === endContainer.TEXT_NODE ? /** @type {Text} */endContainer.data.length : endContainer.childNodes.length; 836 return isDeepChild(startContainer, element, 'firstChild') && isDeepChild(endContainer, element, 'lastChild') && startOffset === 0 && endOffset === endContainerContentLength; 837 } 838 839 /** 840 * Check whether the contents of the element have been entirely selected. 841 * Returns true if there is no possibility of selection. 842 * 843 * @param {HTMLElement|Node} query The element to check. 844 * @param {HTMLElement} container The container that we suspect "query" may be a first or last child of. 845 * @param {"firstChild"|"lastChild"} propName "firstChild" or "lastChild" 846 * 847 * @return {boolean} True if query is a deep first/last child of container, false otherwise. 848 */ 849 function isDeepChild(query, container, propName) { 850 /** @type {HTMLElement | ChildNode | null} */ 851 let candidate = container; 852 do { 853 if (query === candidate) { 854 return true; 855 } 856 candidate = candidate[propName]; 857 } while (candidate); 858 return false; 859 } 860 861 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-form-element.js 862 /** 863 * Internal dependencies 864 */ 865 866 867 /** 868 * 869 * Detects if element is a form element. 870 * 871 * @param {Element} element The element to check. 872 * 873 * @return {boolean} True if form element and false otherwise. 874 */ 875 function isFormElement(element) { 876 if (!element) { 877 return false; 878 } 879 const { 880 tagName 881 } = element; 882 const checkForInputTextarea = isInputOrTextArea(element); 883 return checkForInputTextarea || tagName === 'BUTTON' || tagName === 'SELECT'; 884 } 885 886 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-rtl.js 887 /** 888 * Internal dependencies 889 */ 890 891 892 /** 893 * Whether the element's text direction is right-to-left. 894 * 895 * @param {Element} element The element to check. 896 * 897 * @return {boolean} True if rtl, false if ltr. 898 */ 899 function isRTL(element) { 900 return getComputedStyle(element).direction === 'rtl'; 901 } 902 903 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-range-height.js 904 /** 905 * Gets the height of the range without ignoring zero width rectangles, which 906 * some browsers ignore when creating a union. 907 * 908 * @param {Range} range The range to check. 909 * @return {number | undefined} Height of the range or undefined if the range has no client rectangles. 910 */ 911 function getRangeHeight(range) { 912 const rects = Array.from(range.getClientRects()); 913 if (!rects.length) { 914 return; 915 } 916 const highestTop = Math.min(...rects.map(({ 917 top 918 }) => top)); 919 const lowestBottom = Math.max(...rects.map(({ 920 bottom 921 }) => bottom)); 922 return lowestBottom - highestTop; 923 } 924 925 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-selection-forward.js 926 /** 927 * Internal dependencies 928 */ 929 930 931 /** 932 * Returns true if the given selection object is in the forward direction, or 933 * false otherwise. 934 * 935 * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition 936 * 937 * @param {Selection} selection Selection object to check. 938 * 939 * @return {boolean} Whether the selection is forward. 940 */ 941 function isSelectionForward(selection) { 942 const { 943 anchorNode, 944 focusNode, 945 anchorOffset, 946 focusOffset 947 } = selection; 948 assertIsDefined(anchorNode, 'anchorNode'); 949 assertIsDefined(focusNode, 'focusNode'); 950 const position = anchorNode.compareDocumentPosition(focusNode); 951 952 // Disable reason: `Node#compareDocumentPosition` returns a bitmask value, 953 // so bitwise operators are intended. 954 /* eslint-disable no-bitwise */ 955 // Compare whether anchor node precedes focus node. If focus node (where 956 // end of selection occurs) is after the anchor node, it is forward. 957 if (position & anchorNode.DOCUMENT_POSITION_PRECEDING) { 958 return false; 959 } 960 if (position & anchorNode.DOCUMENT_POSITION_FOLLOWING) { 961 return true; 962 } 963 /* eslint-enable no-bitwise */ 964 965 // `compareDocumentPosition` returns 0 when passed the same node, in which 966 // case compare offsets. 967 if (position === 0) { 968 return anchorOffset <= focusOffset; 969 } 970 971 // This should never be reached, but return true as default case. 972 return true; 973 } 974 975 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/caret-range-from-point.js 976 /** 977 * Polyfill. 978 * Get a collapsed range for a given point. 979 * 980 * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint 981 * 982 * @param {DocumentMaybeWithCaretPositionFromPoint} doc The document of the range. 983 * @param {number} x Horizontal position within the current viewport. 984 * @param {number} y Vertical position within the current viewport. 985 * 986 * @return {Range | null} The best range for the given point. 987 */ 988 function caretRangeFromPoint(doc, x, y) { 989 if (doc.caretRangeFromPoint) { 990 return doc.caretRangeFromPoint(x, y); 991 } 992 if (!doc.caretPositionFromPoint) { 993 return null; 994 } 995 const point = doc.caretPositionFromPoint(x, y); 996 997 // If x or y are negative, outside viewport, or there is no text entry node. 998 // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint 999 if (!point) { 1000 return null; 1001 } 1002 const range = doc.createRange(); 1003 range.setStart(point.offsetNode, point.offset); 1004 range.collapse(true); 1005 return range; 1006 } 1007 1008 /** 1009 * @typedef {{caretPositionFromPoint?: (x: number, y: number)=> CaretPosition | null} & Document } DocumentMaybeWithCaretPositionFromPoint 1010 * @typedef {{ readonly offset: number; readonly offsetNode: Node; getClientRect(): DOMRect | null; }} CaretPosition 1011 */ 1012 1013 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/hidden-caret-range-from-point.js 1014 /** 1015 * Internal dependencies 1016 */ 1017 1018 1019 1020 /** 1021 * Get a collapsed range for a given point. 1022 * Gives the container a temporary high z-index (above any UI). 1023 * This is preferred over getting the UI nodes and set styles there. 1024 * 1025 * @param {Document} doc The document of the range. 1026 * @param {number} x Horizontal position within the current viewport. 1027 * @param {number} y Vertical position within the current viewport. 1028 * @param {HTMLElement} container Container in which the range is expected to be found. 1029 * 1030 * @return {?Range} The best range for the given point. 1031 */ 1032 function hiddenCaretRangeFromPoint(doc, x, y, container) { 1033 const originalZIndex = container.style.zIndex; 1034 const originalPosition = container.style.position; 1035 const { 1036 position = 'static' 1037 } = getComputedStyle(container); 1038 1039 // A z-index only works if the element position is not static. 1040 if (position === 'static') { 1041 container.style.position = 'relative'; 1042 } 1043 container.style.zIndex = '10000'; 1044 const range = caretRangeFromPoint(doc, x, y); 1045 container.style.zIndex = originalZIndex; 1046 container.style.position = originalPosition; 1047 return range; 1048 } 1049 1050 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/scroll-if-no-range.js 1051 /** 1052 * If no range range can be created or it is outside the container, the element 1053 * may be out of view, so scroll it into view and try again. 1054 * 1055 * @param {HTMLElement} container The container to scroll. 1056 * @param {boolean} alignToTop True to align to top, false to bottom. 1057 * @param {Function} callback The callback to create the range. 1058 * 1059 * @return {?Range} The range returned by the callback. 1060 */ 1061 function scrollIfNoRange(container, alignToTop, callback) { 1062 let range = callback(); 1063 1064 // If no range range can be created or it is outside the container, the 1065 // element may be out of view. 1066 if (!range || !range.startContainer || !container.contains(range.startContainer)) { 1067 container.scrollIntoView(alignToTop); 1068 range = callback(); 1069 if (!range || !range.startContainer || !container.contains(range.startContainer)) { 1070 return null; 1071 } 1072 } 1073 return range; 1074 } 1075 1076 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-edge.js 1077 /** 1078 * Internal dependencies 1079 */ 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 /** 1090 * Check whether the selection is at the edge of the container. Checks for 1091 * horizontal position by default. Set `onlyVertical` to true to check only 1092 * vertically. 1093 * 1094 * @param {HTMLElement} container Focusable element. 1095 * @param {boolean} isReverse Set to true to check left, false to check right. 1096 * @param {boolean} [onlyVertical=false] Set to true to check only vertical position. 1097 * 1098 * @return {boolean} True if at the edge, false if not. 1099 */ 1100 function isEdge(container, isReverse, onlyVertical = false) { 1101 if (isInputOrTextArea(container) && typeof container.selectionStart === 'number') { 1102 if (container.selectionStart !== container.selectionEnd) { 1103 return false; 1104 } 1105 if (isReverse) { 1106 return container.selectionStart === 0; 1107 } 1108 return container.value.length === container.selectionStart; 1109 } 1110 if (!( /** @type {HTMLElement} */container.isContentEditable)) { 1111 return true; 1112 } 1113 const { 1114 ownerDocument 1115 } = container; 1116 const { 1117 defaultView 1118 } = ownerDocument; 1119 assertIsDefined(defaultView, 'defaultView'); 1120 const selection = defaultView.getSelection(); 1121 if (!selection || !selection.rangeCount) { 1122 return false; 1123 } 1124 const range = selection.getRangeAt(0); 1125 const collapsedRange = range.cloneRange(); 1126 const isForward = isSelectionForward(selection); 1127 const isCollapsed = selection.isCollapsed; 1128 1129 // Collapse in direction of selection. 1130 if (!isCollapsed) { 1131 collapsedRange.collapse(!isForward); 1132 } 1133 const collapsedRangeRect = getRectangleFromRange(collapsedRange); 1134 const rangeRect = getRectangleFromRange(range); 1135 if (!collapsedRangeRect || !rangeRect) { 1136 return false; 1137 } 1138 1139 // Only consider the multiline selection at the edge if the direction is 1140 // towards the edge. The selection is multiline if it is taller than the 1141 // collapsed selection. 1142 const rangeHeight = getRangeHeight(range); 1143 if (!isCollapsed && rangeHeight && rangeHeight > collapsedRangeRect.height && isForward === isReverse) { 1144 return false; 1145 } 1146 1147 // In the case of RTL scripts, the horizontal edge is at the opposite side. 1148 const isReverseDir = isRTL(container) ? !isReverse : isReverse; 1149 const containerRect = container.getBoundingClientRect(); 1150 1151 // To check if a selection is at the edge, we insert a test selection at the 1152 // edge of the container and check if the selections have the same vertical 1153 // or horizontal position. If they do, the selection is at the edge. 1154 // This method proves to be better than a DOM-based calculation for the 1155 // horizontal edge, since it ignores empty textnodes and a trailing line 1156 // break element. In other words, we need to check visual positioning, not 1157 // DOM positioning. 1158 // It also proves better than using the computed style for the vertical 1159 // edge, because we cannot know the padding and line height reliably in 1160 // pixels. `getComputedStyle` may return a value with different units. 1161 const x = isReverseDir ? containerRect.left + 1 : containerRect.right - 1; 1162 const y = isReverse ? containerRect.top + 1 : containerRect.bottom - 1; 1163 const testRange = scrollIfNoRange(container, isReverse, () => hiddenCaretRangeFromPoint(ownerDocument, x, y, container)); 1164 if (!testRange) { 1165 return false; 1166 } 1167 const testRect = getRectangleFromRange(testRange); 1168 if (!testRect) { 1169 return false; 1170 } 1171 const verticalSide = isReverse ? 'top' : 'bottom'; 1172 const horizontalSide = isReverseDir ? 'left' : 'right'; 1173 const verticalDiff = testRect[verticalSide] - rangeRect[verticalSide]; 1174 const horizontalDiff = testRect[horizontalSide] - collapsedRangeRect[horizontalSide]; 1175 1176 // Allow the position to be 1px off. 1177 const hasVerticalDiff = Math.abs(verticalDiff) <= 1; 1178 const hasHorizontalDiff = Math.abs(horizontalDiff) <= 1; 1179 return onlyVertical ? hasVerticalDiff : hasVerticalDiff && hasHorizontalDiff; 1180 } 1181 1182 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-horizontal-edge.js 1183 /** 1184 * Internal dependencies 1185 */ 1186 1187 1188 /** 1189 * Check whether the selection is horizontally at the edge of the container. 1190 * 1191 * @param {HTMLElement} container Focusable element. 1192 * @param {boolean} isReverse Set to true to check left, false for right. 1193 * 1194 * @return {boolean} True if at the horizontal edge, false if not. 1195 */ 1196 function isHorizontalEdge(container, isReverse) { 1197 return isEdge(container, isReverse); 1198 } 1199 1200 ;// CONCATENATED MODULE: external ["wp","deprecated"] 1201 const external_wp_deprecated_namespaceObject = window["wp"]["deprecated"]; 1202 var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject); 1203 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-number-input.js 1204 /** 1205 * WordPress dependencies 1206 */ 1207 1208 1209 /** 1210 * Internal dependencies 1211 */ 1212 1213 1214 /* eslint-disable jsdoc/valid-types */ 1215 /** 1216 * Check whether the given element is an input field of type number. 1217 * 1218 * @param {Node} node The HTML node. 1219 * 1220 * @return {node is HTMLInputElement} True if the node is number input. 1221 */ 1222 function isNumberInput(node) { 1223 external_wp_deprecated_default()('wp.dom.isNumberInput', { 1224 since: '6.1', 1225 version: '6.5' 1226 }); 1227 /* eslint-enable jsdoc/valid-types */ 1228 return isHTMLInputElement(node) && node.type === 'number' && !isNaN(node.valueAsNumber); 1229 } 1230 1231 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-vertical-edge.js 1232 /** 1233 * Internal dependencies 1234 */ 1235 1236 1237 /** 1238 * Check whether the selection is vertically at the edge of the container. 1239 * 1240 * @param {HTMLElement} container Focusable element. 1241 * @param {boolean} isReverse Set to true to check top, false for bottom. 1242 * 1243 * @return {boolean} True if at the vertical edge, false if not. 1244 */ 1245 function isVerticalEdge(container, isReverse) { 1246 return isEdge(container, isReverse, true); 1247 } 1248 1249 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-edge.js 1250 /** 1251 * Internal dependencies 1252 */ 1253 1254 1255 1256 1257 1258 1259 /** 1260 * Gets the range to place. 1261 * 1262 * @param {HTMLElement} container Focusable element. 1263 * @param {boolean} isReverse True for end, false for start. 1264 * @param {number|undefined} x X coordinate to vertically position. 1265 * 1266 * @return {Range|null} The range to place. 1267 */ 1268 function getRange(container, isReverse, x) { 1269 const { 1270 ownerDocument 1271 } = container; 1272 // In the case of RTL scripts, the horizontal edge is at the opposite side. 1273 const isReverseDir = isRTL(container) ? !isReverse : isReverse; 1274 const containerRect = container.getBoundingClientRect(); 1275 // When placing at the end (isReverse), find the closest range to the bottom 1276 // right corner. When placing at the start, to the top left corner. 1277 // Ensure x is defined and within the container's boundaries. When it's 1278 // exactly at the boundary, it's not considered within the boundaries. 1279 if (x === undefined) { 1280 x = isReverse ? containerRect.right - 1 : containerRect.left + 1; 1281 } else if (x <= containerRect.left) { 1282 x = containerRect.left + 1; 1283 } else if (x >= containerRect.right) { 1284 x = containerRect.right - 1; 1285 } 1286 const y = isReverseDir ? containerRect.bottom - 1 : containerRect.top + 1; 1287 return hiddenCaretRangeFromPoint(ownerDocument, x, y, container); 1288 } 1289 1290 /** 1291 * Places the caret at start or end of a given element. 1292 * 1293 * @param {HTMLElement} container Focusable element. 1294 * @param {boolean} isReverse True for end, false for start. 1295 * @param {number|undefined} x X coordinate to vertically position. 1296 */ 1297 function placeCaretAtEdge(container, isReverse, x) { 1298 if (!container) { 1299 return; 1300 } 1301 container.focus(); 1302 if (isInputOrTextArea(container)) { 1303 // The element may not support selection setting. 1304 if (typeof container.selectionStart !== 'number') { 1305 return; 1306 } 1307 if (isReverse) { 1308 container.selectionStart = container.value.length; 1309 container.selectionEnd = container.value.length; 1310 } else { 1311 container.selectionStart = 0; 1312 container.selectionEnd = 0; 1313 } 1314 return; 1315 } 1316 if (!container.isContentEditable) { 1317 return; 1318 } 1319 const range = scrollIfNoRange(container, isReverse, () => getRange(container, isReverse, x)); 1320 if (!range) return; 1321 const { 1322 ownerDocument 1323 } = container; 1324 const { 1325 defaultView 1326 } = ownerDocument; 1327 assertIsDefined(defaultView, 'defaultView'); 1328 const selection = defaultView.getSelection(); 1329 assertIsDefined(selection, 'selection'); 1330 selection.removeAllRanges(); 1331 selection.addRange(range); 1332 } 1333 1334 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-horizontal-edge.js 1335 /** 1336 * Internal dependencies 1337 */ 1338 1339 1340 /** 1341 * Places the caret at start or end of a given element. 1342 * 1343 * @param {HTMLElement} container Focusable element. 1344 * @param {boolean} isReverse True for end, false for start. 1345 */ 1346 function placeCaretAtHorizontalEdge(container, isReverse) { 1347 return placeCaretAtEdge(container, isReverse, undefined); 1348 } 1349 1350 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-vertical-edge.js 1351 /** 1352 * Internal dependencies 1353 */ 1354 1355 1356 /** 1357 * Places the caret at the top or bottom of a given element. 1358 * 1359 * @param {HTMLElement} container Focusable element. 1360 * @param {boolean} isReverse True for bottom, false for top. 1361 * @param {DOMRect} [rect] The rectangle to position the caret with. 1362 */ 1363 function placeCaretAtVerticalEdge(container, isReverse, rect) { 1364 return placeCaretAtEdge(container, isReverse, rect?.left); 1365 } 1366 1367 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/insert-after.js 1368 /** 1369 * Internal dependencies 1370 */ 1371 1372 1373 /** 1374 * Given two DOM nodes, inserts the former in the DOM as the next sibling of 1375 * the latter. 1376 * 1377 * @param {Node} newNode Node to be inserted. 1378 * @param {Node} referenceNode Node after which to perform the insertion. 1379 * @return {void} 1380 */ 1381 function insertAfter(newNode, referenceNode) { 1382 assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode'); 1383 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); 1384 } 1385 1386 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove.js 1387 /** 1388 * Internal dependencies 1389 */ 1390 1391 1392 /** 1393 * Given a DOM node, removes it from the DOM. 1394 * 1395 * @param {Node} node Node to be removed. 1396 * @return {void} 1397 */ 1398 function remove(node) { 1399 assertIsDefined(node.parentNode, 'node.parentNode'); 1400 node.parentNode.removeChild(node); 1401 } 1402 1403 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace.js 1404 /** 1405 * Internal dependencies 1406 */ 1407 1408 1409 1410 1411 /** 1412 * Given two DOM nodes, replaces the former with the latter in the DOM. 1413 * 1414 * @param {Element} processedNode Node to be removed. 1415 * @param {Element} newNode Node to be inserted in its place. 1416 * @return {void} 1417 */ 1418 function replace(processedNode, newNode) { 1419 assertIsDefined(processedNode.parentNode, 'processedNode.parentNode'); 1420 insertAfter(newNode, processedNode.parentNode); 1421 remove(processedNode); 1422 } 1423 1424 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/unwrap.js 1425 /** 1426 * Internal dependencies 1427 */ 1428 1429 1430 /** 1431 * Unwrap the given node. This means any child nodes are moved to the parent. 1432 * 1433 * @param {Node} node The node to unwrap. 1434 * 1435 * @return {void} 1436 */ 1437 function unwrap(node) { 1438 const parent = node.parentNode; 1439 assertIsDefined(parent, 'node.parentNode'); 1440 while (node.firstChild) { 1441 parent.insertBefore(node.firstChild, node); 1442 } 1443 parent.removeChild(node); 1444 } 1445 1446 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace-tag.js 1447 /** 1448 * Internal dependencies 1449 */ 1450 1451 1452 /** 1453 * Replaces the given node with a new node with the given tag name. 1454 * 1455 * @param {Element} node The node to replace 1456 * @param {string} tagName The new tag name. 1457 * 1458 * @return {Element} The new node. 1459 */ 1460 function replaceTag(node, tagName) { 1461 const newNode = node.ownerDocument.createElement(tagName); 1462 while (node.firstChild) { 1463 newNode.appendChild(node.firstChild); 1464 } 1465 assertIsDefined(node.parentNode, 'node.parentNode'); 1466 node.parentNode.replaceChild(newNode, node); 1467 return newNode; 1468 } 1469 1470 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/wrap.js 1471 /** 1472 * Internal dependencies 1473 */ 1474 1475 1476 /** 1477 * Wraps the given node with a new node with the given tag name. 1478 * 1479 * @param {Element} newNode The node to insert. 1480 * @param {Element} referenceNode The node to wrap. 1481 */ 1482 function wrap(newNode, referenceNode) { 1483 assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode'); 1484 referenceNode.parentNode.insertBefore(newNode, referenceNode); 1485 newNode.appendChild(referenceNode); 1486 } 1487 1488 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/safe-html.js 1489 /** 1490 * Internal dependencies 1491 */ 1492 1493 1494 /** 1495 * Strips scripts and on* attributes from HTML. 1496 * 1497 * @param {string} html HTML to sanitize. 1498 * 1499 * @return {string} The sanitized HTML. 1500 */ 1501 function safeHTML(html) { 1502 const { 1503 body 1504 } = document.implementation.createHTMLDocument(''); 1505 body.innerHTML = html; 1506 const elements = body.getElementsByTagName('*'); 1507 let elementIndex = elements.length; 1508 while (elementIndex--) { 1509 const element = elements[elementIndex]; 1510 if (element.tagName === 'SCRIPT') { 1511 remove(element); 1512 } else { 1513 let attributeIndex = element.attributes.length; 1514 while (attributeIndex--) { 1515 const { 1516 name: key 1517 } = element.attributes[attributeIndex]; 1518 if (key.startsWith('on')) { 1519 element.removeAttribute(key); 1520 } 1521 } 1522 } 1523 } 1524 return body.innerHTML; 1525 } 1526 1527 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/strip-html.js 1528 /** 1529 * Internal dependencies 1530 */ 1531 1532 1533 /** 1534 * Removes any HTML tags from the provided string. 1535 * 1536 * @param {string} html The string containing html. 1537 * 1538 * @return {string} The text content with any html removed. 1539 */ 1540 function stripHTML(html) { 1541 // Remove any script tags or on* attributes otherwise their *contents* will be left 1542 // in place following removal of HTML tags. 1543 html = safeHTML(html); 1544 const doc = document.implementation.createHTMLDocument(''); 1545 doc.body.innerHTML = html; 1546 return doc.body.textContent || ''; 1547 } 1548 1549 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-empty.js 1550 /** 1551 * Recursively checks if an element is empty. An element is not empty if it 1552 * contains text or contains elements with attributes such as images. 1553 * 1554 * @param {Element} element The element to check. 1555 * 1556 * @return {boolean} Whether or not the element is empty. 1557 */ 1558 function isEmpty(element) { 1559 switch (element.nodeType) { 1560 case element.TEXT_NODE: 1561 // We cannot use \s since it includes special spaces which we want 1562 // to preserve. 1563 return /^[ \f\n\r\t\v\u00a0]*$/.test(element.nodeValue || ''); 1564 case element.ELEMENT_NODE: 1565 if (element.hasAttributes()) { 1566 return false; 1567 } else if (!element.hasChildNodes()) { 1568 return true; 1569 } 1570 return /** @type {Element[]} */Array.from(element.childNodes).every(isEmpty); 1571 default: 1572 return true; 1573 } 1574 } 1575 1576 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/phrasing-content.js 1577 /** 1578 * All phrasing content elements. 1579 * 1580 * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0 1581 */ 1582 1583 /** 1584 * @typedef {Record<string,SemanticElementDefinition>} ContentSchema 1585 */ 1586 1587 /** 1588 * @typedef SemanticElementDefinition 1589 * @property {string[]} [attributes] Content attributes 1590 * @property {ContentSchema} [children] Content attributes 1591 */ 1592 1593 /** 1594 * All text-level semantic elements. 1595 * 1596 * @see https://html.spec.whatwg.org/multipage/text-level-semantics.html 1597 * 1598 * @type {ContentSchema} 1599 */ 1600 const textContentSchema = { 1601 strong: {}, 1602 em: {}, 1603 s: {}, 1604 del: {}, 1605 ins: {}, 1606 a: { 1607 attributes: ['href', 'target', 'rel', 'id'] 1608 }, 1609 code: {}, 1610 abbr: { 1611 attributes: ['title'] 1612 }, 1613 sub: {}, 1614 sup: {}, 1615 br: {}, 1616 small: {}, 1617 // To do: fix blockquote. 1618 // cite: {}, 1619 q: { 1620 attributes: ['cite'] 1621 }, 1622 dfn: { 1623 attributes: ['title'] 1624 }, 1625 data: { 1626 attributes: ['value'] 1627 }, 1628 time: { 1629 attributes: ['datetime'] 1630 }, 1631 var: {}, 1632 samp: {}, 1633 kbd: {}, 1634 i: {}, 1635 b: {}, 1636 u: {}, 1637 mark: {}, 1638 ruby: {}, 1639 rt: {}, 1640 rp: {}, 1641 bdi: { 1642 attributes: ['dir'] 1643 }, 1644 bdo: { 1645 attributes: ['dir'] 1646 }, 1647 wbr: {}, 1648 '#text': {} 1649 }; 1650 1651 // Recursion is needed. 1652 // Possible: strong > em > strong. 1653 // Impossible: strong > strong. 1654 const excludedElements = ['#text', 'br']; 1655 Object.keys(textContentSchema).filter(element => !excludedElements.includes(element)).forEach(tag => { 1656 const { 1657 [tag]: removedTag, 1658 ...restSchema 1659 } = textContentSchema; 1660 textContentSchema[tag].children = restSchema; 1661 }); 1662 1663 /** 1664 * Embedded content elements. 1665 * 1666 * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#embedded-content-0 1667 * 1668 * @type {ContentSchema} 1669 */ 1670 const embeddedContentSchema = { 1671 audio: { 1672 attributes: ['src', 'preload', 'autoplay', 'mediagroup', 'loop', 'muted'] 1673 }, 1674 canvas: { 1675 attributes: ['width', 'height'] 1676 }, 1677 embed: { 1678 attributes: ['src', 'type', 'width', 'height'] 1679 }, 1680 img: { 1681 attributes: ['alt', 'src', 'srcset', 'usemap', 'ismap', 'width', 'height'] 1682 }, 1683 object: { 1684 attributes: ['data', 'type', 'name', 'usemap', 'form', 'width', 'height'] 1685 }, 1686 video: { 1687 attributes: ['src', 'poster', 'preload', 'playsinline', 'autoplay', 'mediagroup', 'loop', 'muted', 'controls', 'width', 'height'] 1688 } 1689 }; 1690 1691 /** 1692 * Phrasing content elements. 1693 * 1694 * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0 1695 */ 1696 const phrasingContentSchema = { 1697 ...textContentSchema, 1698 ...embeddedContentSchema 1699 }; 1700 1701 /** 1702 * Get schema of possible paths for phrasing content. 1703 * 1704 * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content 1705 * 1706 * @param {string} [context] Set to "paste" to exclude invisible elements and 1707 * sensitive data. 1708 * 1709 * @return {Partial<ContentSchema>} Schema. 1710 */ 1711 function getPhrasingContentSchema(context) { 1712 if (context !== 'paste') { 1713 return phrasingContentSchema; 1714 } 1715 1716 /** 1717 * @type {Partial<ContentSchema>} 1718 */ 1719 const { 1720 u, 1721 // Used to mark misspelling. Shouldn't be pasted. 1722 abbr, 1723 // Invisible. 1724 data, 1725 // Invisible. 1726 time, 1727 // Invisible. 1728 wbr, 1729 // Invisible. 1730 bdi, 1731 // Invisible. 1732 bdo, 1733 // Invisible. 1734 ...remainingContentSchema 1735 } = { 1736 ...phrasingContentSchema, 1737 // We shouldn't paste potentially sensitive information which is not 1738 // visible to the user when pasted, so strip the attributes. 1739 ins: { 1740 children: phrasingContentSchema.ins.children 1741 }, 1742 del: { 1743 children: phrasingContentSchema.del.children 1744 } 1745 }; 1746 return remainingContentSchema; 1747 } 1748 1749 /** 1750 * Find out whether or not the given node is phrasing content. 1751 * 1752 * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content 1753 * 1754 * @param {Node} node The node to test. 1755 * 1756 * @return {boolean} True if phrasing content, false if not. 1757 */ 1758 function isPhrasingContent(node) { 1759 const tag = node.nodeName.toLowerCase(); 1760 return getPhrasingContentSchema().hasOwnProperty(tag) || tag === 'span'; 1761 } 1762 1763 /** 1764 * @param {Node} node 1765 * @return {boolean} Node is text content 1766 */ 1767 function isTextContent(node) { 1768 const tag = node.nodeName.toLowerCase(); 1769 return textContentSchema.hasOwnProperty(tag) || tag === 'span'; 1770 } 1771 1772 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-element.js 1773 /* eslint-disable jsdoc/valid-types */ 1774 /** 1775 * @param {Node | null | undefined} node 1776 * @return {node is Element} True if node is an Element node 1777 */ 1778 function isElement(node) { 1779 /* eslint-enable jsdoc/valid-types */ 1780 return !!node && node.nodeType === node.ELEMENT_NODE; 1781 } 1782 1783 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/clean-node-list.js 1784 /** 1785 * Internal dependencies 1786 */ 1787 1788 1789 1790 1791 1792 1793 const noop = () => {}; 1794 1795 /* eslint-disable jsdoc/valid-types */ 1796 /** 1797 * @typedef SchemaItem 1798 * @property {string[]} [attributes] Attributes. 1799 * @property {(string | RegExp)[]} [classes] Classnames or RegExp to test against. 1800 * @property {'*' | { [tag: string]: SchemaItem }} [children] Child schemas. 1801 * @property {string[]} [require] Selectors to test required children against. Leave empty or undefined if there are no requirements. 1802 * @property {boolean} allowEmpty Whether to allow nodes without children. 1803 * @property {(node: Node) => boolean} [isMatch] Function to test whether a node is a match. If left undefined any node will be assumed to match. 1804 */ 1805 1806 /** @typedef {{ [tag: string]: SchemaItem }} Schema */ 1807 /* eslint-enable jsdoc/valid-types */ 1808 1809 /** 1810 * Given a schema, unwraps or removes nodes, attributes and classes on a node 1811 * list. 1812 * 1813 * @param {NodeList} nodeList The nodeList to filter. 1814 * @param {Document} doc The document of the nodeList. 1815 * @param {Schema} schema An array of functions that can mutate with the provided node. 1816 * @param {boolean} inline Whether to clean for inline mode. 1817 */ 1818 function cleanNodeList(nodeList, doc, schema, inline) { 1819 Array.from(nodeList).forEach(( /** @type {Node & { nextElementSibling?: unknown }} */node) => { 1820 const tag = node.nodeName.toLowerCase(); 1821 1822 // It's a valid child, if the tag exists in the schema without an isMatch 1823 // function, or with an isMatch function that matches the node. 1824 if (schema.hasOwnProperty(tag) && (!schema[tag].isMatch || schema[tag].isMatch?.(node))) { 1825 if (isElement(node)) { 1826 const { 1827 attributes = [], 1828 classes = [], 1829 children, 1830 require = [], 1831 allowEmpty 1832 } = schema[tag]; 1833 1834 // If the node is empty and it's supposed to have children, 1835 // remove the node. 1836 if (children && !allowEmpty && isEmpty(node)) { 1837 remove(node); 1838 return; 1839 } 1840 if (node.hasAttributes()) { 1841 // Strip invalid attributes. 1842 Array.from(node.attributes).forEach(({ 1843 name 1844 }) => { 1845 if (name !== 'class' && !attributes.includes(name)) { 1846 node.removeAttribute(name); 1847 } 1848 }); 1849 1850 // Strip invalid classes. 1851 // In jsdom-jscore, 'node.classList' can be undefined. 1852 // TODO: Explore patching this in jsdom-jscore. 1853 if (node.classList && node.classList.length) { 1854 const mattchers = classes.map(item => { 1855 if (typeof item === 'string') { 1856 return ( /** @type {string} */className) => className === item; 1857 } else if (item instanceof RegExp) { 1858 return ( /** @type {string} */className) => item.test(className); 1859 } 1860 return noop; 1861 }); 1862 Array.from(node.classList).forEach(name => { 1863 if (!mattchers.some(isMatch => isMatch(name))) { 1864 node.classList.remove(name); 1865 } 1866 }); 1867 if (!node.classList.length) { 1868 node.removeAttribute('class'); 1869 } 1870 } 1871 } 1872 if (node.hasChildNodes()) { 1873 // Do not filter any content. 1874 if (children === '*') { 1875 return; 1876 } 1877 1878 // Continue if the node is supposed to have children. 1879 if (children) { 1880 // If a parent requires certain children, but it does 1881 // not have them, drop the parent and continue. 1882 if (require.length && !node.querySelector(require.join(','))) { 1883 cleanNodeList(node.childNodes, doc, schema, inline); 1884 unwrap(node); 1885 // If the node is at the top, phrasing content, and 1886 // contains children that are block content, unwrap 1887 // the node because it is invalid. 1888 } else if (node.parentNode && node.parentNode.nodeName === 'BODY' && isPhrasingContent(node)) { 1889 cleanNodeList(node.childNodes, doc, schema, inline); 1890 if (Array.from(node.childNodes).some(child => !isPhrasingContent(child))) { 1891 unwrap(node); 1892 } 1893 } else { 1894 cleanNodeList(node.childNodes, doc, children, inline); 1895 } 1896 // Remove children if the node is not supposed to have any. 1897 } else { 1898 while (node.firstChild) { 1899 remove(node.firstChild); 1900 } 1901 } 1902 } 1903 } 1904 // Invalid child. Continue with schema at the same place and unwrap. 1905 } else { 1906 cleanNodeList(node.childNodes, doc, schema, inline); 1907 1908 // For inline mode, insert a line break when unwrapping nodes that 1909 // are not phrasing content. 1910 if (inline && !isPhrasingContent(node) && node.nextElementSibling) { 1911 insertAfter(doc.createElement('br'), node); 1912 } 1913 unwrap(node); 1914 } 1915 }); 1916 } 1917 1918 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove-invalid-html.js 1919 /** 1920 * Internal dependencies 1921 */ 1922 1923 1924 /** 1925 * Given a schema, unwraps or removes nodes, attributes and classes on HTML. 1926 * 1927 * @param {string} HTML The HTML to clean up. 1928 * @param {import('./clean-node-list').Schema} schema Schema for the HTML. 1929 * @param {boolean} inline Whether to clean for inline mode. 1930 * 1931 * @return {string} The cleaned up HTML. 1932 */ 1933 function removeInvalidHTML(HTML, schema, inline) { 1934 const doc = document.implementation.createHTMLDocument(''); 1935 doc.body.innerHTML = HTML; 1936 cleanNodeList(doc.body.childNodes, doc, schema, inline); 1937 return doc.body.innerHTML; 1938 } 1939 1940 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/index.js 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/data-transfer.js 1969 /** 1970 * Gets all files from a DataTransfer object. 1971 * 1972 * @param {DataTransfer} dataTransfer DataTransfer object to inspect. 1973 * 1974 * @return {File[]} An array containing all files. 1975 */ 1976 function getFilesFromDataTransfer(dataTransfer) { 1977 const files = Array.from(dataTransfer.files); 1978 Array.from(dataTransfer.items).forEach(item => { 1979 const file = item.getAsFile(); 1980 if (file && !files.find(({ 1981 name, 1982 type, 1983 size 1984 }) => name === file.name && type === file.type && size === file.size)) { 1985 files.push(file); 1986 } 1987 }); 1988 return files; 1989 } 1990 1991 ;// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/index.js 1992 /** 1993 * Internal dependencies 1994 */ 1995 1996 1997 1998 /** 1999 * Object grouping `focusable` and `tabbable` utils 2000 * under the keys with the same name. 2001 */ 2002 const build_module_focus = { 2003 focusable: focusable_namespaceObject, 2004 tabbable: tabbable_namespaceObject 2005 }; 2006 2007 2008 2009 2010 (window.wp = window.wp || {}).dom = __webpack_exports__; 2011 /******/ })() 2012 ;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Mon Mar 18 08:20:01 2024 | Cross-referenced by PHPXref |