angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

dom.js (63298B)


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