--- a/wp/wp-includes/js/dist/dom.js Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-includes/js/dist/dom.js Wed Sep 21 18:19:35 2022 +0200
@@ -82,19 +82,12 @@
/******/
/******/
/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 462);
+/******/ return __webpack_require__(__webpack_require__.s = "2sUP");
/******/ })
/************************************************************************/
/******/ ({
-/***/ 2:
-/***/ (function(module, exports) {
-
-(function() { module.exports = this["lodash"]; }());
-
-/***/ }),
-
-/***/ 462:
+/***/ "2sUP":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -103,27 +96,35 @@
// EXPORTS
__webpack_require__.d(__webpack_exports__, "focus", function() { return /* binding */ build_module_focus; });
-__webpack_require__.d(__webpack_exports__, "isHorizontalEdge", function() { return /* reexport */ isHorizontalEdge; });
-__webpack_require__.d(__webpack_exports__, "isVerticalEdge", function() { return /* reexport */ isVerticalEdge; });
-__webpack_require__.d(__webpack_exports__, "getRectangleFromRange", function() { return /* reexport */ getRectangleFromRange; });
__webpack_require__.d(__webpack_exports__, "computeCaretRect", function() { return /* reexport */ computeCaretRect; });
-__webpack_require__.d(__webpack_exports__, "placeCaretAtHorizontalEdge", function() { return /* reexport */ placeCaretAtHorizontalEdge; });
-__webpack_require__.d(__webpack_exports__, "placeCaretAtVerticalEdge", function() { return /* reexport */ placeCaretAtVerticalEdge; });
-__webpack_require__.d(__webpack_exports__, "isTextField", function() { return /* reexport */ isTextField; });
-__webpack_require__.d(__webpack_exports__, "isNumberInput", function() { return /* reexport */ isNumberInput; });
__webpack_require__.d(__webpack_exports__, "documentHasTextSelection", function() { return /* reexport */ documentHasTextSelection; });
__webpack_require__.d(__webpack_exports__, "documentHasUncollapsedSelection", function() { return /* reexport */ documentHasUncollapsedSelection; });
__webpack_require__.d(__webpack_exports__, "documentHasSelection", function() { return /* reexport */ documentHasSelection; });
-__webpack_require__.d(__webpack_exports__, "isEntirelySelected", function() { return /* reexport */ isEntirelySelected; });
+__webpack_require__.d(__webpack_exports__, "getRectangleFromRange", function() { return /* reexport */ getRectangleFromRange; });
__webpack_require__.d(__webpack_exports__, "getScrollContainer", function() { return /* reexport */ getScrollContainer; });
__webpack_require__.d(__webpack_exports__, "getOffsetParent", function() { return /* reexport */ getOffsetParent; });
+__webpack_require__.d(__webpack_exports__, "isEntirelySelected", function() { return /* reexport */ isEntirelySelected; });
+__webpack_require__.d(__webpack_exports__, "isHorizontalEdge", function() { return /* reexport */ isHorizontalEdge; });
+__webpack_require__.d(__webpack_exports__, "isNumberInput", function() { return /* reexport */ isNumberInput; });
+__webpack_require__.d(__webpack_exports__, "isTextField", function() { return /* reexport */ isTextField; });
+__webpack_require__.d(__webpack_exports__, "isVerticalEdge", function() { return /* reexport */ isVerticalEdge; });
+__webpack_require__.d(__webpack_exports__, "placeCaretAtHorizontalEdge", function() { return /* reexport */ placeCaretAtHorizontalEdge; });
+__webpack_require__.d(__webpack_exports__, "placeCaretAtVerticalEdge", function() { return /* reexport */ placeCaretAtVerticalEdge; });
__webpack_require__.d(__webpack_exports__, "replace", function() { return /* reexport */ replace; });
__webpack_require__.d(__webpack_exports__, "remove", function() { return /* reexport */ remove; });
__webpack_require__.d(__webpack_exports__, "insertAfter", function() { return /* reexport */ insertAfter; });
__webpack_require__.d(__webpack_exports__, "unwrap", function() { return /* reexport */ unwrap; });
__webpack_require__.d(__webpack_exports__, "replaceTag", function() { return /* reexport */ replaceTag; });
__webpack_require__.d(__webpack_exports__, "wrap", function() { return /* reexport */ wrap; });
-__webpack_require__.d(__webpack_exports__, "__unstableStripHTML", function() { return /* reexport */ __unstableStripHTML; });
+__webpack_require__.d(__webpack_exports__, "__unstableStripHTML", function() { return /* reexport */ stripHTML; });
+__webpack_require__.d(__webpack_exports__, "isEmpty", function() { return /* reexport */ isEmpty; });
+__webpack_require__.d(__webpack_exports__, "removeInvalidHTML", function() { return /* reexport */ removeInvalidHTML; });
+__webpack_require__.d(__webpack_exports__, "isRTL", function() { return /* reexport */ isRTL; });
+__webpack_require__.d(__webpack_exports__, "safeHTML", function() { return /* reexport */ safeHTML; });
+__webpack_require__.d(__webpack_exports__, "getPhrasingContentSchema", function() { return /* reexport */ getPhrasingContentSchema; });
+__webpack_require__.d(__webpack_exports__, "isPhrasingContent", function() { return /* reexport */ isPhrasingContent; });
+__webpack_require__.d(__webpack_exports__, "isTextContent", function() { return /* reexport */ isTextContent; });
+__webpack_require__.d(__webpack_exports__, "getFilesFromDataTransfer", function() { return /* reexport */ getFilesFromDataTransfer; });
// NAMESPACE OBJECT: ./node_modules/@wordpress/dom/build-module/focusable.js
var focusable_namespaceObject = {};
@@ -157,12 +158,12 @@
* AREA elements associated with an IMG:
* - https://w3c.github.io/html/editing.html#data-model
*/
-var 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(',');
+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(',');
/**
* Returns true if the specified element is visible (i.e. neither display: none
* nor visibility: hidden).
*
- * @param {Element} element DOM element to test.
+ * @param {HTMLElement} element DOM element to test.
*
* @return {boolean} Whether element is visible.
*/
@@ -188,20 +189,23 @@
* false otherwise. Area is only focusable if within a map where a named map
* referenced by an image somewhere in the document.
*
- * @param {Element} element DOM area element to test.
+ * @param {HTMLAreaElement} element DOM area element to test.
*
* @return {boolean} Whether area element is valid for focus.
*/
function isValidFocusableArea(element) {
- var map = element.closest('map[name]');
+ /** @type {HTMLMapElement | null} */
+ const map = element.closest('map[name]');
if (!map) {
return false;
}
+ /** @type {HTMLImageElement | null} */
- var img = document.querySelector('img[usemap="#' + map.name + '"]');
+
+ const img = element.ownerDocument.querySelector('img[usemap="#' + map.name + '"]');
return !!img && isVisible(img);
}
/**
@@ -214,24 +218,33 @@
function find(context) {
- var elements = context.querySelectorAll(SELECTOR);
- return Array.from(elements).filter(function (element) {
+ /* eslint-disable jsdoc/no-undefined-types */
+
+ /** @type {NodeListOf<HTMLElement>} */
+
+ /* eslint-enable jsdoc/no-undefined-types */
+ const elements = context.querySelectorAll(SELECTOR);
+ return Array.from(elements).filter(element => {
if (!isVisible(element) || skipFocus(element)) {
return false;
}
- var nodeName = element.nodeName;
+ const {
+ nodeName
+ } = element;
if ('AREA' === nodeName) {
- return isValidFocusableArea(element);
+ return isValidFocusableArea(
+ /** @type {HTMLAreaElement} */
+ element);
}
return true;
});
}
-// EXTERNAL MODULE: external {"this":"lodash"}
-var external_this_lodash_ = __webpack_require__(2);
+// EXTERNAL MODULE: external "lodash"
+var external_lodash_ = __webpack_require__("YLtl");
// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/tabbable.js
/**
@@ -253,11 +266,11 @@
*
* @param {Element} element Element from which to retrieve.
*
- * @return {?number} Tab index of element (default 0).
+ * @return {number} Tab index of element (default 0).
*/
function getTabIndex(element) {
- var tabIndex = element.getAttribute('tabindex');
+ const tabIndex = element.getAttribute('tabindex');
return tabIndex === null ? 0 : parseInt(tabIndex, 10);
}
/**
@@ -272,30 +285,39 @@
function isTabbableIndex(element) {
return getTabIndex(element) !== -1;
}
+/** @typedef {Element & { type?: string, checked?: boolean, name?: string }} MaybeHTMLInputElement */
+
/**
* Returns a stateful reducer function which constructs a filtered array of
* tabbable elements, where at most one radio input is selected for a given
* name, giving priority to checked input, falling back to the first
* encountered.
*
- * @return {Function} Radio group collapse reducer.
+ * @return {(acc: MaybeHTMLInputElement[], el: MaybeHTMLInputElement) => MaybeHTMLInputElement[]} Radio group collapse reducer.
*/
function createStatefulCollapseRadioGroup() {
- var CHOSEN_RADIO_BY_NAME = {};
- return function collapseRadioGroup(result, element) {
- var nodeName = element.nodeName,
- type = element.type,
- checked = element.checked,
- name = element.name; // For all non-radio tabbables, construct to array by concatenating.
+ /** @type {Record<string, MaybeHTMLInputElement>} */
+ const CHOSEN_RADIO_BY_NAME = {};
+ return function collapseRadioGroup(
+ /** @type {MaybeHTMLInputElement[]} */
+ result,
+ /** @type {MaybeHTMLInputElement} */
+ element) {
+ const {
+ nodeName,
+ type,
+ checked,
+ name
+ } = element; // For all non-radio tabbables, construct to array by concatenating.
if (nodeName !== 'INPUT' || type !== 'radio' || !name) {
return result.concat(element);
}
- var hasChosen = CHOSEN_RADIO_BY_NAME.hasOwnProperty(name); // Omit by skipping concatenation if the radio element is not chosen.
+ const hasChosen = CHOSEN_RADIO_BY_NAME.hasOwnProperty(name); // Omit by skipping concatenation if the radio element is not chosen.
- var isChosen = checked || !hasChosen;
+ const isChosen = checked || !hasChosen;
if (!isChosen) {
return result;
@@ -305,8 +327,8 @@
if (hasChosen) {
- var hadChosenElement = CHOSEN_RADIO_BY_NAME[name];
- result = Object(external_this_lodash_["without"])(result, hadChosenElement);
+ const hadChosenElement = CHOSEN_RADIO_BY_NAME[name];
+ result = Object(external_lodash_["without"])(result, hadChosenElement);
}
CHOSEN_RADIO_BY_NAME[name] = element;
@@ -322,21 +344,21 @@
* @param {Element} element Element.
* @param {number} index Array index of element.
*
- * @return {Object} Mapped object with element, index.
+ * @return {{ element: Element, index: number }} Mapped object with element, index.
*/
function mapElementToObjectTabbable(element, index) {
return {
- element: element,
- index: index
+ element,
+ index
};
}
/**
* An array map callback, returning an element of the given mapped object's
* element value.
*
- * @param {Object} object Mapped object with index.
+ * @param {{ element: Element }} object Mapped object with element.
*
* @return {Element} Mapped object element.
*/
@@ -350,16 +372,16 @@
*
* @see mapElementToObjectTabbable
*
- * @param {Object} a First object to compare.
- * @param {Object} b Second object to compare.
+ * @param {{ element: Element, index: number }} a First object to compare.
+ * @param {{ element: Element, index: number }} b Second object to compare.
*
* @return {number} Comparator result.
*/
function compareObjectTabbables(a, b) {
- var aTabIndex = getTabIndex(a.element);
- var bTabIndex = getTabIndex(b.element);
+ const aTabIndex = getTabIndex(a.element);
+ const bTabIndex = getTabIndex(b.element);
if (aTabIndex === bTabIndex) {
return a.index - b.index;
@@ -370,15 +392,20 @@
/**
* Givin focusable elements, filters out tabbable element.
*
- * @param {Array} focusables Focusable elements to filter.
+ * @param {Element[]} focusables Focusable elements to filter.
*
- * @return {Array} Tabbable elements.
+ * @return {Element[]} Tabbable elements.
*/
function filterTabbable(focusables) {
return focusables.filter(isTabbableIndex).map(mapElementToObjectTabbable).sort(compareObjectTabbables).map(mapObjectTabbableToElement).reduce(createStatefulCollapseRadioGroup(), []);
}
+/**
+ * @param {Element} context
+ * @return {Element[]} Tabbable elements within the context.
+ */
+
function tabbable_find(context) {
return filterTabbable(find(context));
@@ -390,13 +417,12 @@
* to the active element.
*/
-function findPrevious() {
- var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document.activeElement;
- var focusables = find(document.body);
- var index = focusables.indexOf(element); // Remove all focusables after and including `element`.
+function findPrevious(element) {
+ const focusables = find(element.ownerDocument.body);
+ const index = focusables.indexOf(element); // Remove all focusables after and including `element`.
focusables.length = index;
- return Object(external_this_lodash_["last"])(filterTabbable(focusables));
+ return Object(external_lodash_["last"])(filterTabbable(focusables));
}
/**
* Given a focusable element, find the next tabbable element.
@@ -405,34 +431,558 @@
* to the active element.
*/
-function findNext() {
- var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document.activeElement;
- var focusables = find(document.body);
- var index = focusables.indexOf(element); // Remove all focusables before and inside `element`.
+function findNext(element) {
+ const focusables = find(element.ownerDocument.body);
+ const index = focusables.indexOf(element); // Remove all focusables before and inside `element`.
- var remaining = focusables.slice(index + 1).filter(function (node) {
- return !element.contains(node);
- });
- return Object(external_this_lodash_["first"])(filterTabbable(remaining));
+ const remaining = focusables.slice(index + 1).filter(node => !element.contains(node));
+ return Object(external_lodash_["first"])(filterTabbable(remaining));
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/utils/assert-is-defined.js
+function assertIsDefined(val, name) {
+ if (false) {}
}
-// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom.js
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-rectangle-from-range.js
+/**
+ * Internal dependencies
+ */
+
/**
- * External dependencies
+ * Get the rectangle of a given Range.
+ *
+ * @param {Range} range The range.
+ *
+ * @return {DOMRect} The rectangle.
+ */
+
+function getRectangleFromRange(range) {
+ // For uncollapsed ranges, get the rectangle that bounds the contents of the
+ // range; this a rectangle enclosing the union of the bounding rectangles
+ // for all the elements in the range.
+ if (!range.collapsed) {
+ const rects = Array.from(range.getClientRects()); // If there's just a single rect, return it.
+
+ if (rects.length === 1) {
+ return rects[0];
+ } // Ignore tiny selection at the edge of a range.
+
+
+ const filteredRects = rects.filter(({
+ width
+ }) => width > 1); // If it's full of tiny selections, return browser default.
+
+ if (filteredRects.length === 0) {
+ return range.getBoundingClientRect();
+ }
+
+ if (filteredRects.length === 1) {
+ return filteredRects[0];
+ }
+
+ let {
+ top: furthestTop,
+ bottom: furthestBottom,
+ left: furthestLeft,
+ right: furthestRight
+ } = filteredRects[0];
+
+ for (const {
+ top,
+ bottom,
+ left,
+ right
+ } of filteredRects) {
+ if (top < furthestTop) furthestTop = top;
+ if (bottom > furthestBottom) furthestBottom = bottom;
+ if (left < furthestLeft) furthestLeft = left;
+ if (right > furthestRight) furthestRight = right;
+ }
+
+ return new window.DOMRect(furthestLeft, furthestTop, furthestRight - furthestLeft, furthestBottom - furthestTop);
+ }
+
+ const {
+ startContainer
+ } = range;
+ const {
+ ownerDocument
+ } = startContainer; // Correct invalid "BR" ranges. The cannot contain any children.
+
+ if (startContainer.nodeName === 'BR') {
+ const {
+ parentNode
+ } = startContainer;
+ assertIsDefined(parentNode, 'parentNode');
+ const index =
+ /** @type {Node[]} */
+ Array.from(parentNode.childNodes).indexOf(startContainer);
+ assertIsDefined(ownerDocument, 'ownerDocument');
+ range = ownerDocument.createRange();
+ range.setStart(parentNode, index);
+ range.setEnd(parentNode, index);
+ }
+
+ let rect = range.getClientRects()[0]; // If the collapsed range starts (and therefore ends) at an element node,
+ // `getClientRects` can be empty in some browsers. This can be resolved
+ // by adding a temporary text node with zero-width space to the range.
+ //
+ // See: https://stackoverflow.com/a/6847328/995445
+
+ if (!rect) {
+ assertIsDefined(ownerDocument, 'ownerDocument');
+ const padNode = ownerDocument.createTextNode('\u200b'); // Do not modify the live range.
+
+ range = range.cloneRange();
+ range.insertNode(padNode);
+ rect = range.getClientRects()[0];
+ assertIsDefined(padNode.parentNode, 'padNode.parentNode');
+ padNode.parentNode.removeChild(padNode);
+ }
+
+ return rect;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/compute-caret-rect.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Get the rectangle for the selection in a container.
+ *
+ * @param {Window} win The window of the selection.
+ *
+ * @return {DOMRect | null} The rectangle.
+ */
+
+function computeCaretRect(win) {
+ const selection = win.getSelection();
+ assertIsDefined(selection, 'selection');
+ const range = selection.rangeCount ? selection.getRangeAt(0) : null;
+
+ if (!range) {
+ return null;
+ }
+
+ return getRectangleFromRange(range);
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-text-selection.js
+/**
+ * Internal dependencies
*/
/**
- * Browser dependencies
+ * Check whether the current document has selected text. This applies to ranges
+ * of text in the document, and not selection inside <input> and <textarea>
+ * elements.
+ *
+ * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects.
+ *
+ * @param {Document} doc The document to check.
+ *
+ * @return {boolean} True if there is selection, false if not.
+ */
+
+function documentHasTextSelection(doc) {
+ assertIsDefined(doc.defaultView, 'doc.defaultView');
+ const selection = doc.defaultView.getSelection();
+ assertIsDefined(selection, 'selection');
+ const range = selection.rangeCount ? selection.getRangeAt(0) : null;
+ return !!range && !range.collapsed;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-html-input-element.js
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * @param {Node} node
+ * @return {node is HTMLInputElement} Whether the node is an HTMLInputElement.
+ */
+function isHTMLInputElement(node) {
+ /* eslint-enable jsdoc/valid-types */
+ return !!node && node.nodeName === 'INPUT';
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-text-field.js
+/**
+ * Internal dependencies
+ */
+
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * Check whether the given element is a text field, where text field is defined
+ * by the ability to select within the input, or that it is contenteditable.
+ *
+ * See: https://html.spec.whatwg.org/#textFieldSelection
+ *
+ * @param {Node} node The HTML element.
+ * @return {node is HTMLElement} True if the element is an text field, false if not.
+ */
+
+function isTextField(node) {
+ /* eslint-enable jsdoc/valid-types */
+ const nonTextInputs = ['button', 'checkbox', 'hidden', 'file', 'radio', 'image', 'range', 'reset', 'submit', 'number'];
+ return isHTMLInputElement(node) && node.type && !nonTextInputs.includes(node.type) || node.nodeName === 'TEXTAREA' ||
+ /** @type {HTMLElement} */
+ node.contentEditable === 'true';
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-number-input.js
+/**
+ * Internal dependencies
+ */
+
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * Check whether the given element is an input field of type number
+ * and has a valueAsNumber
+ *
+ * @param {Node} node The HTML node.
+ *
+ * @return {node is HTMLInputElement} True if the node is input and holds a number.
+ */
+
+function isNumberInput(node) {
+ /* eslint-enable jsdoc/valid-types */
+ return isHTMLInputElement(node) && node.type === 'number' && !!node.valueAsNumber;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/input-field-has-uncollapsed-selection.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Check whether the given element, assumed an input field or textarea,
+ * contains a (uncollapsed) selection of text.
+ *
+ * Note: this is perhaps an abuse of the term "selection", since these elements
+ * manage selection differently and aren't covered by Selection#collapsed.
+ *
+ * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects.
+ *
+ * @param {Element} element The HTML element.
+ *
+ * @return {boolean} Whether the input/textareaa element has some "selection".
+ */
+
+function inputFieldHasUncollapsedSelection(element) {
+ if (!isTextField(element) && !isNumberInput(element)) {
+ return false;
+ }
+
+ try {
+ const {
+ selectionStart,
+ selectionEnd
+ } =
+ /** @type {HTMLInputElement | HTMLTextAreaElement} */
+ element;
+ return selectionStart !== null && selectionStart !== selectionEnd;
+ } catch (error) {
+ // Safari throws an exception when trying to get `selectionStart`
+ // on non-text <input> elements (which, understandably, don't
+ // have the text selection API). We catch this via a try/catch
+ // block, as opposed to a more explicit check of the element's
+ // input types, because of Safari's non-standard behavior. This
+ // also means we don't have to worry about the list of input
+ // types that support `selectionStart` changing as the HTML spec
+ // evolves over time.
+ return false;
+ }
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-uncollapsed-selection.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Check whether the current document has any sort of selection. This includes
+ * ranges of text across elements and any selection inside <input> and
+ * <textarea> elements.
+ *
+ * @param {Document} doc The document to check.
+ *
+ * @return {boolean} Whether there is any sort of "selection" in the document.
+ */
+
+function documentHasUncollapsedSelection(doc) {
+ return documentHasTextSelection(doc) || !!doc.activeElement && inputFieldHasUncollapsedSelection(doc.activeElement);
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/document-has-selection.js
+/**
+ * Internal dependencies
+ */
+
+
+
+/**
+ * Check whether the current document has a selection. This checks for both
+ * focus in an input field and general text selection.
+ *
+ * @param {Document} doc The document to check.
+ *
+ * @return {boolean} True if there is selection, false if not.
+ */
+
+function documentHasSelection(doc) {
+ return !!doc.activeElement && (isTextField(doc.activeElement) || isNumberInput(doc.activeElement) || documentHasTextSelection(doc));
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-computed-style.js
+/**
+ * Internal dependencies
+ */
+
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * @param {Element} element
+ * @return {ReturnType<Window['getComputedStyle']>} The computed style for the element.
+ */
+
+function getComputedStyle(element) {
+ /* eslint-enable jsdoc/valid-types */
+ assertIsDefined(element.ownerDocument.defaultView, 'element.ownerDocument.defaultView');
+ return element.ownerDocument.defaultView.getComputedStyle(element);
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-scroll-container.js
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Given a DOM node, finds the closest scrollable container node.
+ *
+ * @param {Element | null} node Node from which to start.
+ *
+ * @return {Element | undefined} Scrollable container node, if found.
*/
-var _window = window,
- DOMParser = _window.DOMParser,
- getComputedStyle = _window.getComputedStyle;
-var _window$Node = window.Node,
- TEXT_NODE = _window$Node.TEXT_NODE,
- ELEMENT_NODE = _window$Node.ELEMENT_NODE,
- DOCUMENT_POSITION_PRECEDING = _window$Node.DOCUMENT_POSITION_PRECEDING,
- DOCUMENT_POSITION_FOLLOWING = _window$Node.DOCUMENT_POSITION_FOLLOWING;
+function getScrollContainer(node) {
+ if (!node) {
+ return undefined;
+ } // Scrollable if scrollable height exceeds displayed...
+
+
+ if (node.scrollHeight > node.clientHeight) {
+ // ...except when overflow is defined to be hidden or visible
+ const {
+ overflowY
+ } = getComputedStyle(node);
+
+ if (/(auto|scroll)/.test(overflowY)) {
+ return node;
+ }
+ } // Continue traversing
+
+
+ return getScrollContainer(
+ /** @type {Element} */
+ node.parentNode);
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-offset-parent.js
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Returns the closest positioned element, or null under any of the conditions
+ * of the offsetParent specification. Unlike offsetParent, this function is not
+ * limited to HTMLElement and accepts any Node (e.g. Node.TEXT_NODE).
+ *
+ * @see https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
+ *
+ * @param {Node} node Node from which to find offset parent.
+ *
+ * @return {Node | null} Offset parent.
+ */
+
+function getOffsetParent(node) {
+ // Cannot retrieve computed style or offset parent only anything other than
+ // an element node, so find the closest element node.
+ let closestElement;
+
+ while (closestElement =
+ /** @type {Node} */
+ node.parentNode) {
+ if (closestElement.nodeType === closestElement.ELEMENT_NODE) {
+ break;
+ }
+ }
+
+ if (!closestElement) {
+ return null;
+ } // If the closest element is already positioned, return it, as offsetParent
+ // does not otherwise consider the node itself.
+
+
+ if (getComputedStyle(
+ /** @type {Element} */
+ closestElement).position !== 'static') {
+ return closestElement;
+ } // offsetParent is undocumented/draft
+
+
+ return (
+ /** @type {Node & { offsetParent: Node }} */
+ closestElement.offsetParent
+ );
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-input-or-text-area.js
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * @param {Element} element
+ * @return {element is HTMLInputElement | HTMLTextAreaElement} Whether the element is an input or textarea
+ */
+function isInputOrTextArea(element) {
+ /* eslint-enable jsdoc/valid-types */
+ return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA';
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-entirely-selected.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Check whether the contents of the element have been entirely selected.
+ * Returns true if there is no possibility of selection.
+ *
+ * @param {HTMLElement} element The element to check.
+ *
+ * @return {boolean} True if entirely selected, false if not.
+ */
+
+function isEntirelySelected(element) {
+ if (isInputOrTextArea(element)) {
+ return element.selectionStart === 0 && element.value.length === element.selectionEnd;
+ }
+
+ if (!element.isContentEditable) {
+ return true;
+ }
+
+ const {
+ ownerDocument
+ } = element;
+ const {
+ defaultView
+ } = ownerDocument;
+ assertIsDefined(defaultView, 'defaultView');
+ const selection = defaultView.getSelection();
+ assertIsDefined(selection, 'selection');
+ const range = selection.rangeCount ? selection.getRangeAt(0) : null;
+
+ if (!range) {
+ return true;
+ }
+
+ const {
+ startContainer,
+ endContainer,
+ startOffset,
+ endOffset
+ } = range;
+
+ if (startContainer === element && endContainer === element && startOffset === 0 && endOffset === element.childNodes.length) {
+ return true;
+ }
+
+ const lastChild = element.lastChild;
+ assertIsDefined(lastChild, 'lastChild');
+ const endContainerContentLength = endContainer.nodeType === endContainer.TEXT_NODE ?
+ /** @type {Text} */
+ endContainer.data.length : endContainer.childNodes.length;
+ return isDeepChild(startContainer, element, 'firstChild') && isDeepChild(endContainer, element, 'lastChild') && startOffset === 0 && endOffset === endContainerContentLength;
+}
+/**
+ * Check whether the contents of the element have been entirely selected.
+ * Returns true if there is no possibility of selection.
+ *
+ * @param {HTMLElement|Node} query The element to check.
+ * @param {HTMLElement} container The container that we suspect "query" may be a first or last child of.
+ * @param {"firstChild"|"lastChild"} propName "firstChild" or "lastChild"
+ *
+ * @return {boolean} True if query is a deep first/last child of container, false otherwise.
+ */
+
+function isDeepChild(query, container, propName) {
+ /** @type {HTMLElement | ChildNode | null} */
+ let candidate = container;
+
+ do {
+ if (query === candidate) {
+ return true;
+ }
+
+ candidate = candidate[propName];
+ } while (candidate);
+
+ return false;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-rtl.js
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Whether the element's text direction is right-to-left.
+ *
+ * @param {Element} element The element to check.
+ *
+ * @return {boolean} True if rtl, false if ltr.
+ */
+
+function isRTL(element) {
+ return getComputedStyle(element).direction === 'rtl';
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/get-range-height.js
+/**
+ * Gets the height of the range without ignoring zero width rectangles, which
+ * some browsers ignore when creating a union.
+ *
+ * @param {Range} range The range to check.
+ * @return {number | undefined} Height of the range or undefined if the range has no client rectangles.
+ */
+function getRangeHeight(range) {
+ const rects = Array.from(range.getClientRects());
+
+ if (!rects.length) {
+ return;
+ }
+
+ const highestTop = Math.min(...rects.map(({
+ top
+ }) => top));
+ const lowestBottom = Math.max(...rects.map(({
+ bottom
+ }) => bottom));
+ return lowestBottom - highestTop;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-selection-forward.js
+/**
+ * Internal dependencies
+ */
+
/**
* Returns true if the given selection object is in the forward direction, or
* false otherwise.
@@ -445,22 +995,26 @@
*/
function isSelectionForward(selection) {
- var anchorNode = selection.anchorNode,
- focusNode = selection.focusNode,
- anchorOffset = selection.anchorOffset,
- focusOffset = selection.focusOffset;
- var position = anchorNode.compareDocumentPosition(focusNode); // Disable reason: `Node#compareDocumentPosition` returns a bitmask value,
+ const {
+ anchorNode,
+ focusNode,
+ anchorOffset,
+ focusOffset
+ } = selection;
+ assertIsDefined(anchorNode, 'anchorNode');
+ assertIsDefined(focusNode, 'focusNode');
+ const position = anchorNode.compareDocumentPosition(focusNode); // Disable reason: `Node#compareDocumentPosition` returns a bitmask value,
// so bitwise operators are intended.
/* eslint-disable no-bitwise */
// Compare whether anchor node precedes focus node. If focus node (where
// end of selection occurs) is after the anchor node, it is forward.
- if (position & DOCUMENT_POSITION_PRECEDING) {
+ if (position & anchorNode.DOCUMENT_POSITION_PRECEDING) {
return false;
}
- if (position & DOCUMENT_POSITION_FOLLOWING) {
+ if (position & anchorNode.DOCUMENT_POSITION_FOLLOWING) {
return true;
}
/* eslint-enable no-bitwise */
@@ -475,21 +1029,104 @@
return true;
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/caret-range-from-point.js
+/**
+ * Polyfill.
+ * Get a collapsed range for a given point.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
+ *
+ * @param {Document} doc The document of the range.
+ * @param {number} x Horizontal position within the current viewport.
+ * @param {number} y Vertical position within the current viewport.
+ *
+ * @return {Range | null} The best range for the given point.
+ */
+function caretRangeFromPoint(doc, x, y) {
+ if (doc.caretRangeFromPoint) {
+ return doc.caretRangeFromPoint(x, y);
+ }
+
+ if (!doc.caretPositionFromPoint) {
+ return null;
+ }
+
+ const point = doc.caretPositionFromPoint(x, y); // If x or y are negative, outside viewport, or there is no text entry node.
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
+
+ if (!point) {
+ return null;
+ }
+
+ const range = doc.createRange();
+ range.setStart(point.offsetNode, point.offset);
+ range.collapse(true);
+ return range;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/hidden-caret-range-from-point.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Get a collapsed range for a given point.
+ * Gives the container a temporary high z-index (above any UI).
+ * This is preferred over getting the UI nodes and set styles there.
+ *
+ * @param {Document} doc The document of the range.
+ * @param {number} x Horizontal position within the current viewport.
+ * @param {number} y Vertical position within the current viewport.
+ * @param {HTMLElement} container Container in which the range is expected to be found.
+ *
+ * @return {?Range} The best range for the given point.
+ */
+
+function hiddenCaretRangeFromPoint(doc, x, y, container) {
+ const originalZIndex = container.style.zIndex;
+ const originalPosition = container.style.position;
+ const {
+ position = 'static'
+ } = getComputedStyle(container); // A z-index only works if the element position is not static.
+
+ if (position === 'static') {
+ container.style.position = 'relative';
+ }
+
+ container.style.zIndex = '10000';
+ const range = caretRangeFromPoint(doc, x, y);
+ container.style.zIndex = originalZIndex;
+ container.style.position = originalPosition;
+ return range;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-edge.js
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+
+
/**
* Check whether the selection is at the edge of the container. Checks for
* horizontal position by default. Set `onlyVertical` to true to check only
* vertically.
*
- * @param {Element} container Focusable element.
- * @param {boolean} isReverse Set to true to check left, false to check right.
- * @param {boolean} onlyVertical Set to true to check only vertical position.
+ * @param {Element} container Focusable element.
+ * @param {boolean} isReverse Set to true to check left, false to check right.
+ * @param {boolean} [onlyVertical=false] Set to true to check only vertical position.
*
* @return {boolean} True if at the edge, false if not.
*/
-
-function isEdge(container, isReverse, onlyVertical) {
- if (Object(external_this_lodash_["includes"])(['INPUT', 'TEXTAREA'], container.tagName)) {
+function isEdge(container, isReverse, onlyVertical = false) {
+ if (isInputOrTextArea(container)) {
if (container.selectionStart !== container.selectionEnd) {
return false;
}
@@ -501,78 +1138,94 @@
return container.value.length === container.selectionStart;
}
- if (!container.isContentEditable) {
+ if (!
+ /** @type {HTMLElement} */
+ container.isContentEditable) {
return true;
}
- var selection = window.getSelection();
-
- if (!selection.rangeCount) {
- return false;
- }
+ const {
+ ownerDocument
+ } = container;
+ const {
+ defaultView
+ } = ownerDocument;
+ assertIsDefined(defaultView, 'defaultView');
+ const selection = defaultView.getSelection();
- var originalRange = selection.getRangeAt(0);
- var range = originalRange.cloneRange();
- var isForward = isSelectionForward(selection);
- var isCollapsed = selection.isCollapsed; // Collapse in direction of selection.
-
- if (!isCollapsed) {
- range.collapse(!isForward);
- }
-
- var rangeRect = getRectangleFromRange(range);
-
- if (!rangeRect) {
+ if (!selection || !selection.rangeCount) {
return false;
}
- var computedStyle = window.getComputedStyle(container);
- var lineHeight = parseInt(computedStyle.lineHeight, 10) || 0; // Only consider the multiline selection at the edge if the direction is
- // towards the edge.
+ const range = selection.getRangeAt(0);
+ const collapsedRange = range.cloneRange();
+ const isForward = isSelectionForward(selection);
+ const isCollapsed = selection.isCollapsed; // Collapse in direction of selection.
- if (!isCollapsed && rangeRect.height > lineHeight && isForward === isReverse) {
- return false;
+ if (!isCollapsed) {
+ collapsedRange.collapse(!isForward);
}
- var padding = parseInt(computedStyle["padding".concat(isReverse ? 'Top' : 'Bottom')], 10) || 0; // Calculate a buffer that is half the line height. In some browsers, the
- // selection rectangle may not fill the entire height of the line, so we add
- // 3/4 the line height to the selection rectangle to ensure that it is well
- // over its line boundary.
+ const collapsedRangeRect = getRectangleFromRange(collapsedRange);
+ const rangeRect = getRectangleFromRange(range);
- var buffer = 3 * parseInt(lineHeight, 10) / 4;
- var containerRect = container.getBoundingClientRect();
- var originalRangeRect = getRectangleFromRange(originalRange);
- var verticalEdge = isReverse ? containerRect.top + padding > originalRangeRect.top - buffer : containerRect.bottom - padding < originalRangeRect.bottom + buffer;
+ if (!collapsedRangeRect || !rangeRect) {
+ return false;
+ } // Only consider the multiline selection at the edge if the direction is
+ // towards the edge. The selection is multiline if it is taller than the
+ // collapsed selection.
- if (!verticalEdge) {
+
+ const rangeHeight = getRangeHeight(range);
+
+ if (!isCollapsed && rangeHeight && rangeHeight > collapsedRangeRect.height && isForward === isReverse) {
return false;
- }
-
- if (onlyVertical) {
- return true;
} // In the case of RTL scripts, the horizontal edge is at the opposite side.
- var direction = computedStyle.direction;
- var isReverseDir = direction === 'rtl' ? !isReverse : isReverse; // To calculate the horizontal position, we insert a test range and see if
- // this test range has the same horizontal position. This method proves to
- // be better than a DOM-based calculation, because it ignores empty text
- // nodes and a trailing line break element. In other words, we need to check
- // visual positioning, not DOM positioning.
+ const isReverseDir = isRTL(container) ? !isReverse : isReverse;
+ const containerRect = container.getBoundingClientRect(); // To check if a selection is at the edge, we insert a test selection at the
+ // edge of the container and check if the selections have the same vertical
+ // or horizontal position. If they do, the selection is at the edge.
+ // This method proves to be better than a DOM-based calculation for the
+ // horizontal edge, since it ignores empty textnodes and a trailing line
+ // break element. In other words, we need to check visual positioning, not
+ // DOM positioning.
+ // It also proves better than using the computed style for the vertical
+ // edge, because we cannot know the padding and line height reliably in
+ // pixels. `getComputedStyle` may return a value with different units.
- var x = isReverseDir ? containerRect.left + 1 : containerRect.right - 1;
- var y = isReverse ? containerRect.top + buffer : containerRect.bottom - buffer;
- var testRange = hiddenCaretRangeFromPoint(document, x, y, container);
+ const x = isReverseDir ? containerRect.left + 1 : containerRect.right - 1;
+ const y = isReverse ? containerRect.top + 1 : containerRect.bottom - 1;
+ const testRange = hiddenCaretRangeFromPoint(ownerDocument, x, y,
+ /** @type {HTMLElement} */
+ container);
if (!testRange) {
return false;
}
- var side = isReverseDir ? 'left' : 'right';
- var testRect = getRectangleFromRange(testRange); // Allow the position to be 1px off.
+ const testRect = getRectangleFromRange(testRange);
+
+ if (!testRect) {
+ return false;
+ }
+
+ const verticalSide = isReverse ? 'top' : 'bottom';
+ const horizontalSide = isReverseDir ? 'left' : 'right';
+ const verticalDiff = testRect[verticalSide] - rangeRect[verticalSide];
+ const horizontalDiff = testRect[horizontalSide] - collapsedRangeRect[horizontalSide]; // Allow the position to be 1px off.
- return Math.abs(testRect[side] - rangeRect[side]) <= 1;
+ const hasVerticalDiff = Math.abs(verticalDiff) <= 1;
+ const hasHorizontalDiff = Math.abs(horizontalDiff) <= 1;
+ return onlyVertical ? hasVerticalDiff : hasVerticalDiff && hasHorizontalDiff;
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-horizontal-edge.js
+/**
+ * Internal dependencies
+ */
+
/**
* Check whether the selection is horizontally at the edge of the container.
*
@@ -582,10 +1235,15 @@
* @return {boolean} True if at the horizontal edge, false if not.
*/
-
function isHorizontalEdge(container, isReverse) {
return isEdge(container, isReverse);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-vertical-edge.js
+/**
+ * Internal dependencies
+ */
+
/**
* Check whether the selection is vertically at the edge of the container.
*
@@ -598,80 +1256,61 @@
function isVerticalEdge(container, isReverse) {
return isEdge(container, isReverse, true);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-horizontal-edge.js
/**
- * Get the rectangle of a given Range.
- *
- * @param {Range} range The range.
- *
- * @return {DOMRect} The rectangle.
+ * Internal dependencies
+ */
+
+/**
+ * Internal dependencies
*/
-function getRectangleFromRange(range) {
- // For uncollapsed ranges, get the rectangle that bounds the contents of the
- // range; this a rectangle enclosing the union of the bounding rectangles
- // for all the elements in the range.
- if (!range.collapsed) {
- return range.getBoundingClientRect();
- }
- var _range = range,
- startContainer = _range.startContainer; // Correct invalid "BR" ranges. The cannot contain any children.
- if (startContainer.nodeName === 'BR') {
- var parentNode = startContainer.parentNode;
- var index = Array.from(parentNode.childNodes).indexOf(startContainer);
- range = document.createRange();
- range.setStart(parentNode, index);
- range.setEnd(parentNode, index);
- }
- var rect = range.getClientRects()[0]; // If the collapsed range starts (and therefore ends) at an element node,
- // `getClientRects` can be empty in some browsers. This can be resolved
- // by adding a temporary text node with zero-width space to the range.
- //
- // See: https://stackoverflow.com/a/6847328/995445
-
- if (!rect) {
- var padNode = document.createTextNode("\u200B"); // Do not modify the live range.
-
- range = range.cloneRange();
- range.insertNode(padNode);
- rect = range.getClientRects()[0];
- padNode.parentNode.removeChild(padNode);
- }
-
- return rect;
-}
/**
- * Get the rectangle for the selection in a container.
+ * Gets the range to place.
*
- * @return {?DOMRect} The rectangle.
+ * @param {HTMLElement} container Focusable element.
+ * @param {boolean} isReverse True for end, false for start.
+ *
+ * @return {Range|null} The range to place.
*/
-function computeCaretRect() {
- var selection = window.getSelection();
- var range = selection.rangeCount ? selection.getRangeAt(0) : null;
+function getRange(container, isReverse) {
+ const {
+ ownerDocument
+ } = container; // In the case of RTL scripts, the horizontal edge is at the opposite side.
- if (!range) {
- return;
- }
+ const isReverseDir = isRTL(container) ? !isReverse : isReverse;
+ const containerRect = container.getBoundingClientRect(); // When placing at the end (isReverse), find the closest range to the bottom
+ // right corner. When placing at the start, to the top left corner.
- return getRectangleFromRange(range);
+ const x = isReverse ? containerRect.right - 1 : containerRect.left + 1;
+ const y = isReverseDir ? containerRect.bottom - 1 : containerRect.top + 1;
+ return hiddenCaretRangeFromPoint(ownerDocument, x, y, container);
}
/**
* Places the caret at start or end of a given element.
*
- * @param {Element} container Focusable element.
- * @param {boolean} isReverse True for end, false for start.
+ * @param {HTMLElement} container Focusable element.
+ * @param {boolean} isReverse True for end, false for start.
*/
+
function placeCaretAtHorizontalEdge(container, isReverse) {
if (!container) {
return;
}
- if (Object(external_this_lodash_["includes"])(['INPUT', 'TEXTAREA'], container.tagName)) {
- container.focus();
+ container.focus();
+
+ if (isInputOrTextArea(container)) {
+ // The element may not support selection setting.
+ if (typeof container.selectionStart !== 'number') {
+ return;
+ }
if (isReverse) {
container.selectionStart = container.value.length;
@@ -684,101 +1323,52 @@
return;
}
- container.focus();
-
if (!container.isContentEditable) {
return;
- } // Select on extent child of the container, not the container itself. This
- // avoids the selection always being `endOffset` of 1 when placed at end,
- // where `startContainer`, `endContainer` would always be container itself.
-
-
- var rangeTarget = container[isReverse ? 'lastChild' : 'firstChild']; // If no range target, it implies that the container is empty. Focusing is
- // sufficient for caret to be placed correctly.
-
- if (!rangeTarget) {
- return;
}
- var selection = window.getSelection();
- var range = document.createRange();
- range.selectNodeContents(rangeTarget);
- range.collapse(!isReverse);
+ let range = getRange(container, isReverse); // If no range range can be created or it is outside the container, the
+ // element may be out of view.
+
+ if (!range || !range.startContainer || !container.contains(range.startContainer)) {
+ container.scrollIntoView(isReverse);
+ range = getRange(container, isReverse);
+
+ if (!range || !range.startContainer || !container.contains(range.startContainer)) {
+ return;
+ }
+ }
+
+ const {
+ ownerDocument
+ } = container;
+ const {
+ defaultView
+ } = ownerDocument;
+ assertIsDefined(defaultView, 'defaultView');
+ const selection = defaultView.getSelection();
+ assertIsDefined(selection, 'selection');
selection.removeAllRanges();
selection.addRange(range);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/place-caret-at-vertical-edge.js
/**
- * Polyfill.
- * Get a collapsed range for a given point.
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
- *
- * @param {Document} doc The document of the range.
- * @param {number} x Horizontal position within the current viewport.
- * @param {number} y Vertical position within the current viewport.
- *
- * @return {?Range} The best range for the given point.
- */
-
-function caretRangeFromPoint(doc, x, y) {
- if (doc.caretRangeFromPoint) {
- return doc.caretRangeFromPoint(x, y);
- }
-
- if (!doc.caretPositionFromPoint) {
- return null;
- }
-
- var point = doc.caretPositionFromPoint(x, y); // If x or y are negative, outside viewport, or there is no text entry node.
- // https://developer.mozilla.org/en-US/docs/Web/API/Document/caretRangeFromPoint
-
- if (!point) {
- return null;
- }
-
- var range = doc.createRange();
- range.setStart(point.offsetNode, point.offset);
- range.collapse(true);
- return range;
-}
-/**
- * Get a collapsed range for a given point.
- * Gives the container a temporary high z-index (above any UI).
- * This is preferred over getting the UI nodes and set styles there.
- *
- * @param {Document} doc The document of the range.
- * @param {number} x Horizontal position within the current viewport.
- * @param {number} y Vertical position within the current viewport.
- * @param {Element} container Container in which the range is expected to be found.
- *
- * @return {?Range} The best range for the given point.
+ * Internal dependencies
*/
-function hiddenCaretRangeFromPoint(doc, x, y, container) {
- var originalZIndex = container.style.zIndex;
- var originalPosition = container.style.position; // A z-index only works if the element position is not static.
- container.style.zIndex = '10000';
- container.style.position = 'relative';
- var range = caretRangeFromPoint(doc, x, y);
- container.style.zIndex = originalZIndex;
- container.style.position = originalPosition;
- return range;
-}
/**
* Places the caret at the top or bottom of a given element.
*
- * @param {Element} container Focusable element.
+ * @param {HTMLElement} container Focusable element.
* @param {boolean} isReverse True for bottom, false for top.
* @param {DOMRect} [rect] The rectangle to position the caret with.
* @param {boolean} [mayUseScroll=true] True to allow scrolling, false to disallow.
*/
-
-function placeCaretAtVerticalEdge(container, isReverse, rect) {
- var mayUseScroll = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
-
+function placeCaretAtVerticalEdge(container, isReverse, rect, mayUseScroll = true) {
if (!container) {
return;
}
@@ -786,19 +1376,26 @@
if (!rect || !container.isContentEditable) {
placeCaretAtHorizontalEdge(container, isReverse);
return;
- } // Offset by a buffer half the height of the caret rect. This is needed
+ }
+
+ container.focus(); // Offset by a buffer half the height of the caret rect. This is needed
// because caretRangeFromPoint may default to the end of the selection if
// offset is too close to the edge. It's unclear how to precisely calculate
// this threshold; it may be the padded area of some combination of line
// height, caret height, and font size. The buffer offset is effectively
// equivalent to a point at half the height of a line of text.
-
- var buffer = rect.height / 2;
- var editableRect = container.getBoundingClientRect();
- var x = rect.left;
- var y = isReverse ? editableRect.bottom - buffer : editableRect.top + buffer;
- var range = hiddenCaretRangeFromPoint(document, x, y, container);
+ const buffer = rect.height / 2;
+ const editableRect = container.getBoundingClientRect();
+ const x = rect.left;
+ const y = isReverse ? editableRect.bottom - buffer : editableRect.top + buffer;
+ const {
+ ownerDocument
+ } = container;
+ const {
+ defaultView
+ } = ownerDocument;
+ const range = hiddenCaretRangeFromPoint(ownerDocument, x, y, container);
if (!range || !container.contains(range.startContainer)) {
if (mayUseScroll && (!range || !range.startContainer || !range.startContainer.contains(container))) {
@@ -813,219 +1410,56 @@
return;
}
- var selection = window.getSelection();
- selection.removeAllRanges();
- selection.addRange(range);
- container.focus(); // Editable was already focussed, it goes back to old range...
- // This fixes it.
-
+ assertIsDefined(defaultView, 'defaultView');
+ const selection = defaultView.getSelection();
+ assertIsDefined(selection, 'selection');
selection.removeAllRanges();
selection.addRange(range);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/insert-after.js
/**
- * Check whether the given element is a text field, where text field is defined
- * by the ability to select within the input, or that it is contenteditable.
- *
- * See: https://html.spec.whatwg.org/#textFieldSelection
- *
- * @param {HTMLElement} element The HTML element.
- *
- * @return {boolean} True if the element is an text field, false if not.
+ * Internal dependencies
*/
-function isTextField(element) {
- var nodeName = element.nodeName,
- contentEditable = element.contentEditable;
- var nonTextInputs = ['button', 'checkbox', 'hidden', 'file', 'radio', 'image', 'range', 'reset', 'submit', 'number'];
- return nodeName === 'INPUT' && !nonTextInputs.includes(element.type) || nodeName === 'TEXTAREA' || contentEditable === 'true';
-}
/**
- * Check whether the given element is an input field of type number
- * and has a valueAsNumber
- *
- * @param {HTMLElement} element The HTML element.
+ * Given two DOM nodes, inserts the former in the DOM as the next sibling of
+ * the latter.
*
- * @return {boolean} True if the element is input and holds a number.
- */
-
-function isNumberInput(element) {
- var nodeName = element.nodeName,
- type = element.type,
- valueAsNumber = element.valueAsNumber;
- return nodeName === 'INPUT' && type === 'number' && !!valueAsNumber;
-}
-/**
- * Check whether the current document has selected text. This applies to ranges
- * of text in the document, and not selection inside <input> and <textarea>
- * elements.
- *
- * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects.
- *
- * @return {boolean} True if there is selection, false if not.
+ * @param {Node} newNode Node to be inserted.
+ * @param {Node} referenceNode Node after which to perform the insertion.
+ * @return {void}
*/
-function documentHasTextSelection() {
- var selection = window.getSelection();
- var range = selection.rangeCount ? selection.getRangeAt(0) : null;
- return range && !range.collapsed;
+function insertAfter(newNode, referenceNode) {
+ assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode');
+ referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove.js
/**
- * Check whether the given element, assumed an input field or textarea,
- * contains a (uncollapsed) selection of text.
- *
- * Note: this is perhaps an abuse of the term "selection", since these elements
- * manage selection differently and aren't covered by Selection#collapsed.
- *
- * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects.
- *
- * @param {HTMLElement} element The HTML element.
- *
- * @return {boolean} Whether the input/textareaa element has some "selection".
+ * Internal dependencies
*/
-function inputFieldHasUncollapsedSelection(element) {
- if (!isTextField(element) && !isNumberInput(element)) {
- return false;
- }
+/**
+ * Given a DOM node, removes it from the DOM.
+ *
+ * @param {Node} node Node to be removed.
+ * @return {void}
+ */
- try {
- var selectionStart = element.selectionStart,
- selectionEnd = element.selectionEnd;
- return selectionStart !== null && selectionStart !== selectionEnd;
- } catch (error) {
- // Safari throws an exception when trying to get `selectionStart`
- // on non-text <input> elements (which, understandably, don't
- // have the text selection API). We catch this via a try/catch
- // block, as opposed to a more explicit check of the element's
- // input types, because of Safari's non-standard behavior. This
- // also means we don't have to worry about the list of input
- // types that support `selectionStart` changing as the HTML spec
- // evolves over time.
- return false;
- }
+function remove(node) {
+ assertIsDefined(node.parentNode, 'node.parentNode');
+ node.parentNode.removeChild(node);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace.js
/**
- * Check whether the current document has any sort of selection. This includes
- * ranges of text across elements and any selection inside <input> and
- * <textarea> elements.
- *
- * @return {boolean} Whether there is any sort of "selection" in the document.
+ * Internal dependencies
*/
-function documentHasUncollapsedSelection() {
- return documentHasTextSelection() || inputFieldHasUncollapsedSelection(document.activeElement);
-}
-/**
- * Check whether the current document has a selection. This checks for both
- * focus in an input field and general text selection.
- *
- * @return {boolean} True if there is selection, false if not.
- */
-function documentHasSelection() {
- return isTextField(document.activeElement) || isNumberInput(document.activeElement) || documentHasTextSelection();
-}
-/**
- * Check whether the contents of the element have been entirely selected.
- * Returns true if there is no possibility of selection.
- *
- * @param {Element} element The element to check.
- *
- * @return {boolean} True if entirely selected, false if not.
- */
-
-function isEntirelySelected(element) {
- if (Object(external_this_lodash_["includes"])(['INPUT', 'TEXTAREA'], element.nodeName)) {
- return element.selectionStart === 0 && element.value.length === element.selectionEnd;
- }
-
- if (!element.isContentEditable) {
- return true;
- }
-
- var selection = window.getSelection();
- var range = selection.rangeCount ? selection.getRangeAt(0) : null;
-
- if (!range) {
- return true;
- }
-
- var startContainer = range.startContainer,
- endContainer = range.endContainer,
- startOffset = range.startOffset,
- endOffset = range.endOffset;
-
- if (startContainer === element && endContainer === element && startOffset === 0 && endOffset === element.childNodes.length) {
- return true;
- }
-
- var lastChild = element.lastChild;
- var lastChildContentLength = lastChild.nodeType === TEXT_NODE ? lastChild.data.length : lastChild.childNodes.length;
- return startContainer === element.firstChild && endContainer === element.lastChild && startOffset === 0 && endOffset === lastChildContentLength;
-}
-/**
- * Given a DOM node, finds the closest scrollable container node.
- *
- * @param {Element} node Node from which to start.
- *
- * @return {?Element} Scrollable container node, if found.
- */
-
-function getScrollContainer(node) {
- if (!node) {
- return;
- } // Scrollable if scrollable height exceeds displayed...
-
-
- if (node.scrollHeight > node.clientHeight) {
- // ...except when overflow is defined to be hidden or visible
- var _window$getComputedSt = window.getComputedStyle(node),
- overflowY = _window$getComputedSt.overflowY;
-
- if (/(auto|scroll)/.test(overflowY)) {
- return node;
- }
- } // Continue traversing
-
-
- return getScrollContainer(node.parentNode);
-}
-/**
- * Returns the closest positioned element, or null under any of the conditions
- * of the offsetParent specification. Unlike offsetParent, this function is not
- * limited to HTMLElement and accepts any Node (e.g. Node.TEXT_NODE).
- *
- * @see https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
- *
- * @param {Node} node Node from which to find offset parent.
- *
- * @return {?Node} Offset parent.
- */
-
-function getOffsetParent(node) {
- // Cannot retrieve computed style or offset parent only anything other than
- // an element node, so find the closest element node.
- var closestElement;
-
- while (closestElement = node.parentNode) {
- if (closestElement.nodeType === ELEMENT_NODE) {
- break;
- }
- }
-
- if (!closestElement) {
- return null;
- } // If the closest element is already positioned, return it, as offsetParent
- // does not otherwise consider the node itself.
-
-
- if (getComputedStyle(closestElement).position !== 'static') {
- return closestElement;
- }
-
- return closestElement.offsetParent;
-}
/**
* Given two DOM nodes, replaces the former with the latter in the DOM.
*
@@ -1035,31 +1469,16 @@
*/
function replace(processedNode, newNode) {
+ assertIsDefined(processedNode.parentNode, 'processedNode.parentNode');
insertAfter(newNode, processedNode.parentNode);
remove(processedNode);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/unwrap.js
/**
- * Given a DOM node, removes it from the DOM.
- *
- * @param {Element} node Node to be removed.
- * @return {void}
+ * Internal dependencies
*/
-function remove(node) {
- node.parentNode.removeChild(node);
-}
-/**
- * Given two DOM nodes, inserts the former in the DOM as the next sibling of
- * the latter.
- *
- * @param {Element} newNode Node to be inserted.
- * @param {Element} referenceNode Node after which to perform the insertion.
- * @return {void}
- */
-
-function insertAfter(newNode, referenceNode) {
- referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
-}
/**
* Unwrap the given node. This means any child nodes are moved to the parent.
*
@@ -1069,7 +1488,8 @@
*/
function unwrap(node) {
- var parent = node.parentNode;
+ const parent = node.parentNode;
+ assertIsDefined(parent, 'node.parentNode');
while (node.firstChild) {
parent.insertBefore(node.firstChild, node);
@@ -1077,6 +1497,12 @@
parent.removeChild(node);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/replace-tag.js
+/**
+ * Internal dependencies
+ */
+
/**
* Replaces the given node with a new node with the given tag name.
*
@@ -1087,15 +1513,22 @@
*/
function replaceTag(node, tagName) {
- var newNode = node.ownerDocument.createElement(tagName);
+ const newNode = node.ownerDocument.createElement(tagName);
while (node.firstChild) {
newNode.appendChild(node.firstChild);
}
+ assertIsDefined(node.parentNode, 'node.parentNode');
node.parentNode.replaceChild(newNode, node);
return newNode;
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/wrap.js
+/**
+ * Internal dependencies
+ */
+
/**
* Wraps the given node with a new node with the given tag name.
*
@@ -1104,9 +1537,12 @@
*/
function wrap(newNode, referenceNode) {
+ assertIsDefined(referenceNode.parentNode, 'referenceNode.parentNode');
referenceNode.parentNode.insertBefore(newNode, referenceNode);
newNode.appendChild(referenceNode);
}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/strip-html.js
/**
* Removes any HTML tags from the provided string.
*
@@ -1114,10 +1550,503 @@
*
* @return {string} The text content with any html removed.
*/
+function stripHTML(html) {
+ const document = new window.DOMParser().parseFromString(html, 'text/html');
+ return document.body.textContent || '';
+}
-function __unstableStripHTML(html) {
- var document = new DOMParser().parseFromString(html, 'text/html');
- return document.body.textContent || '';
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-empty.js
+/**
+ * Recursively checks if an element is empty. An element is not empty if it
+ * contains text or contains elements with attributes such as images.
+ *
+ * @param {Element} element The element to check.
+ *
+ * @return {boolean} Whether or not the element is empty.
+ */
+function isEmpty(element) {
+ switch (element.nodeType) {
+ case element.TEXT_NODE:
+ // We cannot use \s since it includes special spaces which we want
+ // to preserve.
+ return /^[ \f\n\r\t\v\u00a0]*$/.test(element.nodeValue || '');
+
+ case element.ELEMENT_NODE:
+ if (element.hasAttributes()) {
+ return false;
+ } else if (!element.hasChildNodes()) {
+ return true;
+ }
+
+ return (
+ /** @type {Element[]} */
+ Array.from(element.childNodes).every(isEmpty)
+ );
+
+ default:
+ return true;
+ }
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/phrasing-content.js
+/**
+ * External dependencies
+ */
+
+/**
+ * All phrasing content elements.
+ *
+ * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0
+ */
+
+/**
+ * @typedef {Record<string,SemanticElementDefinition>} ContentSchema
+ */
+
+/**
+ * @typedef SemanticElementDefinition
+ * @property {string[]} [attributes] Content attributes
+ * @property {ContentSchema} [children] Content attributes
+ */
+
+/**
+ * All text-level semantic elements.
+ *
+ * @see https://html.spec.whatwg.org/multipage/text-level-semantics.html
+ *
+ * @type {ContentSchema}
+ */
+
+const textContentSchema = {
+ strong: {},
+ em: {},
+ s: {},
+ del: {},
+ ins: {},
+ a: {
+ attributes: ['href', 'target', 'rel']
+ },
+ code: {},
+ abbr: {
+ attributes: ['title']
+ },
+ sub: {},
+ sup: {},
+ br: {},
+ small: {},
+ // To do: fix blockquote.
+ // cite: {},
+ q: {
+ attributes: ['cite']
+ },
+ dfn: {
+ attributes: ['title']
+ },
+ data: {
+ attributes: ['value']
+ },
+ time: {
+ attributes: ['datetime']
+ },
+ var: {},
+ samp: {},
+ kbd: {},
+ i: {},
+ b: {},
+ u: {},
+ mark: {},
+ ruby: {},
+ rt: {},
+ rp: {},
+ bdi: {
+ attributes: ['dir']
+ },
+ bdo: {
+ attributes: ['dir']
+ },
+ wbr: {},
+ '#text': {}
+}; // Recursion is needed.
+// Possible: strong > em > strong.
+// Impossible: strong > strong.
+
+Object(external_lodash_["without"])(Object.keys(textContentSchema), '#text', 'br').forEach(tag => {
+ textContentSchema[tag].children = Object(external_lodash_["omit"])(textContentSchema, tag);
+});
+/**
+ * Embedded content elements.
+ *
+ * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#embedded-content-0
+ *
+ * @type {ContentSchema}
+ */
+
+const embeddedContentSchema = {
+ audio: {
+ attributes: ['src', 'preload', 'autoplay', 'mediagroup', 'loop', 'muted']
+ },
+ canvas: {
+ attributes: ['width', 'height']
+ },
+ embed: {
+ attributes: ['src', 'type', 'width', 'height']
+ },
+ img: {
+ attributes: ['alt', 'src', 'srcset', 'usemap', 'ismap', 'width', 'height']
+ },
+ object: {
+ attributes: ['data', 'type', 'name', 'usemap', 'form', 'width', 'height']
+ },
+ video: {
+ attributes: ['src', 'poster', 'preload', 'autoplay', 'mediagroup', 'loop', 'muted', 'controls', 'width', 'height']
+ }
+};
+/**
+ * Phrasing content elements.
+ *
+ * @see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content-0
+ */
+
+const phrasingContentSchema = { ...textContentSchema,
+ ...embeddedContentSchema
+};
+/**
+ * Get schema of possible paths for phrasing content.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
+ *
+ * @param {string} [context] Set to "paste" to exclude invisible elements and
+ * sensitive data.
+ *
+ * @return {Partial<ContentSchema>} Schema.
+ */
+
+function getPhrasingContentSchema(context) {
+ if (context !== 'paste') {
+ return phrasingContentSchema;
+ }
+
+ return Object(external_lodash_["omit"])({ ...phrasingContentSchema,
+ // We shouldn't paste potentially sensitive information which is not
+ // visible to the user when pasted, so strip the attributes.
+ ins: {
+ children: phrasingContentSchema.ins.children
+ },
+ del: {
+ children: phrasingContentSchema.del.children
+ }
+ }, ['u', // Used to mark misspelling. Shouldn't be pasted.
+ 'abbr', // Invisible.
+ 'data', // Invisible.
+ 'time', // Invisible.
+ 'wbr', // Invisible.
+ 'bdi', // Invisible.
+ 'bdo' // Invisible.
+ ]);
+}
+/**
+ * Find out whether or not the given node is phrasing content.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
+ *
+ * @param {Node} node The node to test.
+ *
+ * @return {boolean} True if phrasing content, false if not.
+ */
+
+function isPhrasingContent(node) {
+ const tag = node.nodeName.toLowerCase();
+ return getPhrasingContentSchema().hasOwnProperty(tag) || tag === 'span';
+}
+/**
+ * @param {Node} node
+ * @return {boolean} Node is text content
+ */
+
+function isTextContent(node) {
+ const tag = node.nodeName.toLowerCase();
+ return textContentSchema.hasOwnProperty(tag) || tag === 'span';
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/is-element.js
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * @param {Node | null | undefined} node
+ * @return {node is Element} True if node is an Element node
+ */
+function isElement(node) {
+ /* eslint-enable jsdoc/valid-types */
+ return !!node && node.nodeType === node.ELEMENT_NODE;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/clean-node-list.js
+/**
+ * External dependencies
+ */
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+
+
+/* eslint-disable jsdoc/valid-types */
+
+/**
+ * @typedef SchemaItem
+ * @property {string[]} [attributes] Attributes.
+ * @property {(string | RegExp)[]} [classes] Classnames or RegExp to test against.
+ * @property {'*' | { [tag: string]: SchemaItem }} [children] Child schemas.
+ * @property {string[]} [require] Selectors to test required children against. Leave empty or undefined if there are no requirements.
+ * @property {boolean} allowEmpty Whether to allow nodes without children.
+ * @property {(node: Node) => boolean} [isMatch] Function to test whether a node is a match. If left undefined any node will be assumed to match.
+ */
+
+/** @typedef {{ [tag: string]: SchemaItem }} Schema */
+
+/* eslint-enable jsdoc/valid-types */
+
+/**
+ * Given a schema, unwraps or removes nodes, attributes and classes on a node
+ * list.
+ *
+ * @param {NodeList} nodeList The nodeList to filter.
+ * @param {Document} doc The document of the nodeList.
+ * @param {Schema} schema An array of functions that can mutate with the provided node.
+ * @param {boolean} inline Whether to clean for inline mode.
+ */
+
+function cleanNodeList(nodeList, doc, schema, inline) {
+ Array.from(nodeList).forEach(
+ /** @type {Node & { nextElementSibling?: unknown }} */
+ node => {
+ var _schema$tag$isMatch, _schema$tag;
+
+ const tag = node.nodeName.toLowerCase(); // It's a valid child, if the tag exists in the schema without an isMatch
+ // function, or with an isMatch function that matches the node.
+
+ 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))) {
+ if (isElement(node)) {
+ const {
+ attributes = [],
+ classes = [],
+ children,
+ require = [],
+ allowEmpty
+ } = schema[tag]; // If the node is empty and it's supposed to have children,
+ // remove the node.
+
+ if (children && !allowEmpty && isEmpty(node)) {
+ remove(node);
+ return;
+ }
+
+ if (node.hasAttributes()) {
+ // Strip invalid attributes.
+ Array.from(node.attributes).forEach(({
+ name
+ }) => {
+ if (name !== 'class' && !Object(external_lodash_["includes"])(attributes, name)) {
+ node.removeAttribute(name);
+ }
+ }); // Strip invalid classes.
+ // In jsdom-jscore, 'node.classList' can be undefined.
+ // TODO: Explore patching this in jsdom-jscore.
+
+ if (node.classList && node.classList.length) {
+ const mattchers = classes.map(item => {
+ if (typeof item === 'string') {
+ return (
+ /** @type {string} */
+ className => className === item
+ );
+ } else if (item instanceof RegExp) {
+ return (
+ /** @type {string} */
+ className => item.test(className)
+ );
+ }
+
+ return external_lodash_["noop"];
+ });
+ Array.from(node.classList).forEach(name => {
+ if (!mattchers.some(isMatch => isMatch(name))) {
+ node.classList.remove(name);
+ }
+ });
+
+ if (!node.classList.length) {
+ node.removeAttribute('class');
+ }
+ }
+ }
+
+ if (node.hasChildNodes()) {
+ // Do not filter any content.
+ if (children === '*') {
+ return;
+ } // Continue if the node is supposed to have children.
+
+
+ if (children) {
+ // If a parent requires certain children, but it does
+ // not have them, drop the parent and continue.
+ if (require.length && !node.querySelector(require.join(','))) {
+ cleanNodeList(node.childNodes, doc, schema, inline);
+ unwrap(node); // If the node is at the top, phrasing content, and
+ // contains children that are block content, unwrap
+ // the node because it is invalid.
+ } else if (node.parentNode && node.parentNode.nodeName === 'BODY' && isPhrasingContent(node)) {
+ cleanNodeList(node.childNodes, doc, schema, inline);
+
+ if (Array.from(node.childNodes).some(child => !isPhrasingContent(child))) {
+ unwrap(node);
+ }
+ } else {
+ cleanNodeList(node.childNodes, doc, children, inline);
+ } // Remove children if the node is not supposed to have any.
+
+ } else {
+ while (node.firstChild) {
+ remove(node.firstChild);
+ }
+ }
+ }
+ } // Invalid child. Continue with schema at the same place and unwrap.
+
+ } else {
+ cleanNodeList(node.childNodes, doc, schema, inline); // For inline mode, insert a line break when unwrapping nodes that
+ // are not phrasing content.
+
+ if (inline && !isPhrasingContent(node) && node.nextElementSibling) {
+ insertAfter(doc.createElement('br'), node);
+ }
+
+ unwrap(node);
+ }
+ });
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/remove-invalid-html.js
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Given a schema, unwraps or removes nodes, attributes and classes on HTML.
+ *
+ * @param {string} HTML The HTML to clean up.
+ * @param {import('./clean-node-list').Schema} schema Schema for the HTML.
+ * @param {boolean} inline Whether to clean for inline mode.
+ *
+ * @return {string} The cleaned up HTML.
+ */
+
+function removeInvalidHTML(HTML, schema, inline) {
+ const doc = document.implementation.createHTMLDocument('');
+ doc.body.innerHTML = HTML;
+ cleanNodeList(doc.body.childNodes, doc, schema, inline);
+ return doc.body.innerHTML;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/safe-html.js
+/**
+ * Internal dependencies
+ */
+
+/**
+ * Strips scripts and on* attributes from HTML.
+ *
+ * @param {string} html HTML to sanitize.
+ *
+ * @return {string} The sanitized HTML.
+ */
+
+function safeHTML(html) {
+ const {
+ body
+ } = document.implementation.createHTMLDocument('');
+ body.innerHTML = html;
+ const elements = body.getElementsByTagName('*');
+ let elementIndex = elements.length;
+
+ while (elementIndex--) {
+ const element = elements[elementIndex];
+
+ if (element.tagName === 'SCRIPT') {
+ remove(element);
+ } else {
+ let attributeIndex = element.attributes.length;
+
+ while (attributeIndex--) {
+ const {
+ name: key
+ } = element.attributes[attributeIndex];
+
+ if (key.startsWith('on')) {
+ element.removeAttribute(key);
+ }
+ }
+ }
+ }
+
+ return body.innerHTML;
+}
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/dom/index.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/data-transfer.js
+/**
+ * Gets all files from a DataTransfer object.
+ *
+ * @param {DataTransfer} dataTransfer DataTransfer object to inspect.
+ *
+ * @return {File[]} An array containing all files.
+ */
+function getFilesFromDataTransfer(dataTransfer) {
+ const files = Array.from(dataTransfer.files);
+ Array.from(dataTransfer.items).forEach(item => {
+ const file = item.getAsFile();
+
+ if (file && !files.find(({
+ name,
+ type,
+ size
+ }) => name === file.name && type === file.type && size === file.size)) {
+ files.push(file);
+ }
+ });
+ return files;
}
// CONCATENATED MODULE: ./node_modules/@wordpress/dom/build-module/index.js
@@ -1131,13 +2060,22 @@
* under the keys with the same name.
*/
-var build_module_focus = {
+const build_module_focus = {
focusable: focusable_namespaceObject,
tabbable: tabbable_namespaceObject
};
+
+
+/***/ }),
+
+/***/ "YLtl":
+/***/ (function(module, exports) {
+
+(function() { module.exports = window["lodash"]; }());
+
/***/ })
/******/ });
\ No newline at end of file