Нет описания

dom.js 62KB

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