rich-text.js 139 KB

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