rich-text.js 128 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520
  1. /******/ (function() { // webpackBootstrap
  2. /******/ "use strict";
  3. /******/ // The require scope
  4. /******/ var __webpack_require__ = {};
  5. /******/
  6. /************************************************************************/
  7. /******/ /* webpack/runtime/compat get default export */
  8. /******/ !function() {
  9. /******/ // getDefaultExport function for compatibility with non-harmony modules
  10. /******/ __webpack_require__.n = function(module) {
  11. /******/ var getter = module && module.__esModule ?
  12. /******/ function() { return module['default']; } :
  13. /******/ function() { return module; };
  14. /******/ __webpack_require__.d(getter, { a: getter });
  15. /******/ return getter;
  16. /******/ };
  17. /******/ }();
  18. /******/
  19. /******/ /* webpack/runtime/define property getters */
  20. /******/ !function() {
  21. /******/ // define getter functions for harmony exports
  22. /******/ __webpack_require__.d = function(exports, definition) {
  23. /******/ for(var key in definition) {
  24. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  25. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  26. /******/ }
  27. /******/ }
  28. /******/ };
  29. /******/ }();
  30. /******/
  31. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  32. /******/ !function() {
  33. /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
  34. /******/ }();
  35. /******/
  36. /******/ /* webpack/runtime/make namespace object */
  37. /******/ !function() {
  38. /******/ // define __esModule on exports
  39. /******/ __webpack_require__.r = function(exports) {
  40. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  41. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  42. /******/ }
  43. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  44. /******/ };
  45. /******/ }();
  46. /******/
  47. /************************************************************************/
  48. var __webpack_exports__ = {};
  49. // ESM COMPAT FLAG
  50. __webpack_require__.r(__webpack_exports__);
  51. // EXPORTS
  52. __webpack_require__.d(__webpack_exports__, {
  53. "__UNSTABLE_LINE_SEPARATOR": function() { return /* reexport */ LINE_SEPARATOR; },
  54. "__experimentalRichText": function() { return /* reexport */ __experimentalRichText; },
  55. "__unstableCreateElement": function() { return /* reexport */ createElement; },
  56. "__unstableFormatEdit": function() { return /* reexport */ FormatEdit; },
  57. "__unstableInsertLineSeparator": function() { return /* reexport */ insertLineSeparator; },
  58. "__unstableIsEmptyLine": function() { return /* reexport */ isEmptyLine; },
  59. "__unstableToDom": function() { return /* reexport */ toDom; },
  60. "__unstableUseRichText": function() { return /* reexport */ useRichText; },
  61. "applyFormat": function() { return /* reexport */ applyFormat; },
  62. "concat": function() { return /* reexport */ concat; },
  63. "create": function() { return /* reexport */ create; },
  64. "getActiveFormat": function() { return /* reexport */ getActiveFormat; },
  65. "getActiveFormats": function() { return /* reexport */ getActiveFormats; },
  66. "getActiveObject": function() { return /* reexport */ getActiveObject; },
  67. "getTextContent": function() { return /* reexport */ getTextContent; },
  68. "insert": function() { return /* reexport */ insert; },
  69. "insertObject": function() { return /* reexport */ insertObject; },
  70. "isCollapsed": function() { return /* reexport */ isCollapsed; },
  71. "isEmpty": function() { return /* reexport */ isEmpty; },
  72. "join": function() { return /* reexport */ join; },
  73. "registerFormatType": function() { return /* reexport */ registerFormatType; },
  74. "remove": function() { return /* reexport */ remove; },
  75. "removeFormat": function() { return /* reexport */ removeFormat; },
  76. "replace": function() { return /* reexport */ replace_replace; },
  77. "slice": function() { return /* reexport */ slice; },
  78. "split": function() { return /* reexport */ split; },
  79. "store": function() { return /* reexport */ store; },
  80. "toHTMLString": function() { return /* reexport */ toHTMLString; },
  81. "toggleFormat": function() { return /* reexport */ toggleFormat; },
  82. "unregisterFormatType": function() { return /* reexport */ unregisterFormatType; },
  83. "useAnchor": function() { return /* reexport */ useAnchor; },
  84. "useAnchorRef": function() { return /* reexport */ useAnchorRef; }
  85. });
  86. // NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
  87. var selectors_namespaceObject = {};
  88. __webpack_require__.r(selectors_namespaceObject);
  89. __webpack_require__.d(selectors_namespaceObject, {
  90. "getFormatType": function() { return getFormatType; },
  91. "getFormatTypeForBareElement": function() { return getFormatTypeForBareElement; },
  92. "getFormatTypeForClassName": function() { return getFormatTypeForClassName; },
  93. "getFormatTypes": function() { return getFormatTypes; }
  94. });
  95. // NAMESPACE OBJECT: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
  96. var actions_namespaceObject = {};
  97. __webpack_require__.r(actions_namespaceObject);
  98. __webpack_require__.d(actions_namespaceObject, {
  99. "addFormatTypes": function() { return addFormatTypes; },
  100. "removeFormatTypes": function() { return removeFormatTypes; }
  101. });
  102. ;// CONCATENATED MODULE: external ["wp","data"]
  103. var external_wp_data_namespaceObject = window["wp"]["data"];
  104. ;// CONCATENATED MODULE: external "lodash"
  105. var external_lodash_namespaceObject = window["lodash"];
  106. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/reducer.js
  107. /**
  108. * External dependencies
  109. */
  110. /**
  111. * WordPress dependencies
  112. */
  113. /**
  114. * Reducer managing the format types
  115. *
  116. * @param {Object} state Current state.
  117. * @param {Object} action Dispatched action.
  118. *
  119. * @return {Object} Updated state.
  120. */
  121. function formatTypes() {
  122. let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  123. let action = arguments.length > 1 ? arguments[1] : undefined;
  124. switch (action.type) {
  125. case 'ADD_FORMAT_TYPES':
  126. return { ...state,
  127. // Key format types by their name.
  128. ...action.formatTypes.reduce((newFormatTypes, type) => ({ ...newFormatTypes,
  129. [type.name]: type
  130. }), {})
  131. };
  132. case 'REMOVE_FORMAT_TYPES':
  133. return (0,external_lodash_namespaceObject.omit)(state, action.names);
  134. }
  135. return state;
  136. }
  137. /* harmony default export */ var reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
  138. formatTypes
  139. }));
  140. ;// CONCATENATED MODULE: ./node_modules/rememo/rememo.js
  141. /** @typedef {(...args: any[]) => *[]} GetDependants */
  142. /** @typedef {() => void} Clear */
  143. /**
  144. * @typedef {{
  145. * getDependants: GetDependants,
  146. * clear: Clear
  147. * }} EnhancedSelector
  148. */
  149. /**
  150. * Internal cache entry.
  151. *
  152. * @typedef CacheNode
  153. *
  154. * @property {?CacheNode|undefined} [prev] Previous node.
  155. * @property {?CacheNode|undefined} [next] Next node.
  156. * @property {*[]} args Function arguments for cache entry.
  157. * @property {*} val Function result.
  158. */
  159. /**
  160. * @typedef Cache
  161. *
  162. * @property {Clear} clear Function to clear cache.
  163. * @property {boolean} [isUniqueByDependants] Whether dependants are valid in
  164. * considering cache uniqueness. A cache is unique if dependents are all arrays
  165. * or objects.
  166. * @property {CacheNode?} [head] Cache head.
  167. * @property {*[]} [lastDependants] Dependants from previous invocation.
  168. */
  169. /**
  170. * Arbitrary value used as key for referencing cache object in WeakMap tree.
  171. *
  172. * @type {{}}
  173. */
  174. var LEAF_KEY = {};
  175. /**
  176. * Returns the first argument as the sole entry in an array.
  177. *
  178. * @template T
  179. *
  180. * @param {T} value Value to return.
  181. *
  182. * @return {[T]} Value returned as entry in array.
  183. */
  184. function arrayOf(value) {
  185. return [value];
  186. }
  187. /**
  188. * Returns true if the value passed is object-like, or false otherwise. A value
  189. * is object-like if it can support property assignment, e.g. object or array.
  190. *
  191. * @param {*} value Value to test.
  192. *
  193. * @return {boolean} Whether value is object-like.
  194. */
  195. function isObjectLike(value) {
  196. return !!value && 'object' === typeof value;
  197. }
  198. /**
  199. * Creates and returns a new cache object.
  200. *
  201. * @return {Cache} Cache object.
  202. */
  203. function createCache() {
  204. /** @type {Cache} */
  205. var cache = {
  206. clear: function () {
  207. cache.head = null;
  208. },
  209. };
  210. return cache;
  211. }
  212. /**
  213. * Returns true if entries within the two arrays are strictly equal by
  214. * reference from a starting index.
  215. *
  216. * @param {*[]} a First array.
  217. * @param {*[]} b Second array.
  218. * @param {number} fromIndex Index from which to start comparison.
  219. *
  220. * @return {boolean} Whether arrays are shallowly equal.
  221. */
  222. function isShallowEqual(a, b, fromIndex) {
  223. var i;
  224. if (a.length !== b.length) {
  225. return false;
  226. }
  227. for (i = fromIndex; i < a.length; i++) {
  228. if (a[i] !== b[i]) {
  229. return false;
  230. }
  231. }
  232. return true;
  233. }
  234. /**
  235. * Returns a memoized selector function. The getDependants function argument is
  236. * called before the memoized selector and is expected to return an immutable
  237. * reference or array of references on which the selector depends for computing
  238. * its own return value. The memoize cache is preserved only as long as those
  239. * dependant references remain the same. If getDependants returns a different
  240. * reference(s), the cache is cleared and the selector value regenerated.
  241. *
  242. * @template {(...args: *[]) => *} S
  243. *
  244. * @param {S} selector Selector function.
  245. * @param {GetDependants=} getDependants Dependant getter returning an array of
  246. * references used in cache bust consideration.
  247. */
  248. /* harmony default export */ function rememo(selector, getDependants) {
  249. /** @type {WeakMap<*,*>} */
  250. var rootCache;
  251. /** @type {GetDependants} */
  252. var normalizedGetDependants = getDependants ? getDependants : arrayOf;
  253. /**
  254. * Returns the cache for a given dependants array. When possible, a WeakMap
  255. * will be used to create a unique cache for each set of dependants. This
  256. * is feasible due to the nature of WeakMap in allowing garbage collection
  257. * to occur on entries where the key object is no longer referenced. Since
  258. * WeakMap requires the key to be an object, this is only possible when the
  259. * dependant is object-like. The root cache is created as a hierarchy where
  260. * each top-level key is the first entry in a dependants set, the value a
  261. * WeakMap where each key is the next dependant, and so on. This continues
  262. * so long as the dependants are object-like. If no dependants are object-
  263. * like, then the cache is shared across all invocations.
  264. *
  265. * @see isObjectLike
  266. *
  267. * @param {*[]} dependants Selector dependants.
  268. *
  269. * @return {Cache} Cache object.
  270. */
  271. function getCache(dependants) {
  272. var caches = rootCache,
  273. isUniqueByDependants = true,
  274. i,
  275. dependant,
  276. map,
  277. cache;
  278. for (i = 0; i < dependants.length; i++) {
  279. dependant = dependants[i];
  280. // Can only compose WeakMap from object-like key.
  281. if (!isObjectLike(dependant)) {
  282. isUniqueByDependants = false;
  283. break;
  284. }
  285. // Does current segment of cache already have a WeakMap?
  286. if (caches.has(dependant)) {
  287. // Traverse into nested WeakMap.
  288. caches = caches.get(dependant);
  289. } else {
  290. // Create, set, and traverse into a new one.
  291. map = new WeakMap();
  292. caches.set(dependant, map);
  293. caches = map;
  294. }
  295. }
  296. // We use an arbitrary (but consistent) object as key for the last item
  297. // in the WeakMap to serve as our running cache.
  298. if (!caches.has(LEAF_KEY)) {
  299. cache = createCache();
  300. cache.isUniqueByDependants = isUniqueByDependants;
  301. caches.set(LEAF_KEY, cache);
  302. }
  303. return caches.get(LEAF_KEY);
  304. }
  305. /**
  306. * Resets root memoization cache.
  307. */
  308. function clear() {
  309. rootCache = new WeakMap();
  310. }
  311. /* eslint-disable jsdoc/check-param-names */
  312. /**
  313. * The augmented selector call, considering first whether dependants have
  314. * changed before passing it to underlying memoize function.
  315. *
  316. * @param {*} source Source object for derivation.
  317. * @param {...*} extraArgs Additional arguments to pass to selector.
  318. *
  319. * @return {*} Selector result.
  320. */
  321. /* eslint-enable jsdoc/check-param-names */
  322. function callSelector(/* source, ...extraArgs */) {
  323. var len = arguments.length,
  324. cache,
  325. node,
  326. i,
  327. args,
  328. dependants;
  329. // Create copy of arguments (avoid leaking deoptimization).
  330. args = new Array(len);
  331. for (i = 0; i < len; i++) {
  332. args[i] = arguments[i];
  333. }
  334. dependants = normalizedGetDependants.apply(null, args);
  335. cache = getCache(dependants);
  336. // If not guaranteed uniqueness by dependants (primitive type), shallow
  337. // compare against last dependants and, if references have changed,
  338. // destroy cache to recalculate result.
  339. if (!cache.isUniqueByDependants) {
  340. if (
  341. cache.lastDependants &&
  342. !isShallowEqual(dependants, cache.lastDependants, 0)
  343. ) {
  344. cache.clear();
  345. }
  346. cache.lastDependants = dependants;
  347. }
  348. node = cache.head;
  349. while (node) {
  350. // Check whether node arguments match arguments
  351. if (!isShallowEqual(node.args, args, 1)) {
  352. node = node.next;
  353. continue;
  354. }
  355. // At this point we can assume we've found a match
  356. // Surface matched node to head if not already
  357. if (node !== cache.head) {
  358. // Adjust siblings to point to each other.
  359. /** @type {CacheNode} */ (node.prev).next = node.next;
  360. if (node.next) {
  361. node.next.prev = node.prev;
  362. }
  363. node.next = cache.head;
  364. node.prev = null;
  365. /** @type {CacheNode} */ (cache.head).prev = node;
  366. cache.head = node;
  367. }
  368. // Return immediately
  369. return node.val;
  370. }
  371. // No cached value found. Continue to insertion phase:
  372. node = /** @type {CacheNode} */ ({
  373. // Generate the result from original function
  374. val: selector.apply(null, args),
  375. });
  376. // Avoid including the source object in the cache.
  377. args[0] = null;
  378. node.args = args;
  379. // Don't need to check whether node is already head, since it would
  380. // have been returned above already if it was
  381. // Shift existing head down list
  382. if (cache.head) {
  383. cache.head.prev = node;
  384. node.next = cache.head;
  385. }
  386. cache.head = node;
  387. return node.val;
  388. }
  389. callSelector.getDependants = normalizedGetDependants;
  390. callSelector.clear = clear;
  391. clear();
  392. return /** @type {S & EnhancedSelector} */ (callSelector);
  393. }
  394. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/selectors.js
  395. /**
  396. * External dependencies
  397. */
  398. /**
  399. * Returns all the available format types.
  400. *
  401. * @param {Object} state Data state.
  402. *
  403. * @return {Array} Format types.
  404. */
  405. const getFormatTypes = rememo(state => Object.values(state.formatTypes), state => [state.formatTypes]);
  406. /**
  407. * Returns a format type by name.
  408. *
  409. * @param {Object} state Data state.
  410. * @param {string} name Format type name.
  411. *
  412. * @return {Object?} Format type.
  413. */
  414. function getFormatType(state, name) {
  415. return state.formatTypes[name];
  416. }
  417. /**
  418. * Gets the format type, if any, that can handle a bare element (without a
  419. * data-format-type attribute), given the tag name of this element.
  420. *
  421. * @param {Object} state Data state.
  422. * @param {string} bareElementTagName The tag name of the element to find a
  423. * format type for.
  424. * @return {?Object} Format type.
  425. */
  426. function getFormatTypeForBareElement(state, bareElementTagName) {
  427. return (0,external_lodash_namespaceObject.find)(getFormatTypes(state), _ref => {
  428. let {
  429. className,
  430. tagName
  431. } = _ref;
  432. return className === null && bareElementTagName === tagName;
  433. });
  434. }
  435. /**
  436. * Gets the format type, if any, that can handle an element, given its classes.
  437. *
  438. * @param {Object} state Data state.
  439. * @param {string} elementClassName The classes of the element to find a format
  440. * type for.
  441. * @return {?Object} Format type.
  442. */
  443. function getFormatTypeForClassName(state, elementClassName) {
  444. return (0,external_lodash_namespaceObject.find)(getFormatTypes(state), _ref2 => {
  445. let {
  446. className
  447. } = _ref2;
  448. if (className === null) {
  449. return false;
  450. }
  451. return ` ${elementClassName} `.indexOf(` ${className} `) >= 0;
  452. });
  453. }
  454. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/actions.js
  455. /**
  456. * External dependencies
  457. */
  458. /**
  459. * Returns an action object used in signalling that format types have been
  460. * added.
  461. *
  462. * @param {Array|Object} formatTypes Format types received.
  463. *
  464. * @return {Object} Action object.
  465. */
  466. function addFormatTypes(formatTypes) {
  467. return {
  468. type: 'ADD_FORMAT_TYPES',
  469. formatTypes: (0,external_lodash_namespaceObject.castArray)(formatTypes)
  470. };
  471. }
  472. /**
  473. * Returns an action object used to remove a registered format type.
  474. *
  475. * @param {string|Array} names Format name.
  476. *
  477. * @return {Object} Action object.
  478. */
  479. function removeFormatTypes(names) {
  480. return {
  481. type: 'REMOVE_FORMAT_TYPES',
  482. names: (0,external_lodash_namespaceObject.castArray)(names)
  483. };
  484. }
  485. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/store/index.js
  486. /**
  487. * WordPress dependencies
  488. */
  489. /**
  490. * Internal dependencies
  491. */
  492. const STORE_NAME = 'core/rich-text';
  493. /**
  494. * Store definition for the rich-text namespace.
  495. *
  496. * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
  497. *
  498. * @type {Object}
  499. */
  500. const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
  501. reducer: reducer,
  502. selectors: selectors_namespaceObject,
  503. actions: actions_namespaceObject
  504. });
  505. (0,external_wp_data_namespaceObject.register)(store);
  506. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-format-equal.js
  507. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  508. /**
  509. * Optimised equality check for format objects.
  510. *
  511. * @param {?RichTextFormat} format1 Format to compare.
  512. * @param {?RichTextFormat} format2 Format to compare.
  513. *
  514. * @return {boolean} True if formats are equal, false if not.
  515. */
  516. function isFormatEqual(format1, format2) {
  517. // Both not defined.
  518. if (format1 === format2) {
  519. return true;
  520. } // Either not defined.
  521. if (!format1 || !format2) {
  522. return false;
  523. }
  524. if (format1.type !== format2.type) {
  525. return false;
  526. }
  527. const attributes1 = format1.attributes;
  528. const attributes2 = format2.attributes; // Both not defined.
  529. if (attributes1 === attributes2) {
  530. return true;
  531. } // Either not defined.
  532. if (!attributes1 || !attributes2) {
  533. return false;
  534. }
  535. const keys1 = Object.keys(attributes1);
  536. const keys2 = Object.keys(attributes2);
  537. if (keys1.length !== keys2.length) {
  538. return false;
  539. }
  540. const length = keys1.length; // Optimise for speed.
  541. for (let i = 0; i < length; i++) {
  542. const name = keys1[i];
  543. if (attributes1[name] !== attributes2[name]) {
  544. return false;
  545. }
  546. }
  547. return true;
  548. }
  549. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/normalise-formats.js
  550. /**
  551. * Internal dependencies
  552. */
  553. /** @typedef {import('./create').RichTextValue} RichTextValue */
  554. /**
  555. * Normalises formats: ensures subsequent adjacent equal formats have the same
  556. * reference.
  557. *
  558. * @param {RichTextValue} value Value to normalise formats of.
  559. *
  560. * @return {RichTextValue} New value with normalised formats.
  561. */
  562. function normaliseFormats(value) {
  563. const newFormats = value.formats.slice();
  564. newFormats.forEach((formatsAtIndex, index) => {
  565. const formatsAtPreviousIndex = newFormats[index - 1];
  566. if (formatsAtPreviousIndex) {
  567. const newFormatsAtIndex = formatsAtIndex.slice();
  568. newFormatsAtIndex.forEach((format, formatIndex) => {
  569. const previousFormat = formatsAtPreviousIndex[formatIndex];
  570. if (isFormatEqual(format, previousFormat)) {
  571. newFormatsAtIndex[formatIndex] = previousFormat;
  572. }
  573. });
  574. newFormats[index] = newFormatsAtIndex;
  575. }
  576. });
  577. return { ...value,
  578. formats: newFormats
  579. };
  580. }
  581. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/apply-format.js
  582. /**
  583. * Internal dependencies
  584. */
  585. /** @typedef {import('./create').RichTextValue} RichTextValue */
  586. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  587. function replace(array, index, value) {
  588. array = array.slice();
  589. array[index] = value;
  590. return array;
  591. }
  592. /**
  593. * Apply a format object to a Rich Text value from the given `startIndex` to the
  594. * given `endIndex`. Indices are retrieved from the selection if none are
  595. * provided.
  596. *
  597. * @param {RichTextValue} value Value to modify.
  598. * @param {RichTextFormat} format Format to apply.
  599. * @param {number} [startIndex] Start index.
  600. * @param {number} [endIndex] End index.
  601. *
  602. * @return {RichTextValue} A new value with the format applied.
  603. */
  604. function applyFormat(value, format) {
  605. let startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : value.start;
  606. let endIndex = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : value.end;
  607. const {
  608. formats,
  609. activeFormats
  610. } = value;
  611. const newFormats = formats.slice(); // The selection is collapsed.
  612. if (startIndex === endIndex) {
  613. var _newFormats$startInde;
  614. const startFormat = (_newFormats$startInde = newFormats[startIndex]) === null || _newFormats$startInde === void 0 ? void 0 : _newFormats$startInde.find(_ref => {
  615. let {
  616. type
  617. } = _ref;
  618. return type === format.type;
  619. }); // If the caret is at a format of the same type, expand start and end to
  620. // the edges of the format. This is useful to apply new attributes.
  621. if (startFormat) {
  622. const index = newFormats[startIndex].indexOf(startFormat);
  623. while (newFormats[startIndex] && newFormats[startIndex][index] === startFormat) {
  624. newFormats[startIndex] = replace(newFormats[startIndex], index, format);
  625. startIndex--;
  626. }
  627. endIndex++;
  628. while (newFormats[endIndex] && newFormats[endIndex][index] === startFormat) {
  629. newFormats[endIndex] = replace(newFormats[endIndex], index, format);
  630. endIndex++;
  631. }
  632. }
  633. } else {
  634. // Determine the highest position the new format can be inserted at.
  635. let position = +Infinity;
  636. for (let index = startIndex; index < endIndex; index++) {
  637. if (newFormats[index]) {
  638. newFormats[index] = newFormats[index].filter(_ref2 => {
  639. let {
  640. type
  641. } = _ref2;
  642. return type !== format.type;
  643. });
  644. const length = newFormats[index].length;
  645. if (length < position) {
  646. position = length;
  647. }
  648. } else {
  649. newFormats[index] = [];
  650. position = 0;
  651. }
  652. }
  653. for (let index = startIndex; index < endIndex; index++) {
  654. newFormats[index].splice(position, 0, format);
  655. }
  656. }
  657. return normaliseFormats({ ...value,
  658. formats: newFormats,
  659. // Always revise active formats. This serves as a placeholder for new
  660. // inputs with the format so new input appears with the format applied,
  661. // and ensures a format of the same type uses the latest values.
  662. activeFormats: [...((activeFormats === null || activeFormats === void 0 ? void 0 : activeFormats.filter(_ref3 => {
  663. let {
  664. type
  665. } = _ref3;
  666. return type !== format.type;
  667. })) || []), format]
  668. });
  669. }
  670. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create-element.js
  671. /**
  672. * Parse the given HTML into a body element.
  673. *
  674. * Note: The current implementation will return a shared reference, reset on
  675. * each call to `createElement`. Therefore, you should not hold a reference to
  676. * the value to operate upon asynchronously, as it may have unexpected results.
  677. *
  678. * @param {HTMLDocument} document The HTML document to use to parse.
  679. * @param {string} html The HTML to parse.
  680. *
  681. * @return {HTMLBodyElement} Body element with parsed HTML.
  682. */
  683. function createElement(_ref, html) {
  684. let {
  685. implementation
  686. } = _ref;
  687. // Because `createHTMLDocument` is an expensive operation, and with this
  688. // function being internal to `rich-text` (full control in avoiding a risk
  689. // of asynchronous operations on the shared reference), a single document
  690. // is reused and reset for each call to the function.
  691. if (!createElement.body) {
  692. createElement.body = implementation.createHTMLDocument('').body;
  693. }
  694. createElement.body.innerHTML = html;
  695. return createElement.body;
  696. }
  697. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/special-characters.js
  698. /**
  699. * Line separator character, used for multiline text.
  700. */
  701. const LINE_SEPARATOR = '\u2028';
  702. /**
  703. * Object replacement character, used as a placeholder for objects.
  704. */
  705. const OBJECT_REPLACEMENT_CHARACTER = '\ufffc';
  706. /**
  707. * Zero width non-breaking space, used as padding in the editable DOM tree when
  708. * it is empty otherwise.
  709. */
  710. const ZWNBSP = '\ufeff';
  711. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/create.js
  712. /**
  713. * WordPress dependencies
  714. */
  715. /**
  716. * Internal dependencies
  717. */
  718. /**
  719. * @typedef {Object} RichTextFormat
  720. *
  721. * @property {string} type Format type.
  722. */
  723. /**
  724. * @typedef {Array<RichTextFormat>} RichTextFormatList
  725. */
  726. /**
  727. * @typedef {Object} RichTextValue
  728. *
  729. * @property {string} text Text.
  730. * @property {Array<RichTextFormatList>} formats Formats.
  731. * @property {Array<RichTextFormat>} replacements Replacements.
  732. * @property {number|undefined} start Selection start.
  733. * @property {number|undefined} end Selection end.
  734. */
  735. function createEmptyValue() {
  736. return {
  737. formats: [],
  738. replacements: [],
  739. text: ''
  740. };
  741. }
  742. function toFormat(_ref) {
  743. let {
  744. type,
  745. attributes
  746. } = _ref;
  747. let formatType;
  748. if (attributes && attributes.class) {
  749. formatType = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForClassName(attributes.class);
  750. if (formatType) {
  751. // Preserve any additional classes.
  752. attributes.class = ` ${attributes.class} `.replace(` ${formatType.className} `, ' ').trim();
  753. if (!attributes.class) {
  754. delete attributes.class;
  755. }
  756. }
  757. }
  758. if (!formatType) {
  759. formatType = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForBareElement(type);
  760. }
  761. if (!formatType) {
  762. return attributes ? {
  763. type,
  764. attributes
  765. } : {
  766. type
  767. };
  768. }
  769. if (formatType.__experimentalCreatePrepareEditableTree && !formatType.__experimentalCreateOnChangeEditableValue) {
  770. return null;
  771. }
  772. if (!attributes) {
  773. return {
  774. type: formatType.name
  775. };
  776. }
  777. const registeredAttributes = {};
  778. const unregisteredAttributes = {};
  779. const _attributes = { ...attributes
  780. };
  781. for (const key in formatType.attributes) {
  782. const name = formatType.attributes[key];
  783. registeredAttributes[key] = _attributes[name];
  784. if (formatType.__unstableFilterAttributeValue) {
  785. registeredAttributes[key] = formatType.__unstableFilterAttributeValue(key, registeredAttributes[key]);
  786. } // delete the attribute and what's left is considered
  787. // to be unregistered.
  788. delete _attributes[name];
  789. if (typeof registeredAttributes[key] === 'undefined') {
  790. delete registeredAttributes[key];
  791. }
  792. }
  793. for (const name in _attributes) {
  794. unregisteredAttributes[name] = attributes[name];
  795. }
  796. return {
  797. type: formatType.name,
  798. attributes: registeredAttributes,
  799. unregisteredAttributes
  800. };
  801. }
  802. /**
  803. * Create a RichText value from an `Element` tree (DOM), an HTML string or a
  804. * plain text string, with optionally a `Range` object to set the selection. If
  805. * called without any input, an empty value will be created. If
  806. * `multilineTag` is provided, any content of direct children whose type matches
  807. * `multilineTag` will be separated by two newlines. The optional functions can
  808. * be used to filter out content.
  809. *
  810. * A value will have the following shape, which you are strongly encouraged not
  811. * to modify without the use of helper functions:
  812. *
  813. * ```js
  814. * {
  815. * text: string,
  816. * formats: Array,
  817. * replacements: Array,
  818. * ?start: number,
  819. * ?end: number,
  820. * }
  821. * ```
  822. *
  823. * As you can see, text and formatting are separated. `text` holds the text,
  824. * including any replacement characters for objects and lines. `formats`,
  825. * `objects` and `lines` are all sparse arrays of the same length as `text`. It
  826. * holds information about the formatting at the relevant text indices. Finally
  827. * `start` and `end` state which text indices are selected. They are only
  828. * provided if a `Range` was given.
  829. *
  830. * @param {Object} [$1] Optional named arguments.
  831. * @param {Element} [$1.element] Element to create value from.
  832. * @param {string} [$1.text] Text to create value from.
  833. * @param {string} [$1.html] HTML to create value from.
  834. * @param {Range} [$1.range] Range to create value from.
  835. * @param {string} [$1.multilineTag] Multiline tag if the structure is
  836. * multiline.
  837. * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if
  838. * nesting is possible.
  839. * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white
  840. * space characters.
  841. * @param {boolean} [$1.__unstableIsEditableTree]
  842. *
  843. * @return {RichTextValue} A rich text value.
  844. */
  845. function create() {
  846. let {
  847. element,
  848. text,
  849. html,
  850. range,
  851. multilineTag,
  852. multilineWrapperTags,
  853. __unstableIsEditableTree: isEditableTree,
  854. preserveWhiteSpace
  855. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  856. if (typeof text === 'string' && text.length > 0) {
  857. return {
  858. formats: Array(text.length),
  859. replacements: Array(text.length),
  860. text
  861. };
  862. }
  863. if (typeof html === 'string' && html.length > 0) {
  864. // It does not matter which document this is, we're just using it to
  865. // parse.
  866. element = createElement(document, html);
  867. }
  868. if (typeof element !== 'object') {
  869. return createEmptyValue();
  870. }
  871. if (!multilineTag) {
  872. return createFromElement({
  873. element,
  874. range,
  875. isEditableTree,
  876. preserveWhiteSpace
  877. });
  878. }
  879. return createFromMultilineElement({
  880. element,
  881. range,
  882. multilineTag,
  883. multilineWrapperTags,
  884. isEditableTree,
  885. preserveWhiteSpace
  886. });
  887. }
  888. /**
  889. * Helper to accumulate the value's selection start and end from the current
  890. * node and range.
  891. *
  892. * @param {Object} accumulator Object to accumulate into.
  893. * @param {Node} node Node to create value with.
  894. * @param {Range} range Range to create value with.
  895. * @param {Object} value Value that is being accumulated.
  896. */
  897. function accumulateSelection(accumulator, node, range, value) {
  898. if (!range) {
  899. return;
  900. }
  901. const {
  902. parentNode
  903. } = node;
  904. const {
  905. startContainer,
  906. startOffset,
  907. endContainer,
  908. endOffset
  909. } = range;
  910. const currentLength = accumulator.text.length; // Selection can be extracted from value.
  911. if (value.start !== undefined) {
  912. accumulator.start = currentLength + value.start; // Range indicates that the current node has selection.
  913. } else if (node === startContainer && node.nodeType === node.TEXT_NODE) {
  914. accumulator.start = currentLength + startOffset; // Range indicates that the current node is selected.
  915. } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset]) {
  916. accumulator.start = currentLength; // Range indicates that the selection is after the current node.
  917. } else if (parentNode === startContainer && node === startContainer.childNodes[startOffset - 1]) {
  918. accumulator.start = currentLength + value.text.length; // Fallback if no child inside handled the selection.
  919. } else if (node === startContainer) {
  920. accumulator.start = currentLength;
  921. } // Selection can be extracted from value.
  922. if (value.end !== undefined) {
  923. accumulator.end = currentLength + value.end; // Range indicates that the current node has selection.
  924. } else if (node === endContainer && node.nodeType === node.TEXT_NODE) {
  925. accumulator.end = currentLength + endOffset; // Range indicates that the current node is selected.
  926. } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset - 1]) {
  927. accumulator.end = currentLength + value.text.length; // Range indicates that the selection is before the current node.
  928. } else if (parentNode === endContainer && node === endContainer.childNodes[endOffset]) {
  929. accumulator.end = currentLength; // Fallback if no child inside handled the selection.
  930. } else if (node === endContainer) {
  931. accumulator.end = currentLength + endOffset;
  932. }
  933. }
  934. /**
  935. * Adjusts the start and end offsets from a range based on a text filter.
  936. *
  937. * @param {Node} node Node of which the text should be filtered.
  938. * @param {Range} range The range to filter.
  939. * @param {Function} filter Function to use to filter the text.
  940. *
  941. * @return {Object|void} Object containing range properties.
  942. */
  943. function filterRange(node, range, filter) {
  944. if (!range) {
  945. return;
  946. }
  947. const {
  948. startContainer,
  949. endContainer
  950. } = range;
  951. let {
  952. startOffset,
  953. endOffset
  954. } = range;
  955. if (node === startContainer) {
  956. startOffset = filter(node.nodeValue.slice(0, startOffset)).length;
  957. }
  958. if (node === endContainer) {
  959. endOffset = filter(node.nodeValue.slice(0, endOffset)).length;
  960. }
  961. return {
  962. startContainer,
  963. startOffset,
  964. endContainer,
  965. endOffset
  966. };
  967. }
  968. /**
  969. * Collapse any whitespace used for HTML formatting to one space character,
  970. * because it will also be displayed as such by the browser.
  971. *
  972. * @param {string} string
  973. */
  974. function collapseWhiteSpace(string) {
  975. return string.replace(/[\n\r\t]+/g, ' ');
  976. }
  977. /**
  978. * Removes reserved characters used by rich-text (zero width non breaking spaces added by `toTree` and object replacement characters).
  979. *
  980. * @param {string} string
  981. */
  982. function removeReservedCharacters(string) {
  983. // with the global flag, note that we should create a new regex each time OR reset lastIndex state.
  984. return string.replace(new RegExp(`[${ZWNBSP}${OBJECT_REPLACEMENT_CHARACTER}]`, 'gu'), '');
  985. }
  986. /**
  987. * Creates a Rich Text value from a DOM element and range.
  988. *
  989. * @param {Object} $1 Named argements.
  990. * @param {Element} [$1.element] Element to create value from.
  991. * @param {Range} [$1.range] Range to create value from.
  992. * @param {string} [$1.multilineTag] Multiline tag if the structure is
  993. * multiline.
  994. * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if
  995. * nesting is possible.
  996. * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white
  997. * space characters.
  998. * @param {Array} [$1.currentWrapperTags]
  999. * @param {boolean} [$1.isEditableTree]
  1000. *
  1001. * @return {RichTextValue} A rich text value.
  1002. */
  1003. function createFromElement(_ref2) {
  1004. let {
  1005. element,
  1006. range,
  1007. multilineTag,
  1008. multilineWrapperTags,
  1009. currentWrapperTags = [],
  1010. isEditableTree,
  1011. preserveWhiteSpace
  1012. } = _ref2;
  1013. const accumulator = createEmptyValue();
  1014. if (!element) {
  1015. return accumulator;
  1016. }
  1017. if (!element.hasChildNodes()) {
  1018. accumulateSelection(accumulator, element, range, createEmptyValue());
  1019. return accumulator;
  1020. }
  1021. const length = element.childNodes.length; // Optimise for speed.
  1022. for (let index = 0; index < length; index++) {
  1023. const node = element.childNodes[index];
  1024. const type = node.nodeName.toLowerCase();
  1025. if (node.nodeType === node.TEXT_NODE) {
  1026. let filter = removeReservedCharacters;
  1027. if (!preserveWhiteSpace) {
  1028. filter = string => removeReservedCharacters(collapseWhiteSpace(string));
  1029. }
  1030. const text = filter(node.nodeValue);
  1031. range = filterRange(node, range, filter);
  1032. accumulateSelection(accumulator, node, range, {
  1033. text
  1034. }); // Create a sparse array of the same length as `text`, in which
  1035. // formats can be added.
  1036. accumulator.formats.length += text.length;
  1037. accumulator.replacements.length += text.length;
  1038. accumulator.text += text;
  1039. continue;
  1040. }
  1041. if (node.nodeType !== node.ELEMENT_NODE) {
  1042. continue;
  1043. }
  1044. if (isEditableTree && ( // Ignore any placeholders.
  1045. node.getAttribute('data-rich-text-placeholder') || // Ignore any line breaks that are not inserted by us.
  1046. type === 'br' && !node.getAttribute('data-rich-text-line-break'))) {
  1047. accumulateSelection(accumulator, node, range, createEmptyValue());
  1048. continue;
  1049. }
  1050. if (type === 'script') {
  1051. const value = {
  1052. formats: [,],
  1053. replacements: [{
  1054. type,
  1055. attributes: {
  1056. 'data-rich-text-script': node.getAttribute('data-rich-text-script') || encodeURIComponent(node.innerHTML)
  1057. }
  1058. }],
  1059. text: OBJECT_REPLACEMENT_CHARACTER
  1060. };
  1061. accumulateSelection(accumulator, node, range, value);
  1062. mergePair(accumulator, value);
  1063. continue;
  1064. }
  1065. if (type === 'br') {
  1066. accumulateSelection(accumulator, node, range, createEmptyValue());
  1067. mergePair(accumulator, create({
  1068. text: '\n'
  1069. }));
  1070. continue;
  1071. }
  1072. const format = toFormat({
  1073. type,
  1074. attributes: getAttributes({
  1075. element: node
  1076. })
  1077. });
  1078. if (multilineWrapperTags && multilineWrapperTags.indexOf(type) !== -1) {
  1079. const value = createFromMultilineElement({
  1080. element: node,
  1081. range,
  1082. multilineTag,
  1083. multilineWrapperTags,
  1084. currentWrapperTags: [...currentWrapperTags, format],
  1085. isEditableTree,
  1086. preserveWhiteSpace
  1087. });
  1088. accumulateSelection(accumulator, node, range, value);
  1089. mergePair(accumulator, value);
  1090. continue;
  1091. }
  1092. const value = createFromElement({
  1093. element: node,
  1094. range,
  1095. multilineTag,
  1096. multilineWrapperTags,
  1097. isEditableTree,
  1098. preserveWhiteSpace
  1099. });
  1100. accumulateSelection(accumulator, node, range, value);
  1101. if (!format) {
  1102. mergePair(accumulator, value);
  1103. } else if (value.text.length === 0) {
  1104. if (format.attributes) {
  1105. mergePair(accumulator, {
  1106. formats: [,],
  1107. replacements: [format],
  1108. text: OBJECT_REPLACEMENT_CHARACTER
  1109. });
  1110. }
  1111. } else {
  1112. // Indices should share a reference to the same formats array.
  1113. // Only create a new reference if `formats` changes.
  1114. function mergeFormats(formats) {
  1115. if (mergeFormats.formats === formats) {
  1116. return mergeFormats.newFormats;
  1117. }
  1118. const newFormats = formats ? [format, ...formats] : [format];
  1119. mergeFormats.formats = formats;
  1120. mergeFormats.newFormats = newFormats;
  1121. return newFormats;
  1122. } // Since the formats parameter can be `undefined`, preset
  1123. // `mergeFormats` with a new reference.
  1124. mergeFormats.newFormats = [format];
  1125. mergePair(accumulator, { ...value,
  1126. formats: Array.from(value.formats, mergeFormats)
  1127. });
  1128. }
  1129. }
  1130. return accumulator;
  1131. }
  1132. /**
  1133. * Creates a rich text value from a DOM element and range that should be
  1134. * multiline.
  1135. *
  1136. * @param {Object} $1 Named argements.
  1137. * @param {Element} [$1.element] Element to create value from.
  1138. * @param {Range} [$1.range] Range to create value from.
  1139. * @param {string} [$1.multilineTag] Multiline tag if the structure is
  1140. * multiline.
  1141. * @param {Array} [$1.multilineWrapperTags] Tags where lines can be found if
  1142. * nesting is possible.
  1143. * @param {Array} [$1.currentWrapperTags] Whether to prepend a line
  1144. * separator.
  1145. * @param {boolean} [$1.preserveWhiteSpace] Whether or not to collapse white
  1146. * space characters.
  1147. * @param {boolean} [$1.isEditableTree]
  1148. *
  1149. * @return {RichTextValue} A rich text value.
  1150. */
  1151. function createFromMultilineElement(_ref3) {
  1152. let {
  1153. element,
  1154. range,
  1155. multilineTag,
  1156. multilineWrapperTags,
  1157. currentWrapperTags = [],
  1158. isEditableTree,
  1159. preserveWhiteSpace
  1160. } = _ref3;
  1161. const accumulator = createEmptyValue();
  1162. if (!element || !element.hasChildNodes()) {
  1163. return accumulator;
  1164. }
  1165. const length = element.children.length; // Optimise for speed.
  1166. for (let index = 0; index < length; index++) {
  1167. const node = element.children[index];
  1168. if (node.nodeName.toLowerCase() !== multilineTag) {
  1169. continue;
  1170. }
  1171. const value = createFromElement({
  1172. element: node,
  1173. range,
  1174. multilineTag,
  1175. multilineWrapperTags,
  1176. currentWrapperTags,
  1177. isEditableTree,
  1178. preserveWhiteSpace
  1179. }); // Multiline value text should be separated by a line separator.
  1180. if (index !== 0 || currentWrapperTags.length > 0) {
  1181. mergePair(accumulator, {
  1182. formats: [,],
  1183. replacements: currentWrapperTags.length > 0 ? [currentWrapperTags] : [,],
  1184. text: LINE_SEPARATOR
  1185. });
  1186. }
  1187. accumulateSelection(accumulator, node, range, value);
  1188. mergePair(accumulator, value);
  1189. }
  1190. return accumulator;
  1191. }
  1192. /**
  1193. * Gets the attributes of an element in object shape.
  1194. *
  1195. * @param {Object} $1 Named argements.
  1196. * @param {Element} $1.element Element to get attributes from.
  1197. *
  1198. * @return {Object|void} Attribute object or `undefined` if the element has no
  1199. * attributes.
  1200. */
  1201. function getAttributes(_ref4) {
  1202. let {
  1203. element
  1204. } = _ref4;
  1205. if (!element.hasAttributes()) {
  1206. return;
  1207. }
  1208. const length = element.attributes.length;
  1209. let accumulator; // Optimise for speed.
  1210. for (let i = 0; i < length; i++) {
  1211. const {
  1212. name,
  1213. value
  1214. } = element.attributes[i];
  1215. if (name.indexOf('data-rich-text-') === 0) {
  1216. continue;
  1217. }
  1218. const safeName = /^on/i.test(name) ? 'data-disable-rich-text-' + name : name;
  1219. accumulator = accumulator || {};
  1220. accumulator[safeName] = value;
  1221. }
  1222. return accumulator;
  1223. }
  1224. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/concat.js
  1225. /**
  1226. * Internal dependencies
  1227. */
  1228. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1229. /**
  1230. * Concats a pair of rich text values. Not that this mutates `a` and does NOT
  1231. * normalise formats!
  1232. *
  1233. * @param {Object} a Value to mutate.
  1234. * @param {Object} b Value to add read from.
  1235. *
  1236. * @return {Object} `a`, mutated.
  1237. */
  1238. function mergePair(a, b) {
  1239. a.formats = a.formats.concat(b.formats);
  1240. a.replacements = a.replacements.concat(b.replacements);
  1241. a.text += b.text;
  1242. return a;
  1243. }
  1244. /**
  1245. * Combine all Rich Text values into one. This is similar to
  1246. * `String.prototype.concat`.
  1247. *
  1248. * @param {...RichTextValue} values Objects to combine.
  1249. *
  1250. * @return {RichTextValue} A new value combining all given records.
  1251. */
  1252. function concat() {
  1253. for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {
  1254. values[_key] = arguments[_key];
  1255. }
  1256. return normaliseFormats(values.reduce(mergePair, create()));
  1257. }
  1258. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-formats.js
  1259. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1260. /** @typedef {import('./create').RichTextFormatList} RichTextFormatList */
  1261. /**
  1262. * Gets the all format objects at the start of the selection.
  1263. *
  1264. * @param {RichTextValue} value Value to inspect.
  1265. * @param {Array} EMPTY_ACTIVE_FORMATS Array to return if there are no
  1266. * active formats.
  1267. *
  1268. * @return {RichTextFormatList} Active format objects.
  1269. */
  1270. function getActiveFormats(_ref) {
  1271. let {
  1272. formats,
  1273. start,
  1274. end,
  1275. activeFormats
  1276. } = _ref;
  1277. let EMPTY_ACTIVE_FORMATS = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  1278. if (start === undefined) {
  1279. return EMPTY_ACTIVE_FORMATS;
  1280. }
  1281. if (start === end) {
  1282. // For a collapsed caret, it is possible to override the active formats.
  1283. if (activeFormats) {
  1284. return activeFormats;
  1285. }
  1286. const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS;
  1287. const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS; // By default, select the lowest amount of formats possible (which means
  1288. // the caret is positioned outside the format boundary). The user can
  1289. // then use arrow keys to define `activeFormats`.
  1290. if (formatsBefore.length < formatsAfter.length) {
  1291. return formatsBefore;
  1292. }
  1293. return formatsAfter;
  1294. }
  1295. return formats[start] || EMPTY_ACTIVE_FORMATS;
  1296. }
  1297. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-format.js
  1298. /**
  1299. * External dependencies
  1300. */
  1301. /**
  1302. * Internal dependencies
  1303. */
  1304. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1305. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  1306. /**
  1307. * Gets the format object by type at the start of the selection. This can be
  1308. * used to get e.g. the URL of a link format at the current selection, but also
  1309. * to check if a format is active at the selection. Returns undefined if there
  1310. * is no format at the selection.
  1311. *
  1312. * @param {RichTextValue} value Value to inspect.
  1313. * @param {string} formatType Format type to look for.
  1314. *
  1315. * @return {RichTextFormat|undefined} Active format object of the specified
  1316. * type, or undefined.
  1317. */
  1318. function getActiveFormat(value, formatType) {
  1319. return (0,external_lodash_namespaceObject.find)(getActiveFormats(value), {
  1320. type: formatType
  1321. });
  1322. }
  1323. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-active-object.js
  1324. /**
  1325. * Internal dependencies
  1326. */
  1327. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1328. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  1329. /**
  1330. * Gets the active object, if there is any.
  1331. *
  1332. * @param {RichTextValue} value Value to inspect.
  1333. *
  1334. * @return {RichTextFormat|void} Active object, or undefined.
  1335. */
  1336. function getActiveObject(_ref) {
  1337. let {
  1338. start,
  1339. end,
  1340. replacements,
  1341. text
  1342. } = _ref;
  1343. if (start + 1 !== end || text[start] !== OBJECT_REPLACEMENT_CHARACTER) {
  1344. return;
  1345. }
  1346. return replacements[start];
  1347. }
  1348. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-text-content.js
  1349. /**
  1350. * Internal dependencies
  1351. */
  1352. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1353. const pattern = new RegExp(`[${OBJECT_REPLACEMENT_CHARACTER}${LINE_SEPARATOR}]`, 'g');
  1354. /**
  1355. * Get the textual content of a Rich Text value. This is similar to
  1356. * `Element.textContent`.
  1357. *
  1358. * @param {RichTextValue} value Value to use.
  1359. *
  1360. * @return {string} The text content.
  1361. */
  1362. function getTextContent(_ref) {
  1363. let {
  1364. text
  1365. } = _ref;
  1366. return text.replace(pattern, c => c === OBJECT_REPLACEMENT_CHARACTER ? '' : '\n');
  1367. }
  1368. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-collapsed.js
  1369. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1370. /**
  1371. * Check if the selection of a Rich Text value is collapsed or not. Collapsed
  1372. * means that no characters are selected, but there is a caret present. If there
  1373. * is no selection, `undefined` will be returned. This is similar to
  1374. * `window.getSelection().isCollapsed()`.
  1375. *
  1376. * @param {RichTextValue} value The rich text value to check.
  1377. *
  1378. * @return {boolean|undefined} True if the selection is collapsed, false if not,
  1379. * undefined if there is no selection.
  1380. */
  1381. function isCollapsed(_ref) {
  1382. let {
  1383. start,
  1384. end
  1385. } = _ref;
  1386. if (start === undefined || end === undefined) {
  1387. return;
  1388. }
  1389. return start === end;
  1390. }
  1391. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/is-empty.js
  1392. /**
  1393. * Internal dependencies
  1394. */
  1395. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1396. /**
  1397. * Check if a Rich Text value is Empty, meaning it contains no text or any
  1398. * objects (such as images).
  1399. *
  1400. * @param {RichTextValue} value Value to use.
  1401. *
  1402. * @return {boolean} True if the value is empty, false if not.
  1403. */
  1404. function isEmpty(_ref) {
  1405. let {
  1406. text
  1407. } = _ref;
  1408. return text.length === 0;
  1409. }
  1410. /**
  1411. * Check if the current collapsed selection is on an empty line in case of a
  1412. * multiline value.
  1413. *
  1414. * @param {RichTextValue} value Value te check.
  1415. *
  1416. * @return {boolean} True if the line is empty, false if not.
  1417. */
  1418. function isEmptyLine(_ref2) {
  1419. let {
  1420. text,
  1421. start,
  1422. end
  1423. } = _ref2;
  1424. if (start !== end) {
  1425. return false;
  1426. }
  1427. if (text.length === 0) {
  1428. return true;
  1429. }
  1430. if (start === 0 && text.slice(0, 1) === LINE_SEPARATOR) {
  1431. return true;
  1432. }
  1433. if (start === text.length && text.slice(-1) === LINE_SEPARATOR) {
  1434. return true;
  1435. }
  1436. return text.slice(start - 1, end + 1) === `${LINE_SEPARATOR}${LINE_SEPARATOR}`;
  1437. }
  1438. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/join.js
  1439. /**
  1440. * Internal dependencies
  1441. */
  1442. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1443. /**
  1444. * Combine an array of Rich Text values into one, optionally separated by
  1445. * `separator`, which can be a Rich Text value, HTML string, or plain text
  1446. * string. This is similar to `Array.prototype.join`.
  1447. *
  1448. * @param {Array<RichTextValue>} values An array of values to join.
  1449. * @param {string|RichTextValue} [separator] Separator string or value.
  1450. *
  1451. * @return {RichTextValue} A new combined value.
  1452. */
  1453. function join(values) {
  1454. let separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  1455. if (typeof separator === 'string') {
  1456. separator = create({
  1457. text: separator
  1458. });
  1459. }
  1460. return normaliseFormats(values.reduce((accumlator, _ref) => {
  1461. let {
  1462. formats,
  1463. replacements,
  1464. text
  1465. } = _ref;
  1466. return {
  1467. formats: accumlator.formats.concat(separator.formats, formats),
  1468. replacements: accumlator.replacements.concat(separator.replacements, replacements),
  1469. text: accumlator.text + separator.text + text
  1470. };
  1471. }));
  1472. }
  1473. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/register-format-type.js
  1474. /**
  1475. * WordPress dependencies
  1476. */
  1477. /**
  1478. * Internal dependencies
  1479. */
  1480. /**
  1481. * @typedef {Object} WPFormat
  1482. *
  1483. * @property {string} name A string identifying the format. Must be
  1484. * unique across all registered formats.
  1485. * @property {string} tagName The HTML tag this format will wrap the
  1486. * selection with.
  1487. * @property {string} [className] A class to match the format.
  1488. * @property {string} title Name of the format.
  1489. * @property {Function} edit Should return a component for the user to
  1490. * interact with the new registered format.
  1491. */
  1492. /**
  1493. * Registers a new format provided a unique name and an object defining its
  1494. * behavior.
  1495. *
  1496. * @param {string} name Format name.
  1497. * @param {WPFormat} settings Format settings.
  1498. *
  1499. * @return {WPFormat|undefined} The format, if it has been successfully
  1500. * registered; otherwise `undefined`.
  1501. */
  1502. function registerFormatType(name, settings) {
  1503. settings = {
  1504. name,
  1505. ...settings
  1506. };
  1507. if (typeof settings.name !== 'string') {
  1508. window.console.error('Format names must be strings.');
  1509. return;
  1510. }
  1511. if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(settings.name)) {
  1512. window.console.error('Format names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-format');
  1513. return;
  1514. }
  1515. if ((0,external_wp_data_namespaceObject.select)(store).getFormatType(settings.name)) {
  1516. window.console.error('Format "' + settings.name + '" is already registered.');
  1517. return;
  1518. }
  1519. if (typeof settings.tagName !== 'string' || settings.tagName === '') {
  1520. window.console.error('Format tag names must be a string.');
  1521. return;
  1522. }
  1523. if ((typeof settings.className !== 'string' || settings.className === '') && settings.className !== null) {
  1524. window.console.error('Format class names must be a string, or null to handle bare elements.');
  1525. return;
  1526. }
  1527. if (!/^[_a-zA-Z]+[a-zA-Z0-9-]*$/.test(settings.className)) {
  1528. window.console.error('A class name must begin with a letter, followed by any number of hyphens, letters, or numbers.');
  1529. return;
  1530. }
  1531. if (settings.className === null) {
  1532. const formatTypeForBareElement = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForBareElement(settings.tagName);
  1533. if (formatTypeForBareElement) {
  1534. window.console.error(`Format "${formatTypeForBareElement.name}" is already registered to handle bare tag name "${settings.tagName}".`);
  1535. return;
  1536. }
  1537. } else {
  1538. const formatTypeForClassName = (0,external_wp_data_namespaceObject.select)(store).getFormatTypeForClassName(settings.className);
  1539. if (formatTypeForClassName) {
  1540. window.console.error(`Format "${formatTypeForClassName.name}" is already registered to handle class name "${settings.className}".`);
  1541. return;
  1542. }
  1543. }
  1544. if (!('title' in settings) || settings.title === '') {
  1545. window.console.error('The format "' + settings.name + '" must have a title.');
  1546. return;
  1547. }
  1548. if ('keywords' in settings && settings.keywords.length > 3) {
  1549. window.console.error('The format "' + settings.name + '" can have a maximum of 3 keywords.');
  1550. return;
  1551. }
  1552. if (typeof settings.title !== 'string') {
  1553. window.console.error('Format titles must be strings.');
  1554. return;
  1555. }
  1556. (0,external_wp_data_namespaceObject.dispatch)(store).addFormatTypes(settings);
  1557. return settings;
  1558. }
  1559. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove-format.js
  1560. /**
  1561. * Internal dependencies
  1562. */
  1563. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1564. /**
  1565. * Remove any format object from a Rich Text value by type from the given
  1566. * `startIndex` to the given `endIndex`. Indices are retrieved from the
  1567. * selection if none are provided.
  1568. *
  1569. * @param {RichTextValue} value Value to modify.
  1570. * @param {string} formatType Format type to remove.
  1571. * @param {number} [startIndex] Start index.
  1572. * @param {number} [endIndex] End index.
  1573. *
  1574. * @return {RichTextValue} A new value with the format applied.
  1575. */
  1576. function removeFormat(value, formatType) {
  1577. let startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : value.start;
  1578. let endIndex = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : value.end;
  1579. const {
  1580. formats,
  1581. activeFormats
  1582. } = value;
  1583. const newFormats = formats.slice(); // If the selection is collapsed, expand start and end to the edges of the
  1584. // format.
  1585. if (startIndex === endIndex) {
  1586. var _newFormats$startInde;
  1587. const format = (_newFormats$startInde = newFormats[startIndex]) === null || _newFormats$startInde === void 0 ? void 0 : _newFormats$startInde.find(_ref => {
  1588. let {
  1589. type
  1590. } = _ref;
  1591. return type === formatType;
  1592. });
  1593. if (format) {
  1594. while ((_newFormats$startInde2 = newFormats[startIndex]) !== null && _newFormats$startInde2 !== void 0 && _newFormats$startInde2.find(newFormat => newFormat === format)) {
  1595. var _newFormats$startInde2;
  1596. filterFormats(newFormats, startIndex, formatType);
  1597. startIndex--;
  1598. }
  1599. endIndex++;
  1600. while ((_newFormats$endIndex = newFormats[endIndex]) !== null && _newFormats$endIndex !== void 0 && _newFormats$endIndex.find(newFormat => newFormat === format)) {
  1601. var _newFormats$endIndex;
  1602. filterFormats(newFormats, endIndex, formatType);
  1603. endIndex++;
  1604. }
  1605. }
  1606. } else {
  1607. for (let i = startIndex; i < endIndex; i++) {
  1608. if (newFormats[i]) {
  1609. filterFormats(newFormats, i, formatType);
  1610. }
  1611. }
  1612. }
  1613. return normaliseFormats({ ...value,
  1614. formats: newFormats,
  1615. activeFormats: (activeFormats === null || activeFormats === void 0 ? void 0 : activeFormats.filter(_ref2 => {
  1616. let {
  1617. type
  1618. } = _ref2;
  1619. return type !== formatType;
  1620. })) || []
  1621. });
  1622. }
  1623. function filterFormats(formats, index, formatType) {
  1624. const newFormats = formats[index].filter(_ref3 => {
  1625. let {
  1626. type
  1627. } = _ref3;
  1628. return type !== formatType;
  1629. });
  1630. if (newFormats.length) {
  1631. formats[index] = newFormats;
  1632. } else {
  1633. delete formats[index];
  1634. }
  1635. }
  1636. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert.js
  1637. /**
  1638. * Internal dependencies
  1639. */
  1640. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1641. /**
  1642. * Insert a Rich Text value, an HTML string, or a plain text string, into a
  1643. * Rich Text value at the given `startIndex`. Any content between `startIndex`
  1644. * and `endIndex` will be removed. Indices are retrieved from the selection if
  1645. * none are provided.
  1646. *
  1647. * @param {RichTextValue} value Value to modify.
  1648. * @param {RichTextValue|string} valueToInsert Value to insert.
  1649. * @param {number} [startIndex] Start index.
  1650. * @param {number} [endIndex] End index.
  1651. *
  1652. * @return {RichTextValue} A new value with the value inserted.
  1653. */
  1654. function insert(value, valueToInsert) {
  1655. let startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : value.start;
  1656. let endIndex = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : value.end;
  1657. const {
  1658. formats,
  1659. replacements,
  1660. text
  1661. } = value;
  1662. if (typeof valueToInsert === 'string') {
  1663. valueToInsert = create({
  1664. text: valueToInsert
  1665. });
  1666. }
  1667. const index = startIndex + valueToInsert.text.length;
  1668. return normaliseFormats({
  1669. formats: formats.slice(0, startIndex).concat(valueToInsert.formats, formats.slice(endIndex)),
  1670. replacements: replacements.slice(0, startIndex).concat(valueToInsert.replacements, replacements.slice(endIndex)),
  1671. text: text.slice(0, startIndex) + valueToInsert.text + text.slice(endIndex),
  1672. start: index,
  1673. end: index
  1674. });
  1675. }
  1676. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove.js
  1677. /**
  1678. * Internal dependencies
  1679. */
  1680. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1681. /**
  1682. * Remove content from a Rich Text value between the given `startIndex` and
  1683. * `endIndex`. Indices are retrieved from the selection if none are provided.
  1684. *
  1685. * @param {RichTextValue} value Value to modify.
  1686. * @param {number} [startIndex] Start index.
  1687. * @param {number} [endIndex] End index.
  1688. *
  1689. * @return {RichTextValue} A new value with the content removed.
  1690. */
  1691. function remove(value, startIndex, endIndex) {
  1692. return insert(value, create(), startIndex, endIndex);
  1693. }
  1694. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/replace.js
  1695. /**
  1696. * Internal dependencies
  1697. */
  1698. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1699. /**
  1700. * Search a Rich Text value and replace the match(es) with `replacement`. This
  1701. * is similar to `String.prototype.replace`.
  1702. *
  1703. * @param {RichTextValue} value The value to modify.
  1704. * @param {RegExp|string} pattern A RegExp object or literal. Can also be
  1705. * a string. It is treated as a verbatim
  1706. * string and is not interpreted as a
  1707. * regular expression. Only the first
  1708. * occurrence will be replaced.
  1709. * @param {Function|string} replacement The match or matches are replaced with
  1710. * the specified or the value returned by
  1711. * the specified function.
  1712. *
  1713. * @return {RichTextValue} A new value with replacements applied.
  1714. */
  1715. function replace_replace(_ref, pattern, replacement) {
  1716. let {
  1717. formats,
  1718. replacements,
  1719. text,
  1720. start,
  1721. end
  1722. } = _ref;
  1723. text = text.replace(pattern, function (match) {
  1724. for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  1725. rest[_key - 1] = arguments[_key];
  1726. }
  1727. const offset = rest[rest.length - 2];
  1728. let newText = replacement;
  1729. let newFormats;
  1730. let newReplacements;
  1731. if (typeof newText === 'function') {
  1732. newText = replacement(match, ...rest);
  1733. }
  1734. if (typeof newText === 'object') {
  1735. newFormats = newText.formats;
  1736. newReplacements = newText.replacements;
  1737. newText = newText.text;
  1738. } else {
  1739. newFormats = Array(newText.length);
  1740. newReplacements = Array(newText.length);
  1741. if (formats[offset]) {
  1742. newFormats = newFormats.fill(formats[offset]);
  1743. }
  1744. }
  1745. formats = formats.slice(0, offset).concat(newFormats, formats.slice(offset + match.length));
  1746. replacements = replacements.slice(0, offset).concat(newReplacements, replacements.slice(offset + match.length));
  1747. if (start) {
  1748. start = end = offset + newText.length;
  1749. }
  1750. return newText;
  1751. });
  1752. return normaliseFormats({
  1753. formats,
  1754. replacements,
  1755. text,
  1756. start,
  1757. end
  1758. });
  1759. }
  1760. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert-line-separator.js
  1761. /**
  1762. * Internal dependencies
  1763. */
  1764. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1765. /**
  1766. * Insert a line break character into a Rich Text value at the given
  1767. * `startIndex`. Any content between `startIndex` and `endIndex` will be
  1768. * removed. Indices are retrieved from the selection if none are provided.
  1769. *
  1770. * @param {RichTextValue} value Value to modify.
  1771. * @param {number} [startIndex] Start index.
  1772. * @param {number} [endIndex] End index.
  1773. *
  1774. * @return {RichTextValue} A new value with the value inserted.
  1775. */
  1776. function insertLineSeparator(value) {
  1777. let startIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : value.start;
  1778. let endIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : value.end;
  1779. const beforeText = value.text.slice(0, startIndex);
  1780. const previousLineSeparatorIndex = beforeText.lastIndexOf(LINE_SEPARATOR);
  1781. const previousLineSeparatorFormats = value.replacements[previousLineSeparatorIndex];
  1782. let replacements = [,];
  1783. if (previousLineSeparatorFormats) {
  1784. replacements = [previousLineSeparatorFormats];
  1785. }
  1786. const valueToInsert = {
  1787. formats: [,],
  1788. replacements,
  1789. text: LINE_SEPARATOR
  1790. };
  1791. return insert(value, valueToInsert, startIndex, endIndex);
  1792. }
  1793. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/insert-object.js
  1794. /**
  1795. * Internal dependencies
  1796. */
  1797. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1798. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  1799. /**
  1800. * Insert a format as an object into a Rich Text value at the given
  1801. * `startIndex`. Any content between `startIndex` and `endIndex` will be
  1802. * removed. Indices are retrieved from the selection if none are provided.
  1803. *
  1804. * @param {RichTextValue} value Value to modify.
  1805. * @param {RichTextFormat} formatToInsert Format to insert as object.
  1806. * @param {number} [startIndex] Start index.
  1807. * @param {number} [endIndex] End index.
  1808. *
  1809. * @return {RichTextValue} A new value with the object inserted.
  1810. */
  1811. function insertObject(value, formatToInsert, startIndex, endIndex) {
  1812. const valueToInsert = {
  1813. formats: [,],
  1814. replacements: [formatToInsert],
  1815. text: OBJECT_REPLACEMENT_CHARACTER
  1816. };
  1817. return insert(value, valueToInsert, startIndex, endIndex);
  1818. }
  1819. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/slice.js
  1820. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1821. /**
  1822. * Slice a Rich Text value from `startIndex` to `endIndex`. Indices are
  1823. * retrieved from the selection if none are provided. This is similar to
  1824. * `String.prototype.slice`.
  1825. *
  1826. * @param {RichTextValue} value Value to modify.
  1827. * @param {number} [startIndex] Start index.
  1828. * @param {number} [endIndex] End index.
  1829. *
  1830. * @return {RichTextValue} A new extracted value.
  1831. */
  1832. function slice(value) {
  1833. let startIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : value.start;
  1834. let endIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : value.end;
  1835. const {
  1836. formats,
  1837. replacements,
  1838. text
  1839. } = value;
  1840. if (startIndex === undefined || endIndex === undefined) {
  1841. return { ...value
  1842. };
  1843. }
  1844. return {
  1845. formats: formats.slice(startIndex, endIndex),
  1846. replacements: replacements.slice(startIndex, endIndex),
  1847. text: text.slice(startIndex, endIndex)
  1848. };
  1849. }
  1850. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/split.js
  1851. /**
  1852. * Internal dependencies
  1853. */
  1854. /** @typedef {import('./create').RichTextValue} RichTextValue */
  1855. /**
  1856. * Split a Rich Text value in two at the given `startIndex` and `endIndex`, or
  1857. * split at the given separator. This is similar to `String.prototype.split`.
  1858. * Indices are retrieved from the selection if none are provided.
  1859. *
  1860. * @param {RichTextValue} value
  1861. * @param {number|string} [string] Start index, or string at which to split.
  1862. *
  1863. * @return {Array<RichTextValue>|undefined} An array of new values.
  1864. */
  1865. function split(_ref, string) {
  1866. let {
  1867. formats,
  1868. replacements,
  1869. text,
  1870. start,
  1871. end
  1872. } = _ref;
  1873. if (typeof string !== 'string') {
  1874. return splitAtSelection(...arguments);
  1875. }
  1876. let nextStart = 0;
  1877. return text.split(string).map(substring => {
  1878. const startIndex = nextStart;
  1879. const value = {
  1880. formats: formats.slice(startIndex, startIndex + substring.length),
  1881. replacements: replacements.slice(startIndex, startIndex + substring.length),
  1882. text: substring
  1883. };
  1884. nextStart += string.length + substring.length;
  1885. if (start !== undefined && end !== undefined) {
  1886. if (start >= startIndex && start < nextStart) {
  1887. value.start = start - startIndex;
  1888. } else if (start < startIndex && end > startIndex) {
  1889. value.start = 0;
  1890. }
  1891. if (end >= startIndex && end < nextStart) {
  1892. value.end = end - startIndex;
  1893. } else if (start < nextStart && end > nextStart) {
  1894. value.end = substring.length;
  1895. }
  1896. }
  1897. return value;
  1898. });
  1899. }
  1900. function splitAtSelection(_ref2) {
  1901. let {
  1902. formats,
  1903. replacements,
  1904. text,
  1905. start,
  1906. end
  1907. } = _ref2;
  1908. let startIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : start;
  1909. let endIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : end;
  1910. if (start === undefined || end === undefined) {
  1911. return;
  1912. }
  1913. const before = {
  1914. formats: formats.slice(0, startIndex),
  1915. replacements: replacements.slice(0, startIndex),
  1916. text: text.slice(0, startIndex)
  1917. };
  1918. const after = {
  1919. formats: formats.slice(endIndex),
  1920. replacements: replacements.slice(endIndex),
  1921. text: text.slice(endIndex),
  1922. start: 0,
  1923. end: 0
  1924. };
  1925. return [// Ensure newlines are trimmed.
  1926. replace_replace(before, /\u2028+$/, ''), replace_replace(after, /^\u2028+/, '')];
  1927. }
  1928. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/get-format-type.js
  1929. /**
  1930. * WordPress dependencies
  1931. */
  1932. /**
  1933. * Internal dependencies
  1934. */
  1935. /** @typedef {import('./register-format-type').RichTextFormatType} RichTextFormatType */
  1936. /**
  1937. * Returns a registered format type.
  1938. *
  1939. * @param {string} name Format name.
  1940. *
  1941. * @return {RichTextFormatType|undefined} Format type.
  1942. */
  1943. function get_format_type_getFormatType(name) {
  1944. return (0,external_wp_data_namespaceObject.select)(store).getFormatType(name);
  1945. }
  1946. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-tree.js
  1947. /**
  1948. * Internal dependencies
  1949. */
  1950. function restoreOnAttributes(attributes, isEditableTree) {
  1951. if (isEditableTree) {
  1952. return attributes;
  1953. }
  1954. const newAttributes = {};
  1955. for (const key in attributes) {
  1956. let newKey = key;
  1957. if (key.startsWith('data-disable-rich-text-')) {
  1958. newKey = key.slice('data-disable-rich-text-'.length);
  1959. }
  1960. newAttributes[newKey] = attributes[key];
  1961. }
  1962. return newAttributes;
  1963. }
  1964. /**
  1965. * Converts a format object to information that can be used to create an element
  1966. * from (type, attributes and object).
  1967. *
  1968. * @param {Object} $1 Named parameters.
  1969. * @param {string} $1.type The format type.
  1970. * @param {Object} $1.attributes The format attributes.
  1971. * @param {Object} $1.unregisteredAttributes The unregistered format
  1972. * attributes.
  1973. * @param {boolean} $1.object Whether or not it is an object
  1974. * format.
  1975. * @param {boolean} $1.boundaryClass Whether or not to apply a boundary
  1976. * class.
  1977. * @param {boolean} $1.isEditableTree
  1978. *
  1979. * @return {Object} Information to be used for element creation.
  1980. */
  1981. function fromFormat(_ref) {
  1982. let {
  1983. type,
  1984. attributes,
  1985. unregisteredAttributes,
  1986. object,
  1987. boundaryClass,
  1988. isEditableTree
  1989. } = _ref;
  1990. const formatType = get_format_type_getFormatType(type);
  1991. let elementAttributes = {};
  1992. if (boundaryClass) {
  1993. elementAttributes['data-rich-text-format-boundary'] = 'true';
  1994. }
  1995. if (!formatType) {
  1996. if (attributes) {
  1997. elementAttributes = { ...attributes,
  1998. ...elementAttributes
  1999. };
  2000. }
  2001. return {
  2002. type,
  2003. attributes: restoreOnAttributes(elementAttributes, isEditableTree),
  2004. object
  2005. };
  2006. }
  2007. elementAttributes = { ...unregisteredAttributes,
  2008. ...elementAttributes
  2009. };
  2010. for (const name in attributes) {
  2011. const key = formatType.attributes ? formatType.attributes[name] : false;
  2012. if (key) {
  2013. elementAttributes[key] = attributes[name];
  2014. } else {
  2015. elementAttributes[name] = attributes[name];
  2016. }
  2017. }
  2018. if (formatType.className) {
  2019. if (elementAttributes.class) {
  2020. elementAttributes.class = `${formatType.className} ${elementAttributes.class}`;
  2021. } else {
  2022. elementAttributes.class = formatType.className;
  2023. }
  2024. }
  2025. return {
  2026. type: formatType.tagName,
  2027. object: formatType.object,
  2028. attributes: restoreOnAttributes(elementAttributes, isEditableTree)
  2029. };
  2030. }
  2031. /**
  2032. * Checks if both arrays of formats up until a certain index are equal.
  2033. *
  2034. * @param {Array} a Array of formats to compare.
  2035. * @param {Array} b Array of formats to compare.
  2036. * @param {number} index Index to check until.
  2037. */
  2038. function isEqualUntil(a, b, index) {
  2039. do {
  2040. if (a[index] !== b[index]) {
  2041. return false;
  2042. }
  2043. } while (index--);
  2044. return true;
  2045. }
  2046. function toTree(_ref2) {
  2047. let {
  2048. value,
  2049. multilineTag,
  2050. preserveWhiteSpace,
  2051. createEmpty,
  2052. append,
  2053. getLastChild,
  2054. getParent,
  2055. isText,
  2056. getText,
  2057. remove,
  2058. appendText,
  2059. onStartIndex,
  2060. onEndIndex,
  2061. isEditableTree,
  2062. placeholder
  2063. } = _ref2;
  2064. const {
  2065. formats,
  2066. replacements,
  2067. text,
  2068. start,
  2069. end
  2070. } = value;
  2071. const formatsLength = formats.length + 1;
  2072. const tree = createEmpty();
  2073. const multilineFormat = {
  2074. type: multilineTag
  2075. };
  2076. const activeFormats = getActiveFormats(value);
  2077. const deepestActiveFormat = activeFormats[activeFormats.length - 1];
  2078. let lastSeparatorFormats;
  2079. let lastCharacterFormats;
  2080. let lastCharacter; // If we're building a multiline tree, start off with a multiline element.
  2081. if (multilineTag) {
  2082. append(append(tree, {
  2083. type: multilineTag
  2084. }), '');
  2085. lastCharacterFormats = lastSeparatorFormats = [multilineFormat];
  2086. } else {
  2087. append(tree, '');
  2088. }
  2089. for (let i = 0; i < formatsLength; i++) {
  2090. const character = text.charAt(i);
  2091. const shouldInsertPadding = isEditableTree && ( // Pad the line if the line is empty.
  2092. !lastCharacter || lastCharacter === LINE_SEPARATOR || // Pad the line if the previous character is a line break, otherwise
  2093. // the line break won't be visible.
  2094. lastCharacter === '\n');
  2095. let characterFormats = formats[i]; // Set multiline tags in queue for building the tree.
  2096. if (multilineTag) {
  2097. if (character === LINE_SEPARATOR) {
  2098. characterFormats = lastSeparatorFormats = (replacements[i] || []).reduce((accumulator, format) => {
  2099. accumulator.push(format, multilineFormat);
  2100. return accumulator;
  2101. }, [multilineFormat]);
  2102. } else {
  2103. characterFormats = [...lastSeparatorFormats, ...(characterFormats || [])];
  2104. }
  2105. }
  2106. let pointer = getLastChild(tree);
  2107. if (shouldInsertPadding && character === LINE_SEPARATOR) {
  2108. let node = pointer;
  2109. while (!isText(node)) {
  2110. node = getLastChild(node);
  2111. }
  2112. append(getParent(node), ZWNBSP);
  2113. } // Set selection for the start of line.
  2114. if (lastCharacter === LINE_SEPARATOR) {
  2115. let node = pointer;
  2116. while (!isText(node)) {
  2117. node = getLastChild(node);
  2118. }
  2119. if (onStartIndex && start === i) {
  2120. onStartIndex(tree, node);
  2121. }
  2122. if (onEndIndex && end === i) {
  2123. onEndIndex(tree, node);
  2124. }
  2125. }
  2126. if (characterFormats) {
  2127. characterFormats.forEach((format, formatIndex) => {
  2128. if (pointer && lastCharacterFormats && // Reuse the last element if all formats remain the same.
  2129. isEqualUntil(characterFormats, lastCharacterFormats, formatIndex) && ( // Do not reuse the last element if the character is a
  2130. // line separator.
  2131. character !== LINE_SEPARATOR || characterFormats.length - 1 !== formatIndex)) {
  2132. pointer = getLastChild(pointer);
  2133. return;
  2134. }
  2135. const {
  2136. type,
  2137. attributes,
  2138. unregisteredAttributes
  2139. } = format;
  2140. const boundaryClass = isEditableTree && character !== LINE_SEPARATOR && format === deepestActiveFormat;
  2141. const parent = getParent(pointer);
  2142. const newNode = append(parent, fromFormat({
  2143. type,
  2144. attributes,
  2145. unregisteredAttributes,
  2146. boundaryClass,
  2147. isEditableTree
  2148. }));
  2149. if (isText(pointer) && getText(pointer).length === 0) {
  2150. remove(pointer);
  2151. }
  2152. pointer = append(newNode, '');
  2153. });
  2154. } // No need for further processing if the character is a line separator.
  2155. if (character === LINE_SEPARATOR) {
  2156. lastCharacterFormats = characterFormats;
  2157. lastCharacter = character;
  2158. continue;
  2159. } // If there is selection at 0, handle it before characters are inserted.
  2160. if (i === 0) {
  2161. if (onStartIndex && start === 0) {
  2162. onStartIndex(tree, pointer);
  2163. }
  2164. if (onEndIndex && end === 0) {
  2165. onEndIndex(tree, pointer);
  2166. }
  2167. }
  2168. if (character === OBJECT_REPLACEMENT_CHARACTER) {
  2169. var _replacements$i;
  2170. if (!isEditableTree && ((_replacements$i = replacements[i]) === null || _replacements$i === void 0 ? void 0 : _replacements$i.type) === 'script') {
  2171. pointer = append(getParent(pointer), fromFormat({
  2172. type: 'script',
  2173. isEditableTree
  2174. }));
  2175. append(pointer, {
  2176. html: decodeURIComponent(replacements[i].attributes['data-rich-text-script'])
  2177. });
  2178. } else {
  2179. pointer = append(getParent(pointer), fromFormat({ ...replacements[i],
  2180. object: true,
  2181. isEditableTree
  2182. }));
  2183. } // Ensure pointer is text node.
  2184. pointer = append(getParent(pointer), '');
  2185. } else if (!preserveWhiteSpace && character === '\n') {
  2186. pointer = append(getParent(pointer), {
  2187. type: 'br',
  2188. attributes: isEditableTree ? {
  2189. 'data-rich-text-line-break': 'true'
  2190. } : undefined,
  2191. object: true
  2192. }); // Ensure pointer is text node.
  2193. pointer = append(getParent(pointer), '');
  2194. } else if (!isText(pointer)) {
  2195. pointer = append(getParent(pointer), character);
  2196. } else {
  2197. appendText(pointer, character);
  2198. }
  2199. if (onStartIndex && start === i + 1) {
  2200. onStartIndex(tree, pointer);
  2201. }
  2202. if (onEndIndex && end === i + 1) {
  2203. onEndIndex(tree, pointer);
  2204. }
  2205. if (shouldInsertPadding && i === text.length) {
  2206. append(getParent(pointer), ZWNBSP);
  2207. if (placeholder && text.length === 0) {
  2208. append(getParent(pointer), {
  2209. type: 'span',
  2210. attributes: {
  2211. 'data-rich-text-placeholder': placeholder,
  2212. // Necessary to prevent the placeholder from catching
  2213. // selection. The placeholder is also not editable after
  2214. // all.
  2215. contenteditable: 'false',
  2216. style: 'pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;'
  2217. }
  2218. });
  2219. }
  2220. }
  2221. lastCharacterFormats = characterFormats;
  2222. lastCharacter = character;
  2223. }
  2224. return tree;
  2225. }
  2226. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-dom.js
  2227. /**
  2228. * Internal dependencies
  2229. */
  2230. /** @typedef {import('./create').RichTextValue} RichTextValue */
  2231. /**
  2232. * Creates a path as an array of indices from the given root node to the given
  2233. * node.
  2234. *
  2235. * @param {Node} node Node to find the path of.
  2236. * @param {HTMLElement} rootNode Root node to find the path from.
  2237. * @param {Array} path Initial path to build on.
  2238. *
  2239. * @return {Array} The path from the root node to the node.
  2240. */
  2241. function createPathToNode(node, rootNode, path) {
  2242. const parentNode = node.parentNode;
  2243. let i = 0;
  2244. while (node = node.previousSibling) {
  2245. i++;
  2246. }
  2247. path = [i, ...path];
  2248. if (parentNode !== rootNode) {
  2249. path = createPathToNode(parentNode, rootNode, path);
  2250. }
  2251. return path;
  2252. }
  2253. /**
  2254. * Gets a node given a path (array of indices) from the given node.
  2255. *
  2256. * @param {HTMLElement} node Root node to find the wanted node in.
  2257. * @param {Array} path Path (indices) to the wanted node.
  2258. *
  2259. * @return {Object} Object with the found node and the remaining offset (if any).
  2260. */
  2261. function getNodeByPath(node, path) {
  2262. path = [...path];
  2263. while (node && path.length > 1) {
  2264. node = node.childNodes[path.shift()];
  2265. }
  2266. return {
  2267. node,
  2268. offset: path[0]
  2269. };
  2270. }
  2271. function append(element, child) {
  2272. if (typeof child === 'string') {
  2273. child = element.ownerDocument.createTextNode(child);
  2274. }
  2275. const {
  2276. type,
  2277. attributes
  2278. } = child;
  2279. if (type) {
  2280. child = element.ownerDocument.createElement(type);
  2281. for (const key in attributes) {
  2282. child.setAttribute(key, attributes[key]);
  2283. }
  2284. }
  2285. return element.appendChild(child);
  2286. }
  2287. function appendText(node, text) {
  2288. node.appendData(text);
  2289. }
  2290. function getLastChild(_ref) {
  2291. let {
  2292. lastChild
  2293. } = _ref;
  2294. return lastChild;
  2295. }
  2296. function getParent(_ref2) {
  2297. let {
  2298. parentNode
  2299. } = _ref2;
  2300. return parentNode;
  2301. }
  2302. function isText(node) {
  2303. return node.nodeType === node.TEXT_NODE;
  2304. }
  2305. function getText(_ref3) {
  2306. let {
  2307. nodeValue
  2308. } = _ref3;
  2309. return nodeValue;
  2310. }
  2311. function to_dom_remove(node) {
  2312. return node.parentNode.removeChild(node);
  2313. }
  2314. function toDom(_ref4) {
  2315. let {
  2316. value,
  2317. multilineTag,
  2318. prepareEditableTree,
  2319. isEditableTree = true,
  2320. placeholder,
  2321. doc = document
  2322. } = _ref4;
  2323. let startPath = [];
  2324. let endPath = [];
  2325. if (prepareEditableTree) {
  2326. value = { ...value,
  2327. formats: prepareEditableTree(value)
  2328. };
  2329. }
  2330. /**
  2331. * Returns a new instance of a DOM tree upon which RichText operations can be
  2332. * applied.
  2333. *
  2334. * Note: The current implementation will return a shared reference, reset on
  2335. * each call to `createEmpty`. Therefore, you should not hold a reference to
  2336. * the value to operate upon asynchronously, as it may have unexpected results.
  2337. *
  2338. * @return {Object} RichText tree.
  2339. */
  2340. const createEmpty = () => createElement(doc, '');
  2341. const tree = toTree({
  2342. value,
  2343. multilineTag,
  2344. createEmpty,
  2345. append,
  2346. getLastChild,
  2347. getParent,
  2348. isText,
  2349. getText,
  2350. remove: to_dom_remove,
  2351. appendText,
  2352. onStartIndex(body, pointer) {
  2353. startPath = createPathToNode(pointer, body, [pointer.nodeValue.length]);
  2354. },
  2355. onEndIndex(body, pointer) {
  2356. endPath = createPathToNode(pointer, body, [pointer.nodeValue.length]);
  2357. },
  2358. isEditableTree,
  2359. placeholder
  2360. });
  2361. return {
  2362. body: tree,
  2363. selection: {
  2364. startPath,
  2365. endPath
  2366. }
  2367. };
  2368. }
  2369. /**
  2370. * Create an `Element` tree from a Rich Text value and applies the difference to
  2371. * the `Element` tree contained by `current`. If a `multilineTag` is provided,
  2372. * text separated by two new lines will be wrapped in an `Element` of that type.
  2373. *
  2374. * @param {Object} $1 Named arguments.
  2375. * @param {RichTextValue} $1.value Value to apply.
  2376. * @param {HTMLElement} $1.current The live root node to apply the element tree to.
  2377. * @param {string} [$1.multilineTag] Multiline tag.
  2378. * @param {Function} [$1.prepareEditableTree] Function to filter editorable formats.
  2379. * @param {boolean} [$1.__unstableDomOnly] Only apply elements, no selection.
  2380. * @param {string} [$1.placeholder] Placeholder text.
  2381. */
  2382. function apply(_ref5) {
  2383. let {
  2384. value,
  2385. current,
  2386. multilineTag,
  2387. prepareEditableTree,
  2388. __unstableDomOnly,
  2389. placeholder
  2390. } = _ref5;
  2391. // Construct a new element tree in memory.
  2392. const {
  2393. body,
  2394. selection
  2395. } = toDom({
  2396. value,
  2397. multilineTag,
  2398. prepareEditableTree,
  2399. placeholder,
  2400. doc: current.ownerDocument
  2401. });
  2402. applyValue(body, current);
  2403. if (value.start !== undefined && !__unstableDomOnly) {
  2404. applySelection(selection, current);
  2405. }
  2406. }
  2407. function applyValue(future, current) {
  2408. let i = 0;
  2409. let futureChild;
  2410. while (futureChild = future.firstChild) {
  2411. const currentChild = current.childNodes[i];
  2412. if (!currentChild) {
  2413. current.appendChild(futureChild);
  2414. } else if (!currentChild.isEqualNode(futureChild)) {
  2415. if (currentChild.nodeName !== futureChild.nodeName || currentChild.nodeType === currentChild.TEXT_NODE && currentChild.data !== futureChild.data) {
  2416. current.replaceChild(futureChild, currentChild);
  2417. } else {
  2418. const currentAttributes = currentChild.attributes;
  2419. const futureAttributes = futureChild.attributes;
  2420. if (currentAttributes) {
  2421. let ii = currentAttributes.length; // Reverse loop because `removeAttribute` on `currentChild`
  2422. // changes `currentAttributes`.
  2423. while (ii--) {
  2424. const {
  2425. name
  2426. } = currentAttributes[ii];
  2427. if (!futureChild.getAttribute(name)) {
  2428. currentChild.removeAttribute(name);
  2429. }
  2430. }
  2431. }
  2432. if (futureAttributes) {
  2433. for (let ii = 0; ii < futureAttributes.length; ii++) {
  2434. const {
  2435. name,
  2436. value
  2437. } = futureAttributes[ii];
  2438. if (currentChild.getAttribute(name) !== value) {
  2439. currentChild.setAttribute(name, value);
  2440. }
  2441. }
  2442. }
  2443. applyValue(futureChild, currentChild);
  2444. future.removeChild(futureChild);
  2445. }
  2446. } else {
  2447. future.removeChild(futureChild);
  2448. }
  2449. i++;
  2450. }
  2451. while (current.childNodes[i]) {
  2452. current.removeChild(current.childNodes[i]);
  2453. }
  2454. }
  2455. /**
  2456. * Returns true if two ranges are equal, or false otherwise. Ranges are
  2457. * considered equal if their start and end occur in the same container and
  2458. * offset.
  2459. *
  2460. * @param {Range} a First range object to test.
  2461. * @param {Range} b First range object to test.
  2462. *
  2463. * @return {boolean} Whether the two ranges are equal.
  2464. */
  2465. function isRangeEqual(a, b) {
  2466. return a.startContainer === b.startContainer && a.startOffset === b.startOffset && a.endContainer === b.endContainer && a.endOffset === b.endOffset;
  2467. }
  2468. function applySelection(_ref6, current) {
  2469. let {
  2470. startPath,
  2471. endPath
  2472. } = _ref6;
  2473. const {
  2474. node: startContainer,
  2475. offset: startOffset
  2476. } = getNodeByPath(current, startPath);
  2477. const {
  2478. node: endContainer,
  2479. offset: endOffset
  2480. } = getNodeByPath(current, endPath);
  2481. const {
  2482. ownerDocument
  2483. } = current;
  2484. const {
  2485. defaultView
  2486. } = ownerDocument;
  2487. const selection = defaultView.getSelection();
  2488. const range = ownerDocument.createRange();
  2489. range.setStart(startContainer, startOffset);
  2490. range.setEnd(endContainer, endOffset);
  2491. const {
  2492. activeElement
  2493. } = ownerDocument;
  2494. if (selection.rangeCount > 0) {
  2495. // If the to be added range and the live range are the same, there's no
  2496. // need to remove the live range and add the equivalent range.
  2497. if (isRangeEqual(range, selection.getRangeAt(0))) {
  2498. return;
  2499. }
  2500. selection.removeAllRanges();
  2501. }
  2502. selection.addRange(range); // This function is not intended to cause a shift in focus. Since the above
  2503. // selection manipulations may shift focus, ensure that focus is restored to
  2504. // its previous state.
  2505. if (activeElement !== ownerDocument.activeElement) {
  2506. // The `instanceof` checks protect against edge cases where the focused
  2507. // element is not of the interface HTMLElement (does not have a `focus`
  2508. // or `blur` property).
  2509. //
  2510. // See: https://github.com/Microsoft/TypeScript/issues/5901#issuecomment-431649653
  2511. if (activeElement instanceof defaultView.HTMLElement) {
  2512. activeElement.focus();
  2513. }
  2514. }
  2515. }
  2516. ;// CONCATENATED MODULE: external ["wp","escapeHtml"]
  2517. var external_wp_escapeHtml_namespaceObject = window["wp"]["escapeHtml"];
  2518. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/to-html-string.js
  2519. /**
  2520. * WordPress dependencies
  2521. */
  2522. /**
  2523. * Internal dependencies
  2524. */
  2525. /** @typedef {import('./create').RichTextValue} RichTextValue */
  2526. /**
  2527. * Create an HTML string from a Rich Text value. If a `multilineTag` is
  2528. * provided, text separated by a line separator will be wrapped in it.
  2529. *
  2530. * @param {Object} $1 Named argements.
  2531. * @param {RichTextValue} $1.value Rich text value.
  2532. * @param {string} [$1.multilineTag] Multiline tag.
  2533. * @param {boolean} [$1.preserveWhiteSpace] Whether or not to use newline
  2534. * characters for line breaks.
  2535. *
  2536. * @return {string} HTML string.
  2537. */
  2538. function toHTMLString(_ref) {
  2539. let {
  2540. value,
  2541. multilineTag,
  2542. preserveWhiteSpace
  2543. } = _ref;
  2544. const tree = toTree({
  2545. value,
  2546. multilineTag,
  2547. preserveWhiteSpace,
  2548. createEmpty,
  2549. append: to_html_string_append,
  2550. getLastChild: to_html_string_getLastChild,
  2551. getParent: to_html_string_getParent,
  2552. isText: to_html_string_isText,
  2553. getText: to_html_string_getText,
  2554. remove: to_html_string_remove,
  2555. appendText: to_html_string_appendText
  2556. });
  2557. return createChildrenHTML(tree.children);
  2558. }
  2559. function createEmpty() {
  2560. return {};
  2561. }
  2562. function to_html_string_getLastChild(_ref2) {
  2563. let {
  2564. children
  2565. } = _ref2;
  2566. return children && children[children.length - 1];
  2567. }
  2568. function to_html_string_append(parent, object) {
  2569. if (typeof object === 'string') {
  2570. object = {
  2571. text: object
  2572. };
  2573. }
  2574. object.parent = parent;
  2575. parent.children = parent.children || [];
  2576. parent.children.push(object);
  2577. return object;
  2578. }
  2579. function to_html_string_appendText(object, text) {
  2580. object.text += text;
  2581. }
  2582. function to_html_string_getParent(_ref3) {
  2583. let {
  2584. parent
  2585. } = _ref3;
  2586. return parent;
  2587. }
  2588. function to_html_string_isText(_ref4) {
  2589. let {
  2590. text
  2591. } = _ref4;
  2592. return typeof text === 'string';
  2593. }
  2594. function to_html_string_getText(_ref5) {
  2595. let {
  2596. text
  2597. } = _ref5;
  2598. return text;
  2599. }
  2600. function to_html_string_remove(object) {
  2601. const index = object.parent.children.indexOf(object);
  2602. if (index !== -1) {
  2603. object.parent.children.splice(index, 1);
  2604. }
  2605. return object;
  2606. }
  2607. function createElementHTML(_ref6) {
  2608. let {
  2609. type,
  2610. attributes,
  2611. object,
  2612. children
  2613. } = _ref6;
  2614. let attributeString = '';
  2615. for (const key in attributes) {
  2616. if (!(0,external_wp_escapeHtml_namespaceObject.isValidAttributeName)(key)) {
  2617. continue;
  2618. }
  2619. attributeString += ` ${key}="${(0,external_wp_escapeHtml_namespaceObject.escapeAttribute)(attributes[key])}"`;
  2620. }
  2621. if (object) {
  2622. return `<${type}${attributeString}>`;
  2623. }
  2624. return `<${type}${attributeString}>${createChildrenHTML(children)}</${type}>`;
  2625. }
  2626. function createChildrenHTML() {
  2627. let children = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  2628. return children.map(child => {
  2629. if (child.html !== undefined) {
  2630. return child.html;
  2631. }
  2632. return child.text === undefined ? createElementHTML(child) : (0,external_wp_escapeHtml_namespaceObject.escapeEditableHTML)(child.text);
  2633. }).join('');
  2634. }
  2635. ;// CONCATENATED MODULE: external ["wp","a11y"]
  2636. var external_wp_a11y_namespaceObject = window["wp"]["a11y"];
  2637. ;// CONCATENATED MODULE: external ["wp","i18n"]
  2638. var external_wp_i18n_namespaceObject = window["wp"]["i18n"];
  2639. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/toggle-format.js
  2640. /**
  2641. * WordPress dependencies
  2642. */
  2643. /**
  2644. * Internal dependencies
  2645. */
  2646. /** @typedef {import('./create').RichTextValue} RichTextValue */
  2647. /** @typedef {import('./create').RichTextFormat} RichTextFormat */
  2648. /**
  2649. * Toggles a format object to a Rich Text value at the current selection.
  2650. *
  2651. * @param {RichTextValue} value Value to modify.
  2652. * @param {RichTextFormat} format Format to apply or remove.
  2653. *
  2654. * @return {RichTextValue} A new value with the format applied or removed.
  2655. */
  2656. function toggleFormat(value, format) {
  2657. if (getActiveFormat(value, format.type)) {
  2658. // For screen readers, will announce if formatting control is disabled.
  2659. if (format.title) {
  2660. // translators: %s: title of the formatting control
  2661. (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)((0,external_wp_i18n_namespaceObject.__)('%s removed.'), format.title), 'assertive');
  2662. }
  2663. return removeFormat(value, format.type);
  2664. } // For screen readers, will announce if formatting control is enabled.
  2665. if (format.title) {
  2666. // translators: %s: title of the formatting control
  2667. (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)((0,external_wp_i18n_namespaceObject.__)('%s applied.'), format.title), 'assertive');
  2668. }
  2669. return applyFormat(value, format);
  2670. }
  2671. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/unregister-format-type.js
  2672. /**
  2673. * WordPress dependencies
  2674. */
  2675. /**
  2676. * Internal dependencies
  2677. */
  2678. /** @typedef {import('./register-format-type').RichTextFormatType} RichTextFormatType */
  2679. /**
  2680. * Unregisters a format.
  2681. *
  2682. * @param {string} name Format name.
  2683. *
  2684. * @return {RichTextFormatType|undefined} The previous format value, if it has
  2685. * been successfully unregistered;
  2686. * otherwise `undefined`.
  2687. */
  2688. function unregisterFormatType(name) {
  2689. const oldFormat = (0,external_wp_data_namespaceObject.select)(store).getFormatType(name);
  2690. if (!oldFormat) {
  2691. window.console.error(`Format ${name} is not registered.`);
  2692. return;
  2693. }
  2694. (0,external_wp_data_namespaceObject.dispatch)(store).removeFormatTypes(name);
  2695. return oldFormat;
  2696. }
  2697. ;// CONCATENATED MODULE: external ["wp","element"]
  2698. var external_wp_element_namespaceObject = window["wp"]["element"];
  2699. ;// CONCATENATED MODULE: external ["wp","deprecated"]
  2700. var external_wp_deprecated_namespaceObject = window["wp"]["deprecated"];
  2701. var external_wp_deprecated_default = /*#__PURE__*/__webpack_require__.n(external_wp_deprecated_namespaceObject);
  2702. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor-ref.js
  2703. /**
  2704. * WordPress dependencies
  2705. */
  2706. /**
  2707. * Internal dependencies
  2708. */
  2709. /** @typedef {import('@wordpress/element').RefObject} RefObject */
  2710. /** @typedef {import('../register-format-type').RichTextFormatType} RichTextFormatType */
  2711. /** @typedef {import('../create').RichTextValue} RichTextValue */
  2712. /**
  2713. * This hook, to be used in a format type's Edit component, returns the active
  2714. * element that is formatted, or the selection range if no format is active.
  2715. * The returned value is meant to be used for positioning UI, e.g. by passing it
  2716. * to the `Popover` component.
  2717. *
  2718. * @param {Object} $1 Named parameters.
  2719. * @param {RefObject<HTMLElement>} $1.ref React ref of the element
  2720. * containing the editable content.
  2721. * @param {RichTextValue} $1.value Value to check for selection.
  2722. * @param {RichTextFormatType} $1.settings The format type's settings.
  2723. *
  2724. * @return {Element|Range} The active element or selection range.
  2725. */
  2726. function useAnchorRef(_ref) {
  2727. let {
  2728. ref,
  2729. value,
  2730. settings = {}
  2731. } = _ref;
  2732. external_wp_deprecated_default()('`useAnchorRef` hook', {
  2733. since: '6.1',
  2734. version: '6.3',
  2735. alternative: '`useAnchor` hook'
  2736. });
  2737. const {
  2738. tagName,
  2739. className,
  2740. name
  2741. } = settings;
  2742. const activeFormat = name ? getActiveFormat(value, name) : undefined;
  2743. return (0,external_wp_element_namespaceObject.useMemo)(() => {
  2744. if (!ref.current) return;
  2745. const {
  2746. ownerDocument: {
  2747. defaultView
  2748. }
  2749. } = ref.current;
  2750. const selection = defaultView.getSelection();
  2751. if (!selection.rangeCount) {
  2752. return;
  2753. }
  2754. const range = selection.getRangeAt(0);
  2755. if (!activeFormat) {
  2756. return range;
  2757. }
  2758. let element = range.startContainer; // If the caret is right before the element, select the next element.
  2759. element = element.nextElementSibling || element;
  2760. while (element.nodeType !== element.ELEMENT_NODE) {
  2761. element = element.parentNode;
  2762. }
  2763. return element.closest(tagName + (className ? '.' + className : ''));
  2764. }, [activeFormat, value.start, value.end, tagName, className]);
  2765. }
  2766. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-anchor.js
  2767. /**
  2768. * WordPress dependencies
  2769. */
  2770. /**
  2771. * Internal dependencies
  2772. */
  2773. /** @typedef {import('../register-format-type').RichTextFormatType} RichTextFormatType */
  2774. /** @typedef {import('../create').RichTextValue} RichTextValue */
  2775. /**
  2776. * @typedef {Object} VirtualAnchorElement
  2777. * @property {Function} getBoundingClientRect A function returning a DOMRect
  2778. * @property {Document} ownerDocument The element's ownerDocument
  2779. */
  2780. /**
  2781. * This hook, to be used in a format type's Edit component, returns the active
  2782. * element that is formatted, or a virtual element for the selection range if
  2783. * no format is active. The returned value is meant to be used for positioning
  2784. * UI, e.g. by passing it to the `Popover` component via the `anchor` prop.
  2785. *
  2786. * @param {Object} $1 Named parameters.
  2787. * @param {HTMLElement|null} $1.editableContentElement The element containing
  2788. * the editable content.
  2789. * @param {RichTextValue} $1.value Value to check for selection.
  2790. * @param {RichTextFormatType} $1.settings The format type's settings.
  2791. * @return {Element|VirtualAnchorElement|undefined|null} The active element or selection range.
  2792. */
  2793. function useAnchor(_ref) {
  2794. let {
  2795. editableContentElement,
  2796. value,
  2797. settings = {}
  2798. } = _ref;
  2799. const {
  2800. tagName,
  2801. className,
  2802. name
  2803. } = settings;
  2804. const activeFormat = name ? getActiveFormat(value, name) : undefined;
  2805. return (0,external_wp_element_namespaceObject.useMemo)(() => {
  2806. if (!editableContentElement) return;
  2807. const {
  2808. ownerDocument: {
  2809. defaultView
  2810. }
  2811. } = editableContentElement;
  2812. const selection = defaultView.getSelection();
  2813. if (!selection.rangeCount) {
  2814. return;
  2815. }
  2816. const range = selection.getRangeAt(0);
  2817. if (!activeFormat) {
  2818. return {
  2819. ownerDocument: range.startContainer.ownerDocument,
  2820. getBoundingClientRect() {
  2821. return range.getBoundingClientRect();
  2822. }
  2823. };
  2824. }
  2825. let element = range.startContainer; // If the caret is right before the element, select the next element.
  2826. element = element.nextElementSibling || element;
  2827. while (element.nodeType !== element.ELEMENT_NODE) {
  2828. element = element.parentNode;
  2829. }
  2830. return element.closest(tagName + (className ? '.' + className : ''));
  2831. }, [editableContentElement, activeFormat, value.start, value.end, tagName, className]);
  2832. }
  2833. ;// CONCATENATED MODULE: external ["wp","compose"]
  2834. var external_wp_compose_namespaceObject = window["wp"]["compose"];
  2835. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-default-style.js
  2836. /**
  2837. * WordPress dependencies
  2838. */
  2839. /**
  2840. * In HTML, leading and trailing spaces are not visible, and multiple spaces
  2841. * elsewhere are visually reduced to one space. This rule prevents spaces from
  2842. * collapsing so all space is visible in the editor and can be removed. It also
  2843. * prevents some browsers from inserting non-breaking spaces at the end of a
  2844. * line to prevent the space from visually disappearing. Sometimes these non
  2845. * breaking spaces can linger in the editor causing unwanted non breaking spaces
  2846. * in between words. If also prevent Firefox from inserting a trailing `br` node
  2847. * to visualise any trailing space, causing the element to be saved.
  2848. *
  2849. * > Authors are encouraged to set the 'white-space' property on editing hosts
  2850. * > and on markup that was originally created through these editing mechanisms
  2851. * > to the value 'pre-wrap'. Default HTML whitespace handling is not well
  2852. * > suited to WYSIWYG editing, and line wrapping will not work correctly in
  2853. * > some corner cases if 'white-space' is left at its default value.
  2854. *
  2855. * https://html.spec.whatwg.org/multipage/interaction.html#best-practices-for-in-page-editors
  2856. *
  2857. * @type {string}
  2858. */
  2859. const whiteSpace = 'pre-wrap';
  2860. /**
  2861. * A minimum width of 1px will prevent the rich text container from collapsing
  2862. * to 0 width and hiding the caret. This is useful for inline containers.
  2863. */
  2864. const minWidth = '1px';
  2865. function useDefaultStyle() {
  2866. return (0,external_wp_element_namespaceObject.useCallback)(element => {
  2867. if (!element) return;
  2868. element.style.whiteSpace = whiteSpace;
  2869. element.style.minWidth = minWidth;
  2870. }, []);
  2871. }
  2872. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-boundary-style.js
  2873. /**
  2874. * WordPress dependencies
  2875. */
  2876. /*
  2877. * Calculates and renders the format boundary style when the active formats
  2878. * change.
  2879. */
  2880. function useBoundaryStyle(_ref) {
  2881. let {
  2882. record
  2883. } = _ref;
  2884. const ref = (0,external_wp_element_namespaceObject.useRef)();
  2885. const {
  2886. activeFormats = []
  2887. } = record.current;
  2888. (0,external_wp_element_namespaceObject.useEffect)(() => {
  2889. // There's no need to recalculate the boundary styles if no formats are
  2890. // active, because no boundary styles will be visible.
  2891. if (!activeFormats || !activeFormats.length) {
  2892. return;
  2893. }
  2894. const boundarySelector = '*[data-rich-text-format-boundary]';
  2895. const element = ref.current.querySelector(boundarySelector);
  2896. if (!element) {
  2897. return;
  2898. }
  2899. const {
  2900. ownerDocument
  2901. } = element;
  2902. const {
  2903. defaultView
  2904. } = ownerDocument;
  2905. const computedStyle = defaultView.getComputedStyle(element);
  2906. const newColor = computedStyle.color.replace(')', ', 0.2)').replace('rgb', 'rgba');
  2907. const selector = `.rich-text:focus ${boundarySelector}`;
  2908. const rule = `background-color: ${newColor}`;
  2909. const style = `${selector} {${rule}}`;
  2910. const globalStyleId = 'rich-text-boundary-style';
  2911. let globalStyle = ownerDocument.getElementById(globalStyleId);
  2912. if (!globalStyle) {
  2913. globalStyle = ownerDocument.createElement('style');
  2914. globalStyle.id = globalStyleId;
  2915. ownerDocument.head.appendChild(globalStyle);
  2916. }
  2917. if (globalStyle.innerHTML !== style) {
  2918. globalStyle.innerHTML = style;
  2919. }
  2920. }, [activeFormats]);
  2921. return ref;
  2922. }
  2923. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-copy-handler.js
  2924. /**
  2925. * WordPress dependencies
  2926. */
  2927. /**
  2928. * Internal dependencies
  2929. */
  2930. function useCopyHandler(props) {
  2931. const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
  2932. propsRef.current = props;
  2933. return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
  2934. function onCopy(event) {
  2935. const {
  2936. record,
  2937. multilineTag,
  2938. preserveWhiteSpace
  2939. } = propsRef.current;
  2940. if (isCollapsed(record.current) || !element.contains(element.ownerDocument.activeElement)) {
  2941. return;
  2942. }
  2943. const selectedRecord = slice(record.current);
  2944. const plainText = getTextContent(selectedRecord);
  2945. const html = toHTMLString({
  2946. value: selectedRecord,
  2947. multilineTag,
  2948. preserveWhiteSpace
  2949. });
  2950. event.clipboardData.setData('text/plain', plainText);
  2951. event.clipboardData.setData('text/html', html);
  2952. event.clipboardData.setData('rich-text', 'true');
  2953. event.clipboardData.setData('rich-text-multi-line-tag', multilineTag || '');
  2954. event.preventDefault();
  2955. }
  2956. element.addEventListener('copy', onCopy);
  2957. return () => {
  2958. element.removeEventListener('copy', onCopy);
  2959. };
  2960. }, []);
  2961. }
  2962. ;// CONCATENATED MODULE: external ["wp","keycodes"]
  2963. var external_wp_keycodes_namespaceObject = window["wp"]["keycodes"];
  2964. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-format-boundaries.js
  2965. /**
  2966. * WordPress dependencies
  2967. */
  2968. /**
  2969. * Internal dependencies
  2970. */
  2971. const EMPTY_ACTIVE_FORMATS = [];
  2972. function useFormatBoundaries(props) {
  2973. const [, forceRender] = (0,external_wp_element_namespaceObject.useReducer)(() => ({}));
  2974. const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
  2975. propsRef.current = props;
  2976. return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
  2977. function onKeyDown(event) {
  2978. const {
  2979. keyCode,
  2980. shiftKey,
  2981. altKey,
  2982. metaKey,
  2983. ctrlKey
  2984. } = event;
  2985. if ( // Only override left and right keys without modifiers pressed.
  2986. shiftKey || altKey || metaKey || ctrlKey || keyCode !== external_wp_keycodes_namespaceObject.LEFT && keyCode !== external_wp_keycodes_namespaceObject.RIGHT) {
  2987. return;
  2988. }
  2989. const {
  2990. record,
  2991. applyRecord
  2992. } = propsRef.current;
  2993. const {
  2994. text,
  2995. formats,
  2996. start,
  2997. end,
  2998. activeFormats: currentActiveFormats = []
  2999. } = record.current;
  3000. const collapsed = isCollapsed(record.current);
  3001. const {
  3002. ownerDocument
  3003. } = element;
  3004. const {
  3005. defaultView
  3006. } = ownerDocument; // To do: ideally, we should look at visual position instead.
  3007. const {
  3008. direction
  3009. } = defaultView.getComputedStyle(element);
  3010. const reverseKey = direction === 'rtl' ? external_wp_keycodes_namespaceObject.RIGHT : external_wp_keycodes_namespaceObject.LEFT;
  3011. const isReverse = event.keyCode === reverseKey; // If the selection is collapsed and at the very start, do nothing if
  3012. // navigating backward.
  3013. // If the selection is collapsed and at the very end, do nothing if
  3014. // navigating forward.
  3015. if (collapsed && currentActiveFormats.length === 0) {
  3016. if (start === 0 && isReverse) {
  3017. return;
  3018. }
  3019. if (end === text.length && !isReverse) {
  3020. return;
  3021. }
  3022. } // If the selection is not collapsed, let the browser handle collapsing
  3023. // the selection for now. Later we could expand this logic to set
  3024. // boundary positions if needed.
  3025. if (!collapsed) {
  3026. return;
  3027. }
  3028. const formatsBefore = formats[start - 1] || EMPTY_ACTIVE_FORMATS;
  3029. const formatsAfter = formats[start] || EMPTY_ACTIVE_FORMATS;
  3030. const destination = isReverse ? formatsBefore : formatsAfter;
  3031. const isIncreasing = currentActiveFormats.every((format, index) => format === destination[index]);
  3032. let newActiveFormatsLength = currentActiveFormats.length;
  3033. if (!isIncreasing) {
  3034. newActiveFormatsLength--;
  3035. } else if (newActiveFormatsLength < destination.length) {
  3036. newActiveFormatsLength++;
  3037. }
  3038. if (newActiveFormatsLength === currentActiveFormats.length) {
  3039. record.current._newActiveFormats = destination;
  3040. return;
  3041. }
  3042. event.preventDefault();
  3043. const origin = isReverse ? formatsAfter : formatsBefore;
  3044. const source = isIncreasing ? destination : origin;
  3045. const newActiveFormats = source.slice(0, newActiveFormatsLength);
  3046. const newValue = { ...record.current,
  3047. activeFormats: newActiveFormats
  3048. };
  3049. record.current = newValue;
  3050. applyRecord(newValue);
  3051. forceRender();
  3052. }
  3053. element.addEventListener('keydown', onKeyDown);
  3054. return () => {
  3055. element.removeEventListener('keydown', onKeyDown);
  3056. };
  3057. }, []);
  3058. }
  3059. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-select-object.js
  3060. /**
  3061. * WordPress dependencies
  3062. */
  3063. function useSelectObject() {
  3064. return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
  3065. function onClick(event) {
  3066. const {
  3067. target
  3068. } = event; // If the child element has no text content, it must be an object.
  3069. if (target === element || target.textContent) {
  3070. return;
  3071. }
  3072. const {
  3073. ownerDocument
  3074. } = target;
  3075. const {
  3076. defaultView
  3077. } = ownerDocument;
  3078. const range = ownerDocument.createRange();
  3079. const selection = defaultView.getSelection();
  3080. range.selectNode(target);
  3081. selection.removeAllRanges();
  3082. selection.addRange(range);
  3083. }
  3084. element.addEventListener('click', onClick);
  3085. return () => {
  3086. element.removeEventListener('click', onClick);
  3087. };
  3088. }, []);
  3089. }
  3090. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/update-formats.js
  3091. /**
  3092. * Internal dependencies
  3093. */
  3094. /** @typedef {import('./create').RichTextValue} RichTextValue */
  3095. /**
  3096. * Efficiently updates all the formats from `start` (including) until `end`
  3097. * (excluding) with the active formats. Mutates `value`.
  3098. *
  3099. * @param {Object} $1 Named paramentes.
  3100. * @param {RichTextValue} $1.value Value te update.
  3101. * @param {number} $1.start Index to update from.
  3102. * @param {number} $1.end Index to update until.
  3103. * @param {Array} $1.formats Replacement formats.
  3104. *
  3105. * @return {RichTextValue} Mutated value.
  3106. */
  3107. function updateFormats(_ref) {
  3108. let {
  3109. value,
  3110. start,
  3111. end,
  3112. formats
  3113. } = _ref;
  3114. // Start and end may be switched in case of delete.
  3115. const min = Math.min(start, end);
  3116. const max = Math.max(start, end);
  3117. const formatsBefore = value.formats[min - 1] || [];
  3118. const formatsAfter = value.formats[max] || []; // First, fix the references. If any format right before or after are
  3119. // equal, the replacement format should use the same reference.
  3120. value.activeFormats = formats.map((format, index) => {
  3121. if (formatsBefore[index]) {
  3122. if (isFormatEqual(format, formatsBefore[index])) {
  3123. return formatsBefore[index];
  3124. }
  3125. } else if (formatsAfter[index]) {
  3126. if (isFormatEqual(format, formatsAfter[index])) {
  3127. return formatsAfter[index];
  3128. }
  3129. }
  3130. return format;
  3131. });
  3132. while (--end >= start) {
  3133. if (value.activeFormats.length > 0) {
  3134. value.formats[end] = value.activeFormats;
  3135. } else {
  3136. delete value.formats[end];
  3137. }
  3138. }
  3139. return value;
  3140. }
  3141. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-input-and-selection.js
  3142. /**
  3143. * WordPress dependencies
  3144. */
  3145. /**
  3146. * Internal dependencies
  3147. */
  3148. /**
  3149. * All inserting input types that would insert HTML into the DOM.
  3150. *
  3151. * @see https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes
  3152. *
  3153. * @type {Set}
  3154. */
  3155. const INSERTION_INPUT_TYPES_TO_IGNORE = new Set(['insertParagraph', 'insertOrderedList', 'insertUnorderedList', 'insertHorizontalRule', 'insertLink']);
  3156. const use_input_and_selection_EMPTY_ACTIVE_FORMATS = [];
  3157. const PLACEHOLDER_ATTR_NAME = 'data-rich-text-placeholder';
  3158. /**
  3159. * If the selection is set on the placeholder element, collapse the selection to
  3160. * the start (before the placeholder).
  3161. *
  3162. * @param {Window} defaultView
  3163. */
  3164. function fixPlaceholderSelection(defaultView) {
  3165. const selection = defaultView.getSelection();
  3166. const {
  3167. anchorNode,
  3168. anchorOffset
  3169. } = selection;
  3170. if (anchorNode.nodeType !== anchorNode.ELEMENT_NODE) {
  3171. return;
  3172. }
  3173. const targetNode = anchorNode.childNodes[anchorOffset];
  3174. if (!targetNode || targetNode.nodeType !== targetNode.ELEMENT_NODE || !targetNode.hasAttribute(PLACEHOLDER_ATTR_NAME)) {
  3175. return;
  3176. }
  3177. selection.collapseToStart();
  3178. }
  3179. function useInputAndSelection(props) {
  3180. const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
  3181. propsRef.current = props;
  3182. return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
  3183. const {
  3184. ownerDocument
  3185. } = element;
  3186. const {
  3187. defaultView
  3188. } = ownerDocument;
  3189. let isComposing = false;
  3190. let rafId;
  3191. function onInput(event) {
  3192. // Do not trigger a change if characters are being composed.
  3193. // Browsers will usually emit a final `input` event when the
  3194. // characters are composed.
  3195. // As of December 2019, Safari doesn't support
  3196. // nativeEvent.isComposing.
  3197. if (isComposing) {
  3198. return;
  3199. }
  3200. let inputType;
  3201. if (event) {
  3202. inputType = event.inputType;
  3203. }
  3204. const {
  3205. record,
  3206. applyRecord,
  3207. createRecord,
  3208. handleChange
  3209. } = propsRef.current; // The browser formatted something or tried to insert HTML.
  3210. // Overwrite it. It will be handled later by the format library if
  3211. // needed.
  3212. if (inputType && (inputType.indexOf('format') === 0 || INSERTION_INPUT_TYPES_TO_IGNORE.has(inputType))) {
  3213. applyRecord(record.current);
  3214. return;
  3215. }
  3216. const currentValue = createRecord();
  3217. const {
  3218. start,
  3219. activeFormats: oldActiveFormats = []
  3220. } = record.current; // Update the formats between the last and new caret position.
  3221. const change = updateFormats({
  3222. value: currentValue,
  3223. start,
  3224. end: currentValue.start,
  3225. formats: oldActiveFormats
  3226. });
  3227. handleChange(change);
  3228. }
  3229. /**
  3230. * Syncs the selection to local state. A callback for the `selectionchange`
  3231. * native events, `keyup`, `mouseup` and `touchend` synthetic events, and
  3232. * animation frames after the `focus` event.
  3233. *
  3234. * @param {Event|DOMHighResTimeStamp} event
  3235. */
  3236. function handleSelectionChange(event) {
  3237. const {
  3238. record,
  3239. applyRecord,
  3240. createRecord,
  3241. isSelected,
  3242. onSelectionChange
  3243. } = propsRef.current; // Check if the implementor disabled editing. `contentEditable`
  3244. // does disable input, but not text selection, so we must ignore
  3245. // selection changes.
  3246. if (element.contentEditable !== 'true') {
  3247. return;
  3248. } // If the selection changes where the active element is a parent of
  3249. // the rich text instance (writing flow), call `onSelectionChange`
  3250. // for the rich text instance that contains the start or end of the
  3251. // selection.
  3252. if (ownerDocument.activeElement !== element) {
  3253. // Only process if the active elment is contentEditable, either
  3254. // this rich text instance or the writing flow parent. Fixes a
  3255. // bug in Firefox where it strangely selects the closest
  3256. // contentEditable element, even though the click was outside
  3257. // any contentEditable element.
  3258. if (ownerDocument.activeElement.contentEditable !== 'true') {
  3259. return;
  3260. }
  3261. if (!ownerDocument.activeElement.contains(element)) {
  3262. return;
  3263. }
  3264. const selection = defaultView.getSelection();
  3265. const {
  3266. anchorNode,
  3267. focusNode
  3268. } = selection;
  3269. if (element.contains(anchorNode) && element !== anchorNode && element.contains(focusNode) && element !== focusNode) {
  3270. const {
  3271. start,
  3272. end
  3273. } = createRecord();
  3274. record.current.activeFormats = use_input_and_selection_EMPTY_ACTIVE_FORMATS;
  3275. onSelectionChange(start, end);
  3276. } else if (element.contains(anchorNode) && element !== anchorNode) {
  3277. const {
  3278. start,
  3279. end: offset = start
  3280. } = createRecord();
  3281. record.current.activeFormats = use_input_and_selection_EMPTY_ACTIVE_FORMATS;
  3282. onSelectionChange(offset);
  3283. } else if (element.contains(focusNode)) {
  3284. const {
  3285. start,
  3286. end: offset = start
  3287. } = createRecord();
  3288. record.current.activeFormats = use_input_and_selection_EMPTY_ACTIVE_FORMATS;
  3289. onSelectionChange(undefined, offset);
  3290. }
  3291. return;
  3292. }
  3293. if (event.type !== 'selectionchange' && !isSelected) {
  3294. return;
  3295. } // In case of a keyboard event, ignore selection changes during
  3296. // composition.
  3297. if (isComposing) {
  3298. return;
  3299. }
  3300. const {
  3301. start,
  3302. end,
  3303. text
  3304. } = createRecord();
  3305. const oldRecord = record.current; // Fallback mechanism for IE11, which doesn't support the input event.
  3306. // Any input results in a selection change.
  3307. if (text !== oldRecord.text) {
  3308. onInput();
  3309. return;
  3310. }
  3311. if (start === oldRecord.start && end === oldRecord.end) {
  3312. // Sometimes the browser may set the selection on the placeholder
  3313. // element, in which case the caret is not visible. We need to set
  3314. // the caret before the placeholder if that's the case.
  3315. if (oldRecord.text.length === 0 && start === 0) {
  3316. fixPlaceholderSelection(defaultView);
  3317. }
  3318. return;
  3319. }
  3320. const newValue = { ...oldRecord,
  3321. start,
  3322. end,
  3323. // _newActiveFormats may be set on arrow key navigation to control
  3324. // the right boundary position. If undefined, getActiveFormats will
  3325. // give the active formats according to the browser.
  3326. activeFormats: oldRecord._newActiveFormats,
  3327. _newActiveFormats: undefined
  3328. };
  3329. const newActiveFormats = getActiveFormats(newValue, use_input_and_selection_EMPTY_ACTIVE_FORMATS); // Update the value with the new active formats.
  3330. newValue.activeFormats = newActiveFormats; // It is important that the internal value is updated first,
  3331. // otherwise the value will be wrong on render!
  3332. record.current = newValue;
  3333. applyRecord(newValue, {
  3334. domOnly: true
  3335. });
  3336. onSelectionChange(start, end);
  3337. }
  3338. function onCompositionStart() {
  3339. var _element$querySelecto;
  3340. isComposing = true; // Do not update the selection when characters are being composed as
  3341. // this rerenders the component and might destroy internal browser
  3342. // editing state.
  3343. ownerDocument.removeEventListener('selectionchange', handleSelectionChange); // Remove the placeholder. Since the rich text value doesn't update
  3344. // during composition, the placeholder doesn't get removed. There's
  3345. // no need to re-add it, when the value is updated on compositionend
  3346. // it will be re-added when the value is empty.
  3347. (_element$querySelecto = element.querySelector(`[${PLACEHOLDER_ATTR_NAME}]`)) === null || _element$querySelecto === void 0 ? void 0 : _element$querySelecto.remove();
  3348. }
  3349. function onCompositionEnd() {
  3350. isComposing = false; // Ensure the value is up-to-date for browsers that don't emit a final
  3351. // input event after composition.
  3352. onInput({
  3353. inputType: 'insertText'
  3354. }); // Tracking selection changes can be resumed.
  3355. ownerDocument.addEventListener('selectionchange', handleSelectionChange);
  3356. }
  3357. function onFocus() {
  3358. const {
  3359. record,
  3360. isSelected,
  3361. onSelectionChange,
  3362. applyRecord
  3363. } = propsRef.current; // When the whole editor is editable, let writing flow handle
  3364. // selection.
  3365. if (element.parentElement.closest('[contenteditable="true"]')) {
  3366. return;
  3367. }
  3368. if (!isSelected) {
  3369. // We know for certain that on focus, the old selection is invalid.
  3370. // It will be recalculated on the next mouseup, keyup, or touchend
  3371. // event.
  3372. const index = undefined;
  3373. record.current = { ...record.current,
  3374. start: index,
  3375. end: index,
  3376. activeFormats: use_input_and_selection_EMPTY_ACTIVE_FORMATS
  3377. };
  3378. onSelectionChange(index, index);
  3379. } else {
  3380. applyRecord(record.current);
  3381. onSelectionChange(record.current.start, record.current.end);
  3382. } // Update selection as soon as possible, which is at the next animation
  3383. // frame. The event listener for selection changes may be added too late
  3384. // at this point, but this focus event is still too early to calculate
  3385. // the selection.
  3386. rafId = defaultView.requestAnimationFrame(handleSelectionChange);
  3387. }
  3388. element.addEventListener('input', onInput);
  3389. element.addEventListener('compositionstart', onCompositionStart);
  3390. element.addEventListener('compositionend', onCompositionEnd);
  3391. element.addEventListener('focus', onFocus); // Selection updates must be done at these events as they
  3392. // happen before the `selectionchange` event. In some cases,
  3393. // the `selectionchange` event may not even fire, for
  3394. // example when the window receives focus again on click.
  3395. element.addEventListener('keyup', handleSelectionChange);
  3396. element.addEventListener('mouseup', handleSelectionChange);
  3397. element.addEventListener('touchend', handleSelectionChange);
  3398. ownerDocument.addEventListener('selectionchange', handleSelectionChange);
  3399. return () => {
  3400. element.removeEventListener('input', onInput);
  3401. element.removeEventListener('compositionstart', onCompositionStart);
  3402. element.removeEventListener('compositionend', onCompositionEnd);
  3403. element.removeEventListener('focus', onFocus);
  3404. element.removeEventListener('keyup', handleSelectionChange);
  3405. element.removeEventListener('mouseup', handleSelectionChange);
  3406. element.removeEventListener('touchend', handleSelectionChange);
  3407. ownerDocument.removeEventListener('selectionchange', handleSelectionChange);
  3408. defaultView.cancelAnimationFrame(rafId);
  3409. };
  3410. }, []);
  3411. }
  3412. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/remove-line-separator.js
  3413. /**
  3414. * Internal dependencies
  3415. */
  3416. /** @typedef {import('./create').RichTextValue} RichTextValue */
  3417. /**
  3418. * Removes a line separator character, if existing, from a Rich Text value at
  3419. * the current indices. If no line separator exists on the indices it will
  3420. * return undefined.
  3421. *
  3422. * @param {RichTextValue} value Value to modify.
  3423. * @param {boolean} backward Indicates if are removing from the start
  3424. * index or the end index.
  3425. *
  3426. * @return {RichTextValue|undefined} A new value with the line separator
  3427. * removed. Or undefined if no line separator
  3428. * is found on the position.
  3429. */
  3430. function removeLineSeparator(value) {
  3431. let backward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  3432. const {
  3433. replacements,
  3434. text,
  3435. start,
  3436. end
  3437. } = value;
  3438. const collapsed = isCollapsed(value);
  3439. let index = start - 1;
  3440. let removeStart = collapsed ? start - 1 : start;
  3441. let removeEnd = end;
  3442. if (!backward) {
  3443. index = end;
  3444. removeStart = start;
  3445. removeEnd = collapsed ? end + 1 : end;
  3446. }
  3447. if (text[index] !== LINE_SEPARATOR) {
  3448. return;
  3449. }
  3450. let newValue; // If the line separator that is about te be removed
  3451. // contains wrappers, remove the wrappers first.
  3452. if (collapsed && replacements[index] && replacements[index].length) {
  3453. const newReplacements = replacements.slice();
  3454. newReplacements[index] = replacements[index].slice(0, -1);
  3455. newValue = { ...value,
  3456. replacements: newReplacements
  3457. };
  3458. } else {
  3459. newValue = remove(value, removeStart, removeEnd);
  3460. }
  3461. return newValue;
  3462. }
  3463. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/use-delete.js
  3464. /**
  3465. * WordPress dependencies
  3466. */
  3467. /**
  3468. * Internal dependencies
  3469. */
  3470. function useDelete(props) {
  3471. const propsRef = (0,external_wp_element_namespaceObject.useRef)(props);
  3472. propsRef.current = props;
  3473. return (0,external_wp_compose_namespaceObject.useRefEffect)(element => {
  3474. function onKeyDown(event) {
  3475. const {
  3476. keyCode
  3477. } = event;
  3478. const {
  3479. createRecord,
  3480. handleChange,
  3481. multilineTag
  3482. } = propsRef.current;
  3483. if (event.defaultPrevented) {
  3484. return;
  3485. }
  3486. if (keyCode !== external_wp_keycodes_namespaceObject.DELETE && keyCode !== external_wp_keycodes_namespaceObject.BACKSPACE) {
  3487. return;
  3488. }
  3489. const currentValue = createRecord();
  3490. const {
  3491. start,
  3492. end,
  3493. text
  3494. } = currentValue;
  3495. const isReverse = keyCode === external_wp_keycodes_namespaceObject.BACKSPACE; // Always handle full content deletion ourselves.
  3496. if (start === 0 && end !== 0 && end === text.length) {
  3497. handleChange(remove(currentValue));
  3498. event.preventDefault();
  3499. return;
  3500. }
  3501. if (multilineTag) {
  3502. let newValue; // Check to see if we should remove the first item if empty.
  3503. if (isReverse && currentValue.start === 0 && currentValue.end === 0 && isEmptyLine(currentValue)) {
  3504. newValue = removeLineSeparator(currentValue, !isReverse);
  3505. } else {
  3506. newValue = removeLineSeparator(currentValue, isReverse);
  3507. }
  3508. if (newValue) {
  3509. handleChange(newValue);
  3510. event.preventDefault();
  3511. }
  3512. }
  3513. }
  3514. element.addEventListener('keydown', onKeyDown);
  3515. return () => {
  3516. element.removeEventListener('keydown', onKeyDown);
  3517. };
  3518. }, []);
  3519. }
  3520. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/index.js
  3521. /**
  3522. * WordPress dependencies
  3523. */
  3524. /**
  3525. * Internal dependencies
  3526. */
  3527. function useRichText(_ref) {
  3528. let {
  3529. value = '',
  3530. selectionStart,
  3531. selectionEnd,
  3532. placeholder,
  3533. preserveWhiteSpace,
  3534. onSelectionChange,
  3535. onChange,
  3536. __unstableMultilineTag: multilineTag,
  3537. __unstableDisableFormats: disableFormats,
  3538. __unstableIsSelected: isSelected,
  3539. __unstableDependencies = [],
  3540. __unstableAfterParse,
  3541. __unstableBeforeSerialize,
  3542. __unstableAddInvisibleFormats
  3543. } = _ref;
  3544. const registry = (0,external_wp_data_namespaceObject.useRegistry)();
  3545. const [, forceRender] = (0,external_wp_element_namespaceObject.useReducer)(() => ({}));
  3546. const ref = (0,external_wp_element_namespaceObject.useRef)();
  3547. function createRecord() {
  3548. const {
  3549. ownerDocument: {
  3550. defaultView
  3551. }
  3552. } = ref.current;
  3553. const selection = defaultView.getSelection();
  3554. const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
  3555. return create({
  3556. element: ref.current,
  3557. range,
  3558. multilineTag,
  3559. multilineWrapperTags: multilineTag === 'li' ? ['ul', 'ol'] : undefined,
  3560. __unstableIsEditableTree: true,
  3561. preserveWhiteSpace
  3562. });
  3563. }
  3564. function applyRecord(newRecord) {
  3565. let {
  3566. domOnly
  3567. } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  3568. apply({
  3569. value: newRecord,
  3570. current: ref.current,
  3571. multilineTag,
  3572. multilineWrapperTags: multilineTag === 'li' ? ['ul', 'ol'] : undefined,
  3573. prepareEditableTree: __unstableAddInvisibleFormats,
  3574. __unstableDomOnly: domOnly,
  3575. placeholder
  3576. });
  3577. } // Internal values are updated synchronously, unlike props and state.
  3578. const _value = (0,external_wp_element_namespaceObject.useRef)(value);
  3579. const record = (0,external_wp_element_namespaceObject.useRef)();
  3580. function setRecordFromProps() {
  3581. _value.current = value;
  3582. record.current = create({
  3583. html: value,
  3584. multilineTag,
  3585. multilineWrapperTags: multilineTag === 'li' ? ['ul', 'ol'] : undefined,
  3586. preserveWhiteSpace
  3587. });
  3588. if (disableFormats) {
  3589. record.current.formats = Array(value.length);
  3590. record.current.replacements = Array(value.length);
  3591. }
  3592. if (__unstableAfterParse) {
  3593. record.current.formats = __unstableAfterParse(record.current);
  3594. }
  3595. record.current.start = selectionStart;
  3596. record.current.end = selectionEnd;
  3597. }
  3598. const hadSelectionUpdate = (0,external_wp_element_namespaceObject.useRef)(false);
  3599. if (!record.current) {
  3600. var _record$current, _record$current$forma, _record$current$forma2;
  3601. setRecordFromProps(); // Sometimes formats are added programmatically and we need to make
  3602. // sure it's persisted to the block store / markup. If these formats
  3603. // are not applied, they could cause inconsistencies between the data
  3604. // in the visual editor and the frontend. Right now, it's only relevant
  3605. // to the `core/text-color` format, which is applied at runtime in
  3606. // certain circunstances. See the `__unstableFilterAttributeValue`
  3607. // function in `packages/format-library/src/text-color/index.js`.
  3608. // @todo find a less-hacky way of solving this.
  3609. const hasRelevantInitFormat = ((_record$current = record.current) === null || _record$current === void 0 ? void 0 : (_record$current$forma = _record$current.formats[0]) === null || _record$current$forma === void 0 ? void 0 : (_record$current$forma2 = _record$current$forma[0]) === null || _record$current$forma2 === void 0 ? void 0 : _record$current$forma2.type) === 'core/text-color';
  3610. if (hasRelevantInitFormat) {
  3611. handleChangesUponInit(record.current);
  3612. }
  3613. } else if (selectionStart !== record.current.start || selectionEnd !== record.current.end) {
  3614. hadSelectionUpdate.current = isSelected;
  3615. record.current = { ...record.current,
  3616. start: selectionStart,
  3617. end: selectionEnd
  3618. };
  3619. }
  3620. /**
  3621. * Sync the value to global state. The node tree and selection will also be
  3622. * updated if differences are found.
  3623. *
  3624. * @param {Object} newRecord The record to sync and apply.
  3625. */
  3626. function handleChange(newRecord) {
  3627. record.current = newRecord;
  3628. applyRecord(newRecord);
  3629. if (disableFormats) {
  3630. _value.current = newRecord.text;
  3631. } else {
  3632. _value.current = toHTMLString({
  3633. value: __unstableBeforeSerialize ? { ...newRecord,
  3634. formats: __unstableBeforeSerialize(newRecord)
  3635. } : newRecord,
  3636. multilineTag,
  3637. preserveWhiteSpace
  3638. });
  3639. }
  3640. const {
  3641. start,
  3642. end,
  3643. formats,
  3644. text
  3645. } = newRecord; // Selection must be updated first, so it is recorded in history when
  3646. // the content change happens.
  3647. // We batch both calls to only attempt to rerender once.
  3648. registry.batch(() => {
  3649. onSelectionChange(start, end);
  3650. onChange(_value.current, {
  3651. __unstableFormats: formats,
  3652. __unstableText: text
  3653. });
  3654. });
  3655. forceRender();
  3656. }
  3657. function handleChangesUponInit(newRecord) {
  3658. record.current = newRecord;
  3659. _value.current = toHTMLString({
  3660. value: __unstableBeforeSerialize ? { ...newRecord,
  3661. formats: __unstableBeforeSerialize(newRecord)
  3662. } : newRecord,
  3663. multilineTag,
  3664. preserveWhiteSpace
  3665. });
  3666. const {
  3667. formats,
  3668. text
  3669. } = newRecord;
  3670. registry.batch(() => {
  3671. onChange(_value.current, {
  3672. __unstableFormats: formats,
  3673. __unstableText: text
  3674. });
  3675. });
  3676. forceRender();
  3677. }
  3678. function applyFromProps() {
  3679. setRecordFromProps();
  3680. applyRecord(record.current);
  3681. }
  3682. const didMount = (0,external_wp_element_namespaceObject.useRef)(false); // Value updates must happen synchonously to avoid overwriting newer values.
  3683. (0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
  3684. if (didMount.current && value !== _value.current) {
  3685. applyFromProps();
  3686. forceRender();
  3687. }
  3688. }, [value]); // Value updates must happen synchonously to avoid overwriting newer values.
  3689. (0,external_wp_element_namespaceObject.useLayoutEffect)(() => {
  3690. if (!hadSelectionUpdate.current) {
  3691. return;
  3692. }
  3693. if (ref.current.ownerDocument.activeElement !== ref.current) {
  3694. ref.current.focus();
  3695. }
  3696. applyFromProps();
  3697. hadSelectionUpdate.current = false;
  3698. }, [hadSelectionUpdate.current]);
  3699. const mergedRefs = (0,external_wp_compose_namespaceObject.useMergeRefs)([ref, useDefaultStyle(), useBoundaryStyle({
  3700. record
  3701. }), useCopyHandler({
  3702. record,
  3703. multilineTag,
  3704. preserveWhiteSpace
  3705. }), useSelectObject(), useFormatBoundaries({
  3706. record,
  3707. applyRecord
  3708. }), useDelete({
  3709. createRecord,
  3710. handleChange,
  3711. multilineTag
  3712. }), useInputAndSelection({
  3713. record,
  3714. applyRecord,
  3715. createRecord,
  3716. handleChange,
  3717. isSelected,
  3718. onSelectionChange
  3719. }), (0,external_wp_compose_namespaceObject.useRefEffect)(() => {
  3720. applyFromProps();
  3721. didMount.current = true;
  3722. }, [placeholder, ...__unstableDependencies])]);
  3723. return {
  3724. value: record.current,
  3725. onChange: handleChange,
  3726. ref: mergedRefs
  3727. };
  3728. }
  3729. function __experimentalRichText() {}
  3730. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/component/format-edit.js
  3731. /**
  3732. * Internal dependencies
  3733. */
  3734. function FormatEdit(_ref) {
  3735. let {
  3736. formatTypes,
  3737. onChange,
  3738. onFocus,
  3739. value,
  3740. forwardedRef
  3741. } = _ref;
  3742. return formatTypes.map(settings => {
  3743. const {
  3744. name,
  3745. edit: Edit
  3746. } = settings;
  3747. if (!Edit) {
  3748. return null;
  3749. }
  3750. const activeFormat = getActiveFormat(value, name);
  3751. const isActive = activeFormat !== undefined;
  3752. const activeObject = getActiveObject(value);
  3753. const isObjectActive = activeObject !== undefined && activeObject.type === name;
  3754. return (0,external_wp_element_namespaceObject.createElement)(Edit, {
  3755. key: name,
  3756. isActive: isActive,
  3757. activeAttributes: isActive ? activeFormat.attributes || {} : {},
  3758. isObjectActive: isObjectActive,
  3759. activeObjectAttributes: isObjectActive ? activeObject.attributes || {} : {},
  3760. value: value,
  3761. onChange: onChange,
  3762. onFocus: onFocus,
  3763. contentRef: forwardedRef
  3764. });
  3765. });
  3766. }
  3767. ;// CONCATENATED MODULE: ./node_modules/@wordpress/rich-text/build-module/index.js
  3768. (window.wp = window.wp || {}).richText = __webpack_exports__;
  3769. /******/ })()
  3770. ;